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);
}
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 },
strcat(s, ",ATTR2");
if (xfs_sb_version_haslazysbcount(sbp))
strcat(s, ",LAZYSBCOUNT");
+ if (xfs_sb_version_hasprojid32bit(sbp))
+ strcat(s, ",PROJID32BIT");
return s;
}
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]);
status=0
DB_OPTS=""
REPAIR_OPTS=""
-USAGE="Usage: xfs_admin [-efjluV] [-c 0|1] [-L label] [-U uuid] device"
+USAGE="Usage: xfs_admin [-efjlpuV] [-c 0|1] [-L label] [-U uuid] device"
-while getopts "efjluc:L:U:V" c
+while getopts "efjlpuc:L:U:V" c
do
case $c in
c) REPAIR_OPTS=$REPAIR_OPTS" -c lazycount="$OPTARG;;
j) DB_OPTS=$DB_OPTS" -c 'version log2'";;
l) DB_OPTS=$DB_OPTS" -r -c label";;
L) DB_OPTS=$DB_OPTS" -c 'label "$OPTARG"'";;
+ p) DB_OPTS=$DB_OPTS" -c 'version projid32bit'";;
u) DB_OPTS=$DB_OPTS" -r -c uuid";;
U) DB_OPTS=$DB_OPTS" -c 'uuid "$OPTARG"'";;
V) xfs_db -p xfs_admin -V
__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 */
__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 */
#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__ */
__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 */
((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__
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 *);
#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 \
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
*/
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:
* 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
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;
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));
/*
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)) {
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);
}
}
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),
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);
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);
"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);
(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
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"
.SH SYNOPSIS
.B xfs_admin
[
-.B \-eflu
+.B \-eflpu
] [
.BR "\-c 0" | 1
] [
.B \-l
Print the current filesystem label.
.TP
+.B \-p
+Enable 32bit project identifier support (PROJID32BIT feature).
+.TP
.B \-u
Print the current filesystem UUID (Universally Unique IDentifier).
.TP
.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.
"size",
#define I_ATTR 5
"attr",
+#define I_PROJID32BIT 6
+ "projid32bit",
NULL
};
__uint64_t agsize;
xfs_alloc_rec_t *arec;
int attrversion;
+ int projid32bit;
struct xfs_btree_block *block;
int blflag;
int blocklog;
textdomain(PACKAGE);
attrversion = 2;
+ projid32bit = 0;
blflag = bsflag = slflag = ssflag = lslflag = lssflag = 0;
blocklog = blocksize = 0;
sectorlog = lsectorlog = XFS_MIN_SECTORSIZE_LOG;
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);
}
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"
" =%-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,
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 ||
/* 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\
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 )
}
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)
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.