Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ed49188a authored by Steve French's avatar Steve French Committed by Sasha Levin
Browse files

remove directory incorrectly tries to set delete on close on non-empty directories



[ Upstream commit 897fba1172d637d344f009d700f7eb8a1fa262f1 ]

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: default avatarSteve French <steve.french@primarydata.com>
CC: Stable <stable@vger.kernel.org>
Acked-by: default avatarSachin Prabhu <sprabhu@redhat.com>
Signed-off-by: default avatarSasha Levin <sasha.levin@oracle.com>
parent 2acb5949
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@
#define SMB2_OP_DELETE 7
#define SMB2_OP_HARDLINK 8
#define SMB2_OP_SET_EOF 9
#define SMB2_OP_RMDIR 10

/* Used when constructing chained read requests. */
#define CHAINED_REQUEST 1
+6 −2
Original line number Diff line number Diff line
@@ -80,6 +80,10 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
		 * SMB2_open() call.
		 */
		break;
	case SMB2_OP_RMDIR:
		tmprc = SMB2_rmdir(xid, tcon, fid.persistent_fid,
				   fid.volatile_fid);
		break;
	case SMB2_OP_RENAME:
		tmprc = SMB2_rename(xid, tcon, fid.persistent_fid,
				    fid.volatile_fid, (__le16 *)data);
@@ -191,8 +195,8 @@ smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
	   struct cifs_sb_info *cifs_sb)
{
	return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
				  CREATE_NOT_FILE | CREATE_DELETE_ON_CLOSE,
				  NULL, SMB2_OP_DELETE);
				  CREATE_NOT_FILE,
				  NULL, SMB2_OP_RMDIR);
}

int
+16 −0
Original line number Diff line number Diff line
@@ -2335,6 +2335,22 @@ SMB2_rename(const unsigned int xid, struct cifs_tcon *tcon,
	return rc;
}

int
SMB2_rmdir(const unsigned int xid, struct cifs_tcon *tcon,
		  u64 persistent_fid, u64 volatile_fid)
{
	__u8 delete_pending = 1;
	void *data;
	unsigned int size;

	data = &delete_pending;
	size = 1; /* sizeof __u8 */

	return send_set_info(xid, tcon, persistent_fid, volatile_fid,
			current->tgid, FILE_DISPOSITION_INFORMATION, 1, &data,
			&size);
}

int
SMB2_set_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
		  u64 persistent_fid, u64 volatile_fid, __le16 *target_file)
+2 −0
Original line number Diff line number Diff line
@@ -140,6 +140,8 @@ extern int SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
extern int SMB2_rename(const unsigned int xid, struct cifs_tcon *tcon,
		       u64 persistent_fid, u64 volatile_fid,
		       __le16 *target_file);
extern int SMB2_rmdir(const unsigned int xid, struct cifs_tcon *tcon,
		      u64 persistent_fid, u64 volatile_fid);
extern int SMB2_set_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
			     u64 persistent_fid, u64 volatile_fid,
			     __le16 *target_file);