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

Commit a12a1ac7 authored by Jeff Layton's avatar Jeff Layton Committed by Steve French
Browse files

cifs: move rename and delete-on-close logic into helper function



cifs: move rename and delete-on-close logic into helper function

When a file is still open on the server, we attempt to set the
DELETE_ON_CLOSE bit and rename it to a new filename. When the
last opener closes the file, the server should delete it.

This patch moves this mechanism into a helper function and has
the two places in cifs_unlink that do this procedure call it. It
also fixes the open flags to be correct.

Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent 2846d386
Loading
Loading
Loading
Loading
+59 −39
Original line number Diff line number Diff line
@@ -760,6 +760,59 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
	return rc;
}

/*
 * open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
 * and rename it to a random name that hopefully won't conflict with
 * anything else.
 */
static int
cifs_rename_pending_delete(char *full_path, struct inode *inode, int xid)
{
	int oplock = 0;
	int rc;
	__u16 netfid;
	struct cifsInodeInfo *cifsInode = CIFS_I(inode);
	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
	struct cifsTconInfo *tcon = cifs_sb->tcon;
	__u32 dosattr;
	FILE_BASIC_INFO *info_buf;

	rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
			 DELETE|FILE_WRITE_ATTRIBUTES,
			 CREATE_NOT_DIR|CREATE_DELETE_ON_CLOSE,
			 &netfid, &oplock, NULL, cifs_sb->local_nls,
			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
	if (rc != 0)
		goto out;

	/* set ATTR_HIDDEN and clear ATTR_READONLY */
	cifsInode = CIFS_I(inode);
	dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
	if (dosattr == 0)
		dosattr |= ATTR_NORMAL;
	dosattr |= ATTR_HIDDEN;

	info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
	if (info_buf == NULL) {
		rc = -ENOMEM;
		goto out_close;
	}
	info_buf->Attributes = cpu_to_le32(dosattr);
	rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid, current->tgid);
	kfree(info_buf);
	if (rc != 0)
		goto out_close;

	/* silly-rename the file */
	rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls,
				   cifs_sb->mnt_cifs_flags &
					    CIFS_MOUNT_MAP_SPECIAL_CHR);
out_close:
	CIFSSMBClose(xid, tcon, netfid);
out:
	return rc;
}

int cifs_unlink(struct inode *dir, struct dentry *dentry)
{
	int rc = 0;
@@ -805,23 +858,9 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
	} else if (rc == -ENOENT) {
		d_drop(dentry);
	} else if (rc == -ETXTBSY) {
		int oplock = 0;
		__u16 netfid;

		rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, DELETE,
				 CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
				 &netfid, &oplock, NULL, cifs_sb->local_nls,
				 cifs_sb->mnt_cifs_flags &
					CIFS_MOUNT_MAP_SPECIAL_CHR);
		if (rc == 0) {
			CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL,
					      cifs_sb->local_nls,
					      cifs_sb->mnt_cifs_flags &
						CIFS_MOUNT_MAP_SPECIAL_CHR);
			CIFSSMBClose(xid, tcon, netfid);
			if (inode)
		rc = cifs_rename_pending_delete(full_path, inode, xid);
		if (rc == 0)
			drop_nlink(inode);
		}
	} else if (rc == -EACCES) {
		/* try only if r/o attribute set in local lookup data? */
		attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
@@ -848,29 +887,10 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
			if (inode)
				drop_nlink(inode);
		} else if (rc == -ETXTBSY) {
			int oplock = 0;
			__u16 netfid;

			rc = CIFSSMBOpen(xid, tcon, full_path,
					 FILE_OPEN, DELETE,
					 CREATE_NOT_DIR |
					 CREATE_DELETE_ON_CLOSE,
					 &netfid, &oplock, NULL,
					 cifs_sb->local_nls,
					 cifs_sb->mnt_cifs_flags &
					    CIFS_MOUNT_MAP_SPECIAL_CHR);
			if (rc == 0) {
				CIFSSMBRenameOpenFile(xid, tcon,
					netfid, NULL,
					cifs_sb->local_nls,
					cifs_sb->mnt_cifs_flags &
					    CIFS_MOUNT_MAP_SPECIAL_CHR);
				CIFSSMBClose(xid, tcon, netfid);
				if (inode)
			rc = cifs_rename_pending_delete(full_path, inode, xid);
			if (rc == 0)
				drop_nlink(inode);
		}
		/* BB if rc = -ETXTBUSY goto the rename logic BB */
		}
	}
out_reval:
	if (inode) {