Commit 6743099ce57a40509a86849a22317ed4b7516911

Authored by Arkadiusz Mi?kiewicz
Committed by Alex Elder
1 parent 1a1a3e97ba

xfs: Extend project quotas to support 32bit project ids

This patch adds support for 32bit project quota identifiers.

On disk format is backward compatible with 16bit projid numbers. projid
on disk is now kept in two 16bit values - di_projid_lo (which holds the
same position as old 16bit projid value) and new di_projid_hi (takes
existing padding) and converts from/to 32bit value on the fly.

xfs_admin (for existing fs), mkfs.xfs (for new fs) needs to be used
to enable PROJID32BIT support.

Signed-off-by: Arkadiusz Miśkiewicz <arekm@maven.pl>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Alex Elder <aelder@sgi.com>

Showing 16 changed files with 80 additions and 44 deletions Side-by-side Diff

fs/xfs/linux-2.6/xfs_ioctl.c
... ... @@ -790,7 +790,7 @@
790 790 xfs_ilock(ip, XFS_ILOCK_SHARED);
791 791 fa.fsx_xflags = xfs_ip2xflags(ip);
792 792 fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog;
793   - fa.fsx_projid = ip->i_d.di_projid;
  793 + fa.fsx_projid = xfs_get_projid(ip);
794 794  
795 795 if (attr) {
796 796 if (ip->i_afp) {
797 797  
... ... @@ -909,10 +909,10 @@
909 909 return XFS_ERROR(EIO);
910 910  
911 911 /*
912   - * Disallow 32bit project ids because on-disk structure
913   - * is 16bit only.
  912 + * Disallow 32bit project ids when projid32bit feature is not enabled.
914 913 */
915   - if ((mask & FSX_PROJID) && (fa->fsx_projid > (__uint16_t)-1))
  914 + if ((mask & FSX_PROJID) && (fa->fsx_projid > (__uint16_t)-1) &&
  915 + !xfs_sb_version_hasprojid32bit(&ip->i_mount->m_sb))
916 916 return XFS_ERROR(EINVAL);
917 917  
918 918 /*
... ... @@ -961,7 +961,7 @@
961 961 if (mask & FSX_PROJID) {
962 962 if (XFS_IS_QUOTA_RUNNING(mp) &&
963 963 XFS_IS_PQUOTA_ON(mp) &&
964   - ip->i_d.di_projid != fa->fsx_projid) {
  964 + xfs_get_projid(ip) != fa->fsx_projid) {
965 965 ASSERT(tp);
966 966 code = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp,
967 967 capable(CAP_FOWNER) ?
968 968  
... ... @@ -1063,12 +1063,12 @@
1063 1063 * Change the ownerships and register quota modifications
1064 1064 * in the transaction.
1065 1065 */
1066   - if (ip->i_d.di_projid != fa->fsx_projid) {
  1066 + if (xfs_get_projid(ip) != fa->fsx_projid) {
1067 1067 if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp)) {
1068 1068 olddquot = xfs_qm_vop_chown(tp, ip,
1069 1069 &ip->i_gdquot, gdqp);
1070 1070 }
1071   - ip->i_d.di_projid = fa->fsx_projid;
  1071 + xfs_set_projid(ip, fa->fsx_projid);
1072 1072  
1073 1073 /*
1074 1074 * We may have to rev the inode as well as
fs/xfs/linux-2.6/xfs_ioctl32.c
... ... @@ -164,7 +164,8 @@
164 164 get_user(bstat->bs_extsize, &bstat32->bs_extsize) ||
165 165 get_user(bstat->bs_extents, &bstat32->bs_extents) ||
166 166 get_user(bstat->bs_gen, &bstat32->bs_gen) ||
167   - get_user(bstat->bs_projid, &bstat32->bs_projid) ||
  167 + get_user(bstat->bs_projid_lo, &bstat32->bs_projid_lo) ||
  168 + get_user(bstat->bs_projid_hi, &bstat32->bs_projid_hi) ||
168 169 get_user(bstat->bs_dmevmask, &bstat32->bs_dmevmask) ||
169 170 get_user(bstat->bs_dmstate, &bstat32->bs_dmstate) ||
170 171 get_user(bstat->bs_aextents, &bstat32->bs_aextents))
... ... @@ -218,6 +219,7 @@
218 219 put_user(buffer->bs_extents, &p32->bs_extents) ||
219 220 put_user(buffer->bs_gen, &p32->bs_gen) ||
220 221 put_user(buffer->bs_projid, &p32->bs_projid) ||
  222 + put_user(buffer->bs_projid_hi, &p32->bs_projid_hi) ||
221 223 put_user(buffer->bs_dmevmask, &p32->bs_dmevmask) ||
222 224 put_user(buffer->bs_dmstate, &p32->bs_dmstate) ||
223 225 put_user(buffer->bs_aextents, &p32->bs_aextents))
fs/xfs/linux-2.6/xfs_ioctl32.h
... ... @@ -65,8 +65,10 @@
65 65 __s32 bs_extsize; /* extent size */
66 66 __s32 bs_extents; /* number of extents */
67 67 __u32 bs_gen; /* generation count */
68   - __u16 bs_projid; /* project id */
69   - unsigned char bs_pad[14]; /* pad space, unused */
  68 + __u16 bs_projid_lo; /* lower part of project id */
  69 +#define bs_projid bs_projid_lo /* (previously just bs_projid) */
  70 + __u16 bs_projid_hi; /* high part of project id */
  71 + unsigned char bs_pad[12]; /* pad space, unused */
70 72 __u32 bs_dmevmask; /* DMIG event mask */
71 73 __u16 bs_dmstate; /* DMIG state info */
72 74 __u16 bs_aextents; /* attribute number of extents */
fs/xfs/linux-2.6/xfs_linux.h
... ... @@ -143,7 +143,7 @@
143 143 #define SYNCHRONIZE() barrier()
144 144 #define __return_address __builtin_return_address(0)
145 145  
146   -#define dfltprid 0
  146 +#define XFS_PROJID_DEFAULT 0
147 147 #define MAXPATHLEN 1024
148 148  
149 149 #define MIN(a,b) (min(a,b))
fs/xfs/quota/xfs_qm.c
... ... @@ -835,7 +835,7 @@
835 835 xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP,
836 836 flags & XFS_QMOPT_DQALLOC,
837 837 ip->i_udquot, &ip->i_gdquot) :
838   - xfs_qm_dqattach_one(ip, ip->i_d.di_projid, XFS_DQ_PROJ,
  838 + xfs_qm_dqattach_one(ip, xfs_get_projid(ip), XFS_DQ_PROJ,
839 839 flags & XFS_QMOPT_DQALLOC,
840 840 ip->i_udquot, &ip->i_gdquot);
841 841 /*
... ... @@ -1630,7 +1630,7 @@
1630 1630 }
1631 1631  
1632 1632 if (XFS_IS_PQUOTA_ON(mp)) {
1633   - error = xfs_qm_quotacheck_dqadjust(ip, ip->i_d.di_projid,
  1633 + error = xfs_qm_quotacheck_dqadjust(ip, xfs_get_projid(ip),
1634 1634 XFS_DQ_PROJ, nblks, rtblks);
1635 1635 if (error)
1636 1636 goto error0;
... ... @@ -2249,7 +2249,7 @@
2249 2249 xfs_dqunlock(gq);
2250 2250 }
2251 2251 } else if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) {
2252   - if (ip->i_d.di_projid != prid) {
  2252 + if (xfs_get_projid(ip) != prid) {
2253 2253 xfs_iunlock(ip, lockflags);
2254 2254 if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid,
2255 2255 XFS_DQ_PROJ,
... ... @@ -2371,7 +2371,7 @@
2371 2371 }
2372 2372 if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) {
2373 2373 if (XFS_IS_PQUOTA_ON(ip->i_mount) &&
2374   - ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id))
  2374 + xfs_get_projid(ip) != be32_to_cpu(gdqp->q_core.d_id))
2375 2375 prjflags = XFS_QMOPT_ENOSPC;
2376 2376  
2377 2377 if (prjflags ||
... ... @@ -2475,7 +2475,7 @@
2475 2475 ip->i_gdquot = gdqp;
2476 2476 ASSERT(XFS_IS_OQUOTA_ON(mp));
2477 2477 ASSERT((XFS_IS_GQUOTA_ON(mp) ?
2478   - ip->i_d.di_gid : ip->i_d.di_projid) ==
  2478 + ip->i_d.di_gid : xfs_get_projid(ip)) ==
2479 2479 be32_to_cpu(gdqp->q_core.d_id));
2480 2480 xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1);
2481 2481 }
fs/xfs/quota/xfs_qm_bhv.c
... ... @@ -81,7 +81,7 @@
81 81 xfs_mount_t *mp = ip->i_mount;
82 82 xfs_dquot_t *dqp;
83 83  
84   - if (!xfs_qm_dqget(mp, NULL, ip->i_d.di_projid, XFS_DQ_PROJ, 0, &dqp)) {
  84 + if (!xfs_qm_dqget(mp, NULL, xfs_get_projid(ip), XFS_DQ_PROJ, 0, &dqp)) {
85 85 xfs_fill_statvfs_from_dquot(statp, &dqp->q_core);
86 86 xfs_qm_dqput(dqp);
87 87 }
fs/xfs/quota/xfs_qm_syscalls.c
... ... @@ -1165,7 +1165,7 @@
1165 1165 }
1166 1166 xfs_qm_internalqcheck_get_dquots(mp,
1167 1167 (xfs_dqid_t) ip->i_d.di_uid,
1168   - (xfs_dqid_t) ip->i_d.di_projid,
  1168 + (xfs_dqid_t) xfs_get_projid(ip),
1169 1169 (xfs_dqid_t) ip->i_d.di_gid,
1170 1170 &ud, &gd);
1171 1171 if (XFS_IS_UQUOTA_ON(mp)) {
... ... @@ -49,8 +49,9 @@
49 49 __be32 di_uid; /* owner's user id */
50 50 __be32 di_gid; /* owner's group id */
51 51 __be32 di_nlink; /* number of links to file */
52   - __be16 di_projid; /* owner's project id */
53   - __u8 di_pad[8]; /* unused, zeroed space */
  52 + __be16 di_projid_lo; /* lower part of owner's project id */
  53 + __be16 di_projid_hi; /* higher part owner's project id */
  54 + __u8 di_pad[6]; /* unused, zeroed space */
54 55 __be16 di_flushiter; /* incremented on flush */
55 56 xfs_timestamp_t di_atime; /* time last accessed */
56 57 xfs_timestamp_t di_mtime; /* time last modified */
... ... @@ -293,9 +293,11 @@
293 293 __s32 bs_extsize; /* extent size */
294 294 __s32 bs_extents; /* number of extents */
295 295 __u32 bs_gen; /* generation count */
296   - __u16 bs_projid; /* project id */
  296 + __u16 bs_projid_lo; /* lower part of project id */
  297 +#define bs_projid bs_projid_lo /* (previously just bs_projid) */
297 298 __u16 bs_forkoff; /* inode fork offset in bytes */
298   - unsigned char bs_pad[12]; /* pad space, unused */
  299 + __u16 bs_projid_hi; /* higher part of project id */
  300 + unsigned char bs_pad[10]; /* pad space, unused */
299 301 __u32 bs_dmevmask; /* DMIG event mask */
300 302 __u16 bs_dmstate; /* DMIG state info */
301 303 __u16 bs_aextents; /* attribute number of extents */
... ... @@ -660,7 +660,8 @@
660 660 to->di_uid = be32_to_cpu(from->di_uid);
661 661 to->di_gid = be32_to_cpu(from->di_gid);
662 662 to->di_nlink = be32_to_cpu(from->di_nlink);
663   - to->di_projid = be16_to_cpu(from->di_projid);
  663 + to->di_projid_lo = be16_to_cpu(from->di_projid_lo);
  664 + to->di_projid_hi = be16_to_cpu(from->di_projid_hi);
664 665 memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad));
665 666 to->di_flushiter = be16_to_cpu(from->di_flushiter);
666 667 to->di_atime.t_sec = be32_to_cpu(from->di_atime.t_sec);
... ... @@ -695,7 +696,8 @@
695 696 to->di_uid = cpu_to_be32(from->di_uid);
696 697 to->di_gid = cpu_to_be32(from->di_gid);
697 698 to->di_nlink = cpu_to_be32(from->di_nlink);
698   - to->di_projid = cpu_to_be16(from->di_projid);
  699 + to->di_projid_lo = cpu_to_be16(from->di_projid_lo);
  700 + to->di_projid_hi = cpu_to_be16(from->di_projid_hi);
699 701 memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad));
700 702 to->di_flushiter = cpu_to_be16(from->di_flushiter);
701 703 to->di_atime.t_sec = cpu_to_be32(from->di_atime.t_sec);
... ... @@ -874,7 +876,7 @@
874 876 if (ip->i_d.di_version == 1) {
875 877 ip->i_d.di_nlink = ip->i_d.di_onlink;
876 878 ip->i_d.di_onlink = 0;
877   - ip->i_d.di_projid = 0;
  879 + xfs_set_projid(ip, 0);
878 880 }
879 881  
880 882 ip->i_delayed_blks = 0;
... ... @@ -982,7 +984,7 @@
982 984 mode_t mode,
983 985 xfs_nlink_t nlink,
984 986 xfs_dev_t rdev,
985   - xfs_prid_t prid,
  987 + prid_t prid,
986 988 int okalloc,
987 989 xfs_buf_t **ialloc_context,
988 990 boolean_t *call_again,
... ... @@ -1026,7 +1028,7 @@
1026 1028 ASSERT(ip->i_d.di_nlink == nlink);
1027 1029 ip->i_d.di_uid = current_fsuid();
1028 1030 ip->i_d.di_gid = current_fsgid();
1029   - ip->i_d.di_projid = prid;
  1031 + xfs_set_projid(ip, prid);
1030 1032 memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
1031 1033  
1032 1034 /*
... ... @@ -3007,7 +3009,7 @@
3007 3009 memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
3008 3010 memset(&(dip->di_pad[0]), 0,
3009 3011 sizeof(dip->di_pad));
3010   - ASSERT(ip->i_d.di_projid == 0);
  3012 + ASSERT(xfs_get_projid(ip) == 0);
3011 3013 }
3012 3014 }
3013 3015  
... ... @@ -134,8 +134,9 @@
134 134 __uint32_t di_uid; /* owner's user id */
135 135 __uint32_t di_gid; /* owner's group id */
136 136 __uint32_t di_nlink; /* number of links to file */
137   - __uint16_t di_projid; /* owner's project id */
138   - __uint8_t di_pad[8]; /* unused, zeroed space */
  137 + __uint16_t di_projid_lo; /* lower part of owner's project id */
  138 + __uint16_t di_projid_hi; /* higher part of owner's project id */
  139 + __uint8_t di_pad[6]; /* unused, zeroed space */
139 140 __uint16_t di_flushiter; /* incremented on flush */
140 141 xfs_ictimestamp_t di_atime; /* time last accessed */
141 142 xfs_ictimestamp_t di_mtime; /* time last modified */
... ... @@ -334,6 +335,25 @@
334 335 }
335 336  
336 337 /*
  338 + * Project quota id helpers (previously projid was 16bit only
  339 + * and using two 16bit values to hold new 32bit projid was choosen
  340 + * to retain compatibility with "old" filesystems).
  341 + */
  342 +static inline prid_t
  343 +xfs_get_projid(struct xfs_inode *ip)
  344 +{
  345 + return (prid_t)ip->i_d.di_projid_hi << 16 | ip->i_d.di_projid_lo;
  346 +}
  347 +
  348 +static inline void
  349 +xfs_set_projid(struct xfs_inode *ip,
  350 + prid_t projid)
  351 +{
  352 + ip->i_d.di_projid_hi = (__uint16_t) (projid >> 16);
  353 + ip->i_d.di_projid_lo = (__uint16_t) (projid & 0xffff);
  354 +}
  355 +
  356 +/*
337 357 * Manage the i_flush queue embedded in the inode. This completion
338 358 * queue synchronizes processes attempting to flush the in-core
339 359 * inode back to disk.
... ... @@ -455,7 +475,7 @@
455 475 * xfs_inode.c prototypes.
456 476 */
457 477 int xfs_ialloc(struct xfs_trans *, xfs_inode_t *, mode_t,
458   - xfs_nlink_t, xfs_dev_t, xfs_prid_t, int,
  478 + xfs_nlink_t, xfs_dev_t, prid_t, int,
459 479 struct xfs_buf **, boolean_t *, xfs_inode_t **);
460 480  
461 481 uint xfs_ip2xflags(struct xfs_inode *);
... ... @@ -92,7 +92,8 @@
92 92 * further change.
93 93 */
94 94 buf->bs_nlink = dic->di_nlink;
95   - buf->bs_projid = dic->di_projid;
  95 + buf->bs_projid_lo = dic->di_projid_lo;
  96 + buf->bs_projid_hi = dic->di_projid_hi;
96 97 buf->bs_ino = ino;
97 98 buf->bs_mode = dic->di_mode;
98 99 buf->bs_uid = dic->di_uid;
... ... @@ -183,7 +183,7 @@
183 183 * tree quota mechanism would be circumvented.
184 184 */
185 185 if (unlikely((target_dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
186   - (target_dp->i_d.di_projid != src_ip->i_d.di_projid))) {
  186 + (xfs_get_projid(target_dp) != xfs_get_projid(src_ip)))) {
187 187 error = XFS_ERROR(EXDEV);
188 188 goto error_return;
189 189 }
... ... @@ -80,10 +80,12 @@
80 80 #define XFS_SB_VERSION2_RESERVED4BIT 0x00000004
81 81 #define XFS_SB_VERSION2_ATTR2BIT 0x00000008 /* Inline attr rework */
82 82 #define XFS_SB_VERSION2_PARENTBIT 0x00000010 /* parent pointers */
  83 +#define XFS_SB_VERSION2_PROJID32BIT 0x00000080 /* 32 bit project id */
83 84  
84 85 #define XFS_SB_VERSION2_OKREALFBITS \
85 86 (XFS_SB_VERSION2_LAZYSBCOUNTBIT | \
86   - XFS_SB_VERSION2_ATTR2BIT)
  87 + XFS_SB_VERSION2_ATTR2BIT | \
  88 + XFS_SB_VERSION2_PROJID32BIT)
87 89 #define XFS_SB_VERSION2_OKSASHFBITS \
88 90 (0)
89 91 #define XFS_SB_VERSION2_OKREALBITS \
... ... @@ -493,6 +495,12 @@
493 495 sbp->sb_features2 &= ~XFS_SB_VERSION2_ATTR2BIT;
494 496 if (!sbp->sb_features2)
495 497 sbp->sb_versionnum &= ~XFS_SB_VERSION_MOREBITSBIT;
  498 +}
  499 +
  500 +static inline int xfs_sb_version_hasprojid32bit(xfs_sb_t *sbp)
  501 +{
  502 + return xfs_sb_version_hasmorebits(sbp) &&
  503 + (sbp->sb_features2 & XFS_SB_VERSION2_PROJID32BIT);
496 504 }
497 505  
498 506 /*
... ... @@ -73,8 +73,6 @@
73 73 typedef __uint32_t xfs_dablk_t; /* dir/attr block number (in file) */
74 74 typedef __uint32_t xfs_dahash_t; /* dir/attr hash value */
75 75  
76   -typedef __uint16_t xfs_prid_t; /* prid_t truncated to 16bits in XFS */
77   -
78 76 typedef __uint32_t xlog_tid_t; /* transaction ID type */
79 77  
80 78 /*
fs/xfs/xfs_vnodeops.c
... ... @@ -114,7 +114,7 @@
114 114 */
115 115 ASSERT(udqp == NULL);
116 116 ASSERT(gdqp == NULL);
117   - code = xfs_qm_vop_dqalloc(ip, uid, gid, ip->i_d.di_projid,
  117 + code = xfs_qm_vop_dqalloc(ip, uid, gid, xfs_get_projid(ip),
118 118 qflags, &udqp, &gdqp);
119 119 if (code)
120 120 return code;
... ... @@ -1268,7 +1268,7 @@
1268 1268 boolean_t unlock_dp_on_error = B_FALSE;
1269 1269 uint cancel_flags;
1270 1270 int committed;
1271   - xfs_prid_t prid;
  1271 + prid_t prid;
1272 1272 struct xfs_dquot *udqp = NULL;
1273 1273 struct xfs_dquot *gdqp = NULL;
1274 1274 uint resblks;
1275 1275  
... ... @@ -1281,9 +1281,9 @@
1281 1281 return XFS_ERROR(EIO);
1282 1282  
1283 1283 if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
1284   - prid = dp->i_d.di_projid;
  1284 + prid = xfs_get_projid(dp);
1285 1285 else
1286   - prid = dfltprid;
  1286 + prid = XFS_PROJID_DEFAULT;
1287 1287  
1288 1288 /*
1289 1289 * Make sure that we have allocated dquot(s) on disk.
... ... @@ -1882,7 +1882,7 @@
1882 1882 * the tree quota mechanism could be circumvented.
1883 1883 */
1884 1884 if (unlikely((tdp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
1885   - (tdp->i_d.di_projid != sip->i_d.di_projid))) {
  1885 + (xfs_get_projid(tdp) != xfs_get_projid(sip)))) {
1886 1886 error = XFS_ERROR(EXDEV);
1887 1887 goto error_return;
1888 1888 }
... ... @@ -1956,7 +1956,7 @@
1956 1956 int byte_cnt;
1957 1957 int n;
1958 1958 xfs_buf_t *bp;
1959   - xfs_prid_t prid;
  1959 + prid_t prid;
1960 1960 struct xfs_dquot *udqp, *gdqp;
1961 1961 uint resblks;
1962 1962  
1963 1963  
... ... @@ -1979,9 +1979,9 @@
1979 1979  
1980 1980 udqp = gdqp = NULL;
1981 1981 if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
1982   - prid = dp->i_d.di_projid;
  1982 + prid = xfs_get_projid(dp);
1983 1983 else
1984   - prid = (xfs_prid_t)dfltprid;
  1984 + prid = XFS_PROJID_DEFAULT;
1985 1985  
1986 1986 /*
1987 1987 * Make sure that we have allocated dquot(s) on disk.