aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/inode.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2008-09-23 11:48:35 -0400
committerSteve French <sfrench@us.ibm.com>2008-09-23 13:11:03 -0400
commita12a1ac7a474b3680b9cce9f64a4f78123aecf37 (patch)
treeea56c96d7c0b0a81a8629779359ec06eaf922c3d /fs/cifs/inode.c
parent2846d3864738dd6e290755d0692cf377e09ba79f (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.c98
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 */
768static int
769cifs_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);
810out_close:
811 CIFSSMBClose(xid, tcon, netfid);
812out:
813 return rc;
814}
815
763int cifs_unlink(struct inode *dir, struct dentry *dentry) 816int 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 }
875out_reval: 895out_reval: