[linux-cifs-client] [PATCH 3/4] cifs: move silly-rename logic into helper function

Jeff Layton jlayton at redhat.com
Tue Sep 16 11:27:15 GMT 2008


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 silly-renames call it. It
also fixes the open flags to be correct.

Signed-off-by: Jeff Layton <jlayton at redhat.com>
---
 fs/cifs/inode.c |   98 +++++++++++++++++++++++++++++++++----------------------
 1 files changed, 59 insertions(+), 39 deletions(-)

diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 3f0995d..0d557b7 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -667,6 +667,59 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
 	return inode;
 }
 
+/*
+ * 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_silly_rename(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 *pTcon = cifs_sb->tcon;
+	__u32 dosattr;
+	FILE_BASIC_INFO *info_buf;
+
+	rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
+			 DELETE|FILE_ATTRIBUTE_WRITE,
+			 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, pTcon, info_buf, netfid, current->tgid);
+	kfree(info_buf);
+	if (rc != 0)
+		goto out_close;
+
+	/* silly-rename the file */
+	rc = CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL, cifs_sb->local_nls,
+				   cifs_sb->mnt_cifs_flags &
+					    CIFS_MOUNT_MAP_SPECIAL_CHR);
+out_close:
+	CIFSSMBClose(xid, pTcon, netfid);
+out:
+	return rc;
+}
+
 int cifs_unlink(struct inode *pinode, struct dentry *direntry)
 {
 	int rc = 0;
@@ -720,23 +773,9 @@ psx_del_no_retry:
 	} else if (rc == -ENOENT) {
 		d_drop(direntry);
 	} else if (rc == -ETXTBSY) {
-		int oplock = 0;
-		__u16 netfid;
-
-		rc = CIFSSMBOpen(xid, pTcon, 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, pTcon, netfid, NULL,
-					      cifs_sb->local_nls,
-					      cifs_sb->mnt_cifs_flags &
-						CIFS_MOUNT_MAP_SPECIAL_CHR);
-			CIFSSMBClose(xid, pTcon, netfid);
-			if (inode)
-				drop_nlink(inode);
-		}
+		rc = cifs_silly_rename(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);
@@ -764,28 +803,9 @@ psx_del_no_retry:
 			if (inode)
 				drop_nlink(inode);
 		} else if (rc == -ETXTBSY) {
-			int oplock = 0;
-			__u16 netfid;
-
-			rc = CIFSSMBOpen(xid, pTcon, 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, pTcon,
-					netfid, NULL,
-					cifs_sb->local_nls,
-					cifs_sb->mnt_cifs_flags &
-					    CIFS_MOUNT_MAP_SPECIAL_CHR);
-				CIFSSMBClose(xid, pTcon, netfid);
-				if (inode)
-					drop_nlink(inode);
-			}
-		/* BB if rc = -ETXTBUSY goto the rename logic BB */
+			rc = cifs_silly_rename(full_path, inode, xid);
+			if (rc == 0)
+				drop_nlink(inode);
 		}
 	}
 out_reval:
-- 
1.5.5.1



More information about the linux-cifs-client mailing list