[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