diff options
author | Steve French <smfrench@gmail.com> | 2016-05-12 22:20:36 -0400 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2016-05-17 15:09:44 -0400 |
commit | 897fba1172d637d344f009d700f7eb8a1fa262f1 (patch) | |
tree | a57ae696c9ce5d897d3c263dd020cf1f3e33cf7b | |
parent | 5a4f7e8e7ff5e81f57b08797cca41d307878dfc7 (diff) |
remove directory incorrectly tries to set delete on close on non-empty directories
Wrong return code was being returned on SMB3 rmdir of
non-empty directory.
For SMB3 (unlike for cifs), we attempt to delete a directory by
set of delete on close flag on the open. Windows clients set
this flag via a set info (SET_FILE_DISPOSITION to set this flag)
which properly checks if the directory is empty.
With this patch on smb3 mounts we correctly return
"DIRECTORY NOT EMPTY"
on attempts to remove a non-empty directory.
Signed-off-by: Steve French <steve.french@primarydata.com>
CC: Stable <stable@vger.kernel.org>
Acked-by: Sachin Prabhu <sprabhu@redhat.com>
-rw-r--r-- | fs/cifs/smb2glob.h | 1 | ||||
-rw-r--r-- | fs/cifs/smb2inode.c | 8 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.c | 16 | ||||
-rw-r--r-- | fs/cifs/smb2proto.h | 2 |
4 files changed, 25 insertions, 2 deletions
diff --git a/fs/cifs/smb2glob.h b/fs/cifs/smb2glob.h index bc0bb9c34f72..0ffa18094335 100644 --- a/fs/cifs/smb2glob.h +++ b/fs/cifs/smb2glob.h | |||
@@ -44,6 +44,7 @@ | |||
44 | #define SMB2_OP_DELETE 7 | 44 | #define SMB2_OP_DELETE 7 |
45 | #define SMB2_OP_HARDLINK 8 | 45 | #define SMB2_OP_HARDLINK 8 |
46 | #define SMB2_OP_SET_EOF 9 | 46 | #define SMB2_OP_SET_EOF 9 |
47 | #define SMB2_OP_RMDIR 10 | ||
47 | 48 | ||
48 | /* Used when constructing chained read requests. */ | 49 | /* Used when constructing chained read requests. */ |
49 | #define CHAINED_REQUEST 1 | 50 | #define CHAINED_REQUEST 1 |
diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c index 899bbc86f73e..4f0231e685a9 100644 --- a/fs/cifs/smb2inode.c +++ b/fs/cifs/smb2inode.c | |||
@@ -80,6 +80,10 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon, | |||
80 | * SMB2_open() call. | 80 | * SMB2_open() call. |
81 | */ | 81 | */ |
82 | break; | 82 | break; |
83 | case SMB2_OP_RMDIR: | ||
84 | tmprc = SMB2_rmdir(xid, tcon, fid.persistent_fid, | ||
85 | fid.volatile_fid); | ||
86 | break; | ||
83 | case SMB2_OP_RENAME: | 87 | case SMB2_OP_RENAME: |
84 | tmprc = SMB2_rename(xid, tcon, fid.persistent_fid, | 88 | tmprc = SMB2_rename(xid, tcon, fid.persistent_fid, |
85 | fid.volatile_fid, (__le16 *)data); | 89 | fid.volatile_fid, (__le16 *)data); |
@@ -191,8 +195,8 @@ smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, | |||
191 | struct cifs_sb_info *cifs_sb) | 195 | struct cifs_sb_info *cifs_sb) |
192 | { | 196 | { |
193 | return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN, | 197 | return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN, |
194 | CREATE_NOT_FILE | CREATE_DELETE_ON_CLOSE, | 198 | CREATE_NOT_FILE, |
195 | NULL, SMB2_OP_DELETE); | 199 | NULL, SMB2_OP_RMDIR); |
196 | } | 200 | } |
197 | 201 | ||
198 | int | 202 | int |
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 42e1f440eb1e..8f38e33d365b 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
@@ -2575,6 +2575,22 @@ SMB2_rename(const unsigned int xid, struct cifs_tcon *tcon, | |||
2575 | } | 2575 | } |
2576 | 2576 | ||
2577 | int | 2577 | int |
2578 | SMB2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, | ||
2579 | u64 persistent_fid, u64 volatile_fid) | ||
2580 | { | ||
2581 | __u8 delete_pending = 1; | ||
2582 | void *data; | ||
2583 | unsigned int size; | ||
2584 | |||
2585 | data = &delete_pending; | ||
2586 | size = 1; /* sizeof __u8 */ | ||
2587 | |||
2588 | return send_set_info(xid, tcon, persistent_fid, volatile_fid, | ||
2589 | current->tgid, FILE_DISPOSITION_INFORMATION, 1, &data, | ||
2590 | &size); | ||
2591 | } | ||
2592 | |||
2593 | int | ||
2578 | SMB2_set_hardlink(const unsigned int xid, struct cifs_tcon *tcon, | 2594 | SMB2_set_hardlink(const unsigned int xid, struct cifs_tcon *tcon, |
2579 | u64 persistent_fid, u64 volatile_fid, __le16 *target_file) | 2595 | u64 persistent_fid, u64 volatile_fid, __le16 *target_file) |
2580 | { | 2596 | { |
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index 4f07dc93608d..eb2cde2f64ba 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h | |||
@@ -141,6 +141,8 @@ extern int SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, | |||
141 | extern int SMB2_rename(const unsigned int xid, struct cifs_tcon *tcon, | 141 | extern int SMB2_rename(const unsigned int xid, struct cifs_tcon *tcon, |
142 | u64 persistent_fid, u64 volatile_fid, | 142 | u64 persistent_fid, u64 volatile_fid, |
143 | __le16 *target_file); | 143 | __le16 *target_file); |
144 | extern int SMB2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, | ||
145 | u64 persistent_fid, u64 volatile_fid); | ||
144 | extern int SMB2_set_hardlink(const unsigned int xid, struct cifs_tcon *tcon, | 146 | extern int SMB2_set_hardlink(const unsigned int xid, struct cifs_tcon *tcon, |
145 | u64 persistent_fid, u64 volatile_fid, | 147 | u64 persistent_fid, u64 volatile_fid, |
146 | __le16 *target_file); | 148 | __le16 *target_file); |