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

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
...@@ -760,6 +760,59 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid, ...@@ -760,6 +760,59 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
return rc; 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 cifs_unlink(struct inode *dir, struct dentry *dentry)
{ {
int rc = 0; int rc = 0;
...@@ -805,23 +858,9 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -805,23 +858,9 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
} else if (rc == -ENOENT) { } else if (rc == -ENOENT) {
d_drop(dentry); d_drop(dentry);
} else if (rc == -ETXTBSY) { } else if (rc == -ETXTBSY) {
int oplock = 0; rc = cifs_rename_pending_delete(full_path, inode, xid);
__u16 netfid; if (rc == 0)
drop_nlink(inode);
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);
}
} else if (rc == -EACCES) { } else if (rc == -EACCES) {
/* try only if r/o attribute set in local lookup data? */ /* try only if r/o attribute set in local lookup data? */
attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
...@@ -848,28 +887,9 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -848,28 +887,9 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
if (inode) if (inode)
drop_nlink(inode); drop_nlink(inode);
} else if (rc == -ETXTBSY) { } else if (rc == -ETXTBSY) {
int oplock = 0; rc = cifs_rename_pending_delete(full_path, inode, xid);
__u16 netfid; if (rc == 0)
drop_nlink(inode);
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 */
} }
} }
out_reval: out_reval:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment