diff options
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r-- | fs/cifs/inode.c | 39 |
1 files changed, 19 insertions, 20 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index e387ed3f9446..a8c833345fc9 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -837,12 +837,12 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) | |||
837 | int xid; | 837 | int xid; |
838 | char *full_path = NULL; | 838 | char *full_path = NULL; |
839 | struct inode *inode = dentry->d_inode; | 839 | struct inode *inode = dentry->d_inode; |
840 | struct cifsInodeInfo *cifsInode; | 840 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); |
841 | struct super_block *sb = dir->i_sb; | 841 | struct super_block *sb = dir->i_sb; |
842 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 842 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
843 | struct cifsTconInfo *tcon = cifs_sb->tcon; | 843 | struct cifsTconInfo *tcon = cifs_sb->tcon; |
844 | struct iattr *attrs; | 844 | struct iattr *attrs = NULL; |
845 | __u32 dosattr; | 845 | __u32 dosattr = 0, origattr = 0; |
846 | 846 | ||
847 | cFYI(1, ("cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry)); | 847 | cFYI(1, ("cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry)); |
848 | 848 | ||
@@ -867,8 +867,10 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) | |||
867 | goto psx_del_no_retry; | 867 | goto psx_del_no_retry; |
868 | } | 868 | } |
869 | 869 | ||
870 | retry_std_delete: | ||
870 | rc = CIFSSMBDelFile(xid, tcon, full_path, cifs_sb->local_nls, | 871 | rc = CIFSSMBDelFile(xid, tcon, full_path, cifs_sb->local_nls, |
871 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 872 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
873 | |||
872 | psx_del_no_retry: | 874 | psx_del_no_retry: |
873 | if (!rc) { | 875 | if (!rc) { |
874 | if (inode) | 876 | if (inode) |
@@ -879,8 +881,7 @@ psx_del_no_retry: | |||
879 | rc = cifs_rename_pending_delete(full_path, inode, xid); | 881 | rc = cifs_rename_pending_delete(full_path, inode, xid); |
880 | if (rc == 0) | 882 | if (rc == 0) |
881 | drop_nlink(inode); | 883 | drop_nlink(inode); |
882 | } else if (rc == -EACCES) { | 884 | } else if (rc == -EACCES && dosattr == 0) { |
883 | /* try only if r/o attribute set in local lookup data? */ | ||
884 | attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); | 885 | attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); |
885 | if (attrs == NULL) { | 886 | if (attrs == NULL) { |
886 | rc = -ENOMEM; | 887 | rc = -ENOMEM; |
@@ -888,28 +889,25 @@ psx_del_no_retry: | |||
888 | } | 889 | } |
889 | 890 | ||
890 | /* try to reset dos attributes */ | 891 | /* try to reset dos attributes */ |
891 | cifsInode = CIFS_I(inode); | 892 | origattr = cifsInode->cifsAttrs; |
892 | dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY; | 893 | if (origattr == 0) |
894 | origattr |= ATTR_NORMAL; | ||
895 | dosattr = origattr & ~ATTR_READONLY; | ||
893 | if (dosattr == 0) | 896 | if (dosattr == 0) |
894 | dosattr |= ATTR_NORMAL; | 897 | dosattr |= ATTR_NORMAL; |
895 | dosattr |= ATTR_HIDDEN; | 898 | dosattr |= ATTR_HIDDEN; |
896 | 899 | ||
897 | rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr); | 900 | rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr); |
898 | kfree(attrs); | ||
899 | if (rc != 0) | 901 | if (rc != 0) |
900 | goto out_reval; | 902 | goto out_reval; |
901 | rc = CIFSSMBDelFile(xid, tcon, full_path, cifs_sb->local_nls, | 903 | |
902 | cifs_sb->mnt_cifs_flags & | 904 | goto retry_std_delete; |
903 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
904 | if (rc == 0) { | ||
905 | if (inode) | ||
906 | drop_nlink(inode); | ||
907 | } else if (rc == -ETXTBSY) { | ||
908 | rc = cifs_rename_pending_delete(full_path, inode, xid); | ||
909 | if (rc == 0) | ||
910 | drop_nlink(inode); | ||
911 | } | ||
912 | } | 905 | } |
906 | |||
907 | /* undo the setattr if we errored out and it's needed */ | ||
908 | if (rc != 0 && dosattr != 0) | ||
909 | cifs_set_file_info(inode, attrs, xid, full_path, origattr); | ||
910 | |||
913 | out_reval: | 911 | out_reval: |
914 | if (inode) { | 912 | if (inode) { |
915 | cifsInode = CIFS_I(inode); | 913 | cifsInode = CIFS_I(inode); |
@@ -919,9 +917,10 @@ out_reval: | |||
919 | } | 917 | } |
920 | dir->i_ctime = dir->i_mtime = current_fs_time(sb); | 918 | dir->i_ctime = dir->i_mtime = current_fs_time(sb); |
921 | cifsInode = CIFS_I(dir); | 919 | cifsInode = CIFS_I(dir); |
922 | cifsInode->time = 0; /* force revalidate of dir as well */ | 920 | CIFS_I(dir)->time = 0; /* force revalidate of dir as well */ |
923 | 921 | ||
924 | kfree(full_path); | 922 | kfree(full_path); |
923 | kfree(attrs); | ||
925 | FreeXid(xid); | 924 | FreeXid(xid); |
926 | return rc; | 925 | return rc; |
927 | } | 926 | } |