Add projid32bit handling to userspace. mkfs.xfs is able to enable this feature for new filesystems. xfs_db knows what projid_lo/hi are. Signed-off-by: Arkadiusz MiÅkiewicz <arekm@xxxxxxxx> Reviewed-by: Christoph Hellwig <hch@xxxxxx> --- News: - xfs_logprint now prints single 32bit projid instead of two 16bit projid_{lo,hi}. Thus we get the same output format as before. - use %u for displaying projid (instead of %d) - projid32bit flag in mkfs.xfs output separated by coma - bs_projid is back as bs_projid_lo + define for compatibility - man page formatting fix db/check.c | 2 +- db/inode.c | 6 ++++-- db/sb.c | 6 ++++++ include/xfs_dinode.h | 5 +++-- include/xfs_fs.h | 17 +++++++++++++++-- include/xfs_inode.h | 25 ++++++++++++++++++++++--- include/xfs_sb.h | 17 ++++++++++++++++- include/xfs_types.h | 2 -- libxfs/util.c | 13 ++++++++----- libxfs/xfs_ialloc.c | 3 ++- libxfs/xfs_inode.c | 6 ++++-- logprint/log_print_all.c | 4 ++-- man/man3/xfsctl.3 | 6 ++++-- man/man8/mkfs.xfs.8 | 6 ++++++ man/man8/xfs_db.8 | 6 ++++-- mkfs/xfs_mkfs.c | 21 +++++++++++++++++---- mkfs/xfs_mkfs.h | 3 ++- quota/quot.c | 2 +- repair/README | 2 +- 19 files changed, 118 insertions(+), 34 deletions(-) diff --git a/db/check.c b/db/check.c index 4f8a62a..a8939a4 100644 --- a/db/check.c +++ b/db/check.c @@ -2840,7 +2840,7 @@ process_inode( break; } if (ic) { - dqprid = idic.di_projid; /* dquot ID is u32 */ + dqprid = xfs_get_projid(idic); /* dquot ID is u32 */ quota_add(&dqprid, &idic.di_gid, &idic.di_uid, 0, bc, ic, rc); } diff --git a/db/inode.c b/db/inode.c index 4aa4e1a..6f8592a 100644 --- a/db/inode.c +++ b/db/inode.c @@ -81,8 +81,10 @@ const field_t inode_core_flds[] = { FLD_COUNT, TYP_NONE }, { "onlink", FLDT_UINT16D, OI(COFF(onlink)), inode_core_onlink_count, FLD_COUNT, TYP_NONE }, - { "projid", FLDT_UINT16D, OI(COFF(projid)), inode_core_projid_count, - FLD_COUNT, TYP_NONE }, + { "projid_lo", FLDT_UINT16D, OI(COFF(projid_lo)), + inode_core_projid_count, FLD_COUNT, TYP_NONE }, + { "projid_hi", FLDT_UINT16D, OI(COFF(projid_hi)), + inode_core_projid_count, FLD_COUNT, TYP_NONE }, { "uid", FLDT_UINT32D, OI(COFF(uid)), C1, 0, TYP_NONE }, { "gid", FLDT_UINT32D, OI(COFF(gid)), C1, 0, TYP_NONE }, { "flushiter", FLDT_UINT16D, OI(COFF(flushiter)), C1, 0, TYP_NONE }, diff --git a/db/sb.c b/db/sb.c index 961a939..21f38c5 100644 --- a/db/sb.c +++ b/db/sb.c @@ -620,6 +620,8 @@ version_string( strcat(s, ",ATTR2"); if (xfs_sb_version_haslazysbcount(sbp)) strcat(s, ",LAZYSBCOUNT"); + if (xfs_sb_version_hasprojid32bit(sbp)) + strcat(s, ",PROJID32BIT"); return s; } @@ -696,6 +698,10 @@ version_f( xfs_sb_version_addattr2(&mp->m_sb); version = mp->m_sb.sb_versionnum; features = mp->m_sb.sb_features2; + } else if (!strcasecmp(argv[1], "projid32bit")) { + xfs_sb_version_addprojid32bit(&mp->m_sb); + version = mp->m_sb.sb_versionnum; + features = mp->m_sb.sb_features2; } else { dbprintf(_("%s: invalid version change command \"%s\"\n"), progname, argv[1]); diff --git a/include/xfs_dinode.h b/include/xfs_dinode.h index d7cf392..f28c088 100644 --- a/include/xfs_dinode.h +++ b/include/xfs_dinode.h @@ -52,8 +52,9 @@ typedef struct xfs_dinode_core { __be32 di_uid; /* owner's user id */ __be32 di_gid; /* owner's group id */ __be32 di_nlink; /* number of links to file */ - __be16 di_projid; /* owner's project id */ - __u8 di_pad[8]; /* unused, zeroed space */ + __be16 di_projid_lo; /* lower part of owner's project id */ + __be16 di_projid_hi; /* higher part owner's project id */ + __u8 di_pad[6]; /* unused, zeroed space */ __be16 di_flushiter; /* incremented on flush */ xfs_timestamp_t di_atime; /* time last accessed */ xfs_timestamp_t di_mtime; /* time last modified */ diff --git a/include/xfs_fs.h b/include/xfs_fs.h index 74e7274..47c1e93 100644 --- a/include/xfs_fs.h +++ b/include/xfs_fs.h @@ -299,9 +299,11 @@ typedef struct xfs_bstat { __s32 bs_extsize; /* extent size */ __s32 bs_extents; /* number of extents */ __u32 bs_gen; /* generation count */ - __u16 bs_projid; /* project id */ + __u16 bs_projid_lo; /* lower part of project id */ +#define bs_projid bs_projid_lo __u16 bs_forkoff; /* inode fork offset in bytes */ - unsigned char bs_pad[12]; /* pad space, unused */ + __u16 bs_projid_hi; /* higher part of project id */ + unsigned char bs_pad[10]; /* pad space, unused */ __u32 bs_dmevmask; /* DMIG event mask */ __u16 bs_dmstate; /* DMIG state info */ __u16 bs_aextents; /* attribute number of extents */ @@ -506,4 +508,15 @@ typedef struct xfs_handle { #define BBTOB(bbs) ((bbs) << BBSHIFT) #endif +/* + * Project quota id helpers (previously projid was 16bit only + * and using two 16bit values to hold new 32bit projid was choosen + * to retain compatibility with "old" filesystems). + */ +static inline __uint32_t +bstat_get_projid(struct xfs_bstat *bs) +{ + return (__uint32_t)bs->bs_projid_hi << 16 | bs->bs_projid_lo; +} + #endif /* __XFS_FS_H__ */ diff --git a/include/xfs_inode.h b/include/xfs_inode.h index b19b467..7e6fc91 100644 --- a/include/xfs_inode.h +++ b/include/xfs_inode.h @@ -124,8 +124,9 @@ typedef struct xfs_icdinode { __uint32_t di_uid; /* owner's user id */ __uint32_t di_gid; /* owner's group id */ __uint32_t di_nlink; /* number of links to file */ - __uint16_t di_projid; /* owner's project id */ - __uint8_t di_pad[8]; /* unused, zeroed space */ + __uint16_t di_projid_lo; /* lower part of owner's project id */ + __uint16_t di_projid_hi; /* higher part of owner's project id */ + __uint8_t di_pad[6]; /* unused, zeroed space */ __uint16_t di_flushiter; /* incremented on flush */ xfs_ictimestamp_t di_atime; /* time last accessed */ xfs_ictimestamp_t di_mtime; /* time last modified */ @@ -204,6 +205,24 @@ typedef struct xfs_icdinode { ((ip)->i_d.di_anextents = (n))) +/* + * Project quota id helpers (previously projid was 16bit only + * and using two 16bit values to hold new 32bit projid was choosen + * to retain compatibility with "old" filesystems). + */ +static inline __uint32_t +xfs_get_projid(struct xfs_icdinode i_d) +{ + return (__uint32_t)i_d.di_projid_hi << 16 | i_d.di_projid_lo; +} + +static inline void +xfs_set_projid(struct xfs_icdinode *i_d, + __uint32_t projid) +{ + i_d->di_projid_hi = (__uint16_t) (projid >> 16); + i_d->di_projid_lo = (__uint16_t) (projid & 0xffff); +} #ifdef __KERNEL__ @@ -510,7 +529,7 @@ int xfs_finish_reclaim_all(struct xfs_mount *, int); int xfs_iread(struct xfs_mount *, struct xfs_trans *, xfs_ino_t, xfs_inode_t **, xfs_daddr_t, uint); int xfs_ialloc(struct xfs_trans *, xfs_inode_t *, mode_t, - xfs_nlink_t, xfs_dev_t, struct cred *, xfs_prid_t, + xfs_nlink_t, xfs_dev_t, struct cred *, prid_t, int, struct xfs_buf **, boolean_t *, xfs_inode_t **); uint xfs_ip2xflags(struct xfs_inode *); diff --git a/include/xfs_sb.h b/include/xfs_sb.h index 1e86489..f88dc32 100644 --- a/include/xfs_sb.h +++ b/include/xfs_sb.h @@ -80,10 +80,12 @@ struct xfs_mount; #define XFS_SB_VERSION2_RESERVED4BIT 0x00000004 #define XFS_SB_VERSION2_ATTR2BIT 0x00000008 /* Inline attr rework */ #define XFS_SB_VERSION2_PARENTBIT 0x00000010 /* parent pointers */ +#define XFS_SB_VERSION2_PROJID32BIT 0x00000080 /* 32 bit project id */ #define XFS_SB_VERSION2_OKREALFBITS \ (XFS_SB_VERSION2_LAZYSBCOUNTBIT | \ - XFS_SB_VERSION2_ATTR2BIT) + XFS_SB_VERSION2_ATTR2BIT | \ + XFS_SB_VERSION2_PROJID32BIT) #define XFS_SB_VERSION2_OKSASHFBITS \ (0) #define XFS_SB_VERSION2_OKREALBITS \ @@ -489,6 +491,19 @@ static inline void xfs_sb_version_removeattr2(xfs_sb_t *sbp) sbp->sb_versionnum &= ~XFS_SB_VERSION_MOREBITSBIT; } +static inline int xfs_sb_version_hasprojid32bit(xfs_sb_t *sbp) +{ + return xfs_sb_version_hasmorebits(sbp) && + (sbp->sb_features2 & XFS_SB_VERSION2_PROJID32BIT); +} + +static inline void xfs_sb_version_addprojid32bit(xfs_sb_t *sbp) +{ + sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT; + sbp->sb_features2 |= XFS_SB_VERSION2_PROJID32BIT; + sbp->sb_bad_features2 |= XFS_SB_VERSION2_PROJID32BIT; +} + /* * end of superblock version macros */ diff --git a/include/xfs_types.h b/include/xfs_types.h index 0f51916..228b948 100644 --- a/include/xfs_types.h +++ b/include/xfs_types.h @@ -81,8 +81,6 @@ typedef __int32_t xfs_tid_t; /* transaction identifier */ typedef __uint32_t xfs_dablk_t; /* dir/attr block number (in file) */ typedef __uint32_t xfs_dahash_t; /* dir/attr hash value */ -typedef __uint16_t xfs_prid_t; /* prid_t truncated to 16bits in XFS */ - /* * These types are 64 bits on disk but are either 32 or 64 bits in memory. * Disk based types: diff --git a/libxfs/util.c b/libxfs/util.c index 409fb92..077d2a2 100644 --- a/libxfs/util.c +++ b/libxfs/util.c @@ -134,7 +134,7 @@ libxfs_iread( * made it 32 bits long. If this is an old format inode, * convert it in memory to look like a new one. If it gets * flushed to disk we will convert back before flushing or - * logging it. We zero out the new projid field and the old link + * logging it. We zero out the new projid_lo/hi field and the old link * count field. We'll handle clearing the pad field (the remains * of the old uuid field) when we actually convert the inode to * the new format. We don't change the version number so that we @@ -143,7 +143,7 @@ libxfs_iread( if (ip->i_d.di_version == XFS_DINODE_VERSION_1) { ip->i_d.di_nlink = ip->i_d.di_onlink; ip->i_d.di_onlink = 0; - ip->i_d.di_projid = 0; + xfs_set_projid(&ip->i_d, 0); } ip->i_delayed_blks = 0; @@ -219,7 +219,7 @@ libxfs_ialloc( ASSERT(ip->i_d.di_nlink == nlink); ip->i_d.di_uid = cr->cr_uid; ip->i_d.di_gid = cr->cr_gid; - ip->i_d.di_projid = pip ? 0 : fsx->fsx_projid; + xfs_set_projid(&ip->i_d, pip ? 0 : fsx->fsx_projid); memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad)); /* @@ -231,7 +231,10 @@ libxfs_ialloc( if (xfs_sb_version_hasnlink(&tp->t_mountp->m_sb) && ip->i_d.di_version == XFS_DINODE_VERSION_1) { ip->i_d.di_version = XFS_DINODE_VERSION_2; - /* old link count, projid field, pad field already zeroed */ + /* + * old link count, projid_lo/hi field, pad field + * already zeroed + */ } if (pip && (pip->i_d.di_mode & S_ISGID)) { @@ -446,7 +449,7 @@ libxfs_iflush_int(xfs_inode_t *ip, xfs_buf_t *bp) memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad)); memset(&(dip->di_core.di_pad[0]), 0, sizeof(dip->di_core.di_pad)); - ASSERT(ip->i_d.di_projid == 0); + ASSERT(xfs_get_projid(ip->i_d) == 0); } } diff --git a/libxfs/xfs_ialloc.c b/libxfs/xfs_ialloc.c index 39fdf96..32ae4b0 100644 --- a/libxfs/xfs_ialloc.c +++ b/libxfs/xfs_ialloc.c @@ -46,7 +46,8 @@ xfs_ialloc_log_di( offsetof(xfs_dinode_core_t, di_uid), offsetof(xfs_dinode_core_t, di_gid), offsetof(xfs_dinode_core_t, di_nlink), - offsetof(xfs_dinode_core_t, di_projid), + offsetof(xfs_dinode_core_t, di_projid_lo), + offsetof(xfs_dinode_core_t, di_projid_hi), offsetof(xfs_dinode_core_t, di_pad), offsetof(xfs_dinode_core_t, di_atime), offsetof(xfs_dinode_core_t, di_mtime), diff --git a/libxfs/xfs_inode.c b/libxfs/xfs_inode.c index b0adabc..1c9ea3b 100644 --- a/libxfs/xfs_inode.c +++ b/libxfs/xfs_inode.c @@ -589,7 +589,8 @@ xfs_dinode_from_disk( to->di_uid = be32_to_cpu(from->di_uid); to->di_gid = be32_to_cpu(from->di_gid); to->di_nlink = be32_to_cpu(from->di_nlink); - to->di_projid = be16_to_cpu(from->di_projid); + to->di_projid_lo = be16_to_cpu(from->di_projid_lo); + to->di_projid_hi = be16_to_cpu(from->di_projid_hi); memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad)); to->di_flushiter = be16_to_cpu(from->di_flushiter); to->di_atime.t_sec = be32_to_cpu(from->di_atime.t_sec); @@ -624,7 +625,8 @@ xfs_dinode_to_disk( to->di_uid = cpu_to_be32(from->di_uid); to->di_gid = cpu_to_be32(from->di_gid); to->di_nlink = cpu_to_be32(from->di_nlink); - to->di_projid = cpu_to_be16(from->di_projid); + to->di_projid_lo = cpu_to_be16(from->di_projid_lo); + to->di_projid_hi = cpu_to_be16(from->di_projid_hi); memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad)); to->di_flushiter = cpu_to_be16(from->di_flushiter); to->di_atime.t_sec = cpu_to_be32(from->di_atime.t_sec); diff --git a/logprint/log_print_all.c b/logprint/log_print_all.c index c21e05c..7bd4617 100644 --- a/logprint/log_print_all.c +++ b/logprint/log_print_all.c @@ -238,8 +238,8 @@ xlog_recover_print_inode_core( "onlink:%d\n"), (di->di_magic>>8) & 0xff, di->di_magic & 0xff, di->di_mode, di->di_version, di->di_format, di->di_onlink); - printf(_(" uid:%d gid:%d nlink:%d projid:%d\n"), - di->di_uid, di->di_gid, di->di_nlink, (uint)di->di_projid); + printf(_(" uid:%d gid:%d nlink:%d projid:%u\n"), + di->di_uid, di->di_gid, di->di_nlink, xfs_get_projid(*di)); printf(_(" atime:%d mtime:%d ctime:%d\n"), di->di_atime.t_sec, di->di_mtime.t_sec, di->di_ctime.t_sec); printf(_(" flushiter:%d\n"), di->di_flushiter); diff --git a/man/man3/xfsctl.3 b/man/man3/xfsctl.3 index 784b3e0..30d2238 100644 --- a/man/man3/xfsctl.3 +++ b/man/man3/xfsctl.3 @@ -564,8 +564,10 @@ The structure has the following elements: (number of extents), .B bs_gen (generation count), -.B bs_projid -(project id), +.B bs_projid_lo +(project id - low word), +.B bs_projid_hi +(project id - high word, used when projid32bit feature is enabled), .B bs_dmevmask (DMIG event mask), .B bs_dmstate diff --git a/man/man8/mkfs.xfs.8 b/man/man8/mkfs.xfs.8 index fdd38d4..fa52152 100644 --- a/man/man8/mkfs.xfs.8 +++ b/man/man8/mkfs.xfs.8 @@ -350,6 +350,12 @@ between attribute and extent data. The previous version 1, which has fixed regions for attribute and extent data, is kept for backwards compatibility with kernels older than version 2.6.16. +.TP +.BI projid32bit[= value ] +This is used to enable 32bit quota project identifiers. The +.I value +is either 0 or 1, with 1 signifying that 32bit projid are to be enabled. +If the value is omitted, 0 is assumed. .RE .TP .BI \-l " log_section_options" diff --git a/man/man8/xfs_db.8 b/man/man8/xfs_db.8 index 629ae58..17ac601 100644 --- a/man/man8/xfs_db.8 +++ b/man/man8/xfs_db.8 @@ -1474,8 +1474,10 @@ number of links to the file in a version 1 inode. .B nlinkv2 number of links to the file in a version 2 inode. .TP -.B projid -owner's project id (version 2 inode only). +.B projid_lo +owner's project id (low word; version 2 inode only). +.B projid_hi +owner's project id (high word; version 2 inode only). .TP .B uid owner's user id. diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index 2d09e36..5b3b9a7 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -106,6 +106,8 @@ char *iopts[] = { "size", #define I_ATTR 5 "attr", +#define I_PROJID32BIT 6 + "projid32bit", NULL }; @@ -829,6 +831,7 @@ main( __uint64_t agsize; xfs_alloc_rec_t *arec; int attrversion; + int projid32bit; struct xfs_btree_block *block; int blflag; int blocklog; @@ -923,6 +926,7 @@ main( textdomain(PACKAGE); attrversion = 2; + projid32bit = 0; blflag = bsflag = slflag = ssflag = lslflag = lssflag = 0; blocklog = blocksize = 0; sectorlog = lsectorlog = XFS_MIN_SECTORSIZE_LOG; @@ -1259,6 +1263,14 @@ main( illegal(value, "i attr"); attrversion = c; break; + case I_PROJID32BIT: + if (!value) + value = "0"; + c = atoi(value); + if (c < 0 || c > 1) + illegal(value, "i projid32bit"); + projid32bit = c; + break; default: unknown('i', value); } @@ -2261,7 +2273,7 @@ an AG size that is one stripe unit smaller, for example %llu.\n"), if (!qflag || Nflag) { printf(_( "meta-data=%-22s isize=%-6d agcount=%lld, agsize=%lld blks\n" - " =%-22s sectsz=%-5u attr=%u\n" + " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n" "data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" "naming =version %-14u bsize=%-6u ascii-ci=%d\n" @@ -2269,7 +2281,7 @@ an AG size that is one stripe unit smaller, for example %llu.\n"), " =%-22s sectsz=%-5u sunit=%d blks, lazy-count=%d\n" "realtime =%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n"), dfile, isize, (long long)agcount, (long long)agsize, - "", sectorsize, attrversion, + "", sectorsize, attrversion, projid32bit, "", blocksize, (long long)dblocks, imaxpct, "", dsunit, dswidth, dirversion, dirblocksize, nci, @@ -2336,7 +2348,7 @@ an AG size that is one stripe unit smaller, for example %llu.\n"), sbp->sb_logsectsize = 0; } sbp->sb_features2 = XFS_SB_VERSION2_MKFS(lazy_sb_counters, - attrversion == 2, 0); + attrversion == 2, projid32bit == 1, 0); sbp->sb_versionnum = XFS_SB_VERSION_MKFS(iaflag, dsunit != 0, logversion == 2, attrversion == 1, (sectorsize != BBSIZE || @@ -2804,7 +2816,8 @@ usage( void ) /* data subvol */ [-d agcount=n,agsize=n,file,name=xxx,size=num,\n\ (sunit=value,swidth=value|su=num,sw=num),\n\ sectlog=n|sectsize=num\n\ -/* inode size */ [-i log=n|perblock=n|size=num,maxpct=n,attr=0|1|2]\n\ +/* inode size */ [-i log=n|perblock=n|size=num,maxpct=n,attr=0|1|2,\n\ + projid32bit=0|1]\n\ /* log subvol */ [-l agnum=n,internal,size=num,logdev=xxx,version=n\n\ sunit=value|su=num,sectlog=n|sectsize=num,\n\ lazy-count=0|1]\n\ diff --git a/mkfs/xfs_mkfs.h b/mkfs/xfs_mkfs.h index 49401d6..f25a7f3 100644 --- a/mkfs/xfs_mkfs.h +++ b/mkfs/xfs_mkfs.h @@ -36,9 +36,10 @@ XFS_DFL_SB_VERSION_BITS | \ 0 ) : XFS_SB_VERSION_1 ) -#define XFS_SB_VERSION2_MKFS(lazycount, attr2, parent) (\ +#define XFS_SB_VERSION2_MKFS(lazycount, attr2, projid32bit, parent) (\ ((lazycount) ? XFS_SB_VERSION2_LAZYSBCOUNTBIT : 0) | \ ((attr2) ? XFS_SB_VERSION2_ATTR2BIT : 0) | \ + ((projid32bit) ? XFS_SB_VERSION2_PROJID32BIT : 0) | \ ((parent) ? XFS_SB_VERSION2_PARENTBIT : 0) | \ 0 ) diff --git a/quota/quot.c b/quota/quot.c index 09d349f..54387ea 100644 --- a/quota/quot.c +++ b/quota/quot.c @@ -102,7 +102,7 @@ quot_bulkstat_add( } for (i = 0; i < 3; i++) { id = (i == 0) ? p->bs_uid : ((i == 1) ? - p->bs_gid : p->bs_projid); + p->bs_gid : bstat_get_projid(p)); hp = &duhash[i][id % DUHASH]; for (dp = *hp; dp; dp = dp->next) if (dp->id == id) diff --git a/repair/README b/repair/README index 69cb0c5..7f168e6 100644 --- a/repair/README +++ b/repair/README @@ -130,7 +130,7 @@ D - 0) rewrite directory leaf block holemap comparison code. it does describe doesn't conflict with reality. D - 0) rewrite setting nlinks handling -- for version 1 - inodes, set both nlinks and onlinks (zero projid + inodes, set both nlinks and onlinks (zero projid_lo/hi and pad) if we have to change anything. For version 2, I think we're ok. -- 1.7.3.1 _______________________________________________ xfs mailing list xfs@xxxxxxxxxxx http://oss.sgi.com/mailman/listinfo/xfs