Skip to content

Commit bb57c81

Browse files
dhowellssmfrench
authored andcommitted
cifs: Fix rmdir failure due to ongoing I/O on deleted file
The cifs_io_request struct (a wrapper around netfs_io_request) holds open the file on the server, even beyond the local Linux file being closed. This can cause problems with Windows-based filesystems as the file's name still exists after deletion until the file is closed, preventing the parent directory from being removed and causing spurious test failures in xfstests due to inability to remove a directory. The symptom looks something like this in the test output: rm: cannot remove '/mnt/scratch/test/p0/d3': Directory not empty rm: cannot remove '/mnt/scratch/test/p1/dc/dae': Directory not empty Fix this by waiting in unlink and rename for any outstanding I/O requests to be completed on the target file before removing that file. Note that this doesn't prevent Linux from trying to start new requests after deletion if it still has the file open locally - something that's perfectly acceptable on a UNIX system. Note also that whilst I've marked this as fixing the commit to make cifs use netfslib, I don't know that it won't occur before that. Fixes: 3ee1a1f ("cifs: Cut over to using netfslib") Signed-off-by: David Howells <[email protected]> Acked-by: Paulo Alcantara (Red Hat) <[email protected]> cc: Jeff Layton <[email protected]> cc: [email protected] cc: [email protected] cc: [email protected] Signed-off-by: Steve French <[email protected]>
1 parent 6d44a78 commit bb57c81

File tree

1 file changed

+4
-1
lines changed

1 file changed

+4
-1
lines changed

fs/smb/client/inode.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1947,6 +1947,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
19471947
goto unlink_out;
19481948
}
19491949

1950+
netfs_wait_for_outstanding_io(inode);
19501951
cifs_close_deferred_file_under_dentry(tcon, full_path);
19511952
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
19521953
if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
@@ -2464,8 +2465,10 @@ cifs_rename2(struct mnt_idmap *idmap, struct inode *source_dir,
24642465
}
24652466

24662467
cifs_close_deferred_file_under_dentry(tcon, from_name);
2467-
if (d_inode(target_dentry) != NULL)
2468+
if (d_inode(target_dentry) != NULL) {
2469+
netfs_wait_for_outstanding_io(d_inode(target_dentry));
24682470
cifs_close_deferred_file_under_dentry(tcon, to_name);
2471+
}
24692472

24702473
rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
24712474
to_name);

0 commit comments

Comments
 (0)