aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2008-09-16 19:50:58 -0400
committerSteve French <sfrench@us.ibm.com>2008-09-16 19:50:58 -0400
commit388e57b2759672a3e3ede0d2f7e95124b417b0a3 (patch)
tree19ed097fb752aec1983435f43e3a64612939beb1
parent5f0319a79043457d2555f059fac68c1d840ce381 (diff)
[CIFS] use common code for turning off ATTR_READONLY in cifs_unlink
We already have a cifs_set_file_info function that can flip DOS attribute bits. Have cifs_unlink call it to handle turning ATTR_HIDDEN on and ATTR_READONLY off when an unlink attempt returns -EACCES. This also removes a level of indentation from cifs_unlink. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
-rw-r--r--fs/cifs/inode.c306
1 files changed, 139 insertions, 167 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 511c52616794..8dbc7c90309c 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -665,6 +665,101 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
665 return inode; 665 return inode;
666} 666}
667 667
668static int
669cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
670 char *full_path, __u32 dosattr)
671{
672 int rc;
673 int oplock = 0;
674 __u16 netfid;
675 __u32 netpid;
676 bool set_time = false;
677 struct cifsFileInfo *open_file;
678 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
679 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
680 struct cifsTconInfo *pTcon = cifs_sb->tcon;
681 FILE_BASIC_INFO info_buf;
682
683 if (attrs->ia_valid & ATTR_ATIME) {
684 set_time = true;
685 info_buf.LastAccessTime =
686 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
687 } else
688 info_buf.LastAccessTime = 0;
689
690 if (attrs->ia_valid & ATTR_MTIME) {
691 set_time = true;
692 info_buf.LastWriteTime =
693 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
694 } else
695 info_buf.LastWriteTime = 0;
696
697 /*
698 * Samba throws this field away, but windows may actually use it.
699 * Do not set ctime unless other time stamps are changed explicitly
700 * (i.e. by utimes()) since we would then have a mix of client and
701 * server times.
702 */
703 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
704 cFYI(1, ("CIFS - CTIME changed"));
705 info_buf.ChangeTime =
706 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
707 } else
708 info_buf.ChangeTime = 0;
709
710 info_buf.CreationTime = 0; /* don't change */
711 info_buf.Attributes = cpu_to_le32(dosattr);
712
713 /*
714 * If the file is already open for write, just use that fileid
715 */
716 open_file = find_writable_file(cifsInode);
717 if (open_file) {
718 netfid = open_file->netfid;
719 netpid = open_file->pid;
720 goto set_via_filehandle;
721 }
722
723 /*
724 * NT4 apparently returns success on this call, but it doesn't
725 * really work.
726 */
727 if (!(pTcon->ses->flags & CIFS_SES_NT4)) {
728 rc = CIFSSMBSetPathInfo(xid, pTcon, full_path,
729 &info_buf, cifs_sb->local_nls,
730 cifs_sb->mnt_cifs_flags &
731 CIFS_MOUNT_MAP_SPECIAL_CHR);
732 if (rc != -EOPNOTSUPP && rc != -EINVAL)
733 goto out;
734 }
735
736 cFYI(1, ("calling SetFileInfo since SetPathInfo for "
737 "times not supported by this server"));
738 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
739 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
740 CREATE_NOT_DIR, &netfid, &oplock,
741 NULL, cifs_sb->local_nls,
742 cifs_sb->mnt_cifs_flags &
743 CIFS_MOUNT_MAP_SPECIAL_CHR);
744
745 if (rc != 0) {
746 if (rc == -EIO)
747 rc = -EINVAL;
748 goto out;
749 }
750
751 netpid = current->tgid;
752
753set_via_filehandle:
754 rc = CIFSSMBSetFileInfo(xid, pTcon, &info_buf, netfid, netpid);
755 if (open_file == NULL)
756 CIFSSMBClose(xid, pTcon, netfid);
757 else
758 atomic_dec(&open_file->wrtPending);
759out:
760 return rc;
761}
762
668int cifs_unlink(struct inode *dir, struct dentry *dentry) 763int cifs_unlink(struct inode *dir, struct dentry *dentry)
669{ 764{
670 int rc = 0; 765 int rc = 0;
@@ -675,7 +770,8 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
675 struct super_block *sb = dir->i_sb; 770 struct super_block *sb = dir->i_sb;
676 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 771 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
677 struct cifsTconInfo *tcon = cifs_sb->tcon; 772 struct cifsTconInfo *tcon = cifs_sb->tcon;
678 FILE_BASIC_INFO *pinfo_buf; 773 struct iattr *attrs;
774 __u32 dosattr;
679 775
680 cFYI(1, ("cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry)); 776 cFYI(1, ("cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry));
681 777
@@ -728,84 +824,55 @@ psx_del_no_retry:
728 } 824 }
729 } else if (rc == -EACCES) { 825 } else if (rc == -EACCES) {
730 /* try only if r/o attribute set in local lookup data? */ 826 /* try only if r/o attribute set in local lookup data? */
731 pinfo_buf = kzalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL); 827 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
732 if (pinfo_buf) { 828 if (attrs == NULL) {
733 /* ATTRS set to normal clears r/o bit */ 829 rc = -ENOMEM;
734 pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL); 830 goto out_reval;
735 if (!(tcon->ses->flags & CIFS_SES_NT4))
736 rc = CIFSSMBSetPathInfo(xid, tcon, full_path,
737 pinfo_buf,
738 cifs_sb->local_nls,
739 cifs_sb->mnt_cifs_flags &
740 CIFS_MOUNT_MAP_SPECIAL_CHR);
741 else
742 rc = -EOPNOTSUPP;
743
744 if (rc == -EOPNOTSUPP) {
745 int oplock = 0;
746 __u16 netfid;
747 /* rc = CIFSSMBSetAttrLegacy(xid, tcon,
748 full_path,
749 (__u16)ATTR_NORMAL,
750 cifs_sb->local_nls);
751 For some strange reason it seems that NT4 eats the
752 old setattr call without actually setting the
753 attributes so on to the third attempted workaround
754 */
755
756 /* BB could scan to see if we already have it open
757 and pass in pid of opener to function */
758 rc = CIFSSMBOpen(xid, tcon, full_path,
759 FILE_OPEN, SYNCHRONIZE |
760 FILE_WRITE_ATTRIBUTES, 0,
761 &netfid, &oplock, NULL,
762 cifs_sb->local_nls,
763 cifs_sb->mnt_cifs_flags &
764 CIFS_MOUNT_MAP_SPECIAL_CHR);
765 if (rc == 0) {
766 rc = CIFSSMBSetFileInfo(xid, tcon,
767 pinfo_buf,
768 netfid,
769 current->tgid);
770 CIFSSMBClose(xid, tcon, netfid);
771 }
772 }
773 kfree(pinfo_buf);
774 } 831 }
832
833 /* try to reset dos attributes */
834 cifsInode = CIFS_I(inode);
835 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
836 if (dosattr == 0)
837 dosattr |= ATTR_NORMAL;
838 dosattr |= ATTR_HIDDEN;
839
840 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
841 kfree(attrs);
842 if (rc != 0)
843 goto out_reval;
844 rc = CIFSSMBDelFile(xid, tcon, full_path, cifs_sb->local_nls,
845 cifs_sb->mnt_cifs_flags &
846 CIFS_MOUNT_MAP_SPECIAL_CHR);
775 if (rc == 0) { 847 if (rc == 0) {
776 rc = CIFSSMBDelFile(xid, tcon, full_path, 848 if (inode)
777 cifs_sb->local_nls, 849 drop_nlink(inode);
778 cifs_sb->mnt_cifs_flags & 850 } else if (rc == -ETXTBSY) {
779 CIFS_MOUNT_MAP_SPECIAL_CHR); 851 int oplock = 0;
780 if (!rc) { 852 __u16 netfid;
853
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);
781 if (inode) 869 if (inode)
782 drop_nlink(inode); 870 drop_nlink(inode);
783 } else if (rc == -ETXTBSY) {
784 int oplock = 0;
785 __u16 netfid;
786
787 rc = CIFSSMBOpen(xid, tcon, full_path,
788 FILE_OPEN, DELETE,
789 CREATE_NOT_DIR |
790 CREATE_DELETE_ON_CLOSE,
791 &netfid, &oplock, NULL,
792 cifs_sb->local_nls,
793 cifs_sb->mnt_cifs_flags &
794 CIFS_MOUNT_MAP_SPECIAL_CHR);
795 if (rc == 0) {
796 CIFSSMBRenameOpenFile(xid, tcon,
797 netfid, NULL,
798 cifs_sb->local_nls,
799 cifs_sb->mnt_cifs_flags &
800 CIFS_MOUNT_MAP_SPECIAL_CHR);
801 CIFSSMBClose(xid, tcon, netfid);
802 if (inode)
803 drop_nlink(inode);
804 }
805 /* BB if rc = -ETXTBUSY goto the rename logic BB */
806 } 871 }
872 /* BB if rc = -ETXTBUSY goto the rename logic BB */
807 } 873 }
808 } 874 }
875out_reval:
809 if (inode) { 876 if (inode) {
810 cifsInode = CIFS_I(inode); 877 cifsInode = CIFS_I(inode);
811 cifsInode->time = 0; /* will force revalidate to get info 878 cifsInode->time = 0; /* will force revalidate to get info
@@ -1499,101 +1566,6 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
1499} 1566}
1500 1567
1501static int 1568static int
1502cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
1503 char *full_path, __u32 dosattr)
1504{
1505 int rc;
1506 int oplock = 0;
1507 __u16 netfid;
1508 __u32 netpid;
1509 bool set_time = false;
1510 struct cifsFileInfo *open_file;
1511 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1512 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1513 struct cifsTconInfo *pTcon = cifs_sb->tcon;
1514 FILE_BASIC_INFO info_buf;
1515
1516 if (attrs->ia_valid & ATTR_ATIME) {
1517 set_time = true;
1518 info_buf.LastAccessTime =
1519 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
1520 } else
1521 info_buf.LastAccessTime = 0;
1522
1523 if (attrs->ia_valid & ATTR_MTIME) {
1524 set_time = true;
1525 info_buf.LastWriteTime =
1526 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
1527 } else
1528 info_buf.LastWriteTime = 0;
1529
1530 /*
1531 * Samba throws this field away, but windows may actually use it.
1532 * Do not set ctime unless other time stamps are changed explicitly
1533 * (i.e. by utimes()) since we would then have a mix of client and
1534 * server times.
1535 */
1536 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
1537 cFYI(1, ("CIFS - CTIME changed"));
1538 info_buf.ChangeTime =
1539 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
1540 } else
1541 info_buf.ChangeTime = 0;
1542
1543 info_buf.CreationTime = 0; /* don't change */
1544 info_buf.Attributes = cpu_to_le32(dosattr);
1545
1546 /*
1547 * If the file is already open for write, just use that fileid
1548 */
1549 open_file = find_writable_file(cifsInode);
1550 if (open_file) {
1551 netfid = open_file->netfid;
1552 netpid = open_file->pid;
1553 goto set_via_filehandle;
1554 }
1555
1556 /*
1557 * NT4 apparently returns success on this call, but it doesn't
1558 * really work.
1559 */
1560 if (!(pTcon->ses->flags & CIFS_SES_NT4)) {
1561 rc = CIFSSMBSetPathInfo(xid, pTcon, full_path,
1562 &info_buf, cifs_sb->local_nls,
1563 cifs_sb->mnt_cifs_flags &
1564 CIFS_MOUNT_MAP_SPECIAL_CHR);
1565 if (rc != -EOPNOTSUPP && rc != -EINVAL)
1566 goto out;
1567 }
1568
1569 cFYI(1, ("calling SetFileInfo since SetPathInfo for "
1570 "times not supported by this server"));
1571 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
1572 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
1573 CREATE_NOT_DIR, &netfid, &oplock,
1574 NULL, cifs_sb->local_nls,
1575 cifs_sb->mnt_cifs_flags &
1576 CIFS_MOUNT_MAP_SPECIAL_CHR);
1577
1578 if (rc != 0) {
1579 if (rc == -EIO)
1580 rc = -EINVAL;
1581 goto out;
1582 }
1583
1584 netpid = current->tgid;
1585
1586set_via_filehandle:
1587 rc = CIFSSMBSetFileInfo(xid, pTcon, &info_buf, netfid, netpid);
1588 if (open_file == NULL)
1589 CIFSSMBClose(xid, pTcon, netfid);
1590 else
1591 atomic_dec(&open_file->wrtPending);
1592out:
1593 return rc;
1594}
1595
1596static int
1597cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) 1569cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
1598{ 1570{
1599 int rc; 1571 int rc;