diff options
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/cifsfs.h | 2 | ||||
-rw-r--r-- | fs/cifs/inode.c | 90 |
2 files changed, 42 insertions, 50 deletions
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 135c965c4137..f7b4a5cd837b 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -41,7 +41,7 @@ extern int cifs_create(struct inode *, struct dentry *, int, | |||
41 | struct nameidata *); | 41 | struct nameidata *); |
42 | extern struct dentry *cifs_lookup(struct inode *, struct dentry *, | 42 | extern struct dentry *cifs_lookup(struct inode *, struct dentry *, |
43 | struct nameidata *); | 43 | struct nameidata *); |
44 | extern int cifs_unlink(struct inode *, struct dentry *); | 44 | extern int cifs_unlink(struct inode *dir, struct dentry *dentry); |
45 | extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *); | 45 | extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *); |
46 | extern int cifs_mknod(struct inode *, struct dentry *, int, dev_t); | 46 | extern int cifs_mknod(struct inode *, struct dentry *, int, dev_t); |
47 | extern int cifs_mkdir(struct inode *, struct dentry *, int); | 47 | extern int cifs_mkdir(struct inode *, struct dentry *, int); |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 9c548f110102..511c52616794 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -665,40 +665,34 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino) | |||
665 | return inode; | 665 | return inode; |
666 | } | 666 | } |
667 | 667 | ||
668 | int cifs_unlink(struct inode *inode, struct dentry *direntry) | 668 | int cifs_unlink(struct inode *dir, struct dentry *dentry) |
669 | { | 669 | { |
670 | int rc = 0; | 670 | int rc = 0; |
671 | int xid; | 671 | int xid; |
672 | struct cifs_sb_info *cifs_sb; | ||
673 | struct cifsTconInfo *pTcon; | ||
674 | char *full_path = NULL; | 672 | char *full_path = NULL; |
673 | struct inode *inode = dentry->d_inode; | ||
675 | struct cifsInodeInfo *cifsInode; | 674 | struct cifsInodeInfo *cifsInode; |
675 | struct super_block *sb = dir->i_sb; | ||
676 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | ||
677 | struct cifsTconInfo *tcon = cifs_sb->tcon; | ||
676 | FILE_BASIC_INFO *pinfo_buf; | 678 | FILE_BASIC_INFO *pinfo_buf; |
677 | 679 | ||
678 | cFYI(1, ("cifs_unlink, inode = 0x%p", inode)); | 680 | cFYI(1, ("cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry)); |
679 | 681 | ||
680 | xid = GetXid(); | 682 | xid = GetXid(); |
681 | 683 | ||
682 | if (inode) | 684 | /* Unlink can be called from rename so we can not take the |
683 | cifs_sb = CIFS_SB(inode->i_sb); | 685 | * sb->s_vfs_rename_mutex here */ |
684 | else | 686 | full_path = build_path_from_dentry(dentry); |
685 | cifs_sb = CIFS_SB(direntry->d_sb); | ||
686 | pTcon = cifs_sb->tcon; | ||
687 | |||
688 | /* Unlink can be called from rename so we can not grab the sem here | ||
689 | since we deadlock otherwise */ | ||
690 | /* mutex_lock(&direntry->d_sb->s_vfs_rename_mutex);*/ | ||
691 | full_path = build_path_from_dentry(direntry); | ||
692 | /* mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex);*/ | ||
693 | if (full_path == NULL) { | 687 | if (full_path == NULL) { |
694 | FreeXid(xid); | 688 | FreeXid(xid); |
695 | return -ENOMEM; | 689 | return -ENOMEM; |
696 | } | 690 | } |
697 | 691 | ||
698 | if ((pTcon->ses->capabilities & CAP_UNIX) && | 692 | if ((tcon->ses->capabilities & CAP_UNIX) && |
699 | (CIFS_UNIX_POSIX_PATH_OPS_CAP & | 693 | (CIFS_UNIX_POSIX_PATH_OPS_CAP & |
700 | le64_to_cpu(pTcon->fsUnixInfo.Capability))) { | 694 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { |
701 | rc = CIFSPOSIXDelFile(xid, pTcon, full_path, | 695 | rc = CIFSPOSIXDelFile(xid, tcon, full_path, |
702 | SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls, | 696 | SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls, |
703 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 697 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
704 | cFYI(1, ("posix del rc %d", rc)); | 698 | cFYI(1, ("posix del rc %d", rc)); |
@@ -706,31 +700,31 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) | |||
706 | goto psx_del_no_retry; | 700 | goto psx_del_no_retry; |
707 | } | 701 | } |
708 | 702 | ||
709 | rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls, | 703 | rc = CIFSSMBDelFile(xid, tcon, full_path, cifs_sb->local_nls, |
710 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 704 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
711 | psx_del_no_retry: | 705 | psx_del_no_retry: |
712 | if (!rc) { | 706 | if (!rc) { |
713 | if (direntry->d_inode) | 707 | if (inode) |
714 | drop_nlink(direntry->d_inode); | 708 | drop_nlink(inode); |
715 | } else if (rc == -ENOENT) { | 709 | } else if (rc == -ENOENT) { |
716 | d_drop(direntry); | 710 | d_drop(dentry); |
717 | } else if (rc == -ETXTBSY) { | 711 | } else if (rc == -ETXTBSY) { |
718 | int oplock = 0; | 712 | int oplock = 0; |
719 | __u16 netfid; | 713 | __u16 netfid; |
720 | 714 | ||
721 | rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE, | 715 | rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, DELETE, |
722 | CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE, | 716 | CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE, |
723 | &netfid, &oplock, NULL, cifs_sb->local_nls, | 717 | &netfid, &oplock, NULL, cifs_sb->local_nls, |
724 | cifs_sb->mnt_cifs_flags & | 718 | cifs_sb->mnt_cifs_flags & |
725 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 719 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
726 | if (rc == 0) { | 720 | if (rc == 0) { |
727 | CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL, | 721 | CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, |
728 | cifs_sb->local_nls, | 722 | cifs_sb->local_nls, |
729 | cifs_sb->mnt_cifs_flags & | 723 | cifs_sb->mnt_cifs_flags & |
730 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 724 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
731 | CIFSSMBClose(xid, pTcon, netfid); | 725 | CIFSSMBClose(xid, tcon, netfid); |
732 | if (direntry->d_inode) | 726 | if (inode) |
733 | drop_nlink(direntry->d_inode); | 727 | drop_nlink(inode); |
734 | } | 728 | } |
735 | } else if (rc == -EACCES) { | 729 | } else if (rc == -EACCES) { |
736 | /* try only if r/o attribute set in local lookup data? */ | 730 | /* try only if r/o attribute set in local lookup data? */ |
@@ -738,8 +732,8 @@ psx_del_no_retry: | |||
738 | if (pinfo_buf) { | 732 | if (pinfo_buf) { |
739 | /* ATTRS set to normal clears r/o bit */ | 733 | /* ATTRS set to normal clears r/o bit */ |
740 | pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL); | 734 | pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL); |
741 | if (!(pTcon->ses->flags & CIFS_SES_NT4)) | 735 | if (!(tcon->ses->flags & CIFS_SES_NT4)) |
742 | rc = CIFSSMBSetPathInfo(xid, pTcon, full_path, | 736 | rc = CIFSSMBSetPathInfo(xid, tcon, full_path, |
743 | pinfo_buf, | 737 | pinfo_buf, |
744 | cifs_sb->local_nls, | 738 | cifs_sb->local_nls, |
745 | cifs_sb->mnt_cifs_flags & | 739 | cifs_sb->mnt_cifs_flags & |
@@ -750,7 +744,7 @@ psx_del_no_retry: | |||
750 | if (rc == -EOPNOTSUPP) { | 744 | if (rc == -EOPNOTSUPP) { |
751 | int oplock = 0; | 745 | int oplock = 0; |
752 | __u16 netfid; | 746 | __u16 netfid; |
753 | /* rc = CIFSSMBSetAttrLegacy(xid, pTcon, | 747 | /* rc = CIFSSMBSetAttrLegacy(xid, tcon, |
754 | full_path, | 748 | full_path, |
755 | (__u16)ATTR_NORMAL, | 749 | (__u16)ATTR_NORMAL, |
756 | cifs_sb->local_nls); | 750 | cifs_sb->local_nls); |
@@ -761,7 +755,7 @@ psx_del_no_retry: | |||
761 | 755 | ||
762 | /* BB could scan to see if we already have it open | 756 | /* BB could scan to see if we already have it open |
763 | and pass in pid of opener to function */ | 757 | and pass in pid of opener to function */ |
764 | rc = CIFSSMBOpen(xid, pTcon, full_path, | 758 | rc = CIFSSMBOpen(xid, tcon, full_path, |
765 | FILE_OPEN, SYNCHRONIZE | | 759 | FILE_OPEN, SYNCHRONIZE | |
766 | FILE_WRITE_ATTRIBUTES, 0, | 760 | FILE_WRITE_ATTRIBUTES, 0, |
767 | &netfid, &oplock, NULL, | 761 | &netfid, &oplock, NULL, |
@@ -769,28 +763,28 @@ psx_del_no_retry: | |||
769 | cifs_sb->mnt_cifs_flags & | 763 | cifs_sb->mnt_cifs_flags & |
770 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 764 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
771 | if (rc == 0) { | 765 | if (rc == 0) { |
772 | rc = CIFSSMBSetFileInfo(xid, pTcon, | 766 | rc = CIFSSMBSetFileInfo(xid, tcon, |
773 | pinfo_buf, | 767 | pinfo_buf, |
774 | netfid, | 768 | netfid, |
775 | current->tgid); | 769 | current->tgid); |
776 | CIFSSMBClose(xid, pTcon, netfid); | 770 | CIFSSMBClose(xid, tcon, netfid); |
777 | } | 771 | } |
778 | } | 772 | } |
779 | kfree(pinfo_buf); | 773 | kfree(pinfo_buf); |
780 | } | 774 | } |
781 | if (rc == 0) { | 775 | if (rc == 0) { |
782 | rc = CIFSSMBDelFile(xid, pTcon, full_path, | 776 | rc = CIFSSMBDelFile(xid, tcon, full_path, |
783 | cifs_sb->local_nls, | 777 | cifs_sb->local_nls, |
784 | cifs_sb->mnt_cifs_flags & | 778 | cifs_sb->mnt_cifs_flags & |
785 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 779 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
786 | if (!rc) { | 780 | if (!rc) { |
787 | if (direntry->d_inode) | 781 | if (inode) |
788 | drop_nlink(direntry->d_inode); | 782 | drop_nlink(inode); |
789 | } else if (rc == -ETXTBSY) { | 783 | } else if (rc == -ETXTBSY) { |
790 | int oplock = 0; | 784 | int oplock = 0; |
791 | __u16 netfid; | 785 | __u16 netfid; |
792 | 786 | ||
793 | rc = CIFSSMBOpen(xid, pTcon, full_path, | 787 | rc = CIFSSMBOpen(xid, tcon, full_path, |
794 | FILE_OPEN, DELETE, | 788 | FILE_OPEN, DELETE, |
795 | CREATE_NOT_DIR | | 789 | CREATE_NOT_DIR | |
796 | CREATE_DELETE_ON_CLOSE, | 790 | CREATE_DELETE_ON_CLOSE, |
@@ -799,30 +793,28 @@ psx_del_no_retry: | |||
799 | cifs_sb->mnt_cifs_flags & | 793 | cifs_sb->mnt_cifs_flags & |
800 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 794 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
801 | if (rc == 0) { | 795 | if (rc == 0) { |
802 | CIFSSMBRenameOpenFile(xid, pTcon, | 796 | CIFSSMBRenameOpenFile(xid, tcon, |
803 | netfid, NULL, | 797 | netfid, NULL, |
804 | cifs_sb->local_nls, | 798 | cifs_sb->local_nls, |
805 | cifs_sb->mnt_cifs_flags & | 799 | cifs_sb->mnt_cifs_flags & |
806 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 800 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
807 | CIFSSMBClose(xid, pTcon, netfid); | 801 | CIFSSMBClose(xid, tcon, netfid); |
808 | if (direntry->d_inode) | 802 | if (inode) |
809 | drop_nlink(direntry->d_inode); | 803 | drop_nlink(inode); |
810 | } | 804 | } |
811 | /* BB if rc = -ETXTBUSY goto the rename logic BB */ | 805 | /* BB if rc = -ETXTBUSY goto the rename logic BB */ |
812 | } | 806 | } |
813 | } | 807 | } |
814 | } | 808 | } |
815 | if (direntry->d_inode) { | ||
816 | cifsInode = CIFS_I(direntry->d_inode); | ||
817 | cifsInode->time = 0; /* will force revalidate to get info | ||
818 | when needed */ | ||
819 | direntry->d_inode->i_ctime = current_fs_time(inode->i_sb); | ||
820 | } | ||
821 | if (inode) { | 809 | if (inode) { |
822 | inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb); | ||
823 | cifsInode = CIFS_I(inode); | 810 | cifsInode = CIFS_I(inode); |
824 | cifsInode->time = 0; /* force revalidate of dir as well */ | 811 | cifsInode->time = 0; /* will force revalidate to get info |
812 | when needed */ | ||
813 | inode->i_ctime = current_fs_time(sb); | ||
825 | } | 814 | } |
815 | dir->i_ctime = dir->i_mtime = current_fs_time(sb); | ||
816 | cifsInode = CIFS_I(dir); | ||
817 | cifsInode->time = 0; /* force revalidate of dir as well */ | ||
826 | 818 | ||
827 | kfree(full_path); | 819 | kfree(full_path); |
828 | FreeXid(xid); | 820 | FreeXid(xid); |