Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

smb: client: fix data loss due to broken rename(2)

Rename of open files in SMB2+ has been broken for a very long time,
resulting in data loss as the CIFS client would fail the rename(2)
call with -ENOENT and then removing the target file.

Fix this by implementing ->rename_pending_delete() for SMB2+, which
will rename busy files to random filenames (e.g. silly rename) during
unlink(2) or rename(2), and then marking them to delete-on-close.

Besides, introduce a FIND_WR_NO_PENDING_DELETE flag to prevent open(2)
from reusing open handles that had been marked as delete pending.
Handle it in cifs_get_readable_path() as well.

Reported-by: Jean-Baptiste Denis <jbdenis@pasteur.fr>
Closes: https://marc.info/?i=16aeb380-30d4-4551-9134-4e7d1dc833c0@pasteur.fr
Reviewed-by: David Howells <dhowells@redhat.com>
Cc: stable@vger.kernel.org
Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.org>
Cc: Frank Sorenson <sorenson@redhat.com>
Cc: Olga Kornievskaia <okorniev@redhat.com>
Cc: Benjamin Coddington <bcodding@redhat.com>
Cc: Scott Mayhew <smayhew@redhat.com>
Cc: linux-cifs@vger.kernel.org
Signed-off-by: Steve French <stfrench@microsoft.com>

authored by

Paulo Alcantara and committed by
Steve French
c5ea3065 90f7c100

+268 -72
+9 -4
fs/smb/client/cifsglob.h
··· 87 87 #define SMB_INTERFACE_POLL_INTERVAL 600 88 88 89 89 /* maximum number of PDUs in one compound */ 90 - #define MAX_COMPOUND 7 90 + #define MAX_COMPOUND 10 91 91 92 92 /* 93 93 * Default number of credits to keep available for SMB3. ··· 1882 1882 1883 1883 1884 1884 /* cifs_get_writable_file() flags */ 1885 - #define FIND_WR_ANY 0 1886 - #define FIND_WR_FSUID_ONLY 1 1887 - #define FIND_WR_WITH_DELETE 2 1885 + enum cifs_writable_file_flags { 1886 + FIND_WR_ANY = 0U, 1887 + FIND_WR_FSUID_ONLY = (1U << 0), 1888 + FIND_WR_WITH_DELETE = (1U << 1), 1889 + FIND_WR_NO_PENDING_DELETE = (1U << 2), 1890 + }; 1888 1891 1889 1892 #define MID_FREE 0 1890 1893 #define MID_REQUEST_ALLOCATED 1 ··· 2346 2343 struct kvec qi_iov; 2347 2344 struct kvec io_iov[SMB2_IOCTL_IOV_SIZE]; 2348 2345 struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE]; 2346 + struct kvec unlink_iov[SMB2_SET_INFO_IOV_SIZE]; 2347 + struct kvec rename_iov[SMB2_SET_INFO_IOV_SIZE]; 2349 2348 struct kvec close_iov; 2350 2349 struct smb2_file_rename_info_hdr rename_info; 2351 2350 struct smb2_file_link_info_hdr link_info;
+17 -1
fs/smb/client/file.c
··· 998 998 999 999 /* Get the cached handle as SMB2 close is deferred */ 1000 1000 if (OPEN_FMODE(file->f_flags) & FMODE_WRITE) { 1001 - rc = cifs_get_writable_path(tcon, full_path, FIND_WR_FSUID_ONLY, &cfile); 1001 + rc = cifs_get_writable_path(tcon, full_path, 1002 + FIND_WR_FSUID_ONLY | 1003 + FIND_WR_NO_PENDING_DELETE, 1004 + &cfile); 1002 1005 } else { 1003 1006 rc = cifs_get_readable_path(tcon, full_path, &cfile); 1004 1007 } ··· 2533 2530 continue; 2534 2531 if (with_delete && !(open_file->fid.access & DELETE)) 2535 2532 continue; 2533 + if ((flags & FIND_WR_NO_PENDING_DELETE) && 2534 + open_file->status_file_deleted) 2535 + continue; 2536 2536 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { 2537 2537 if (!open_file->invalidHandle) { 2538 2538 /* found a good writable file */ ··· 2653 2647 spin_unlock(&tcon->open_file_lock); 2654 2648 free_dentry_path(page); 2655 2649 *ret_file = find_readable_file(cinode, 0); 2650 + if (*ret_file) { 2651 + spin_lock(&cinode->open_file_lock); 2652 + if ((*ret_file)->status_file_deleted) { 2653 + spin_unlock(&cinode->open_file_lock); 2654 + cifsFileInfo_put(*ret_file); 2655 + *ret_file = NULL; 2656 + } else { 2657 + spin_unlock(&cinode->open_file_lock); 2658 + } 2659 + } 2656 2660 return *ret_file ? 0 : -ENOENT; 2657 2661 } 2658 2662
+69 -17
fs/smb/client/inode.c
··· 1931 1931 * but will return the EACCES to the caller. Note that the VFS does not call 1932 1932 * unlink on negative dentries currently. 1933 1933 */ 1934 - int cifs_unlink(struct inode *dir, struct dentry *dentry) 1934 + static int __cifs_unlink(struct inode *dir, struct dentry *dentry, bool sillyrename) 1935 1935 { 1936 1936 int rc = 0; 1937 1937 unsigned int xid; ··· 2003 2003 goto psx_del_no_retry; 2004 2004 } 2005 2005 2006 - rc = server->ops->unlink(xid, tcon, full_path, cifs_sb, dentry); 2006 + if (sillyrename || (server->vals->protocol_id > SMB10_PROT_ID && 2007 + d_is_positive(dentry) && d_count(dentry) > 2)) 2008 + rc = -EBUSY; 2009 + else 2010 + rc = server->ops->unlink(xid, tcon, full_path, cifs_sb, dentry); 2007 2011 2008 2012 psx_del_no_retry: 2009 2013 if (!rc) { ··· 2073 2069 if (rehash) 2074 2070 d_rehash(dentry); 2075 2071 return rc; 2072 + } 2073 + 2074 + int cifs_unlink(struct inode *dir, struct dentry *dentry) 2075 + { 2076 + return __cifs_unlink(dir, dentry, false); 2076 2077 } 2077 2078 2078 2079 static int ··· 2367 2358 rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb); 2368 2359 cifs_put_tlink(tlink); 2369 2360 2361 + cifsInode = CIFS_I(d_inode(direntry)); 2362 + 2370 2363 if (!rc) { 2364 + set_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags); 2371 2365 spin_lock(&d_inode(direntry)->i_lock); 2372 2366 i_size_write(d_inode(direntry), 0); 2373 2367 clear_nlink(d_inode(direntry)); 2374 2368 spin_unlock(&d_inode(direntry)->i_lock); 2375 2369 } 2376 2370 2377 - cifsInode = CIFS_I(d_inode(direntry)); 2378 2371 /* force revalidate to go get info when needed */ 2379 2372 cifsInode->time = 0; 2380 2373 ··· 2469 2458 } 2470 2459 #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 2471 2460 do_rename_exit: 2472 - if (rc == 0) 2461 + if (rc == 0) { 2473 2462 d_move(from_dentry, to_dentry); 2463 + /* Force a new lookup */ 2464 + d_drop(from_dentry); 2465 + } 2474 2466 cifs_put_tlink(tlink); 2475 2467 return rc; 2476 2468 } ··· 2484 2470 struct dentry *target_dentry, unsigned int flags) 2485 2471 { 2486 2472 const char *from_name, *to_name; 2473 + struct TCP_Server_Info *server; 2487 2474 void *page1, *page2; 2488 2475 struct cifs_sb_info *cifs_sb; 2489 2476 struct tcon_link *tlink; ··· 2520 2505 if (IS_ERR(tlink)) 2521 2506 return PTR_ERR(tlink); 2522 2507 tcon = tlink_tcon(tlink); 2508 + server = tcon->ses->server; 2523 2509 2524 2510 page1 = alloc_dentry_path(); 2525 2511 page2 = alloc_dentry_path(); ··· 2607 2591 2608 2592 unlink_target: 2609 2593 #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 2610 - 2611 - /* Try unlinking the target dentry if it's not negative */ 2612 - if (d_really_is_positive(target_dentry) && (rc == -EACCES || rc == -EEXIST)) { 2613 - if (d_is_dir(target_dentry)) 2614 - tmprc = cifs_rmdir(target_dir, target_dentry); 2615 - else 2616 - tmprc = cifs_unlink(target_dir, target_dentry); 2617 - if (tmprc) 2618 - goto cifs_rename_exit; 2619 - rc = cifs_do_rename(xid, source_dentry, from_name, 2620 - target_dentry, to_name); 2621 - if (!rc) 2622 - rehash = false; 2594 + if (d_really_is_positive(target_dentry)) { 2595 + if (!rc) { 2596 + struct inode *inode = d_inode(target_dentry); 2597 + /* 2598 + * Samba and ksmbd servers allow renaming a target 2599 + * directory that is open, so make sure to update 2600 + * ->i_nlink and then mark it as delete pending. 2601 + */ 2602 + if (S_ISDIR(inode->i_mode)) { 2603 + drop_cached_dir_by_name(xid, tcon, to_name, cifs_sb); 2604 + spin_lock(&inode->i_lock); 2605 + i_size_write(inode, 0); 2606 + clear_nlink(inode); 2607 + spin_unlock(&inode->i_lock); 2608 + set_bit(CIFS_INO_DELETE_PENDING, &CIFS_I(inode)->flags); 2609 + CIFS_I(inode)->time = 0; /* force reval */ 2610 + inode_set_ctime_current(inode); 2611 + inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); 2612 + } 2613 + } else if (rc == -EACCES || rc == -EEXIST) { 2614 + /* 2615 + * Rename failed, possibly due to a busy target. 2616 + * Retry it by unliking the target first. 2617 + */ 2618 + if (d_is_dir(target_dentry)) { 2619 + tmprc = cifs_rmdir(target_dir, target_dentry); 2620 + } else { 2621 + tmprc = __cifs_unlink(target_dir, target_dentry, 2622 + server->vals->protocol_id > SMB10_PROT_ID); 2623 + } 2624 + if (tmprc) { 2625 + /* 2626 + * Some servers will return STATUS_ACCESS_DENIED 2627 + * or STATUS_DIRECTORY_NOT_EMPTY when failing to 2628 + * rename a non-empty directory. Make sure to 2629 + * propagate the appropriate error back to 2630 + * userspace. 2631 + */ 2632 + if (tmprc == -EEXIST || tmprc == -ENOTEMPTY) 2633 + rc = tmprc; 2634 + goto cifs_rename_exit; 2635 + } 2636 + rc = cifs_do_rename(xid, source_dentry, from_name, 2637 + target_dentry, to_name); 2638 + if (!rc) 2639 + rehash = false; 2640 + } 2623 2641 } 2624 2642 2625 2643 /* force revalidate to go get info when needed */ ··· 2679 2629 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); 2680 2630 struct cached_fid *cfid = NULL; 2681 2631 2632 + if (test_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags)) 2633 + return false; 2682 2634 if (cifs_i->time == 0) 2683 2635 return true; 2684 2636
+1 -2
fs/smb/client/smb2glob.h
··· 30 30 SMB2_OP_QUERY_DIR, 31 31 SMB2_OP_MKDIR, 32 32 SMB2_OP_RENAME, 33 - SMB2_OP_DELETE, 34 33 SMB2_OP_HARDLINK, 35 34 SMB2_OP_SET_EOF, 36 - SMB2_OP_RMDIR, 35 + SMB2_OP_UNLINK, 37 36 SMB2_OP_POSIX_QUERY_INFO, 38 37 SMB2_OP_SET_REPARSE, 39 38 SMB2_OP_GET_REPARSE,
+162 -42
fs/smb/client/smb2inode.c
··· 346 346 trace_smb3_posix_query_info_compound_enter(xid, tcon->tid, 347 347 ses->Suid, full_path); 348 348 break; 349 - case SMB2_OP_DELETE: 350 - trace_smb3_delete_enter(xid, tcon->tid, ses->Suid, full_path); 351 - break; 352 349 case SMB2_OP_MKDIR: 353 350 /* 354 351 * Directories are created through parameters in the ··· 353 356 */ 354 357 trace_smb3_mkdir_enter(xid, tcon->tid, ses->Suid, full_path); 355 358 break; 356 - case SMB2_OP_RMDIR: 357 - rqst[num_rqst].rq_iov = &vars->si_iov[0]; 359 + case SMB2_OP_UNLINK: 360 + rqst[num_rqst].rq_iov = vars->unlink_iov; 358 361 rqst[num_rqst].rq_nvec = 1; 359 362 360 363 size[0] = 1; /* sizeof __u8 See MS-FSCC section 2.4.11 */ 361 364 data[0] = &delete_pending[0]; 362 365 363 - rc = SMB2_set_info_init(tcon, server, 364 - &rqst[num_rqst], COMPOUND_FID, 365 - COMPOUND_FID, current->tgid, 366 - FILE_DISPOSITION_INFORMATION, 367 - SMB2_O_INFO_FILE, 0, data, size); 368 - if (rc) 366 + if (cfile) { 367 + rc = SMB2_set_info_init(tcon, server, 368 + &rqst[num_rqst], 369 + cfile->fid.persistent_fid, 370 + cfile->fid.volatile_fid, 371 + current->tgid, 372 + FILE_DISPOSITION_INFORMATION, 373 + SMB2_O_INFO_FILE, 0, 374 + data, size); 375 + } else { 376 + rc = SMB2_set_info_init(tcon, server, 377 + &rqst[num_rqst], 378 + COMPOUND_FID, 379 + COMPOUND_FID, 380 + current->tgid, 381 + FILE_DISPOSITION_INFORMATION, 382 + SMB2_O_INFO_FILE, 0, 383 + data, size); 384 + } 385 + if (!rc && (!cfile || num_rqst > 1)) { 386 + smb2_set_next_command(tcon, &rqst[num_rqst]); 387 + smb2_set_related(&rqst[num_rqst]); 388 + } else if (rc) { 369 389 goto finished; 370 - smb2_set_next_command(tcon, &rqst[num_rqst]); 371 - smb2_set_related(&rqst[num_rqst++]); 372 - trace_smb3_rmdir_enter(xid, tcon->tid, ses->Suid, full_path); 390 + } 391 + num_rqst++; 392 + trace_smb3_unlink_enter(xid, tcon->tid, ses->Suid, full_path); 373 393 break; 374 394 case SMB2_OP_SET_EOF: 375 395 rqst[num_rqst].rq_iov = &vars->si_iov[0]; ··· 456 442 ses->Suid, full_path); 457 443 break; 458 444 case SMB2_OP_RENAME: 459 - rqst[num_rqst].rq_iov = &vars->si_iov[0]; 445 + rqst[num_rqst].rq_iov = vars->rename_iov; 460 446 rqst[num_rqst].rq_nvec = 2; 461 447 462 448 len = in_iov[i].iov_len; ··· 746 732 trace_smb3_posix_query_info_compound_done(xid, tcon->tid, 747 733 ses->Suid); 748 734 break; 749 - case SMB2_OP_DELETE: 750 - if (rc) 751 - trace_smb3_delete_err(xid, tcon->tid, ses->Suid, rc); 752 - else { 753 - /* 754 - * If dentry (hence, inode) is NULL, lease break is going to 755 - * take care of degrading leases on handles for deleted files. 756 - */ 757 - if (inode) 758 - cifs_mark_open_handles_for_deleted_file(inode, full_path); 759 - trace_smb3_delete_done(xid, tcon->tid, ses->Suid); 760 - } 761 - break; 762 735 case SMB2_OP_MKDIR: 763 736 if (rc) 764 737 trace_smb3_mkdir_err(xid, tcon->tid, ses->Suid, rc); ··· 766 765 trace_smb3_rename_done(xid, tcon->tid, ses->Suid); 767 766 SMB2_set_info_free(&rqst[num_rqst++]); 768 767 break; 769 - case SMB2_OP_RMDIR: 770 - if (rc) 771 - trace_smb3_rmdir_err(xid, tcon->tid, ses->Suid, rc); 768 + case SMB2_OP_UNLINK: 769 + if (!rc) 770 + trace_smb3_unlink_done(xid, tcon->tid, ses->Suid); 772 771 else 773 - trace_smb3_rmdir_done(xid, tcon->tid, ses->Suid); 772 + trace_smb3_unlink_err(xid, tcon->tid, ses->Suid, rc); 774 773 SMB2_set_info_free(&rqst[num_rqst++]); 775 774 break; 776 775 case SMB2_OP_SET_EOF: ··· 1167 1166 FILE_OPEN, CREATE_NOT_FILE, ACL_NO_MODE); 1168 1167 return smb2_compound_op(xid, tcon, cifs_sb, 1169 1168 name, &oparms, NULL, 1170 - &(int){SMB2_OP_RMDIR}, 1, 1169 + &(int){SMB2_OP_UNLINK}, 1, 1171 1170 NULL, NULL, NULL, NULL); 1172 1171 } 1173 1172 ··· 1176 1175 struct cifs_sb_info *cifs_sb, struct dentry *dentry) 1177 1176 { 1178 1177 struct cifs_open_parms oparms; 1178 + struct inode *inode = NULL; 1179 + int rc; 1179 1180 1180 - oparms = CIFS_OPARMS(cifs_sb, tcon, name, 1181 - DELETE, FILE_OPEN, 1182 - CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT, 1183 - ACL_NO_MODE); 1184 - int rc = smb2_compound_op(xid, tcon, cifs_sb, name, &oparms, 1185 - NULL, &(int){SMB2_OP_DELETE}, 1, 1186 - NULL, NULL, NULL, dentry); 1181 + if (dentry) 1182 + inode = d_inode(dentry); 1183 + 1184 + oparms = CIFS_OPARMS(cifs_sb, tcon, name, DELETE, 1185 + FILE_OPEN, OPEN_REPARSE_POINT, ACL_NO_MODE); 1186 + rc = smb2_compound_op(xid, tcon, cifs_sb, name, &oparms, 1187 + NULL, &(int){SMB2_OP_UNLINK}, 1188 + 1, NULL, NULL, NULL, dentry); 1187 1189 if (rc == -EINVAL) { 1188 1190 cifs_dbg(FYI, "invalid lease key, resending request without lease"); 1189 1191 rc = smb2_compound_op(xid, tcon, cifs_sb, name, &oparms, 1190 - NULL, &(int){SMB2_OP_DELETE}, 1, 1191 - NULL, NULL, NULL, NULL); 1192 + NULL, &(int){SMB2_OP_UNLINK}, 1193 + 1, NULL, NULL, NULL, NULL); 1192 1194 } 1195 + /* 1196 + * If dentry (hence, inode) is NULL, lease break is going to 1197 + * take care of degrading leases on handles for deleted files. 1198 + */ 1199 + if (!rc && inode) 1200 + cifs_mark_open_handles_for_deleted_file(inode, name); 1193 1201 return rc; 1194 1202 } 1195 1203 ··· 1449 1439 data.reparse.io.buftype = CIFS_NO_BUFFER; 1450 1440 out: 1451 1441 cifs_free_open_info(&data); 1442 + return rc; 1443 + } 1444 + 1445 + static inline __le16 *utf16_smb2_path(struct cifs_sb_info *cifs_sb, 1446 + const char *name, size_t namelen) 1447 + { 1448 + int len; 1449 + 1450 + if (*name == '\\' || 1451 + (cifs_sb_master_tlink(cifs_sb) && 1452 + cifs_sb_master_tcon(cifs_sb)->posix_extensions && *name == '/')) 1453 + name++; 1454 + return cifs_strndup_to_utf16(name, namelen, &len, 1455 + cifs_sb->local_nls, 1456 + cifs_remap(cifs_sb)); 1457 + } 1458 + 1459 + int smb2_rename_pending_delete(const char *full_path, 1460 + struct dentry *dentry, 1461 + const unsigned int xid) 1462 + { 1463 + struct cifs_sb_info *cifs_sb = CIFS_SB(d_inode(dentry)->i_sb); 1464 + struct cifsInodeInfo *cinode = CIFS_I(d_inode(dentry)); 1465 + __le16 *utf16_path __free(kfree) = NULL; 1466 + __u32 co = file_create_options(dentry); 1467 + int cmds[] = { 1468 + SMB2_OP_SET_INFO, 1469 + SMB2_OP_RENAME, 1470 + SMB2_OP_UNLINK, 1471 + }; 1472 + const int num_cmds = ARRAY_SIZE(cmds); 1473 + char *to_name __free(kfree) = NULL; 1474 + __u32 attrs = cinode->cifsAttrs; 1475 + struct cifs_open_parms oparms; 1476 + static atomic_t sillycounter; 1477 + struct cifsFileInfo *cfile; 1478 + struct tcon_link *tlink; 1479 + struct cifs_tcon *tcon; 1480 + struct kvec iov[2]; 1481 + const char *ppath; 1482 + void *page; 1483 + size_t len; 1484 + int rc; 1485 + 1486 + tlink = cifs_sb_tlink(cifs_sb); 1487 + if (IS_ERR(tlink)) 1488 + return PTR_ERR(tlink); 1489 + tcon = tlink_tcon(tlink); 1490 + 1491 + page = alloc_dentry_path(); 1492 + 1493 + ppath = build_path_from_dentry(dentry->d_parent, page); 1494 + if (IS_ERR(ppath)) { 1495 + rc = PTR_ERR(ppath); 1496 + goto out; 1497 + } 1498 + 1499 + len = strlen(ppath) + strlen("/.__smb1234") + 1; 1500 + to_name = kmalloc(len, GFP_KERNEL); 1501 + if (!to_name) { 1502 + rc = -ENOMEM; 1503 + goto out; 1504 + } 1505 + 1506 + scnprintf(to_name, len, "%s%c.__smb%04X", ppath, CIFS_DIR_SEP(cifs_sb), 1507 + atomic_inc_return(&sillycounter) & 0xffff); 1508 + 1509 + utf16_path = utf16_smb2_path(cifs_sb, to_name, len); 1510 + if (!utf16_path) { 1511 + rc = -ENOMEM; 1512 + goto out; 1513 + } 1514 + 1515 + drop_cached_dir_by_name(xid, tcon, full_path, cifs_sb); 1516 + oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, 1517 + DELETE | FILE_WRITE_ATTRIBUTES, 1518 + FILE_OPEN, co, ACL_NO_MODE); 1519 + 1520 + attrs &= ~ATTR_READONLY; 1521 + if (!attrs) 1522 + attrs = ATTR_NORMAL; 1523 + if (d_inode(dentry)->i_nlink <= 1) 1524 + attrs |= ATTR_HIDDEN; 1525 + iov[0].iov_base = &(FILE_BASIC_INFO) { 1526 + .Attributes = cpu_to_le32(attrs), 1527 + }; 1528 + iov[0].iov_len = sizeof(FILE_BASIC_INFO); 1529 + iov[1].iov_base = utf16_path; 1530 + iov[1].iov_len = sizeof(*utf16_path) * UniStrlen((wchar_t *)utf16_path); 1531 + 1532 + cifs_get_writable_path(tcon, full_path, FIND_WR_WITH_DELETE, &cfile); 1533 + rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, iov, 1534 + cmds, num_cmds, cfile, NULL, NULL, dentry); 1535 + if (rc == -EINVAL) { 1536 + cifs_dbg(FYI, "invalid lease key, resending request without lease\n"); 1537 + cifs_get_writable_path(tcon, full_path, 1538 + FIND_WR_WITH_DELETE, &cfile); 1539 + rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, iov, 1540 + cmds, num_cmds, cfile, NULL, NULL, NULL); 1541 + } 1542 + if (!rc) { 1543 + set_bit(CIFS_INO_DELETE_PENDING, &cinode->flags); 1544 + } else { 1545 + cifs_tcon_dbg(FYI, "%s: failed to rename '%s' to '%s': %d\n", 1546 + __func__, full_path, to_name, rc); 1547 + rc = -EIO; 1548 + } 1549 + out: 1550 + cifs_put_tlink(tlink); 1551 + free_dentry_path(page); 1452 1552 return rc; 1453 1553 }
+4
fs/smb/client/smb2ops.c
··· 5398 5398 .llseek = smb3_llseek, 5399 5399 .is_status_io_timeout = smb2_is_status_io_timeout, 5400 5400 .is_network_name_deleted = smb2_is_network_name_deleted, 5401 + .rename_pending_delete = smb2_rename_pending_delete, 5401 5402 }; 5402 5403 #endif /* CIFS_ALLOW_INSECURE_LEGACY */ 5403 5404 ··· 5504 5503 .llseek = smb3_llseek, 5505 5504 .is_status_io_timeout = smb2_is_status_io_timeout, 5506 5505 .is_network_name_deleted = smb2_is_network_name_deleted, 5506 + .rename_pending_delete = smb2_rename_pending_delete, 5507 5507 }; 5508 5508 5509 5509 struct smb_version_operations smb30_operations = { ··· 5621 5619 .llseek = smb3_llseek, 5622 5620 .is_status_io_timeout = smb2_is_status_io_timeout, 5623 5621 .is_network_name_deleted = smb2_is_network_name_deleted, 5622 + .rename_pending_delete = smb2_rename_pending_delete, 5624 5623 }; 5625 5624 5626 5625 struct smb_version_operations smb311_operations = { ··· 5738 5735 .llseek = smb3_llseek, 5739 5736 .is_status_io_timeout = smb2_is_status_io_timeout, 5740 5737 .is_network_name_deleted = smb2_is_network_name_deleted, 5738 + .rename_pending_delete = smb2_rename_pending_delete, 5741 5739 }; 5742 5740 5743 5741 #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+3
fs/smb/client/smb2proto.h
··· 317 317 int smb2_make_nfs_node(unsigned int xid, struct inode *inode, 318 318 struct dentry *dentry, struct cifs_tcon *tcon, 319 319 const char *full_path, umode_t mode, dev_t dev); 320 + int smb2_rename_pending_delete(const char *full_path, 321 + struct dentry *dentry, 322 + const unsigned int xid); 320 323 321 324 #endif /* _SMB2PROTO_H */
+3 -6
fs/smb/client/trace.h
··· 669 669 DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(posix_query_info_compound_enter); 670 670 DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(hardlink_enter); 671 671 DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(rename_enter); 672 - DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(rmdir_enter); 672 + DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(unlink_enter); 673 673 DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(set_eof_enter); 674 674 DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(set_info_compound_enter); 675 675 DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(set_reparse_compound_enter); 676 676 DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(get_reparse_compound_enter); 677 677 DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(query_wsl_ea_compound_enter); 678 - DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(delete_enter); 679 678 DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(mkdir_enter); 680 679 DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(tdis_enter); 681 680 DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(mknod_enter); ··· 709 710 DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(posix_query_info_compound_done); 710 711 DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(hardlink_done); 711 712 DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(rename_done); 712 - DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(rmdir_done); 713 + DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(unlink_done); 713 714 DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(set_eof_done); 714 715 DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(set_info_compound_done); 715 716 DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(set_reparse_compound_done); 716 717 DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(get_reparse_compound_done); 717 718 DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(query_wsl_ea_compound_done); 718 - DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(delete_done); 719 719 DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(mkdir_done); 720 720 DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(tdis_done); 721 721 DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(mknod_done); ··· 754 756 DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(posix_query_info_compound_err); 755 757 DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(hardlink_err); 756 758 DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(rename_err); 757 - DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(rmdir_err); 759 + DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(unlink_err); 758 760 DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(set_eof_err); 759 761 DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(set_info_compound_err); 760 762 DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(set_reparse_compound_err); 761 763 DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(get_reparse_compound_err); 762 764 DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(query_wsl_ea_compound_err); 763 765 DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(mkdir_err); 764 - DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(delete_err); 765 766 DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(tdis_err); 766 767 DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(mknod_err); 767 768