aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/inode.c
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2008-10-19 20:44:19 -0400
committerSteve French <sfrench@us.ibm.com>2008-10-19 20:44:19 -0400
commit3270958b717a13d0228803254609c19184854b9b (patch)
tree50d1affc68add3e89798f647bb6abc7532f62e51 /fs/cifs/inode.c
parent9a8165fce724d1aba21e2c713ac6ba11dbfecafa (diff)
[CIFS] undo changes in cifs_rename_pending_delete if it errors out
The cifs_rename_pending_delete process involves multiple steps. If it fails and we're going to return error, we don't want to leave things in a half-finished state. Add code to the function to undo changes if a call fails. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r--fs/cifs/inode.c102
1 files changed, 70 insertions, 32 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index dea9eeb58b00..232ab16d7fd4 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -773,16 +773,17 @@ out:
773 * anything else. 773 * anything else.
774 */ 774 */
775static int 775static int
776cifs_rename_pending_delete(char *full_path, struct inode *inode, int xid) 776cifs_rename_pending_delete(char *full_path, struct dentry *dentry, int xid)
777{ 777{
778 int oplock = 0; 778 int oplock = 0;
779 int rc; 779 int rc;
780 __u16 netfid; 780 __u16 netfid;
781 struct inode *inode = dentry->d_inode;
781 struct cifsInodeInfo *cifsInode = CIFS_I(inode); 782 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
782 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 783 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
783 struct cifsTconInfo *tcon = cifs_sb->tcon; 784 struct cifsTconInfo *tcon = cifs_sb->tcon;
784 __u32 dosattr; 785 __u32 dosattr, origattr;
785 FILE_BASIC_INFO *info_buf; 786 FILE_BASIC_INFO *info_buf = NULL;
786 787
787 rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, 788 rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
788 DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR, 789 DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
@@ -791,50 +792,87 @@ cifs_rename_pending_delete(char *full_path, struct inode *inode, int xid)
791 if (rc != 0) 792 if (rc != 0)
792 goto out; 793 goto out;
793 794
794 /* set ATTR_HIDDEN and clear ATTR_READONLY */ 795 origattr = cifsInode->cifsAttrs;
795 cifsInode = CIFS_I(inode); 796 if (origattr == 0)
796 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY; 797 origattr |= ATTR_NORMAL;
798
799 dosattr = origattr & ~ATTR_READONLY;
797 if (dosattr == 0) 800 if (dosattr == 0)
798 dosattr |= ATTR_NORMAL; 801 dosattr |= ATTR_NORMAL;
799 dosattr |= ATTR_HIDDEN; 802 dosattr |= ATTR_HIDDEN;
800 803
801 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL); 804 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
802 if (info_buf == NULL) { 805 if (dosattr != origattr) {
803 rc = -ENOMEM; 806 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
804 goto out_close; 807 if (info_buf == NULL) {
808 rc = -ENOMEM;
809 goto out_close;
810 }
811 info_buf->Attributes = cpu_to_le32(dosattr);
812 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
813 current->tgid);
814 /* although we would like to mark the file hidden
815 if that fails we will still try to rename it */
816 if (rc != 0) {
817 cifsInode->cifsAttrs = dosattr;
818 else
819 dosattr = origattr; /* since not able to change them */
805 } 820 }
806 info_buf->Attributes = cpu_to_le32(dosattr);
807 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid, current->tgid);
808 kfree(info_buf);
809 if (rc != 0)
810 goto out_close;
811 cifsInode->cifsAttrs = dosattr;
812 821
813 /* rename the file */ 822 /* rename the file */
814 rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls, 823 rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls,
815 cifs_sb->mnt_cifs_flags & 824 cifs_sb->mnt_cifs_flags &
816 CIFS_MOUNT_MAP_SPECIAL_CHR); 825 CIFS_MOUNT_MAP_SPECIAL_CHR);
817 if (rc != 0) 826 if (rc != 0) {
818 goto out; 827 rc = -ETXTBSY;
819 828 goto undo_setattr;
820 /* set DELETE_ON_CLOSE */ 829 }
821 rc = CIFSSMBSetFileDisposition(xid, tcon, true, netfid, current->tgid);
822 830
823 /* 831 /* try to set DELETE_ON_CLOSE */
824 * some samba versions return -ENOENT when we try to set the file 832 if (!cifsInode->delete_pending) {
825 * disposition here. Likely a samba bug, but work around it for now. 833 rc = CIFSSMBSetFileDisposition(xid, tcon, true, netfid,
826 * This means that some cifsXXX files may hang around after they 834 current->tgid);
827 * shouldn't. 835 /*
828 * 836 * some samba versions return -ENOENT when we try to set the
829 * BB: remove this once fixed samba servers are in the field 837 * file disposition here. Likely a samba bug, but work around
830 */ 838 * it for now. This means that some cifsXXX files may hang
831 if (rc == -ENOENT) 839 * around after they shouldn't.
832 rc = 0; 840 *
841 * BB: remove this hack after more servers have the fix
842 */
843 if (rc == -ENOENT)
844 rc = 0;
845 else if (rc != 0) {
846 rc = -ETXTBSY;
847 goto undo_rename;
848 }
849 cifsInode->delete_pending = true;
850 }
833 851
834out_close: 852out_close:
835 CIFSSMBClose(xid, tcon, netfid); 853 CIFSSMBClose(xid, tcon, netfid);
836out: 854out:
855 kfree(info_buf);
837 return rc; 856 return rc;
857
858 /*
859 * reset everything back to the original state. Don't bother
860 * dealing with errors here since we can't do anything about
861 * them anyway.
862 */
863undo_rename:
864 CIFSSMBRenameOpenFile(xid, tcon, netfid, dentry->d_name.name,
865 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
866 CIFS_MOUNT_MAP_SPECIAL_CHR);
867undo_setattr:
868 if (dosattr != origattr) {
869 info_buf->Attributes = cpu_to_le32(origattr);
870 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
871 current->tgid))
872 cifsInode->cifsAttrs = origattr;
873 }
874
875 goto out_close;
838} 876}
839 877
840int cifs_unlink(struct inode *dir, struct dentry *dentry) 878int cifs_unlink(struct inode *dir, struct dentry *dentry)
@@ -884,7 +922,7 @@ psx_del_no_retry:
884 } else if (rc == -ENOENT) { 922 } else if (rc == -ENOENT) {
885 d_drop(dentry); 923 d_drop(dentry);
886 } else if (rc == -ETXTBSY) { 924 } else if (rc == -ETXTBSY) {
887 rc = cifs_rename_pending_delete(full_path, inode, xid); 925 rc = cifs_rename_pending_delete(full_path, dentry, xid);
888 if (rc == 0) 926 if (rc == 0)
889 drop_nlink(inode); 927 drop_nlink(inode);
890 } else if (rc == -EACCES && dosattr == 0) { 928 } else if (rc == -EACCES && dosattr == 0) {