diff options
Diffstat (limited to 'fs/xfs/xfs_iops.c')
-rw-r--r-- | fs/xfs/xfs_iops.c | 94 |
1 files changed, 63 insertions, 31 deletions
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index f4cd7204e236..4e4d6511185b 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c | |||
@@ -537,6 +537,30 @@ xfs_setattr_time( | |||
537 | } | 537 | } |
538 | } | 538 | } |
539 | 539 | ||
540 | static int | ||
541 | xfs_vn_change_ok( | ||
542 | struct dentry *dentry, | ||
543 | struct iattr *iattr) | ||
544 | { | ||
545 | struct inode *inode = d_inode(dentry); | ||
546 | struct xfs_inode *ip = XFS_I(inode); | ||
547 | struct xfs_mount *mp = ip->i_mount; | ||
548 | |||
549 | if (mp->m_flags & XFS_MOUNT_RDONLY) | ||
550 | return -EROFS; | ||
551 | |||
552 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
553 | return -EIO; | ||
554 | |||
555 | return setattr_prepare(dentry, iattr); | ||
556 | } | ||
557 | |||
558 | /* | ||
559 | * Set non-size attributes of an inode. | ||
560 | * | ||
561 | * Caution: The caller of this function is responsible for calling | ||
562 | * setattr_prepare() or otherwise verifying the change is fine. | ||
563 | */ | ||
540 | int | 564 | int |
541 | xfs_setattr_nonsize( | 565 | xfs_setattr_nonsize( |
542 | struct xfs_inode *ip, | 566 | struct xfs_inode *ip, |
@@ -553,21 +577,6 @@ xfs_setattr_nonsize( | |||
553 | struct xfs_dquot *udqp = NULL, *gdqp = NULL; | 577 | struct xfs_dquot *udqp = NULL, *gdqp = NULL; |
554 | struct xfs_dquot *olddquot1 = NULL, *olddquot2 = NULL; | 578 | struct xfs_dquot *olddquot1 = NULL, *olddquot2 = NULL; |
555 | 579 | ||
556 | trace_xfs_setattr(ip); | ||
557 | |||
558 | /* If acls are being inherited, we already have this checked */ | ||
559 | if (!(flags & XFS_ATTR_NOACL)) { | ||
560 | if (mp->m_flags & XFS_MOUNT_RDONLY) | ||
561 | return -EROFS; | ||
562 | |||
563 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
564 | return -EIO; | ||
565 | |||
566 | error = inode_change_ok(inode, iattr); | ||
567 | if (error) | ||
568 | return error; | ||
569 | } | ||
570 | |||
571 | ASSERT((mask & ATTR_SIZE) == 0); | 580 | ASSERT((mask & ATTR_SIZE) == 0); |
572 | 581 | ||
573 | /* | 582 | /* |
@@ -741,8 +750,27 @@ out_dqrele: | |||
741 | return error; | 750 | return error; |
742 | } | 751 | } |
743 | 752 | ||
753 | int | ||
754 | xfs_vn_setattr_nonsize( | ||
755 | struct dentry *dentry, | ||
756 | struct iattr *iattr) | ||
757 | { | ||
758 | struct xfs_inode *ip = XFS_I(d_inode(dentry)); | ||
759 | int error; | ||
760 | |||
761 | trace_xfs_setattr(ip); | ||
762 | |||
763 | error = xfs_vn_change_ok(dentry, iattr); | ||
764 | if (error) | ||
765 | return error; | ||
766 | return xfs_setattr_nonsize(ip, iattr, 0); | ||
767 | } | ||
768 | |||
744 | /* | 769 | /* |
745 | * Truncate file. Must have write permission and not be a directory. | 770 | * Truncate file. Must have write permission and not be a directory. |
771 | * | ||
772 | * Caution: The caller of this function is responsible for calling | ||
773 | * setattr_prepare() or otherwise verifying the change is fine. | ||
746 | */ | 774 | */ |
747 | int | 775 | int |
748 | xfs_setattr_size( | 776 | xfs_setattr_size( |
@@ -758,18 +786,6 @@ xfs_setattr_size( | |||
758 | uint commit_flags = 0; | 786 | uint commit_flags = 0; |
759 | bool did_zeroing = false; | 787 | bool did_zeroing = false; |
760 | 788 | ||
761 | trace_xfs_setattr(ip); | ||
762 | |||
763 | if (mp->m_flags & XFS_MOUNT_RDONLY) | ||
764 | return -EROFS; | ||
765 | |||
766 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
767 | return -EIO; | ||
768 | |||
769 | error = inode_change_ok(inode, iattr); | ||
770 | if (error) | ||
771 | return error; | ||
772 | |||
773 | ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); | 789 | ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); |
774 | ASSERT(xfs_isilocked(ip, XFS_MMAPLOCK_EXCL)); | 790 | ASSERT(xfs_isilocked(ip, XFS_MMAPLOCK_EXCL)); |
775 | ASSERT(S_ISREG(ip->i_d.di_mode)); | 791 | ASSERT(S_ISREG(ip->i_d.di_mode)); |
@@ -941,16 +957,32 @@ out_trans_cancel: | |||
941 | goto out_unlock; | 957 | goto out_unlock; |
942 | } | 958 | } |
943 | 959 | ||
960 | int | ||
961 | xfs_vn_setattr_size( | ||
962 | struct dentry *dentry, | ||
963 | struct iattr *iattr) | ||
964 | { | ||
965 | struct xfs_inode *ip = XFS_I(d_inode(dentry)); | ||
966 | int error; | ||
967 | |||
968 | trace_xfs_setattr(ip); | ||
969 | |||
970 | error = xfs_vn_change_ok(dentry, iattr); | ||
971 | if (error) | ||
972 | return error; | ||
973 | return xfs_setattr_size(ip, iattr); | ||
974 | } | ||
975 | |||
944 | STATIC int | 976 | STATIC int |
945 | xfs_vn_setattr( | 977 | xfs_vn_setattr( |
946 | struct dentry *dentry, | 978 | struct dentry *dentry, |
947 | struct iattr *iattr) | 979 | struct iattr *iattr) |
948 | { | 980 | { |
949 | struct xfs_inode *ip = XFS_I(d_inode(dentry)); | ||
950 | int error; | 981 | int error; |
951 | 982 | ||
952 | if (iattr->ia_valid & ATTR_SIZE) { | 983 | if (iattr->ia_valid & ATTR_SIZE) { |
953 | uint iolock = XFS_IOLOCK_EXCL; | 984 | struct xfs_inode *ip = XFS_I(d_inode(dentry)); |
985 | uint iolock = XFS_IOLOCK_EXCL; | ||
954 | 986 | ||
955 | xfs_ilock(ip, iolock); | 987 | xfs_ilock(ip, iolock); |
956 | error = xfs_break_layouts(d_inode(dentry), &iolock, true); | 988 | error = xfs_break_layouts(d_inode(dentry), &iolock, true); |
@@ -958,11 +990,11 @@ xfs_vn_setattr( | |||
958 | xfs_ilock(ip, XFS_MMAPLOCK_EXCL); | 990 | xfs_ilock(ip, XFS_MMAPLOCK_EXCL); |
959 | iolock |= XFS_MMAPLOCK_EXCL; | 991 | iolock |= XFS_MMAPLOCK_EXCL; |
960 | 992 | ||
961 | error = xfs_setattr_size(ip, iattr); | 993 | error = xfs_vn_setattr_size(dentry, iattr); |
962 | } | 994 | } |
963 | xfs_iunlock(ip, iolock); | 995 | xfs_iunlock(ip, iolock); |
964 | } else { | 996 | } else { |
965 | error = xfs_setattr_nonsize(ip, iattr, 0); | 997 | error = xfs_vn_setattr_nonsize(dentry, iattr); |
966 | } | 998 | } |
967 | 999 | ||
968 | return error; | 1000 | return error; |