History

Merge tag '6.7-rc4-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French: "Six smb3 client fixes: - Fixes for copy_file_range and clone (cache invalidation and file size), also addresses an xfstest failure - Fix to return proper error if REMAP_FILE_DEDUP set (also fixes xfstest generic/304) - Fix potential null pointer reference with DFS - Multichannel fix addressing (reverting an earlier patch) some of the problems with enabling/disabling channels dynamically Still working on a followon multichannel fix to address another issue found in reconnect testing that will send next week" * tag '6.7-rc4-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6: cifs: reconnect worker should take reference on server struct unconditionally Revert "cifs: reconnect work should have reference on server struct" cifs: Fix non-availability of dedup breaking generic/304 smb: client: fix potential NULL deref in parse_dfs_referrals() cifs: Fix flushing, invalidation and file size with FICLONE cifs: Fix flushing, invalidation and file size with copy_file_range()

Linus Torvalds committed 2 years ago

Commit 20993062 parents f2e8a57 04909194 files · +187 −58Browse files

Unified · Split

4 files
  1. fs/smb/client/cifsfs.c +159 −15
  2. fs/smb/client/connect.c +10 −25
  3. fs/smb/client/smb2ops.c +2 −0
  4. fs/smb/client/smb2pdu.c +16 −18
fs/smb/client/cifsfs.c+159−15
@@ -1196,32 +1196,103 @@ const struct inode_operations cifs_symlink_inode_ops = { · 1195 unmodified lines
1196 .listxattr = cifs_listxattr,1196 .listxattr = cifs_listxattr,
1197};1197};
1198 1198
1199/*
1200 * Advance the EOF marker to after the source range.
1201 */
1202static int cifs_precopy_set_eof(struct inode *src_inode, struct cifsInodeInfo *src_cifsi,
1203 struct cifs_tcon *src_tcon,
1204 unsigned int xid, loff_t src_end)
1205{
1206 struct cifsFileInfo *writeable_srcfile;
1207 int rc = -EINVAL;
1208
1209 writeable_srcfile = find_writable_file(src_cifsi, FIND_WR_FSUID_ONLY);
1210 if (writeable_srcfile) {
1211 if (src_tcon->ses->server->ops->set_file_size)
1212 rc = src_tcon->ses->server->ops->set_file_size(
1213 xid, src_tcon, writeable_srcfile,
1214 src_inode->i_size, true /* no need to set sparse */);
1215 else
1216 rc = -ENOSYS;
1217 cifsFileInfo_put(writeable_srcfile);
1218 cifs_dbg(FYI, "SetFSize for copychunk rc = %d\n", rc);
1219 }
1220
1221 if (rc < 0)
1222 goto set_failed;
1223
1224 netfs_resize_file(&src_cifsi->netfs, src_end);
1225 fscache_resize_cookie(cifs_inode_cookie(src_inode), src_end);
1226 return 0;
1227
1228set_failed:
1229 return filemap_write_and_wait(src_inode->i_mapping);
1230}
1231
1232/*
1233 * Flush out either the folio that overlaps the beginning of a range in which
1234 * pos resides or the folio that overlaps the end of a range unless that folio
1235 * is entirely within the range we're going to invalidate. We extend the flush
1236 * bounds to encompass the folio.
1237 */
1238static int cifs_flush_folio(struct inode *inode, loff_t pos, loff_t *_fstart, loff_t *_fend,
1239 bool first)
1240{
1241 struct folio *folio;
1242 unsigned long long fpos, fend;
1243 pgoff_t index = pos / PAGE_SIZE;
1244 size_t size;
1245 int rc = 0;
1246
1247 folio = filemap_get_folio(inode->i_mapping, index);
1248 if (IS_ERR(folio))
1249 return 0;
1250
1251 size = folio_size(folio);
1252 fpos = folio_pos(folio);
1253 fend = fpos + size - 1;
1254 *_fstart = min_t(unsigned long long, *_fstart, fpos);
1255 *_fend = max_t(unsigned long long, *_fend, fend);
1256 if ((first && pos == fpos) || (!first && pos == fend))
1257 goto out;
1258
1259 rc = filemap_write_and_wait_range(inode->i_mapping, fpos, fend);
1260out:
1261 folio_put(folio);
1262 return rc;
1263}
1264
1199static loff_t cifs_remap_file_range(struct file *src_file, loff_t off,1265static loff_t cifs_remap_file_range(struct file *src_file, loff_t off,
1200 struct file *dst_file, loff_t destoff, loff_t len,1266 struct file *dst_file, loff_t destoff, loff_t len,
1201 unsigned int remap_flags)1267 unsigned int remap_flags)
1202{1268{
1203 struct inode *src_inode = file_inode(src_file);1269 struct inode *src_inode = file_inode(src_file);
1204 struct inode *target_inode = file_inode(dst_file);1270 struct inode *target_inode = file_inode(dst_file);
1271 struct cifsInodeInfo *src_cifsi = CIFS_I(src_inode);
1272 struct cifsInodeInfo *target_cifsi = CIFS_I(target_inode);
1205 struct cifsFileInfo *smb_file_src = src_file->private_data;1273 struct cifsFileInfo *smb_file_src = src_file->private_data;
1206 struct cifsFileInfo *smb_file_target;1274 struct cifsFileInfo *smb_file_target = dst_file->private_data;
1207 struct cifs_tcon *target_tcon;1275 struct cifs_tcon *target_tcon, *src_tcon;
1276 unsigned long long destend, fstart, fend, new_size;
1208 unsigned int xid;1277 unsigned int xid;
1209 int rc;1278 int rc;
1210 1279
1211 if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY))1280 if (remap_flags & REMAP_FILE_DEDUP)
1281 return -EOPNOTSUPP;
1282 if (remap_flags & ~REMAP_FILE_ADVISORY)
1212 return -EINVAL;1283 return -EINVAL;
1213 1284
1214 cifs_dbg(FYI, "clone range\n");1285 cifs_dbg(FYI, "clone range\n");
1215 1286
1216 xid = get_xid();1287 xid = get_xid();
1217 1288
1218 if (!src_file->private_data || !dst_file->private_data) {1289 if (!smb_file_src || !smb_file_target) {
1219 rc = -EBADF;1290 rc = -EBADF;
1220 cifs_dbg(VFS, "missing cifsFileInfo on copy range src file\n");1291 cifs_dbg(VFS, "missing cifsFileInfo on copy range src file\n");
1221 goto out;1292 goto out;
1222 }1293 }
1223 1294
1224 smb_file_target = dst_file->private_data;1295 src_tcon = tlink_tcon(smb_file_src->tlink);
1225 target_tcon = tlink_tcon(smb_file_target->tlink);1296 target_tcon = tlink_tcon(smb_file_target->tlink);
1226 1297
1227 /*1298 /*
@@ -1234,20 +1305,63 @@ static loff_t cifs_remap_file_range(struct file *src_file, loff_t off, · 6 unmodified lines
1234 if (len == 0)1305 if (len == 0)
1235 len = src_inode->i_size - off;1306 len = src_inode->i_size - off;
1236 1307
1237 cifs_dbg(FYI, "about to flush pages\n");1308 cifs_dbg(FYI, "clone range\n");
1238 /* should we flush first and last page first */
1239 truncate_inode_pages_range(&target_inode->i_data, destoff,
1240 PAGE_ALIGN(destoff + len)-1);
1241 1309
1242 if (target_tcon->ses->server->ops->duplicate_extents)1310 /* Flush the source buffer */
1311 rc = filemap_write_and_wait_range(src_inode->i_mapping, off,
1312 off + len - 1);
1313 if (rc)
1314 goto unlock;
1315
1316 /* The server-side copy will fail if the source crosses the EOF marker.
1317 * Advance the EOF marker after the flush above to the end of the range
1318 * if it's short of that.
1319 */
1320 if (src_cifsi->netfs.remote_i_size < off + len) {
1321 rc = cifs_precopy_set_eof(src_inode, src_cifsi, src_tcon, xid, off + len);
1322 if (rc < 0)
1323 goto unlock;
1324 }
1325
1326 new_size = destoff + len;
1327 destend = destoff + len - 1;
1328
1329 /* Flush the folios at either end of the destination range to prevent
1330 * accidental loss of dirty data outside of the range.
1331 */
1332 fstart = destoff;
1333 fend = destend;
1334
1335 rc = cifs_flush_folio(target_inode, destoff, &fstart, &fend, true);
1336 if (rc)
1337 goto unlock;
1338 rc = cifs_flush_folio(target_inode, destend, &fstart, &fend, false);
1339 if (rc)
1340 goto unlock;
1341
1342 /* Discard all the folios that overlap the destination region. */
1343 cifs_dbg(FYI, "about to discard pages %llx-%llx\n", fstart, fend);
1344 truncate_inode_pages_range(&target_inode->i_data, fstart, fend);
1345
1346 fscache_invalidate(cifs_inode_cookie(target_inode), NULL,
1347 i_size_read(target_inode), 0);
1348
1349 rc = -EOPNOTSUPP;
1350 if (target_tcon->ses->server->ops->duplicate_extents) {
1243 rc = target_tcon->ses->server->ops->duplicate_extents(xid,1351 rc = target_tcon->ses->server->ops->duplicate_extents(xid,
1244 smb_file_src, smb_file_target, off, len, destoff);1352 smb_file_src, smb_file_target, off, len, destoff);
1245 else1353 if (rc == 0 && new_size > i_size_read(target_inode)) {
1246 rc = -EOPNOTSUPP;1354 truncate_setsize(target_inode, new_size);
1355 netfs_resize_file(&target_cifsi->netfs, new_size);
1356 fscache_resize_cookie(cifs_inode_cookie(target_inode),
1357 new_size);
1358 }
1359 }
1247 1360
1248 /* force revalidate of size and timestamps of target file now1361 /* force revalidate of size and timestamps of target file now
1249 that target is updated on the server */1362 that target is updated on the server */
1250 CIFS_I(target_inode)->time = 0;1363 CIFS_I(target_inode)->time = 0;
1364unlock:
1251 /* although unlocking in the reverse order from locking is not1365 /* although unlocking in the reverse order from locking is not
1252 strictly necessary here it is a little cleaner to be consistent */1366 strictly necessary here it is a little cleaner to be consistent */
1253 unlock_two_nondirectories(src_inode, target_inode);1367 unlock_two_nondirectories(src_inode, target_inode);
@@ -1263,10 +1377,12 @@ ssize_t cifs_file_copychunk_range(unsigned int xid, · 9 unmodified lines
1263{1377{
1264 struct inode *src_inode = file_inode(src_file);1378 struct inode *src_inode = file_inode(src_file);
1265 struct inode *target_inode = file_inode(dst_file);1379 struct inode *target_inode = file_inode(dst_file);
1380 struct cifsInodeInfo *src_cifsi = CIFS_I(src_inode);
1266 struct cifsFileInfo *smb_file_src;1381 struct cifsFileInfo *smb_file_src;
1267 struct cifsFileInfo *smb_file_target;1382 struct cifsFileInfo *smb_file_target;
1268 struct cifs_tcon *src_tcon;1383 struct cifs_tcon *src_tcon;
1269 struct cifs_tcon *target_tcon;1384 struct cifs_tcon *target_tcon;
1385 unsigned long long destend, fstart, fend;
1270 ssize_t rc;1386 ssize_t rc;
1271 1387
1272 cifs_dbg(FYI, "copychunk range\n");1388 cifs_dbg(FYI, "copychunk range\n");
@@ -1306,13 +1422,41 @@ ssize_t cifs_file_copychunk_range(unsigned int xid, · 33 unmodified lines
1306 if (rc)1422 if (rc)
1307 goto unlock;1423 goto unlock;
1308 1424
1309 /* should we flush first and last page first */1425 /* The server-side copy will fail if the source crosses the EOF marker.
1310 truncate_inode_pages(&target_inode->i_data, 0);1426 * Advance the EOF marker after the flush above to the end of the range
1427 * if it's short of that.
1428 */
1429 if (src_cifsi->server_eof < off + len) {
1430 rc = cifs_precopy_set_eof(src_inode, src_cifsi, src_tcon, xid, off + len);
1431 if (rc < 0)
1432 goto unlock;
1433 }
1434
1435 destend = destoff + len - 1;
1436
1437 /* Flush the folios at either end of the destination range to prevent
1438 * accidental loss of dirty data outside of the range.
1439 */
1440 fstart = destoff;
1441 fend = destend;
1442
1443 rc = cifs_flush_folio(target_inode, destoff, &fstart, &fend, true);
1444 if (rc)
1445 goto unlock;
1446 rc = cifs_flush_folio(target_inode, destend, &fstart, &fend, false);
1447 if (rc)
1448 goto unlock;
1449
1450 /* Discard all the folios that overlap the destination region. */
1451 truncate_inode_pages_range(&target_inode->i_data, fstart, fend);
1311 1452
1312 rc = file_modified(dst_file);1453 rc = file_modified(dst_file);
1313 if (!rc)1454 if (!rc) {
1314 rc = target_tcon->ses->server->ops->copychunk_range(xid,1455 rc = target_tcon->ses->server->ops->copychunk_range(xid,
1315 smb_file_src, smb_file_target, off, len, destoff);1456 smb_file_src, smb_file_target, off, len, destoff);
1457 if (rc > 0 && destoff + rc > i_size_read(target_inode))
1458 truncate_setsize(target_inode, destoff + rc);
1459 }
1316 1460
1317 file_accessed(src_file);1461 file_accessed(src_file);
1318 1462
fs/smb/client/connect.c+10−25
@@ -402,13 +402,7 @@ static int __cifs_reconnect(struct TCP_Server_Info *server, · 401 unmodified lines
402 spin_unlock(&server->srv_lock);402 spin_unlock(&server->srv_lock);
403 cifs_swn_reset_server_dstaddr(server);403 cifs_swn_reset_server_dstaddr(server);
404 cifs_server_unlock(server);404 cifs_server_unlock(server);
405 405 mod_delayed_work(cifsiod_wq, &server->reconnect, 0);
406 /* increase ref count which reconnect work will drop */
407 spin_lock(&cifs_tcp_ses_lock);
408 server->srv_count++;
409 spin_unlock(&cifs_tcp_ses_lock);
410 if (mod_delayed_work(cifsiod_wq, &server->reconnect, 0))
411 cifs_put_tcp_session(server, false);
412 }406 }
413 } while (server->tcpStatus == CifsNeedReconnect);407 } while (server->tcpStatus == CifsNeedReconnect);
414 408
@@ -538,13 +532,7 @@ static int reconnect_dfs_server(struct TCP_Server_Info *server) · 123 unmodified lines
538 spin_unlock(&server->srv_lock);532 spin_unlock(&server->srv_lock);
539 cifs_swn_reset_server_dstaddr(server);533 cifs_swn_reset_server_dstaddr(server);
540 cifs_server_unlock(server);534 cifs_server_unlock(server);
541 535 mod_delayed_work(cifsiod_wq, &server->reconnect, 0);
542 /* increase ref count which reconnect work will drop */
543 spin_lock(&cifs_tcp_ses_lock);
544 server->srv_count++;
545 spin_unlock(&cifs_tcp_ses_lock);
546 if (mod_delayed_work(cifsiod_wq, &server->reconnect, 0))
547 cifs_put_tcp_session(server, false);
548 } while (server->tcpStatus == CifsNeedReconnect);536 } while (server->tcpStatus == CifsNeedReconnect);
549 537
550 mutex_lock(&server->refpath_lock);538 mutex_lock(&server->refpath_lock);
@@ -1620,25 +1608,22 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect) · 1069 unmodified lines
1620 list_del_init(&server->tcp_ses_list);1608 list_del_init(&server->tcp_ses_list);
1621 spin_unlock(&cifs_tcp_ses_lock);1609 spin_unlock(&cifs_tcp_ses_lock);
1622 1610
1623 /* For secondary channels, we pick up ref-count on the primary server */
1624 if (SERVER_IS_CHAN(server))
1625 cifs_put_tcp_session(server->primary_server, from_reconnect);
1626
1627 cancel_delayed_work_sync(&server->echo);1611 cancel_delayed_work_sync(&server->echo);
1628 1612
1629 if (from_reconnect) {1613 if (from_reconnect)
1630 /*1614 /*
1631 * Avoid deadlock here: reconnect work calls1615 * Avoid deadlock here: reconnect work calls
1632 * cifs_put_tcp_session() at its end. Need to be sure1616 * cifs_put_tcp_session() at its end. Need to be sure
1633 * that reconnect work does nothing with server pointer after1617 * that reconnect work does nothing with server pointer after
1634 * that step.1618 * that step.
1635 */1619 */
1636 if (cancel_delayed_work(&server->reconnect))1620 cancel_delayed_work(&server->reconnect);
1637 cifs_put_tcp_session(server, from_reconnect);1621 else
1638 } else {1622 cancel_delayed_work_sync(&server->reconnect);
1639 if (cancel_delayed_work_sync(&server->reconnect))1623
1640 cifs_put_tcp_session(server, from_reconnect);1624 /* For secondary channels, we pick up ref-count on the primary server */
1641 }1625 if (SERVER_IS_CHAN(server))
1626 cifs_put_tcp_session(server->primary_server, from_reconnect);
1642 1627
1643 spin_lock(&server->srv_lock);1628 spin_lock(&server->srv_lock);
1644 server->tcpStatus = CifsExiting;1629 server->tcpStatus = CifsExiting;
fs/smb/client/smb2ops.c+2−0
@@ -2836,6 +2836,8 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses, · 2835 unmodified lines
2836 usleep_range(512, 2048);2836 usleep_range(512, 2048);
2837 } while (++retry_count < 5);2837 } while (++retry_count < 5);
2838 2838
2839 if (!rc && !dfs_rsp)
2840 rc = -EIO;
2839 if (rc) {2841 if (rc) {
2840 if (!is_retryable_error(rc) && rc != -ENOENT && rc != -EOPNOTSUPP)2842 if (!is_retryable_error(rc) && rc != -ENOENT && rc != -EOPNOTSUPP)
2841 cifs_tcon_dbg(VFS, "%s: ioctl error: rc=%d\n", __func__, rc);2843 cifs_tcon_dbg(VFS, "%s: ioctl error: rc=%d\n", __func__, rc);
fs/smb/client/smb2pdu.c+16−18
@@ -158,7 +158,7 @@ out: · 157 unmodified lines
158 158
159static int159static int
160smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,160smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
161 struct TCP_Server_Info *server)161 struct TCP_Server_Info *server, bool from_reconnect)
162{162{
163 int rc = 0;163 int rc = 0;
164 struct nls_table *nls_codepage = NULL;164 struct nls_table *nls_codepage = NULL;
@@ -331,7 +331,7 @@ again: · 166 unmodified lines
331 * as cifs_put_tcp_session takes a higher lock331 * as cifs_put_tcp_session takes a higher lock
332 * i.e. cifs_tcp_ses_lock332 * i.e. cifs_tcp_ses_lock
333 */333 */
334 cifs_put_tcp_session(server, 1);334 cifs_put_tcp_session(server, from_reconnect);
335 335
336 server->terminate = true;336 server->terminate = true;
337 cifs_signal_cifsd_for_reconnect(server, false);337 cifs_signal_cifsd_for_reconnect(server, false);
@@ -499,7 +499,7 @@ static int smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon, · 161 unmodified lines
499{499{
500 int rc;500 int rc;
501 501
502 rc = smb2_reconnect(smb2_command, tcon, server);502 rc = smb2_reconnect(smb2_command, tcon, server, false);
503 if (rc)503 if (rc)
504 return rc;504 return rc;
505 505
@@ -3895,6 +3895,15 @@ void smb2_reconnect_server(struct work_struct *work) · 3389 unmodified lines
3895 int rc;3895 int rc;
3896 bool resched = false;3896 bool resched = false;
3897 3897
3898 /* first check if ref count has reached 0, if not inc ref count */
3899 spin_lock(&cifs_tcp_ses_lock);
3900 if (!server->srv_count) {
3901 spin_unlock(&cifs_tcp_ses_lock);
3902 return;
3903 }
3904 server->srv_count++;
3905 spin_unlock(&cifs_tcp_ses_lock);
3906
3898 /* If server is a channel, select the primary channel */3907 /* If server is a channel, select the primary channel */
3899 pserver = SERVER_IS_CHAN(server) ? server->primary_server : server;3908 pserver = SERVER_IS_CHAN(server) ? server->primary_server : server;
3900 3909
@@ -3952,11 +3961,10 @@ void smb2_reconnect_server(struct work_struct *work) · 51 unmodified lines
3952 }3961 }
3953 spin_unlock(&ses->chan_lock);3962 spin_unlock(&ses->chan_lock);
3954 }3963 }
3955
3956 spin_unlock(&cifs_tcp_ses_lock);3964 spin_unlock(&cifs_tcp_ses_lock);
3957 3965
3958 list_for_each_entry_safe(tcon, tcon2, &tmp_list, rlist) {3966 list_for_each_entry_safe(tcon, tcon2, &tmp_list, rlist) {
3959 rc = smb2_reconnect(SMB2_INTERNAL_CMD, tcon, server);3967 rc = smb2_reconnect(SMB2_INTERNAL_CMD, tcon, server, true);
3960 if (!rc)3968 if (!rc)
3961 cifs_reopen_persistent_handles(tcon);3969 cifs_reopen_persistent_handles(tcon);
3962 else3970 else
@@ -3989,7 +3997,7 @@ void smb2_reconnect_server(struct work_struct *work) · 26 unmodified lines
3989 /* now reconnect sessions for necessary channels */3997 /* now reconnect sessions for necessary channels */
3990 list_for_each_entry_safe(ses, ses2, &tmp_ses_list, rlist) {3998 list_for_each_entry_safe(ses, ses2, &tmp_ses_list, rlist) {
3991 tcon->ses = ses;3999 tcon->ses = ses;
3992 rc = smb2_reconnect(SMB2_INTERNAL_CMD, tcon, server);4000 rc = smb2_reconnect(SMB2_INTERNAL_CMD, tcon, server, true);
3993 if (rc)4001 if (rc)
3994 resched = true;4002 resched = true;
3995 list_del_init(&ses->rlist);4003 list_del_init(&ses->rlist);
@@ -3999,13 +4007,8 @@ void smb2_reconnect_server(struct work_struct *work) · 3 unmodified lines
3999 4007
4000done:4008done:
4001 cifs_dbg(FYI, "Reconnecting tcons and channels finished\n");4009 cifs_dbg(FYI, "Reconnecting tcons and channels finished\n");
4002 if (resched) {4010 if (resched)
4003 queue_delayed_work(cifsiod_wq, &server->reconnect, 2 * HZ);4011 queue_delayed_work(cifsiod_wq, &server->reconnect, 2 * HZ);
4004 mutex_unlock(&pserver->reconnect_mutex);
4005
4006 /* no need to put tcp session as we're retrying */
4007 return;
4008 }
4009 mutex_unlock(&pserver->reconnect_mutex);4012 mutex_unlock(&pserver->reconnect_mutex);
4010 4013
4011 /* now we can safely release srv struct */4014 /* now we can safely release srv struct */
@@ -4029,12 +4032,7 @@ SMB2_echo(struct TCP_Server_Info *server) · 17 unmodified lines
4029 server->ops->need_neg(server)) {4032 server->ops->need_neg(server)) {
4030 spin_unlock(&server->srv_lock);4033 spin_unlock(&server->srv_lock);
4031 /* No need to send echo on newly established connections */4034 /* No need to send echo on newly established connections */
4032 spin_lock(&cifs_tcp_ses_lock);4035 mod_delayed_work(cifsiod_wq, &server->reconnect, 0);
4033 server->srv_count++;
4034 spin_unlock(&cifs_tcp_ses_lock);
4035 if (mod_delayed_work(cifsiod_wq, &server->reconnect, 0))
4036 cifs_put_tcp_session(server, false);
4037
4038 return rc;4036 return rc;
4039 }4037 }
4040 spin_unlock(&server->srv_lock);4038 spin_unlock(&server->srv_lock);