Merge tag '5.14-rc2-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs fixes from Steve French:
"Five cifs/smb3 fixes, including a DFS failover fix, two fallocate
fixes, and two trivial coverity cleanups"

* tag '5.14-rc2-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6:
cifs: fix fallocate when trying to allocate a hole.
CIFS: Clarify SMB1 code for POSIX delete file
CIFS: Clarify SMB1 code for POSIX Create
cifs: support share failover when remounting
cifs: only write 64kb at a time when fallocating a small region of a file

+247 -55
+7 -3
fs/cifs/cifssmb.c
··· 873 873 InformationLevel) - 4; 874 874 offset = param_offset + params; 875 875 876 - /* Setup pointer to Request Data (inode type) */ 877 - pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset); 876 + /* Setup pointer to Request Data (inode type). 877 + * Note that SMB offsets are from the beginning of SMB which is 4 bytes 878 + * in, after RFC1001 field 879 + */ 880 + pRqD = (struct unlink_psx_rq *)((char *)(pSMB) + offset + 4); 878 881 pRqD->type = cpu_to_le16(type); 879 882 pSMB->ParameterOffset = cpu_to_le16(param_offset); 880 883 pSMB->DataOffset = cpu_to_le16(offset); ··· 1084 1081 param_offset = offsetof(struct smb_com_transaction2_spi_req, 1085 1082 InformationLevel) - 4; 1086 1083 offset = param_offset + params; 1087 - pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset); 1084 + /* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */ 1085 + pdata = (OPEN_PSX_REQ *)((char *)(pSMB) + offset + 4); 1088 1086 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC); 1089 1087 pdata->Permissions = cpu_to_le64(mode); 1090 1088 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
+2 -2
fs/cifs/connect.c
··· 220 220 #ifdef CONFIG_CIFS_DFS_UPCALL 221 221 struct super_block *sb = NULL; 222 222 struct cifs_sb_info *cifs_sb = NULL; 223 - struct dfs_cache_tgt_list tgt_list = {0}; 223 + struct dfs_cache_tgt_list tgt_list = DFS_CACHE_TGT_LIST_INIT(tgt_list); 224 224 struct dfs_cache_tgt_iterator *tgt_it = NULL; 225 225 #endif 226 226 ··· 3130 3130 { 3131 3131 int rc; 3132 3132 char *npath = NULL; 3133 - struct dfs_cache_tgt_list tgt_list = {0}; 3133 + struct dfs_cache_tgt_list tgt_list = DFS_CACHE_TGT_LIST_INIT(tgt_list); 3134 3134 struct dfs_cache_tgt_iterator *tgt_it = NULL; 3135 3135 struct smb3_fs_context tmp_ctx = {NULL}; 3136 3136
+191 -38
fs/cifs/dfs_cache.c
··· 19 19 #include "cifs_debug.h" 20 20 #include "cifs_unicode.h" 21 21 #include "smb2glob.h" 22 + #include "dns_resolve.h" 22 23 23 24 #include "dfs_cache.h" 24 25 ··· 912 911 913 912 err_free_it: 914 913 list_for_each_entry_safe(it, nit, head, it_list) { 914 + list_del(&it->it_list); 915 915 kfree(it->it_name); 916 916 kfree(it); 917 917 } ··· 1295 1293 return 0; 1296 1294 } 1297 1295 1296 + static bool target_share_equal(struct TCP_Server_Info *server, const char *s1, const char *s2) 1297 + { 1298 + char unc[sizeof("\\\\") + SERVER_NAME_LENGTH] = {0}; 1299 + const char *host; 1300 + size_t hostlen; 1301 + char *ip = NULL; 1302 + struct sockaddr sa; 1303 + bool match; 1304 + int rc; 1305 + 1306 + if (strcasecmp(s1, s2)) 1307 + return false; 1308 + 1309 + /* 1310 + * Resolve share's hostname and check if server address matches. Otherwise just ignore it 1311 + * as we could not have upcall to resolve hostname or failed to convert ip address. 1312 + */ 1313 + match = true; 1314 + extract_unc_hostname(s1, &host, &hostlen); 1315 + scnprintf(unc, sizeof(unc), "\\\\%.*s", (int)hostlen, host); 1316 + 1317 + rc = dns_resolve_server_name_to_ip(unc, &ip, NULL); 1318 + if (rc < 0) { 1319 + cifs_dbg(FYI, "%s: could not resolve %.*s. assuming server address matches.\n", 1320 + __func__, (int)hostlen, host); 1321 + return true; 1322 + } 1323 + 1324 + if (!cifs_convert_address(&sa, ip, strlen(ip))) { 1325 + cifs_dbg(VFS, "%s: failed to convert address \'%s\'. skip address matching.\n", 1326 + __func__, ip); 1327 + } else { 1328 + mutex_lock(&server->srv_mutex); 1329 + match = cifs_match_ipaddr((struct sockaddr *)&server->dstaddr, &sa); 1330 + mutex_unlock(&server->srv_mutex); 1331 + } 1332 + 1333 + kfree(ip); 1334 + return match; 1335 + } 1336 + 1337 + /* 1338 + * Mark dfs tcon for reconnecting when the currently connected tcon does not match any of the new 1339 + * target shares in @refs. 1340 + */ 1341 + static void mark_for_reconnect_if_needed(struct cifs_tcon *tcon, struct dfs_cache_tgt_list *tl, 1342 + const struct dfs_info3_param *refs, int numrefs) 1343 + { 1344 + struct dfs_cache_tgt_iterator *it; 1345 + int i; 1346 + 1347 + for (it = dfs_cache_get_tgt_iterator(tl); it; it = dfs_cache_get_next_tgt(tl, it)) { 1348 + for (i = 0; i < numrefs; i++) { 1349 + if (target_share_equal(tcon->ses->server, dfs_cache_get_tgt_name(it), 1350 + refs[i].node_name)) 1351 + return; 1352 + } 1353 + } 1354 + 1355 + cifs_dbg(FYI, "%s: no cached or matched targets. mark dfs share for reconnect.\n", __func__); 1356 + for (i = 0; i < tcon->ses->chan_count; i++) { 1357 + spin_lock(&GlobalMid_Lock); 1358 + if (tcon->ses->chans[i].server->tcpStatus != CifsExiting) 1359 + tcon->ses->chans[i].server->tcpStatus = CifsNeedReconnect; 1360 + spin_unlock(&GlobalMid_Lock); 1361 + } 1362 + } 1363 + 1364 + /* Refresh dfs referral of tcon and mark it for reconnect if needed */ 1365 + static int refresh_tcon(struct cifs_ses **sessions, struct cifs_tcon *tcon, bool force_refresh) 1366 + { 1367 + const char *path = tcon->dfs_path + 1; 1368 + struct cifs_ses *ses; 1369 + struct cache_entry *ce; 1370 + struct dfs_info3_param *refs = NULL; 1371 + int numrefs = 0; 1372 + bool needs_refresh = false; 1373 + struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl); 1374 + int rc = 0; 1375 + unsigned int xid; 1376 + 1377 + ses = find_ipc_from_server_path(sessions, path); 1378 + if (IS_ERR(ses)) { 1379 + cifs_dbg(FYI, "%s: could not find ipc session\n", __func__); 1380 + return PTR_ERR(ses); 1381 + } 1382 + 1383 + down_read(&htable_rw_lock); 1384 + ce = lookup_cache_entry(path); 1385 + needs_refresh = force_refresh || IS_ERR(ce) || cache_entry_expired(ce); 1386 + if (!IS_ERR(ce)) { 1387 + rc = get_targets(ce, &tl); 1388 + if (rc) 1389 + cifs_dbg(FYI, "%s: could not get dfs targets: %d\n", __func__, rc); 1390 + } 1391 + up_read(&htable_rw_lock); 1392 + 1393 + if (!needs_refresh) { 1394 + rc = 0; 1395 + goto out; 1396 + } 1397 + 1398 + xid = get_xid(); 1399 + rc = get_dfs_referral(xid, ses, path, &refs, &numrefs); 1400 + free_xid(xid); 1401 + 1402 + /* Create or update a cache entry with the new referral */ 1403 + if (!rc) { 1404 + dump_refs(refs, numrefs); 1405 + 1406 + down_write(&htable_rw_lock); 1407 + ce = lookup_cache_entry(path); 1408 + if (IS_ERR(ce)) 1409 + add_cache_entry_locked(refs, numrefs); 1410 + else if (force_refresh || cache_entry_expired(ce)) 1411 + update_cache_entry_locked(ce, refs, numrefs); 1412 + up_write(&htable_rw_lock); 1413 + 1414 + mark_for_reconnect_if_needed(tcon, &tl, refs, numrefs); 1415 + } 1416 + 1417 + out: 1418 + dfs_cache_free_tgts(&tl); 1419 + free_dfs_info_array(refs, numrefs); 1420 + return rc; 1421 + } 1422 + 1423 + /** 1424 + * dfs_cache_remount_fs - remount a DFS share 1425 + * 1426 + * Reconfigure dfs mount by forcing a new DFS referral and if the currently cached targets do not 1427 + * match any of the new targets, mark it for reconnect. 1428 + * 1429 + * @cifs_sb: cifs superblock. 1430 + * 1431 + * Return zero if remounted, otherwise non-zero. 1432 + */ 1433 + int dfs_cache_remount_fs(struct cifs_sb_info *cifs_sb) 1434 + { 1435 + struct cifs_tcon *tcon; 1436 + struct mount_group *mg; 1437 + struct cifs_ses *sessions[CACHE_MAX_ENTRIES + 1] = {NULL}; 1438 + int rc; 1439 + 1440 + if (!cifs_sb || !cifs_sb->master_tlink) 1441 + return -EINVAL; 1442 + 1443 + tcon = cifs_sb_master_tcon(cifs_sb); 1444 + if (!tcon->dfs_path) { 1445 + cifs_dbg(FYI, "%s: not a dfs tcon\n", __func__); 1446 + return 0; 1447 + } 1448 + 1449 + if (uuid_is_null(&cifs_sb->dfs_mount_id)) { 1450 + cifs_dbg(FYI, "%s: tcon has no dfs mount group id\n", __func__); 1451 + return -EINVAL; 1452 + } 1453 + 1454 + mutex_lock(&mount_group_list_lock); 1455 + mg = find_mount_group_locked(&cifs_sb->dfs_mount_id); 1456 + if (IS_ERR(mg)) { 1457 + mutex_unlock(&mount_group_list_lock); 1458 + cifs_dbg(FYI, "%s: tcon has ipc session to refresh referral\n", __func__); 1459 + return PTR_ERR(mg); 1460 + } 1461 + kref_get(&mg->refcount); 1462 + mutex_unlock(&mount_group_list_lock); 1463 + 1464 + spin_lock(&mg->lock); 1465 + memcpy(&sessions, mg->sessions, mg->num_sessions * sizeof(mg->sessions[0])); 1466 + spin_unlock(&mg->lock); 1467 + 1468 + /* 1469 + * After reconnecting to a different server, unique ids won't match anymore, so we disable 1470 + * serverino. This prevents dentry revalidation to think the dentry are stale (ESTALE). 1471 + */ 1472 + cifs_autodisable_serverino(cifs_sb); 1473 + /* 1474 + * Force the use of prefix path to support failover on DFS paths that resolve to targets 1475 + * that have different prefix paths. 1476 + */ 1477 + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; 1478 + rc = refresh_tcon(sessions, tcon, true); 1479 + 1480 + kref_put(&mg->refcount, mount_group_release); 1481 + return rc; 1482 + } 1483 + 1298 1484 /* 1299 1485 * Refresh all active dfs mounts regardless of whether they are in cache or not. 1300 1486 * (cache can be cleared) ··· 1493 1303 struct cifs_ses *ses; 1494 1304 struct cifs_tcon *tcon, *ntcon; 1495 1305 struct list_head tcons; 1496 - unsigned int xid; 1497 1306 1498 1307 INIT_LIST_HEAD(&tcons); 1499 1308 ··· 1510 1321 spin_unlock(&cifs_tcp_ses_lock); 1511 1322 1512 1323 list_for_each_entry_safe(tcon, ntcon, &tcons, ulist) { 1513 - const char *path = tcon->dfs_path + 1; 1514 - struct cache_entry *ce; 1515 - struct dfs_info3_param *refs = NULL; 1516 - int numrefs = 0; 1517 - bool needs_refresh = false; 1518 - int rc = 0; 1519 - 1520 1324 list_del_init(&tcon->ulist); 1521 - 1522 - ses = find_ipc_from_server_path(sessions, path); 1523 - if (IS_ERR(ses)) 1524 - goto next_tcon; 1525 - 1526 - down_read(&htable_rw_lock); 1527 - ce = lookup_cache_entry(path); 1528 - needs_refresh = IS_ERR(ce) || cache_entry_expired(ce); 1529 - up_read(&htable_rw_lock); 1530 - 1531 - if (!needs_refresh) 1532 - goto next_tcon; 1533 - 1534 - xid = get_xid(); 1535 - rc = get_dfs_referral(xid, ses, path, &refs, &numrefs); 1536 - free_xid(xid); 1537 - 1538 - /* Create or update a cache entry with the new referral */ 1539 - if (!rc) { 1540 - down_write(&htable_rw_lock); 1541 - ce = lookup_cache_entry(path); 1542 - if (IS_ERR(ce)) 1543 - add_cache_entry_locked(refs, numrefs); 1544 - else if (cache_entry_expired(ce)) 1545 - update_cache_entry_locked(ce, refs, numrefs); 1546 - up_write(&htable_rw_lock); 1547 - } 1548 - 1549 - next_tcon: 1550 - free_dfs_info_array(refs, numrefs); 1325 + refresh_tcon(sessions, tcon, false); 1551 1326 cifs_put_tcon(tcon); 1552 1327 } 1553 1328 }
+3
fs/cifs/dfs_cache.h
··· 13 13 #include <linux/uuid.h> 14 14 #include "cifsglob.h" 15 15 16 + #define DFS_CACHE_TGT_LIST_INIT(var) { .tl_numtgts = 0, .tl_list = LIST_HEAD_INIT((var).tl_list), } 17 + 16 18 struct dfs_cache_tgt_list { 17 19 int tl_numtgts; 18 20 struct list_head tl_list; ··· 46 44 void dfs_cache_put_refsrv_sessions(const uuid_t *mount_id); 47 45 void dfs_cache_add_refsrv_session(const uuid_t *mount_id, struct cifs_ses *ses); 48 46 char *dfs_cache_canonical_path(const char *path, const struct nls_table *cp, int remap); 47 + int dfs_cache_remount_fs(struct cifs_sb_info *cifs_sb); 49 48 50 49 static inline struct dfs_cache_tgt_iterator * 51 50 dfs_cache_get_next_tgt(struct dfs_cache_tgt_list *tl,
+7
fs/cifs/fs_context.c
··· 13 13 #include <linux/magic.h> 14 14 #include <linux/security.h> 15 15 #include <net/net_namespace.h> 16 + #ifdef CONFIG_CIFS_DFS_UPCALL 17 + #include "dfs_cache.h" 18 + #endif 16 19 */ 17 20 18 21 #include <linux/ctype.h> ··· 782 779 smb3_cleanup_fs_context_contents(cifs_sb->ctx); 783 780 rc = smb3_fs_context_dup(cifs_sb->ctx, ctx); 784 781 smb3_update_mnt_flags(cifs_sb); 782 + #ifdef CONFIG_CIFS_DFS_UPCALL 783 + if (!rc) 784 + rc = dfs_cache_remount_fs(cifs_sb); 785 + #endif 785 786 786 787 return rc; 787 788 }
+37 -12
fs/cifs/smb2ops.c
··· 3617 3617 char *buf) 3618 3618 { 3619 3619 struct cifs_io_parms io_parms = {0}; 3620 - int nbytes; 3620 + int rc, nbytes; 3621 3621 struct kvec iov[2]; 3622 3622 3623 3623 io_parms.netfid = cfile->fid.netfid; ··· 3625 3625 io_parms.tcon = tcon; 3626 3626 io_parms.persistent_fid = cfile->fid.persistent_fid; 3627 3627 io_parms.volatile_fid = cfile->fid.volatile_fid; 3628 - io_parms.offset = off; 3629 - io_parms.length = len; 3630 3628 3631 - /* iov[0] is reserved for smb header */ 3632 - iov[1].iov_base = buf; 3633 - iov[1].iov_len = io_parms.length; 3634 - return SMB2_write(xid, &io_parms, &nbytes, iov, 1); 3629 + while (len) { 3630 + io_parms.offset = off; 3631 + io_parms.length = len; 3632 + if (io_parms.length > SMB2_MAX_BUFFER_SIZE) 3633 + io_parms.length = SMB2_MAX_BUFFER_SIZE; 3634 + /* iov[0] is reserved for smb header */ 3635 + iov[1].iov_base = buf; 3636 + iov[1].iov_len = io_parms.length; 3637 + rc = SMB2_write(xid, &io_parms, &nbytes, iov, 1); 3638 + if (rc) 3639 + break; 3640 + if (nbytes > len) 3641 + return -EINVAL; 3642 + buf += nbytes; 3643 + off += nbytes; 3644 + len -= nbytes; 3645 + } 3646 + return rc; 3635 3647 } 3636 3648 3637 3649 static int smb3_simple_fallocate_range(unsigned int xid, ··· 3666 3654 1024 * sizeof(struct file_allocated_range_buffer), 3667 3655 (char **)&out_data, &out_data_len); 3668 3656 if (rc) 3669 - goto out; 3670 - /* 3671 - * It is already all allocated 3672 - */ 3673 - if (out_data_len == 0) 3674 3657 goto out; 3675 3658 3676 3659 buf = kzalloc(1024 * 1024, GFP_KERNEL); ··· 3787 3780 if ((cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) == 0) { 3788 3781 rc = 0; 3789 3782 goto out; 3783 + } 3784 + 3785 + if (keep_size == true) { 3786 + /* 3787 + * We can not preallocate pages beyond the end of the file 3788 + * in SMB2 3789 + */ 3790 + if (off >= i_size_read(inode)) { 3791 + rc = 0; 3792 + goto out; 3793 + } 3794 + /* 3795 + * For fallocates that are partially beyond the end of file, 3796 + * clamp len so we only fallocate up to the end of file. 3797 + */ 3798 + if (off + len > i_size_read(inode)) { 3799 + len = i_size_read(inode) - off; 3800 + } 3790 3801 } 3791 3802 3792 3803 if ((keep_size == true) || (i_size_read(inode) >= off + len)) {