cifs: move rename and delete-on-close logic into helper function
authorJeff Layton <jlayton@redhat.com>
Tue, 23 Sep 2008 15:48:35 +0000 (11:48 -0400)
committerSteve French <sfrench@us.ibm.com>
Tue, 23 Sep 2008 17:11:03 +0000 (17:11 +0000)
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: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
fs/cifs/inode.c

index 8dbc7c9..660aac8 100644 (file)
@@ -760,6 +760,59 @@ out:
        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 @@ psx_del_no_retry:
        } 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)
-                               drop_nlink(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,28 +887,9 @@ psx_del_no_retry:
                        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)
-                                       drop_nlink(inode);
-                       }
-               /* BB if rc = -ETXTBUSY goto the rename logic BB */
+                       rc = cifs_rename_pending_delete(full_path, inode, xid);
+                       if (rc == 0)
+                               drop_nlink(inode);
                }
        }
 out_reval: