From 9ac1f72ee932287f4bd313d09aa8e847a700644e Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 7 Oct 2008 18:42:52 +0000 Subject: [PATCH] --- yaml --- r: 111157 b: refs/heads/master c: 6050247d8089037d6d8ea0f3c62fe4a931c1ab14 h: refs/heads/master i: 111155: 99cc007f97f95afd447c1c2a8e1263b6d23a89b9 v: v3 --- [refs] | 2 +- trunk/fs/cifs/inode.c | 39 +++++++++++++++++++-------------------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/[refs] b/[refs] index c238e379d711..38cc29b22cd8 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 6b37faa175311128dc920aaa57a5f7fab85537d7 +refs/heads/master: 6050247d8089037d6d8ea0f3c62fe4a931c1ab14 diff --git a/trunk/fs/cifs/inode.c b/trunk/fs/cifs/inode.c index e387ed3f9446..a8c833345fc9 100644 --- a/trunk/fs/cifs/inode.c +++ b/trunk/fs/cifs/inode.c @@ -837,12 +837,12 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) int xid; char *full_path = NULL; struct inode *inode = dentry->d_inode; - struct cifsInodeInfo *cifsInode; + struct cifsInodeInfo *cifsInode = CIFS_I(inode); struct super_block *sb = dir->i_sb; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); struct cifsTconInfo *tcon = cifs_sb->tcon; - struct iattr *attrs; - __u32 dosattr; + struct iattr *attrs = NULL; + __u32 dosattr = 0, origattr = 0; cFYI(1, ("cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry)); @@ -867,8 +867,10 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) goto psx_del_no_retry; } +retry_std_delete: rc = CIFSSMBDelFile(xid, tcon, full_path, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + psx_del_no_retry: if (!rc) { if (inode) @@ -879,8 +881,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) 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? */ + } else if (rc == -EACCES && dosattr == 0) { attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); if (attrs == NULL) { rc = -ENOMEM; @@ -888,28 +889,25 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) } /* try to reset dos attributes */ - cifsInode = CIFS_I(inode); - dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY; + origattr = cifsInode->cifsAttrs; + if (origattr == 0) + origattr |= ATTR_NORMAL; + dosattr = origattr & ~ATTR_READONLY; if (dosattr == 0) dosattr |= ATTR_NORMAL; dosattr |= ATTR_HIDDEN; rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr); - kfree(attrs); if (rc != 0) goto out_reval; - rc = CIFSSMBDelFile(xid, tcon, full_path, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - if (rc == 0) { - if (inode) - drop_nlink(inode); - } else if (rc == -ETXTBSY) { - rc = cifs_rename_pending_delete(full_path, inode, xid); - if (rc == 0) - drop_nlink(inode); - } + + goto retry_std_delete; } + + /* undo the setattr if we errored out and it's needed */ + if (rc != 0 && dosattr != 0) + cifs_set_file_info(inode, attrs, xid, full_path, origattr); + out_reval: if (inode) { cifsInode = CIFS_I(inode); @@ -919,9 +917,10 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) } dir->i_ctime = dir->i_mtime = current_fs_time(sb); cifsInode = CIFS_I(dir); - cifsInode->time = 0; /* force revalidate of dir as well */ + CIFS_I(dir)->time = 0; /* force revalidate of dir as well */ kfree(full_path); + kfree(attrs); FreeXid(xid); return rc; }