diff options
author | Jeff Layton <jlayton@redhat.com> | 2008-09-23 11:48:35 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2008-09-23 13:11:03 -0400 |
commit | a12a1ac7a474b3680b9cce9f64a4f78123aecf37 (patch) | |
tree | ea56c96d7c0b0a81a8629779359ec06eaf922c3d /fs/cifs/inode.c | |
parent | 2846d3864738dd6e290755d0692cf377e09ba79f (diff) |
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: 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.c | 98 |
1 files changed, 59 insertions, 39 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 8dbc7c90309c..660aac81160a 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -760,6 +760,59 @@ out: | |||
760 | return rc; | 760 | return rc; |
761 | } | 761 | } |
762 | 762 | ||
763 | /* | ||
764 | * open the given file (if it isn't already), set the DELETE_ON_CLOSE bit | ||
765 | * and rename it to a random name that hopefully won't conflict with | ||
766 | * anything else. | ||
767 | */ | ||
768 | static int | ||
769 | cifs_rename_pending_delete(char *full_path, struct inode *inode, int xid) | ||
770 | { | ||
771 | int oplock = 0; | ||
772 | int rc; | ||
773 | __u16 netfid; | ||
774 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | ||
775 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
776 | struct cifsTconInfo *tcon = cifs_sb->tcon; | ||
777 | __u32 dosattr; | ||
778 | FILE_BASIC_INFO *info_buf; | ||
779 | |||
780 | rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, | ||
781 | DELETE|FILE_WRITE_ATTRIBUTES, | ||
782 | CREATE_NOT_DIR|CREATE_DELETE_ON_CLOSE, | ||
783 | &netfid, &oplock, NULL, cifs_sb->local_nls, | ||
784 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
785 | if (rc != 0) | ||
786 | goto out; | ||
787 | |||
788 | /* set ATTR_HIDDEN and clear ATTR_READONLY */ | ||
789 | cifsInode = CIFS_I(inode); | ||
790 | dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY; | ||
791 | if (dosattr == 0) | ||
792 | dosattr |= ATTR_NORMAL; | ||
793 | dosattr |= ATTR_HIDDEN; | ||
794 | |||
795 | info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL); | ||
796 | if (info_buf == NULL) { | ||
797 | rc = -ENOMEM; | ||
798 | goto out_close; | ||
799 | } | ||
800 | info_buf->Attributes = cpu_to_le32(dosattr); | ||
801 | rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid, current->tgid); | ||
802 | kfree(info_buf); | ||
803 | if (rc != 0) | ||
804 | goto out_close; | ||
805 | |||
806 | /* silly-rename the file */ | ||
807 | rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls, | ||
808 | cifs_sb->mnt_cifs_flags & | ||
809 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
810 | out_close: | ||
811 | CIFSSMBClose(xid, tcon, netfid); | ||
812 | out: | ||
813 | return rc; | ||
814 | } | ||
815 | |||
763 | int cifs_unlink(struct inode *dir, struct dentry *dentry) | 816 | int cifs_unlink(struct inode *dir, struct dentry *dentry) |
764 | { | 817 | { |
765 | int rc = 0; | 818 | int rc = 0; |
@@ -805,23 +858,9 @@ psx_del_no_retry: | |||
805 | } else if (rc == -ENOENT) { | 858 | } else if (rc == -ENOENT) { |
806 | d_drop(dentry); | 859 | d_drop(dentry); |
807 | } else if (rc == -ETXTBSY) { | 860 | } else if (rc == -ETXTBSY) { |
808 | int oplock = 0; | 861 | rc = cifs_rename_pending_delete(full_path, inode, xid); |
809 | __u16 netfid; | 862 | if (rc == 0) |
810 | 863 | drop_nlink(inode); | |
811 | rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, DELETE, | ||
812 | CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE, | ||
813 | &netfid, &oplock, NULL, cifs_sb->local_nls, | ||
814 | cifs_sb->mnt_cifs_flags & | ||
815 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
816 | if (rc == 0) { | ||
817 | CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, | ||
818 | cifs_sb->local_nls, | ||
819 | cifs_sb->mnt_cifs_flags & | ||
820 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
821 | CIFSSMBClose(xid, tcon, netfid); | ||
822 | if (inode) | ||
823 | drop_nlink(inode); | ||
824 | } | ||
825 | } else if (rc == -EACCES) { | 864 | } else if (rc == -EACCES) { |
826 | /* try only if r/o attribute set in local lookup data? */ | 865 | /* try only if r/o attribute set in local lookup data? */ |
827 | attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); | 866 | attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); |
@@ -848,28 +887,9 @@ psx_del_no_retry: | |||
848 | if (inode) | 887 | if (inode) |
849 | drop_nlink(inode); | 888 | drop_nlink(inode); |
850 | } else if (rc == -ETXTBSY) { | 889 | } else if (rc == -ETXTBSY) { |
851 | int oplock = 0; | 890 | rc = cifs_rename_pending_delete(full_path, inode, xid); |
852 | __u16 netfid; | 891 | if (rc == 0) |
853 | 892 | drop_nlink(inode); | |
854 | rc = CIFSSMBOpen(xid, tcon, full_path, | ||
855 | FILE_OPEN, DELETE, | ||
856 | CREATE_NOT_DIR | | ||
857 | CREATE_DELETE_ON_CLOSE, | ||
858 | &netfid, &oplock, NULL, | ||
859 | cifs_sb->local_nls, | ||
860 | cifs_sb->mnt_cifs_flags & | ||
861 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
862 | if (rc == 0) { | ||
863 | CIFSSMBRenameOpenFile(xid, tcon, | ||
864 | netfid, NULL, | ||
865 | cifs_sb->local_nls, | ||
866 | cifs_sb->mnt_cifs_flags & | ||
867 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
868 | CIFSSMBClose(xid, tcon, netfid); | ||
869 | if (inode) | ||
870 | drop_nlink(inode); | ||
871 | } | ||
872 | /* BB if rc = -ETXTBUSY goto the rename logic BB */ | ||
873 | } | 893 | } |
874 | } | 894 | } |
875 | out_reval: | 895 | out_reval: |