diff options
Diffstat (limited to 'fs/xfs/xfs_vnodeops.c')
-rw-r--r-- | fs/xfs/xfs_vnodeops.c | 95 |
1 files changed, 64 insertions, 31 deletions
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 25a526629b12..1377c868f3f4 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. | 2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms of version 2 of the GNU General Public License as | 5 | * under the terms of version 2 of the GNU General Public License as |
@@ -351,21 +351,28 @@ xfs_setattr( | |||
351 | * If the IDs do change before we take the ilock, we're covered | 351 | * If the IDs do change before we take the ilock, we're covered |
352 | * because the i_*dquot fields will get updated anyway. | 352 | * because the i_*dquot fields will get updated anyway. |
353 | */ | 353 | */ |
354 | if (XFS_IS_QUOTA_ON(mp) && (mask & (XFS_AT_UID|XFS_AT_GID))) { | 354 | if (XFS_IS_QUOTA_ON(mp) && |
355 | (mask & (XFS_AT_UID|XFS_AT_GID|XFS_AT_PROJID))) { | ||
355 | uint qflags = 0; | 356 | uint qflags = 0; |
356 | 357 | ||
357 | if (mask & XFS_AT_UID) { | 358 | if ((mask & XFS_AT_UID) && XFS_IS_UQUOTA_ON(mp)) { |
358 | uid = vap->va_uid; | 359 | uid = vap->va_uid; |
359 | qflags |= XFS_QMOPT_UQUOTA; | 360 | qflags |= XFS_QMOPT_UQUOTA; |
360 | } else { | 361 | } else { |
361 | uid = ip->i_d.di_uid; | 362 | uid = ip->i_d.di_uid; |
362 | } | 363 | } |
363 | if (mask & XFS_AT_GID) { | 364 | if ((mask & XFS_AT_GID) && XFS_IS_GQUOTA_ON(mp)) { |
364 | gid = vap->va_gid; | 365 | gid = vap->va_gid; |
365 | qflags |= XFS_QMOPT_GQUOTA; | 366 | qflags |= XFS_QMOPT_GQUOTA; |
366 | } else { | 367 | } else { |
367 | gid = ip->i_d.di_gid; | 368 | gid = ip->i_d.di_gid; |
368 | } | 369 | } |
370 | if ((mask & XFS_AT_PROJID) && XFS_IS_PQUOTA_ON(mp)) { | ||
371 | projid = vap->va_projid; | ||
372 | qflags |= XFS_QMOPT_PQUOTA; | ||
373 | } else { | ||
374 | projid = ip->i_d.di_projid; | ||
375 | } | ||
369 | /* | 376 | /* |
370 | * We take a reference when we initialize udqp and gdqp, | 377 | * We take a reference when we initialize udqp and gdqp, |
371 | * so it is important that we never blindly double trip on | 378 | * so it is important that we never blindly double trip on |
@@ -373,7 +380,8 @@ xfs_setattr( | |||
373 | */ | 380 | */ |
374 | ASSERT(udqp == NULL); | 381 | ASSERT(udqp == NULL); |
375 | ASSERT(gdqp == NULL); | 382 | ASSERT(gdqp == NULL); |
376 | code = XFS_QM_DQVOPALLOC(mp, ip, uid,gid, qflags, &udqp, &gdqp); | 383 | code = XFS_QM_DQVOPALLOC(mp, ip, uid, gid, projid, qflags, |
384 | &udqp, &gdqp); | ||
377 | if (code) | 385 | if (code) |
378 | return (code); | 386 | return (code); |
379 | } | 387 | } |
@@ -499,8 +507,6 @@ xfs_setattr( | |||
499 | * that the group ID supplied to the chown() function | 507 | * that the group ID supplied to the chown() function |
500 | * shall be equal to either the group ID or one of the | 508 | * shall be equal to either the group ID or one of the |
501 | * supplementary group IDs of the calling process. | 509 | * supplementary group IDs of the calling process. |
502 | * | ||
503 | * XXX: How does restricted_chown affect projid? | ||
504 | */ | 510 | */ |
505 | if (restricted_chown && | 511 | if (restricted_chown && |
506 | (iuid != uid || (igid != gid && | 512 | (iuid != uid || (igid != gid && |
@@ -510,10 +516,11 @@ xfs_setattr( | |||
510 | goto error_return; | 516 | goto error_return; |
511 | } | 517 | } |
512 | /* | 518 | /* |
513 | * Do a quota reservation only if uid or gid is actually | 519 | * Do a quota reservation only if uid/projid/gid is actually |
514 | * going to change. | 520 | * going to change. |
515 | */ | 521 | */ |
516 | if ((XFS_IS_UQUOTA_ON(mp) && iuid != uid) || | 522 | if ((XFS_IS_UQUOTA_ON(mp) && iuid != uid) || |
523 | (XFS_IS_PQUOTA_ON(mp) && iprojid != projid) || | ||
517 | (XFS_IS_GQUOTA_ON(mp) && igid != gid)) { | 524 | (XFS_IS_GQUOTA_ON(mp) && igid != gid)) { |
518 | ASSERT(tp); | 525 | ASSERT(tp); |
519 | code = XFS_QM_DQVOPCHOWNRESV(mp, tp, ip, udqp, gdqp, | 526 | code = XFS_QM_DQVOPCHOWNRESV(mp, tp, ip, udqp, gdqp, |
@@ -774,6 +781,7 @@ xfs_setattr( | |||
774 | } | 781 | } |
775 | if (igid != gid) { | 782 | if (igid != gid) { |
776 | if (XFS_IS_GQUOTA_ON(mp)) { | 783 | if (XFS_IS_GQUOTA_ON(mp)) { |
784 | ASSERT(!XFS_IS_PQUOTA_ON(mp)); | ||
777 | ASSERT(mask & XFS_AT_GID); | 785 | ASSERT(mask & XFS_AT_GID); |
778 | ASSERT(gdqp); | 786 | ASSERT(gdqp); |
779 | olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip, | 787 | olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip, |
@@ -782,6 +790,13 @@ xfs_setattr( | |||
782 | ip->i_d.di_gid = gid; | 790 | ip->i_d.di_gid = gid; |
783 | } | 791 | } |
784 | if (iprojid != projid) { | 792 | if (iprojid != projid) { |
793 | if (XFS_IS_PQUOTA_ON(mp)) { | ||
794 | ASSERT(!XFS_IS_GQUOTA_ON(mp)); | ||
795 | ASSERT(mask & XFS_AT_PROJID); | ||
796 | ASSERT(gdqp); | ||
797 | olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip, | ||
798 | &ip->i_gdquot, gdqp); | ||
799 | } | ||
785 | ip->i_d.di_projid = projid; | 800 | ip->i_d.di_projid = projid; |
786 | /* | 801 | /* |
787 | * We may have to rev the inode as well as | 802 | * We may have to rev the inode as well as |
@@ -843,6 +858,8 @@ xfs_setattr( | |||
843 | di_flags |= XFS_DIFLAG_NOATIME; | 858 | di_flags |= XFS_DIFLAG_NOATIME; |
844 | if (vap->va_xflags & XFS_XFLAG_NODUMP) | 859 | if (vap->va_xflags & XFS_XFLAG_NODUMP) |
845 | di_flags |= XFS_DIFLAG_NODUMP; | 860 | di_flags |= XFS_DIFLAG_NODUMP; |
861 | if (vap->va_xflags & XFS_XFLAG_PROJINHERIT) | ||
862 | di_flags |= XFS_DIFLAG_PROJINHERIT; | ||
846 | if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) { | 863 | if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) { |
847 | if (vap->va_xflags & XFS_XFLAG_RTINHERIT) | 864 | if (vap->va_xflags & XFS_XFLAG_RTINHERIT) |
848 | di_flags |= XFS_DIFLAG_RTINHERIT; | 865 | di_flags |= XFS_DIFLAG_RTINHERIT; |
@@ -1898,7 +1915,9 @@ xfs_create( | |||
1898 | /* Return through std_return after this point. */ | 1915 | /* Return through std_return after this point. */ |
1899 | 1916 | ||
1900 | udqp = gdqp = NULL; | 1917 | udqp = gdqp = NULL; |
1901 | if (vap->va_mask & XFS_AT_PROJID) | 1918 | if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) |
1919 | prid = dp->i_d.di_projid; | ||
1920 | else if (vap->va_mask & XFS_AT_PROJID) | ||
1902 | prid = (xfs_prid_t)vap->va_projid; | 1921 | prid = (xfs_prid_t)vap->va_projid; |
1903 | else | 1922 | else |
1904 | prid = (xfs_prid_t)dfltprid; | 1923 | prid = (xfs_prid_t)dfltprid; |
@@ -1907,7 +1926,7 @@ xfs_create( | |||
1907 | * Make sure that we have allocated dquot(s) on disk. | 1926 | * Make sure that we have allocated dquot(s) on disk. |
1908 | */ | 1927 | */ |
1909 | error = XFS_QM_DQVOPALLOC(mp, dp, | 1928 | error = XFS_QM_DQVOPALLOC(mp, dp, |
1910 | current_fsuid(credp), current_fsgid(credp), | 1929 | current_fsuid(credp), current_fsgid(credp), prid, |
1911 | XFS_QMOPT_QUOTALL|XFS_QMOPT_INHERIT, &udqp, &gdqp); | 1930 | XFS_QMOPT_QUOTALL|XFS_QMOPT_INHERIT, &udqp, &gdqp); |
1912 | if (error) | 1931 | if (error) |
1913 | goto std_return; | 1932 | goto std_return; |
@@ -2604,17 +2623,7 @@ xfs_link( | |||
2604 | if (src_vp->v_type == VDIR) | 2623 | if (src_vp->v_type == VDIR) |
2605 | return XFS_ERROR(EPERM); | 2624 | return XFS_ERROR(EPERM); |
2606 | 2625 | ||
2607 | /* | ||
2608 | * For now, manually find the XFS behavior descriptor for | ||
2609 | * the source vnode. If it doesn't exist then something | ||
2610 | * is wrong and we should just return an error. | ||
2611 | * Eventually we need to figure out how link is going to | ||
2612 | * work in the face of stacked vnodes. | ||
2613 | */ | ||
2614 | src_bdp = vn_bhv_lookup_unlocked(VN_BHV_HEAD(src_vp), &xfs_vnodeops); | 2626 | src_bdp = vn_bhv_lookup_unlocked(VN_BHV_HEAD(src_vp), &xfs_vnodeops); |
2615 | if (src_bdp == NULL) { | ||
2616 | return XFS_ERROR(EXDEV); | ||
2617 | } | ||
2618 | sip = XFS_BHVTOI(src_bdp); | 2627 | sip = XFS_BHVTOI(src_bdp); |
2619 | tdp = XFS_BHVTOI(target_dir_bdp); | 2628 | tdp = XFS_BHVTOI(target_dir_bdp); |
2620 | mp = tdp->i_mount; | 2629 | mp = tdp->i_mount; |
@@ -2681,6 +2690,17 @@ xfs_link( | |||
2681 | goto error_return; | 2690 | goto error_return; |
2682 | } | 2691 | } |
2683 | 2692 | ||
2693 | /* | ||
2694 | * If we are using project inheritance, we only allow hard link | ||
2695 | * creation in our tree when the project IDs are the same; else | ||
2696 | * the tree quota mechanism could be circumvented. | ||
2697 | */ | ||
2698 | if (unlikely((tdp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) && | ||
2699 | (tdp->i_d.di_projid != sip->i_d.di_projid))) { | ||
2700 | error = XFS_ERROR(EPERM); | ||
2701 | goto error_return; | ||
2702 | } | ||
2703 | |||
2684 | if (resblks == 0 && | 2704 | if (resblks == 0 && |
2685 | (error = XFS_DIR_CANENTER(mp, tp, tdp, target_name, | 2705 | (error = XFS_DIR_CANENTER(mp, tp, tdp, target_name, |
2686 | target_namelen))) | 2706 | target_namelen))) |
@@ -2803,7 +2823,9 @@ xfs_mkdir( | |||
2803 | 2823 | ||
2804 | mp = dp->i_mount; | 2824 | mp = dp->i_mount; |
2805 | udqp = gdqp = NULL; | 2825 | udqp = gdqp = NULL; |
2806 | if (vap->va_mask & XFS_AT_PROJID) | 2826 | if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) |
2827 | prid = dp->i_d.di_projid; | ||
2828 | else if (vap->va_mask & XFS_AT_PROJID) | ||
2807 | prid = (xfs_prid_t)vap->va_projid; | 2829 | prid = (xfs_prid_t)vap->va_projid; |
2808 | else | 2830 | else |
2809 | prid = (xfs_prid_t)dfltprid; | 2831 | prid = (xfs_prid_t)dfltprid; |
@@ -2812,7 +2834,7 @@ xfs_mkdir( | |||
2812 | * Make sure that we have allocated dquot(s) on disk. | 2834 | * Make sure that we have allocated dquot(s) on disk. |
2813 | */ | 2835 | */ |
2814 | error = XFS_QM_DQVOPALLOC(mp, dp, | 2836 | error = XFS_QM_DQVOPALLOC(mp, dp, |
2815 | current_fsuid(credp), current_fsgid(credp), | 2837 | current_fsuid(credp), current_fsgid(credp), prid, |
2816 | XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); | 2838 | XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); |
2817 | if (error) | 2839 | if (error) |
2818 | goto std_return; | 2840 | goto std_return; |
@@ -3357,7 +3379,9 @@ xfs_symlink( | |||
3357 | /* Return through std_return after this point. */ | 3379 | /* Return through std_return after this point. */ |
3358 | 3380 | ||
3359 | udqp = gdqp = NULL; | 3381 | udqp = gdqp = NULL; |
3360 | if (vap->va_mask & XFS_AT_PROJID) | 3382 | if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) |
3383 | prid = dp->i_d.di_projid; | ||
3384 | else if (vap->va_mask & XFS_AT_PROJID) | ||
3361 | prid = (xfs_prid_t)vap->va_projid; | 3385 | prid = (xfs_prid_t)vap->va_projid; |
3362 | else | 3386 | else |
3363 | prid = (xfs_prid_t)dfltprid; | 3387 | prid = (xfs_prid_t)dfltprid; |
@@ -3366,7 +3390,7 @@ xfs_symlink( | |||
3366 | * Make sure that we have allocated dquot(s) on disk. | 3390 | * Make sure that we have allocated dquot(s) on disk. |
3367 | */ | 3391 | */ |
3368 | error = XFS_QM_DQVOPALLOC(mp, dp, | 3392 | error = XFS_QM_DQVOPALLOC(mp, dp, |
3369 | current_fsuid(credp), current_fsgid(credp), | 3393 | current_fsuid(credp), current_fsgid(credp), prid, |
3370 | XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); | 3394 | XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); |
3371 | if (error) | 3395 | if (error) |
3372 | goto std_return; | 3396 | goto std_return; |
@@ -4028,7 +4052,7 @@ xfs_finish_reclaim_all(xfs_mount_t *mp, int noblock) | |||
4028 | * errno on error | 4052 | * errno on error |
4029 | * | 4053 | * |
4030 | */ | 4054 | */ |
4031 | int | 4055 | STATIC int |
4032 | xfs_alloc_file_space( | 4056 | xfs_alloc_file_space( |
4033 | xfs_inode_t *ip, | 4057 | xfs_inode_t *ip, |
4034 | xfs_off_t offset, | 4058 | xfs_off_t offset, |
@@ -4151,9 +4175,8 @@ retry: | |||
4151 | break; | 4175 | break; |
4152 | } | 4176 | } |
4153 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 4177 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
4154 | error = XFS_TRANS_RESERVE_QUOTA_BYDQUOTS(mp, tp, | 4178 | error = XFS_TRANS_RESERVE_QUOTA(mp, tp, |
4155 | ip->i_udquot, ip->i_gdquot, resblks, 0, rt ? | 4179 | ip->i_udquot, ip->i_gdquot, resblks, 0, 0); |
4156 | XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS); | ||
4157 | if (error) | 4180 | if (error) |
4158 | goto error1; | 4181 | goto error1; |
4159 | 4182 | ||
@@ -4305,6 +4328,7 @@ xfs_free_file_space( | |||
4305 | xfs_off_t len, | 4328 | xfs_off_t len, |
4306 | int attr_flags) | 4329 | int attr_flags) |
4307 | { | 4330 | { |
4331 | vnode_t *vp; | ||
4308 | int committed; | 4332 | int committed; |
4309 | int done; | 4333 | int done; |
4310 | xfs_off_t end_dmi_offset; | 4334 | xfs_off_t end_dmi_offset; |
@@ -4325,9 +4349,11 @@ xfs_free_file_space( | |||
4325 | xfs_trans_t *tp; | 4349 | xfs_trans_t *tp; |
4326 | int need_iolock = 1; | 4350 | int need_iolock = 1; |
4327 | 4351 | ||
4328 | vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address); | 4352 | vp = XFS_ITOV(ip); |
4329 | mp = ip->i_mount; | 4353 | mp = ip->i_mount; |
4330 | 4354 | ||
4355 | vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); | ||
4356 | |||
4331 | if ((error = XFS_QM_DQATTACH(mp, ip, 0))) | 4357 | if ((error = XFS_QM_DQATTACH(mp, ip, 0))) |
4332 | return error; | 4358 | return error; |
4333 | 4359 | ||
@@ -4344,7 +4370,7 @@ xfs_free_file_space( | |||
4344 | DM_EVENT_ENABLED(XFS_MTOVFS(mp), ip, DM_EVENT_WRITE)) { | 4370 | DM_EVENT_ENABLED(XFS_MTOVFS(mp), ip, DM_EVENT_WRITE)) { |
4345 | if (end_dmi_offset > ip->i_d.di_size) | 4371 | if (end_dmi_offset > ip->i_d.di_size) |
4346 | end_dmi_offset = ip->i_d.di_size; | 4372 | end_dmi_offset = ip->i_d.di_size; |
4347 | error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, XFS_ITOV(ip), | 4373 | error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, vp, |
4348 | offset, end_dmi_offset - offset, | 4374 | offset, end_dmi_offset - offset, |
4349 | AT_DELAY_FLAG(attr_flags), NULL); | 4375 | AT_DELAY_FLAG(attr_flags), NULL); |
4350 | if (error) | 4376 | if (error) |
@@ -4363,7 +4389,14 @@ xfs_free_file_space( | |||
4363 | ioffset = offset & ~(rounding - 1); | 4389 | ioffset = offset & ~(rounding - 1); |
4364 | if (ilen & (rounding - 1)) | 4390 | if (ilen & (rounding - 1)) |
4365 | ilen = (ilen + rounding) & ~(rounding - 1); | 4391 | ilen = (ilen + rounding) & ~(rounding - 1); |
4366 | xfs_inval_cached_pages(XFS_ITOV(ip), &(ip->i_iocore), ioffset, 0, 0); | 4392 | |
4393 | if (VN_CACHED(vp) != 0) { | ||
4394 | xfs_inval_cached_trace(&ip->i_iocore, ioffset, -1, | ||
4395 | ctooff(offtoct(ioffset)), -1); | ||
4396 | VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(ioffset)), | ||
4397 | -1, FI_REMAPF_LOCKED); | ||
4398 | } | ||
4399 | |||
4367 | /* | 4400 | /* |
4368 | * Need to zero the stuff we're not freeing, on disk. | 4401 | * Need to zero the stuff we're not freeing, on disk. |
4369 | * If its a realtime file & can't use unwritten extents then we | 4402 | * If its a realtime file & can't use unwritten extents then we |