xfs: Support for interacting with multiple user namespaces
Subsystems (2)
cover xfs: Support for interacting with multiple user namespaces
Or replace uids, gids, and projids with kuids, kgids, and kprojids
In support of user namespaces I have introduced into the kernel kuids, kgids, and kprojids. The most important characteristic of these ids is that they are not assignment compatible with uids, gids, and projids coming from userspace nor are they assignment compatible with uids, gids or projids stored on disk. This assignment incompatibility makes it easy to ensure that conversions are introduced at the edge of userspace and at the interface between on-disk and in-memory data structures.
Getting all of the conversions in all of the right places is important because if one is missed it can easily become a permission check that compares the wrong values.
While doing these conversions I have learned time and time again that if I do not push kuids and kgids down into every in memory data structure I can find there will be important conversions that are missed.
Converting xfs is an interesting challenge because of the way xfs handles it's inode data is very atypical. XFS does two things no other filesystem in linux does. XFS dumps it's in-memory inode structure directly into the on-disk journal without any conversion. After an inode has been evicted from vfs inode cache XFS continues to cache the inode for a time, so that if the inode is needed before all of the state for the inode has been written to disk an uptodate copy can be obtained from the in-memory cached inode.
Interacting with users in different user namespaces for filesystems for the most part is easy. The vfs data structures hand off kuids and kgids to the filesystem. The filesystem then places those kuids and kgids in it's in memory data structures (if it has any beyond struct inode). When data is read from disk the uid and gid values are converted from values in the initial user namespace to kuid and kgid values. When data is written to disk the kuids and kgids are converted into uid and gid values in the initial user namespace.
The initial user namespace is chosen for data on disk, because that is the user namespace that the data on disk uses for unconverted filesystems.
When interacting with userspace processes the values are stored in the current user namespace, which is different for each process.
For example in this chunk of code that has caused some questions what is happening is:
+ if (mask & FSX_PROJID) {
+ projid = make_kprojid(current_user_ns(), fa->fsx_projid);
+ if (!projid_valid(projid))
+ return XFS_ERROR(EINVAL);
fsx_projid is coming from userspace so we convert it from whatever the userspace value is in the current user namespace to a kprojid.
+ /*
+ * Disallow 32bit project ids when projid32bit feature is not enabled.
+ */
+ if ((from_kprojid(&init_user_ns, projid) > (__uint16_t)-1) &&
The disk might only support 16bit project ids. So the kprojid is converted into a projid in the initial user namespace to see what the value we will eventually try to store on-disk is. If the on-disk value is larger than (2^16-1) an error is flagged.
+ !xfs_sb_version_hasprojid32bit(&ip->i_mount->m_sb))
+ return XFS_ERROR(EINVAL);
+ }
In earlier versions of this patchset I have run afoul of the fact that the in-memory inode is dumped to disk making a change to that data structure an ABI change, and then I ran afoul of the fact that despite the fact that struct xfs_inode survives the embedded struct inode may be evicted from the vfs and become invalid and all of it's contents stomped with inode_init_always.
Given the number of ioctls that xfs supports it would be irresponsible to do anything except insist that kuids, kgids, and kprojids are used in all of in memory data structures of xfs, as otherwise it becomes trivially easy to miss a needed conversion with the advent of a new ioctl.
It has been suggested that kuids, and kgids are a vfs construct and should stop at the vfs and should not be used in xfs data structures. They are not a vfs construct they are a kernel construct and are used everywhere in the kernel. xfs does not get to be an exception.
To put kuids, kgids, and kprojids in all of the xfs data structures without breaking the on-disk ABI, this patchset moves struct xfs_icdinode from struct xfs_inode to xfs_log_item, and introduces a set of conversion functions. Introducing the separation between on-disk and in-memory format that is needed to properly perform this conversion.
I have a few additional patches not included in this posting sitting in my development tree that removes the extra copie that this change introduces into xfs_inode_item_format.
xfstests in this instance are boring the same 17 tests keep failing both before and after my changes.
I don't care through which tree these changes are merged. If you would like to take these in through xfs tree that would be great. Otherwise I will be happy to take these changes through my user namespace tree.
Eric
Eric W. Biederman (14):
xfs: Convert uids and gids in xfs acls to/from kuids and kgids
xfs: Separate the in core and the logged inode.
xfs: Store projectid as a single variable.
xfs: Update inode uids, gids, and projids to be kuids, kgids, and kprojids
xfs: Update xfs_ioctl_setattr to handle projids in any user namespace
xfs: Use kuids and kgids in xfs_setattr_nonsize
xfs: Update ioctl(XFS_IOC_FREE_EOFBLOCKS) to handle callers in any userspace
xfs: Use kprojids when allocating inodes.
xfs: Modify xfs_qm_vop_dqalloc to take kuids, kgids, and kprojids.
xfs: Push struct kqid into xfs_qm_scall_qmlim and xfs_qm_scall_getquota
xfs: Modify xfs_qm_dqget to take a struct kqid.
xfs: Remember the kqid for a quota
xfs: Use q_id instead of q_core.d_id.
xfs: Enable building with user namespaces enabled.
fs/xfs/xfs_acl.c | 23 ++++++- fs/xfs/xfs_dquot.c | 39 ++++++++---- fs/xfs/xfs_dquot.h | 13 +++- fs/xfs/xfs_icache.c | 14 ++-- fs/xfs/xfs_icache.h | 11 +++- fs/xfs/xfs_inode.c | 160 +++++++++++++++++++++++++++++++++------------- fs/xfs/xfs_inode.h | 51 +++++++++------ fs/xfs/xfs_inode_item.c | 3 +- fs/xfs/xfs_inode_item.h | 1 + fs/xfs/xfs_ioctl.c | 52 ++++++++++++--- fs/xfs/xfs_iops.c | 14 ++-- fs/xfs/xfs_itable.c | 47 +++++++------- fs/xfs/xfs_qm.c | 83 ++++++++++++------------ fs/xfs/xfs_qm.h | 4 +- fs/xfs/xfs_qm_bhv.c | 2 +- fs/xfs/xfs_qm_syscalls.c | 24 ++++--- fs/xfs/xfs_quota.h | 4 +- fs/xfs/xfs_quotaops.c | 20 +----- fs/xfs/xfs_rename.c | 2 +- fs/xfs/xfs_trace.h | 2 +- fs/xfs/xfs_trans_dquot.c | 8 +-- fs/xfs/xfs_utils.c | 2 +- fs/xfs/xfs_utils.h | 2 +- fs/xfs/xfs_vnodeops.c | 14 ++-- init/Kconfig | 1 - 25 files changed, 366 insertions(+), 230 deletions(-)
A message that is not in the archive (sent off-list or not yet received): 87boan3prc.fsf-aS9lmoZGLiVWk0Htik3J/[email protected]
PATCH 1/14 xfs: Convert uids and gids in xfs acls to/from kuids and kgids
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
- When reading from disk convert on disk uids and gids to kuids and kgids
- When writing to the disk convert in memory kuids and kgids to uids and gids.
- Don't write e_id as that field only exists when user namespace support is disabled.
- Use uid_eq when testing to see if current_fsuid() is allowed to set the acls for a file.
--- fs/xfs/xfs_acl.c | 23 +++++++++++++++++++---- 1 files changed, 19 insertions(+), 4 deletions(-)
fs/xfs/xfs_acl.c +19 -4
@@ -64,14 +64,17 @@ xfs_acl_from_disk(struct xfs_acl *aclp)switch (acl_e->e_tag) {case ACL_USER : + acl_e->e_uid =make_kuid (&init_user_ns, +be32_to_cpu (ace->ae_id)); +break ;case ACL_GROUP : - acl_e->e_id =be32_to_cpu (ace->ae_id); + acl_e->e_gid =make_kgid (&init_user_ns, +be32_to_cpu (ace->ae_id));break ;case ACL_USER_OBJ :case ACL_GROUP_OBJ :case ACL_MASK :case ACL_OTHER : - acl_e->e_id =ACL_UNDEFINED_ID ;break ;default : goto fail;
@@ -97,8 +100,20 @@ xfs_acl_to_disk(struct xfs_acl *aclp, const struct posix_acl *acl) acl_e = &acl->a_entries[i]; ace->ae_tag =cpu_to_be32 (acl_e->e_tag); - ace->ae_id =cpu_to_be32 (acl_e->e_id); ace->ae_perm =cpu_to_be16 (acl_e->e_perm); +switch (acl_e->e_tag) { +case ACL_USER : + ace->ae_id =cpu_to_be32 ( +from_kuid (&init_user_ns, acl_e->e_uid)); +break ; +case ACL_GROUP : + ace->ae_id =cpu_to_be32 ( +from_kgid (&init_user_ns, acl_e->e_gid)); +break ; +default : + ace->ae_id =cpu_to_be32 (ACL_UNDEFINED_ID ); +break ; + } } }
@@ -355,7 +370,7 @@ xfs_xattr_acl_set(struct dentry *dentry, const char *name,return -EINVAL ;if (type ==ACL_TYPE_DEFAULT && !S_ISDIR (inode->i_mode))return value ? -EACCES :0 ; -if ((current_fsuid () != inode->i_uid) && !capable (CAP_FOWNER )) +if ((!uid_eq (current_fsuid (), inode->i_uid)) && !capable (CAP_FOWNER ))return -EPERM ;if (!value)
Signature · 1 line
1.7.5.4
A message that is not in the archive (sent off-list or not yet received): 1363213395-10988-1-git-send-email-ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]
PATCH 2/14 xfs: Separate the in core and the logged inode.
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Add xfs_inode_from_disk xfs_inode_to_disk and xfs_inode_to_log to handle changes.
Add an extra copy of struct xfs_icdinode into struct xfs_inode_log_item ultimately it will be the only copy but for the moment it is a temporary copy.
In struct xfs_inode change the type of i_d to an anonymous structure with all of the same members as struct xfs_icdinode.
Modify the two places that create a pointer to ip->i_d as a shortcut to get shorter names to use ip->i_d directly.
--- fs/xfs/xfs_icache.c | 2 +- fs/xfs/xfs_inode.c | 138 ++++++++++++++++++++++++++++++++++------------- fs/xfs/xfs_inode.h | 31 ++++++++++- fs/xfs/xfs_inode_item.c | 3 +- fs/xfs/xfs_inode_item.h | 1 + fs/xfs/xfs_itable.c | 45 +++++++-------- 6 files changed, 155 insertions(+), 65 deletions(-)
fs/xfs/xfs_icache.c +1 -1
@@ -82,7 +82,7 @@ xfs_inode_alloc(memset (&ip->i_df,0 ,sizeof (xfs_ifork_t)); ip->i_flags =0 ; ip->i_delayed_blks =0 ; -memset (&ip->i_d,0 ,sizeof (xfs_icdinode_t)); +memset (&ip->i_d,0 ,sizeof (ip->i_d));return ip; }
fs/xfs/xfs_inode.c +101 -39
164 lines not on this page · raw message
fs/xfs/xfs_inode.h +30 -1
@@ -243,7 +243,34 @@ typedef struct xfs_inode {unsigned long i_flags;/* see defined flags below */ unsigned int i_delayed_blks;/* count of delay alloc blks */ -xfs_icdinode_t i_d;/* most of ondisk inode */ +struct { +u16 di_magic;/* inode magic # = XFS_DINODE_MAGIC */ +u16 di_mode;/* mode and type of file */ +s8 di_version;/* inode version */ +s8 di_format;/* format of di_c data */ +u16 di_onlink;/* old number of links to file */ +u32 di_uid;/* owner's user id */ +u32 di_gid;/* owner's group id */ +u32 di_nlink;/* number of links to file */ +u16 di_projid_lo;/* lower part of owner's project id */ +u16 di_projid_hi;/* higher part of owner's project id */ +u8 di_pad[6 ];/* unused, zeroed space */ +u16 di_flushiter;/* incremented on flush */ +xfs_ictimestamp_t di_atime;/* time last accessed */ +xfs_ictimestamp_t di_mtime;/* time last modified */ +xfs_ictimestamp_t di_ctime;/* time created/inode modified */ +xfs_fsize_t di_size;/* number of bytes in file */ +xfs_drfsbno_t di_nblocks;/* # of direct & btree blocks used */ +xfs_extlen_t di_extsize;/* basic/minimum extent size for file */ +xfs_extnum_t di_nextents;/* number of extents in data fork */ +xfs_aextnum_t di_anextents;/* number of extents in attribute fork*/ +u8 di_forkoff;/* attr fork offs, <<3 for 64b align */ +s8 di_aformat;/* format of attr fork's data */ +u32 di_dmevmask;/* DMIG event mask */ +u16 di_dmstate;/* DMIG state info */ +u16 di_flags;/* random flags, XFS_DIFLAG_... */ +u32 di_gen;/* generation number */ + } i_d;/* most of ondisk inode */ /* VFS inode */ struct inode i_vnode;/* embedded VFS inode */
@@ -550,6 +577,8 @@ do { \#define XFS_IGET_UNTRUSTED 0x2#define XFS_IGET_DONTCACHE 0x4 +void xfs_inode_to_log (struct xfs_icdinode *to,struct xfs_inode *from); +int xfs_imap_to_bp (struct xfs_mount *,struct xfs_trans *,struct xfs_imap *,struct xfs_dinode **,struct xfs_buf **,uint ,uint );
fs/xfs/xfs_inode_item.c +2 -1
@@ -178,7 +178,7 @@ xfs_inode_item_format( vecp++; nvecs =1 ; - vecp->i_addr = &ip->i_d; + vecp->i_addr = &iip->ili_d; vecp->i_len =sizeof (struct xfs_icdinode ); vecp->i_type =XLOG_REG_TYPE_ICORE ; vecp++;
@@ -212,6 +212,7 @@ xfs_inode_item_format(memset (&(ip->i_d.di_pad[0 ]),0 ,sizeof (ip->i_d.di_pad)); } } +xfs_inode_to_log (&iip->ili_d, ip);switch (ip->i_d.di_format) {case XFS_DINODE_FMT_EXTENTS :
fs/xfs/xfs_inode_item.h +1 -0
@@ -138,6 +138,7 @@ struct xfs_mount; typedef struct xfs_inode_log_item { xfs_log_item_t ili_item; /* common portion */ struct xfs_inode *ili_inode; /* inode ptr */ + struct xfs_icdinode ili_d; /* most of ondisk inode */ xfs_lsn_t ili_flush_lsn; /* lsn at last flush */ xfs_lsn_t ili_last_lsn; /* lsn at last transaction */ unsigned short ili_lock_flags; /* lock flags */
fs/xfs/xfs_itable.c +21 -24
71 lines not on this page · raw message
Signature · 1 line
1.7.5.4
PATCH 3/14 xfs: Store projectid as a single variable.
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
xfs_get_projid is torturous to read and when you don't have the justification of maintaining an on-disk ABI there is really no point. So merge di_projid_lo and di_projid_hi in xfs_inode into di_projid. That is cheaper to read and cheaper to write and can handle future needs. Update all callers of xfs_get_projid and xfs_set_projid to use i_d.di_projid instead.
--- fs/xfs/xfs_icache.c | 2 +- fs/xfs/xfs_inode.c | 18 +++++++++--------- fs/xfs/xfs_inode.h | 22 +--------------------- fs/xfs/xfs_ioctl.c | 8 ++++---- fs/xfs/xfs_iops.c | 2 +- fs/xfs/xfs_itable.c | 4 ++-- fs/xfs/xfs_qm.c | 10 +++++----- fs/xfs/xfs_qm_bhv.c | 2 +- fs/xfs/xfs_rename.c | 2 +- fs/xfs/xfs_vnodeops.c | 6 +++--- 10 files changed, 28 insertions(+), 48 deletions(-)
fs/xfs/xfs_icache.c +1 -1
@@ -1210,7 +1210,7 @@ xfs_inode_match_id(return 0 ;if (eofb->eof_flags &XFS_EOF_FLAGS_PRID && -xfs_get_projid (ip) != eofb->eof_prid) + ip->i_d.di_projid != eofb->eof_prid)return 0 ;return 1 ;
fs/xfs/xfs_inode.c +9 -9
@@ -842,8 +842,8 @@ static void xfs_inode_from_disk(struct xfs_inode *to, struct xfs_dinode *from) to->i_d.di_uid =be32_to_cpu (from->di_uid); to->i_d.di_gid =be32_to_cpu (from->di_gid); to->i_d.di_nlink =be32_to_cpu (from->di_nlink); - to->i_d.di_projid_lo =be16_to_cpu (from->di_projid_lo); - to->i_d.di_projid_hi =be16_to_cpu (from->di_projid_hi); + to->i_d.di_projid = (((u32 )be16_to_cpu (from->di_projid_hi)) <<16 ) | +be16_to_cpu (from->di_projid_lo);memcpy (to->i_d.di_pad, from->di_pad,sizeof (to->i_d.di_pad)); to->i_d.di_flushiter =be16_to_cpu (from->di_flushiter); to->i_d.di_atime.t_sec =be32_to_cpu (from->di_atime.t_sec);
@@ -875,8 +875,8 @@ static void xfs_inode_to_disk(struct xfs_dinode *to, struct xfs_inode *from) to->di_uid =cpu_to_be32 (from->i_d.di_uid); to->di_gid =cpu_to_be32 (from->i_d.di_gid); to->di_nlink =cpu_to_be32 (from->i_d.di_nlink); - to->di_projid_lo =cpu_to_be16 (from->i_d.di_projid_lo); - to->di_projid_hi =cpu_to_be16 (from->i_d.di_projid_hi); + to->di_projid_lo =cpu_to_be16 (from->i_d.di_projid &0xffff ); + to->di_projid_hi =cpu_to_be16 (from->i_d.di_projid >>16 );memcpy (to->di_pad, from->i_d.di_pad,sizeof (to->di_pad)); to->di_flushiter =cpu_to_be16 (from->i_d.di_flushiter); to->di_atime.t_sec =cpu_to_be32 (from->i_d.di_atime.t_sec);
@@ -909,8 +909,8 @@ void xfs_inode_to_log(struct xfs_icdinode *to, struct xfs_inode *from) to->di_uid = from->i_d.di_uid; to->di_gid = from->i_d.di_gid; to->di_nlink = from->i_d.di_nlink; - to->di_projid_lo = from->i_d.di_projid_lo; - to->di_projid_hi = from->i_d.di_projid_hi; + to->di_projid_lo = from->i_d.di_projid &0xffff ; + to->di_projid_hi = from->i_d.di_projid >>16 ;memcpy (to->di_pad, from->i_d.di_pad,sizeof (to->di_pad)); to->di_flushiter = from->i_d.di_flushiter; to->di_atime.t_sec = from->i_d.di_atime.t_sec;
@@ -1112,7 +1112,7 @@ xfs_iread(if (ip->i_d.di_version ==1 ) { ip->i_d.di_nlink = ip->i_d.di_onlink; ip->i_d.di_onlink =0 ; -xfs_set_projid (ip,0 ); + ip->i_d.di_projid =0 ; } ip->i_delayed_blks =0 ;
@@ -1261,7 +1261,7 @@ xfs_ialloc(ASSERT (ip->i_d.di_nlink == nlink); ip->i_d.di_uid =current_fsuid (); ip->i_d.di_gid =current_fsgid (); -xfs_set_projid (ip, prid); + ip->i_d.di_projid = prid;memset (&(ip->i_d.di_pad[0 ]),0 ,sizeof (ip->i_d.di_pad));/*
@@ -2895,7 +2895,7 @@ xfs_iflush_int(memset (&(ip->i_d.di_pad[0 ]),0 ,sizeof (ip->i_d.di_pad));memset (&(dip->di_pad[0 ]),0 ,sizeof (dip->di_pad)); -ASSERT (xfs_get_projid (ip) ==0 ); +ASSERT (ip->i_d.di_projid ==0 ); } }
fs/xfs/xfs_inode.h +1 -21
@@ -252,8 +252,7 @@ typedef struct xfs_inode {u32 di_uid;/* owner's user id */ u32 di_gid;/* owner's group id */ u32 di_nlink;/* number of links to file */ -u16 di_projid_lo;/* lower part of owner's project id */ -u16 di_projid_hi;/* higher part of owner's project id */ +projid_t di_projid;/* owner's project id */ u8 di_pad[6 ];/* unused, zeroed space */ u16 di_flushiter;/* incremented on flush */ xfs_ictimestamp_t di_atime;/* time last accessed */
@@ -382,25 +381,6 @@ xfs_iflags_test_and_set(xfs_inode_t *ip, unsigned short flags) }/* -* Project quota id helpers (previously projid was 16bit only -* and using two 16bit values to hold new 32bit projid was chosen -* to retain compatibility with "old" filesystems). -*/ -static inline prid_t -xfs_get_projid (struct xfs_inode *ip) -{ -return (prid_t )ip->i_d.di_projid_hi <<16 | ip->i_d.di_projid_lo; -} - -static inline void -xfs_set_projid (struct xfs_inode *ip, -prid_t projid) -{ - ip->i_d.di_projid_hi = (__uint16_t) (projid >>16 ); - ip->i_d.di_projid_lo = (__uint16_t) (projid &0xffff ); -} - -/* * In-core inode flags. */ #define XFS_IRECLAIM (1 << 0)/* started reclaiming this inode */
fs/xfs/xfs_ioctl.c +4 -4
@@ -815,7 +815,7 @@ xfs_ioc_fsgetxattr(xfs_ilock (ip,XFS_ILOCK_SHARED ); fa.fsx_xflags =xfs_ip2xflags (ip); fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog; - fa.fsx_projid =xfs_get_projid (ip); + fa.fsx_projid = ip->i_d.di_projid;if (attr) {if (ip->i_afp) {
@@ -986,7 +986,7 @@ xfs_ioctl_setattr(if (mask &FSX_PROJID ) {if (XFS_IS_QUOTA_RUNNING (mp) &&XFS_IS_PQUOTA_ON (mp) && -xfs_get_projid (ip) != fa->fsx_projid) { + ip->i_d.di_projid != fa->fsx_projid) {ASSERT (tp); code = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp, capable(CAP_FOWNER) ?
@@ -1104,12 +1104,12 @@ xfs_ioctl_setattr(* Change the ownerships and register quota modifications * in the transaction. */ -if (xfs_get_projid (ip) != fa->fsx_projid) { +if (ip->i_d.di_projid != fa->fsx_projid) {if (XFS_IS_QUOTA_RUNNING (mp) &&XFS_IS_PQUOTA_ON (mp)) { olddquot =xfs_qm_vop_chown (tp, ip, &ip->i_gdquot, gdqp); } -xfs_set_projid (ip, fa->fsx_projid); + ip->i_d.di_projid = fa->fsx_projid;/* * We may have to rev the inode as well as
fs/xfs/xfs_iops.c +1 -1
@@ -516,7 +516,7 @@ xfs_setattr_nonsize(*/ ASSERT (udqp ==NULL );ASSERT (gdqp ==NULL ); - error =xfs_qm_vop_dqalloc (ip, uid, gid,xfs_get_projid (ip), + error =xfs_qm_vop_dqalloc (ip, uid, gid, ip->i_d.di_projid, qflags, &udqp, &gdqp);if (error)return error;
fs/xfs/xfs_itable.c +2 -2
@@ -88,8 +88,8 @@ xfs_bulkstat_one_int(* further change. */ buf->bs_nlink = ip->i_d.di_nlink; - buf->bs_projid_lo = ip->i_d.di_projid_lo; - buf->bs_projid_hi = ip->i_d.di_projid_hi; + buf->bs_projid_lo = (u16)(ip->i_d.di_projid &0xffff ); + buf->bs_projid_hi = (u16)(ip->i_d.di_projid >>16 ); buf->bs_ino = ino; buf->bs_mode = ip->i_d.di_mode; buf->bs_uid = ip->i_d.di_uid;
fs/xfs/xfs_qm.c +5 -5
@@ -530,7 +530,7 @@ xfs_qm_dqattach_locked( xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP, flags & XFS_QMOPT_DQALLOC, ip->i_udquot, &ip->i_gdquot) : -xfs_qm_dqattach_one (ip,xfs_get_projid (ip),XFS_DQ_PROJ , +xfs_qm_dqattach_one (ip, ip->i_d.di_projid,XFS_DQ_PROJ , flags &XFS_QMOPT_DQALLOC , ip->i_udquot, &ip->i_gdquot);/*
@@ -1172,7 +1172,7 @@ xfs_qm_dqusage_adjust( }if (XFS_IS_PQUOTA_ON (mp)) { - error =xfs_qm_quotacheck_dqadjust (ip,xfs_get_projid (ip), + error =xfs_qm_quotacheck_dqadjust (ip, ip->i_d.di_projid,XFS_DQ_PROJ , nblks, rtblks);if (error) goto error0;
@@ -1704,7 +1704,7 @@ xfs_qm_vop_dqalloc( gq = xfs_qm_dqhold(ip->i_gdquot); } } else if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) { - if (xfs_get_projid(ip) != prid) { + if (ip->i_d.di_projid != prid) { xfs_iunlock(ip, lockflags); if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid, XFS_DQ_PROJ,
@@ -1819,7 +1819,7 @@ xfs_qm_vop_chown_reserve( }if (XFS_IS_OQUOTA_ON (ip->i_mount) && gdqp) {if (XFS_IS_PQUOTA_ON (ip->i_mount) && -xfs_get_projid (ip) !=be32_to_cpu (gdqp->q_core.d_id)) + ip->i_d.di_projid !=be32_to_cpu (gdqp->q_core.d_id)) prjflags =XFS_QMOPT_ENOSPC ; if (prjflags ||
@@ -1917,7 +1917,7 @@ xfs_qm_vop_create_dqattach(ASSERT (ip->i_gdquot ==NULL );ASSERT (XFS_IS_OQUOTA_ON (mp));ASSERT ((XFS_IS_GQUOTA_ON (mp) ? - ip->i_d.di_gid :xfs_get_projid (ip)) == + ip->i_d.di_gid : ip->i_d.di_projid) ==be32_to_cpu (gdqp->q_core.d_id)); ip->i_gdquot =xfs_qm_dqhold (gdqp);
fs/xfs/xfs_qm_bhv.c +1 -1
@@ -79,7 +79,7 @@ xfs_qm_statvfs(xfs_mount_t *mp = ip->i_mount;xfs_dquot_t *dqp; -if (!xfs_qm_dqget (mp,NULL ,xfs_get_projid (ip),XFS_DQ_PROJ ,0 , &dqp)) { +if (!xfs_qm_dqget (mp,NULL , ip->i_d.di_projid,XFS_DQ_PROJ ,0 , &dqp)) {xfs_fill_statvfs_from_dquot (statp, dqp);xfs_qm_dqput (dqp); }
fs/xfs/xfs_rename.c +1 -1
@@ -171,7 +171,7 @@ xfs_rename(* tree quota mechanism would be circumvented. */ if (unlikely ((target_dp->i_d.di_flags &XFS_DIFLAG_PROJINHERIT ) && - (xfs_get_projid (target_dp) !=xfs_get_projid (src_ip)))) { + (target_dp->i_d.di_projid != src_ip->i_d.di_projid))) { error =XFS_ERROR (EXDEV ); goto error_return; }
fs/xfs/xfs_vnodeops.c +3 -3
@@ -741,7 +741,7 @@ xfs_create(return XFS_ERROR (EIO );if (dp->i_d.di_flags &XFS_DIFLAG_PROJINHERIT ) - prid =xfs_get_projid (dp); + prid = dp->i_d.di_projid;else prid =XFS_PROJID_DEFAULT ;
@@ -1305,7 +1305,7 @@ xfs_link(* the tree quota mechanism could be circumvented. */ if (unlikely ((tdp->i_d.di_flags &XFS_DIFLAG_PROJINHERIT ) && - (xfs_get_projid (tdp) !=xfs_get_projid (sip)))) { + (tdp->i_d.di_projid != sip->i_d.di_projid))) { error =XFS_ERROR (EXDEV ); goto error_return; }
@@ -1402,7 +1402,7 @@ xfs_symlink( udqp = gdqp =NULL ;if (dp->i_d.di_flags &XFS_DIFLAG_PROJINHERIT ) - prid =xfs_get_projid (dp); + prid = dp->i_d.di_projid;else prid =XFS_PROJID_DEFAULT ;
Signature · 1 line
1.7.5.4
PATCH 4/14 xfs: Update inode uids, gids, and projids to be kuids, kgids, and kprojids
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Update i_projid on struct xfs_inode to be of type kprojid_t.
Update the logic in xfs_inode_from_disk when the values are read from disk to convert their on-disk values into the internal kernel representation.
Update xfs_inode_to_disk and xfs_inode_to_log to convert from the internal kernel representation to the on-disk values when updating the on-disk fields.
Update comparisons against these fields to use uid_eq, gid_eq and projid_eq.
--- fs/xfs/xfs_icache.c | 6 +++--- fs/xfs/xfs_inode.c | 37 +++++++++++++++++++++++-------------- fs/xfs/xfs_inode.h | 6 +++--- fs/xfs/xfs_ioctl.c | 8 ++++---- fs/xfs/xfs_itable.c | 10 ++++++---- fs/xfs/xfs_qm.c | 20 ++++++++++---------- fs/xfs/xfs_rename.c | 2 +- fs/xfs/xfs_vnodeops.c | 2 +- 8 files changed, 51 insertions(+), 40 deletions(-)
fs/xfs/xfs_icache.c +3 -3
@@ -1202,15 +1202,15 @@ xfs_inode_match_id( struct xfs_eofblocks *eofb) {if (eofb->eof_flags &XFS_EOF_FLAGS_UID && - ip->i_d.di_uid != eofb->eof_uid) + !uid_eq (ip->i_d.di_uid, eofb->eof_uid))return 0 ;if (eofb->eof_flags &XFS_EOF_FLAGS_GID && - ip->i_d.di_gid != eofb->eof_gid) + !gid_eq (ip->i_d.di_gid, eofb->eof_gid))return 0 ;if (eofb->eof_flags &XFS_EOF_FLAGS_PRID && - ip->i_d.di_projid != eofb->eof_prid) + !projid_eq (ip->i_d.di_projid, eofb->eof_prid))return 0 ;return 1 ;
fs/xfs/xfs_inode.c +23 -14
@@ -834,16 +834,18 @@ xfs_iformat_btree(static void xfs_inode_from_disk (struct xfs_inode *to,struct xfs_dinode *from) { +projid_t projid; to->i_d.di_magic =be16_to_cpu (from->di_magic); to->i_d.di_mode =be16_to_cpu (from->di_mode); to->i_d.di_version = from ->di_version; to->i_d.di_format = from->di_format; to->i_d.di_onlink =be16_to_cpu (from->di_onlink); - to->i_d.di_uid =be32_to_cpu (from->di_uid); - to->i_d.di_gid =be32_to_cpu (from->di_gid); + to->i_d.di_uid =make_kuid (&init_user_ns,be32_to_cpu (from->di_uid)); + to->i_d.di_gid =make_kgid (&init_user_ns,be32_to_cpu (from->di_gid)); to->i_d.di_nlink =be32_to_cpu (from->di_nlink); - to->i_d.di_projid = (((u32 )be16_to_cpu (from->di_projid_hi)) <<16 ) | + projid = (((u32 )be16_to_cpu (from->di_projid_hi)) <<16 ) |be16_to_cpu (from->di_projid_lo); + to->i_d.di_projid =make_kprojid (&init_user_ns, projid);memcpy (to->i_d.di_pad, from->di_pad,sizeof (to->i_d.di_pad)); to->i_d.di_flushiter =be16_to_cpu (from->di_flushiter); to->i_d.di_atime.t_sec =be32_to_cpu (from->di_atime.t_sec);
@@ -867,16 +869,19 @@ static void xfs_inode_from_disk(struct xfs_inode *to, struct xfs_dinode *from)static void xfs_inode_to_disk (struct xfs_dinode *to,struct xfs_inode *from) { +uid_t uid =from_kuid (&init_user_ns, from->i_d.di_uid); +gid_t gid =from_kgid (&init_user_ns, from->i_d.di_gid); +projid_t projid =from_kprojid (&init_user_ns, from->i_d.di_projid); to->di_magic =cpu_to_be16 (from->i_d.di_magic); to->di_mode =cpu_to_be16 (from->i_d.di_mode); to->di_version = from->i_d.di_version; to->di_format = from->i_d.di_format; to->di_onlink =cpu_to_be16 (from->i_d.di_onlink); - to->di_uid =cpu_to_be32 (from->i_d.di_uid); - to->di_gid =cpu_to_be32 (from->i_d.di_gid); + to->di_uid =cpu_to_be32 (uid); + to->di_gid =cpu_to_be32 (gid); to->di_nlink =cpu_to_be32 (from->i_d.di_nlink); - to->di_projid_lo =cpu_to_be16 (from->i_d.di_projid &0xffff ); - to->di_projid_hi =cpu_to_be16 (from->i_d.di_projid >>16 ); + to->di_projid_lo =cpu_to_be16 (projid &0xffff ); + to->di_projid_hi =cpu_to_be16 (projid >>16 );memcpy (to->di_pad, from->i_d.di_pad,sizeof (to->di_pad)); to->di_flushiter =cpu_to_be16 (from->i_d.di_flushiter); to->di_atime.t_sec =cpu_to_be32 (from->i_d.di_atime.t_sec);
@@ -901,16 +906,19 @@ static void xfs_inode_to_disk(struct xfs_dinode *to, struct xfs_inode *from)void xfs_inode_to_log (struct xfs_icdinode *to,struct xfs_inode *from) {/* xfs_inode_to_disk without the endian changes */ +uid_t uid =from_kuid (&init_user_ns, from->i_d.di_uid); +gid_t gid =from_kgid (&init_user_ns, from->i_d.di_gid); +projid_t projid =from_kprojid (&init_user_ns, from->i_d.di_projid); to->di_magic = from->i_d.di_magic; to->di_mode = from->i_d.di_mode; to->di_version = from->i_d.di_version; to->di_format = from->i_d.di_format; to->di_onlink = from->i_d.di_onlink; - to->di_uid = from->i_d.di_uid; - to->di_gid = from->i_d.di_gid; + to->di_uid = uid; + to->di_gid = gid; to->di_nlink = from->i_d.di_nlink; - to->di_projid_lo = from->i_d.di_projid &0xffff ; - to->di_projid_hi = from->i_d.di_projid >>16 ; + to->di_projid_lo = projid &0xffff ; + to->di_projid_hi = projid >>16 ;memcpy (to->di_pad, from->i_d.di_pad,sizeof (to->di_pad)); to->di_flushiter = from->i_d.di_flushiter; to->di_atime.t_sec = from->i_d.di_atime.t_sec;
@@ -1112,7 +1120,7 @@ xfs_iread(if (ip->i_d.di_version ==1 ) { ip->i_d.di_nlink = ip->i_d.di_onlink; ip->i_d.di_onlink =0 ; - ip->i_d.di_projid =0 ; + ip->i_d.di_projid =make_kprojid (&init_user_ns,0 ); } ip->i_delayed_blks =0 ;
@@ -1299,7 +1307,7 @@ xfs_ialloc(*/ if ((irix_sgid_inherit) && (ip->i_d.di_mode &S_ISGID ) && - (!in_group_p ((gid_t )ip->i_d.di_gid))) { + (!in_group_p (ip->i_d.di_gid))) { ip->i_d.di_mode &= ~S_ISGID ; }
@@ -2895,7 +2903,8 @@ xfs_iflush_int(memset (&(ip->i_d.di_pad[0 ]),0 ,sizeof (ip->i_d.di_pad));memset (&(dip->di_pad[0 ]),0 ,sizeof (dip->di_pad)); -ASSERT (ip->i_d.di_projid ==0 ); +ASSERT (projid_eq (ip->i_d.di_projid, +make_kprojid (&init_user_ns,0 ))); } }
fs/xfs/xfs_inode.h +3 -3
@@ -249,10 +249,10 @@ typedef struct xfs_inode {s8 di_version;/* inode version */ s8 di_format;/* format of di_c data */ u16 di_onlink;/* old number of links to file */ -u32 di_uid;/* owner's user id */ -u32 di_gid;/* owner's group id */ +kuid_t di_uid;/* owner's user id */ +kgid_t di_gid;/* owner's group id */ u32 di_nlink;/* number of links to file */ -projid_t di_projid;/* owner's project id */ +kprojid_t di_projid;/* owner's project id */ u8 di_pad[6 ];/* unused, zeroed space */ u16 di_flushiter;/* incremented on flush */ xfs_ictimestamp_t di_atime;/* time last accessed */
fs/xfs/xfs_ioctl.c +4 -4
@@ -815,7 +815,7 @@ xfs_ioc_fsgetxattr(xfs_ilock (ip,XFS_ILOCK_SHARED ); fa.fsx_xflags =xfs_ip2xflags (ip); fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog; - fa.fsx_projid = ip->i_d.di_projid; + fa.fsx_projid =from_kprojid_munged (current_user_ns (), ip->i_d.di_projid);if (attr) {if (ip->i_afp) {
@@ -975,7 +975,7 @@ xfs_ioctl_setattr(* to the file owner ID, except in cases where the * CAP_FSETID capability is applicable. */ -if (current_fsuid () != ip->i_d.di_uid && !capable (CAP_FOWNER )) { +if (!uid_eq (current_fsuid (), ip->i_d.di_uid) && !capable (CAP_FOWNER )) { code =XFS_ERROR (EPERM ); goto error_return; }
@@ -986,7 +986,7 @@ xfs_ioctl_setattr(if (mask &FSX_PROJID ) {if (XFS_IS_QUOTA_RUNNING (mp) &&XFS_IS_PQUOTA_ON (mp) && - ip->i_d.di_projid != fa->fsx_projid) { + !projid_eq (ip->i_d.di_projid, fa->fsx_projid)) {ASSERT (tp); code = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp, capable(CAP_FOWNER) ?
@@ -1104,7 +1104,7 @@ xfs_ioctl_setattr(* Change the ownerships and register quota modifications * in the transaction. */ -if (ip->i_d.di_projid != fa->fsx_projid) { +if (!projid_eq (ip->i_d.di_projid, fa->fsx_projid)) {if (XFS_IS_QUOTA_RUNNING (mp) &&XFS_IS_PQUOTA_ON (mp)) { olddquot =xfs_qm_vop_chown (tp, ip, &ip->i_gdquot, gdqp);
fs/xfs/xfs_itable.c +6 -4
@@ -63,6 +63,7 @@ xfs_bulkstat_one_int(struct xfs_inode *ip;/* incore inode pointer */ struct xfs_bstat *buf;/* return buffer */ int error =0 ;/* error value */ +projid_t projid; *stat =BULKSTAT_RV_NOTHING ;
@@ -88,12 +89,13 @@ xfs_bulkstat_one_int(* further change. */ buf->bs_nlink = ip->i_d.di_nlink; - buf->bs_projid_lo = (u16)(ip->i_d.di_projid &0xffff ); - buf->bs_projid_hi = (u16)(ip->i_d.di_projid >>16 ); + projid =from_kprojid_munged (current_user_ns (), ip->i_d.di_projid); + buf->bs_projid_lo = projid &0xffff ; + buf->bs_projid_hi = projid >>16 ; buf->bs_ino = ino; buf->bs_mode = ip->i_d.di_mode; - buf->bs_uid = ip->i_d.di_uid; - buf->bs_gid = ip->i_d.di_gid; + buf->bs_uid =from_kuid_munged (current_user_ns (), ip->i_d.di_uid); + buf->bs_gid =from_kgid_munged (current_user_ns (), ip->i_d.di_gid); buf->bs_size = ip->i_d.di_size; buf->bs_atime.tv_sec = ip->i_d.di_atime.t_sec; buf->bs_atime.tv_nsec = ip->i_d.di_atime.t_nsec;
fs/xfs/xfs_qm.c +10 -10
@@ -1649,7 +1649,7 @@ xfs_qm_vop_dqalloc( uq = gq =NULL ;if ((flags &XFS_QMOPT_UQUOTA ) &&XFS_IS_UQUOTA_ON (mp)) { -if (ip->i_d.di_uid != uid) { +if (!uid_eq (ip->i_d.di_uid, uid)) {/* * What we need is the dquot that has this uid, and * if we send the inode to dqget, the uid of the inode
@@ -1684,7 +1684,7 @@ xfs_qm_vop_dqalloc( } } if ((flags & XFS_QMOPT_GQUOTA) && XFS_IS_GQUOTA_ON(mp)) { - if (ip->i_d.di_gid != gid) { + if (!gid_eq(ip->i_d.di_gid, gid)) { xfs_iunlock(ip, lockflags); if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)gid, XFS_DQ_GROUP,
@@ -1704,7 +1704,7 @@ xfs_qm_vop_dqalloc( gq = xfs_qm_dqhold(ip->i_gdquot); } } else if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) { - if (ip->i_d.di_projid != prid) { + if (!projid_eq(ip->i_d.di_projid, prid)) { xfs_iunlock(ip, lockflags); if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid, XFS_DQ_PROJ,
@@ -1805,7 +1805,7 @@ xfs_qm_vop_chown_reserve( XFS_QMOPT_RES_RTBLKS :XFS_QMOPT_RES_REGBLKS ;if (XFS_IS_UQUOTA_ON (mp) && udqp && - ip->i_d.di_uid != (uid_t )be32_to_cpu (udqp->q_core.d_id)) { + !uid_eq (ip->i_d.di_uid, (uid_t )be32_to_cpu (udqp->q_core.d_id))) { delblksudq = udqp;/* * If there are delayed allocation blocks, then we have to
@@ -1819,12 +1819,12 @@ xfs_qm_vop_chown_reserve( }if (XFS_IS_OQUOTA_ON (ip->i_mount) && gdqp) {if (XFS_IS_PQUOTA_ON (ip->i_mount) && - ip->i_d.di_projid !=be32_to_cpu (gdqp->q_core.d_id)) + !projid_eq (ip->i_d.di_projid,be32_to_cpu (gdqp->q_core.d_id))) prjflags =XFS_QMOPT_ENOSPC ;if (prjflags || (XFS_IS_GQUOTA_ON (ip->i_mount) && - ip->i_d.di_gid !=be32_to_cpu (gdqp->q_core.d_id))) { + !gid_eq (ip->i_d.di_gid,be32_to_cpu (gdqp->q_core.d_id)))) { delblksgdq = gdqp;if (delblks) {ASSERT (ip->i_gdquot);
@@ -1908,7 +1908,7 @@ xfs_qm_vop_create_dqattach(if (udqp) {ASSERT (ip->i_udquot ==NULL );ASSERT (XFS_IS_UQUOTA_ON (mp)); -ASSERT (ip->i_d.di_uid ==be32_to_cpu (udqp->q_core.d_id)); +ASSERT (uid_eq (ip->i_d.di_uid,be32_to_cpu (udqp->q_core.d_id))); ip->i_udquot =xfs_qm_dqhold (udqp);xfs_trans_mod_dquot (tp, udqp,XFS_TRANS_DQ_ICOUNT ,1 );
@@ -1916,9 +1916,9 @@ xfs_qm_vop_create_dqattach(if (gdqp) {ASSERT (ip->i_gdquot ==NULL );ASSERT (XFS_IS_OQUOTA_ON (mp)); -ASSERT ((XFS_IS_GQUOTA_ON (mp) ? - ip->i_d.di_gid : ip->i_d.di_projid) == -be32_to_cpu (gdqp->q_core.d_id)); +ASSERT (XFS_IS_GQUOTA_ON (mp) ? +gid_eq (ip->i_d.di_gid,be32_to_cpu (gdqp->q_core.d_id)): +projid_eq (ip->i_d.di_projid,be32_to_cpu (gdqp->q_core.d_id))); ip->i_gdquot =xfs_qm_dqhold (gdqp);xfs_trans_mod_dquot (tp, gdqp,XFS_TRANS_DQ_ICOUNT ,1 );
fs/xfs/xfs_rename.c +1 -1
@@ -171,7 +171,7 @@ xfs_rename(* tree quota mechanism would be circumvented. */ if (unlikely ((target_dp->i_d.di_flags &XFS_DIFLAG_PROJINHERIT ) && - (target_dp->i_d.di_projid != src_ip->i_d.di_projid))) { + !projid_eq (target_dp->i_d.di_projid, src_ip->i_d.di_projid))) { error =XFS_ERROR (EXDEV ); goto error_return; }
fs/xfs/xfs_vnodeops.c +1 -1
@@ -1305,7 +1305,7 @@ xfs_link(* the tree quota mechanism could be circumvented. */ if (unlikely ((tdp->i_d.di_flags &XFS_DIFLAG_PROJINHERIT ) && - (tdp->i_d.di_projid != sip->i_d.di_projid))) { + !projid_eq (tdp->i_d.di_projid, sip->i_d.di_projid))) { error =XFS_ERROR (EXDEV ); goto error_return; }
Signature · 1 line
1.7.5.4
PATCH 5/14 xfs: Update xfs_ioctl_setattr to handle projids in any user namespace
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
- Convert the userspace value in fa->fsx_projid into a kprojid and store it in the variable projid.
- Verify that xfs can store the projid after it is converted into xfs's user namespace.
- Replace uses of fa->fsx_projid with projid throughout xfs_ioctl_setattr.
--- fs/xfs/xfs_ioctl.c | 26 ++++++++++++++++++-------- 1 files changed, 18 insertions(+), 8 deletions(-)
fs/xfs/xfs_ioctl.c +18 -8
@@ -925,6 +925,7 @@ xfs_ioctl_setattr(struct xfs_dquot *gdqp =NULL ;struct xfs_dquot *olddquot =NULL ;int code; +kprojid_t projid =INVALID_PROJID ;trace_xfs_ioctl_setattr (ip);
@@ -934,11 +935,20 @@ xfs_ioctl_setattr(return XFS_ERROR (EIO );/* -* Disallow 32bit project ids when projid32bit feature is not enabled. +* Verify the specifid project id is valid. */ -if ((mask &FSX_PROJID ) && (fa->fsx_projid > (__uint16_t)-1 ) && - !xfs_sb_version_hasprojid32bit (&ip->i_mount->m_sb)) -return XFS_ERROR (EINVAL ); +if (mask &FSX_PROJID ) { + projid =make_kprojid (current_user_ns (), fa->fsx_projid); +if (!projid_valid (projid)) +return XFS_ERROR (EINVAL ); + +/* +* Disallow 32bit project ids when projid32bit feature is not enabled. +*/ +if ((from_kprojid (&init_user_ns, projid) > (__uint16_t)-1 ) && + !xfs_sb_version_hasprojid32bit (&ip->i_mount->m_sb)) +return XFS_ERROR (EINVAL ); + }/* * If disk quotas is on, we make sure that the dquots do exist on disk,
@@ -950,7 +960,7 @@ xfs_ioctl_setattr(*/ if (XFS_IS_QUOTA_ON (mp) && (mask &FSX_PROJID )) { code =xfs_qm_vop_dqalloc (ip, ip->i_d.di_uid, - ip->i_d.di_gid, fa->fsx_projid, + ip->i_d.di_gid, projid,XFS_QMOPT_PQUOTA , &udqp, &gdqp);if (code)return code;
@@ -986,7 +996,7 @@ xfs_ioctl_setattr(if (mask &FSX_PROJID ) {if (XFS_IS_QUOTA_RUNNING (mp) &&XFS_IS_PQUOTA_ON (mp) && - !projid_eq (ip->i_d.di_projid, fa->fsx_projid)) { + !projid_eq (ip->i_d.di_projid, projid)) {ASSERT (tp); code = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp, capable(CAP_FOWNER) ?
@@ -1104,12 +1114,12 @@ xfs_ioctl_setattr(* Change the ownerships and register quota modifications * in the transaction. */ -if (!projid_eq (ip->i_d.di_projid, fa->fsx_projid)) { +if (!projid_eq (ip->i_d.di_projid, projid)) {if (XFS_IS_QUOTA_RUNNING (mp) &&XFS_IS_PQUOTA_ON (mp)) { olddquot =xfs_qm_vop_chown (tp, ip, &ip->i_gdquot, gdqp); } - ip->i_d.di_projid = fa->fsx_projid; + ip->i_d.di_projid = projid;/* * We may have to rev the inode as well as
Signature · 1 line
1.7.5.4
PATCH 6/14 xfs: Use kuids and kgids in xfs_setattr_nonsize
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
--- fs/xfs/xfs_iops.c | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-)
fs/xfs/xfs_iops.c +6 -6
@@ -466,8 +466,8 @@ xfs_setattr_nonsize(int mask = iattr->ia_valid;xfs_trans_t *tp;int error; -uid_t uid =0 , iuid =0 ; -gid_t gid =0 , igid =0 ; +kuid_t uid =GLOBAL_ROOT_UID , iuid =GLOBAL_ROOT_UID ; +kgid_t gid =GLOBAL_ROOT_GID , igid =GLOBAL_ROOT_GID ;struct xfs_dquot *udqp =NULL , *gdqp =NULL ;struct xfs_dquot *olddquot1 =NULL , *olddquot2 =NULL ;
@@ -549,8 +549,8 @@ xfs_setattr_nonsize(* going to change. */ if (XFS_IS_QUOTA_RUNNING (mp) && - ((XFS_IS_UQUOTA_ON (mp) && iuid != uid) || - (XFS_IS_GQUOTA_ON (mp) && igid != gid))) { + ((XFS_IS_UQUOTA_ON (mp) && !uid_eq (iuid, uid)) || + (XFS_IS_GQUOTA_ON (mp) && !gid_eq (igid, gid)))) {ASSERT (tp); error = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp, capable(CAP_FOWNER) ?
@@ -580,7 +580,7 @@ xfs_setattr_nonsize(* Change the ownerships and register quota modifications * in the transaction. */ -if (iuid != uid) { +if (!uid_eq (iuid, uid)) {if (XFS_IS_QUOTA_RUNNING (mp) &&XFS_IS_UQUOTA_ON (mp)) {ASSERT (mask &ATTR_UID );ASSERT (udqp);
@@ -590,7 +590,7 @@ xfs_setattr_nonsize( ip->i_d.di_uid = uid; inode->i_uid = uid; } -if (igid != gid) { +if (!gid_eq (igid, gid)) {if (XFS_IS_QUOTA_RUNNING (mp) &&XFS_IS_GQUOTA_ON (mp)) {ASSERT (!XFS_IS_PQUOTA_ON (mp));ASSERT (mask &ATTR_GID );
Signature · 1 line
1.7.5.4
PATCH 7/14 xfs: Update ioctl(XFS_IOC_FREE_EOFBLOCKS) to handle callers in any userspace
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
- Modify the ioctl to convert from uids, gid, and projids in the current user namespace to kuids, kgids, and kprojids, and to report an error if the conversion fails.
- Create struct xfs_internal_eofblocks to hold the same information as struct xfs_eofblocks but with uids, gids, and projids stored as kuids, kgids, and kprojids preventing confusion.
- Pass struct xfs_interanl_eofblocks into xfs_icache_free_eofblocks and it's helpers ensuring there will not be confusing about which user namespace identifiers that need to be compared are in.
--- fs/xfs/xfs_icache.c | 8 ++++---- fs/xfs/xfs_icache.h | 11 ++++++++++- fs/xfs/xfs_ioctl.c | 22 +++++++++++++++++++++- 3 files changed, 35 insertions(+), 6 deletions(-)
fs/xfs/xfs_icache.c +4 -4
@@ -1199,7 +1199,7 @@ xfs_reclaim_inodes_count( STATIC intxfs_inode_match_id (struct xfs_inode *ip, -struct xfs_eofblocks *eofb) +struct xfs_internal_eofblocks *eofb) {if (eofb->eof_flags &XFS_EOF_FLAGS_UID && !uid_eq (ip->i_d.di_uid, eofb->eof_uid))
@@ -1210,7 +1210,7 @@ xfs_inode_match_id(return 0 ;if (eofb->eof_flags &XFS_EOF_FLAGS_PRID && - !projid_eq (ip->i_d.di_projid, eofb->eof_prid)) + !projid_eq (ip->i_d.di_projid, eofb->eof_projid))return 0 ;return 1 ;
@@ -1224,7 +1224,7 @@ xfs_inode_free_eofblocks( void *args) {int ret; -struct xfs_eofblocks *eofb = args; +struct xfs_internal_eofblocks *eofb = args;if (!xfs_can_free_eofblocks (ip, false)) {/* inode could be preallocated or append-only */
@@ -1263,7 +1263,7 @@ xfs_inode_free_eofblocks(int xfs_icache_free_eofblocks (struct xfs_mount *mp, -struct xfs_eofblocks *eofb) +struct xfs_internal_eofblocks *eofb) {int flags =SYNC_TRYLOCK ;
fs/xfs/xfs_icache.h +10 -1
@@ -35,9 +35,18 @@ void xfs_reclaim_inodes_nr(struct xfs_mount *mp, int nr_to_scan);void xfs_inode_set_reclaim_tag (struct xfs_inode *ip); +struct xfs_internal_eofblocks { +u32 eof_version; +u32 eof_flags; +kuid_t eof_uid; +kgid_t eof_gid; +kprojid_t eof_projid; +u64 eof_min_file_size; +}; +void xfs_inode_set_eofblocks_tag (struct xfs_inode *ip);void xfs_inode_clear_eofblocks_tag (struct xfs_inode *ip); -int xfs_icache_free_eofblocks (struct xfs_mount *,struct xfs_eofblocks *); +int xfs_icache_free_eofblocks (struct xfs_mount *,struct xfs_internal_eofblocks *);void xfs_eofblocks_worker (struct work_struct *);int xfs_sync_inode_grab (struct xfs_inode *ip);
fs/xfs/xfs_ioctl.c +21 -1
@@ -1615,6 +1615,7 @@ xfs_file_ioctl(case XFS_IOC_FREE_EOFBLOCKS : {struct xfs_eofblocks eofb; +struct xfs_internal_eofblocks keofb;if (copy_from_user (&eofb, arg,sizeof (eofb)))return -XFS_ERROR (EFAULT );
@@ -1629,7 +1630,26 @@ xfs_file_ioctl( memchr_inv(eofb.pad64, 0, sizeof(eofb.pad64))) return -XFS_ERROR(EINVAL); - error =xfs_icache_free_eofblocks (mp, &eofb); + keofb.eof_version = eofb.eof_version; + keofb.eof_flags = eofb.eof_flags; +if (eofb.eof_flags &XFS_EOF_FLAGS_UID ) { + keofb.eof_uid =make_kuid (current_user_ns (), eofb.eof_uid); +if (!uid_valid (keofb.eof_uid)) +return -XFS_ERROR (EINVAL ); + } +if (eofb.eof_flags &XFS_EOF_FLAGS_GID ) { + keofb.eof_gid =make_kgid (current_user_ns (), eofb.eof_gid); +if (!gid_valid (keofb.eof_gid)) +return -XFS_ERROR (EINVAL ); + } +if (eofb.eof_flags &XFS_EOF_FLAGS_PRID ) { + keofb.eof_projid =make_kprojid (current_user_ns (), eofb.eof_prid); +if (!projid_valid (keofb.eof_projid)) +return -XFS_ERROR (EINVAL ); + } + keofb.eof_min_file_size = eofb.eof_min_file_size; + + error =xfs_icache_free_eofblocks (mp, &keofb);return -error; }
Signature · 1 line
1.7.5.4
PATCH 8/14 xfs: Use kprojids when allocating inodes.
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
In xfs_create and xfs_symlink compute the desired kprojid and pass it down into xfs_ialloc.
--- fs/xfs/xfs_inode.c | 5 +++-- fs/xfs/xfs_inode.h | 2 +- fs/xfs/xfs_qm.c | 4 +++- fs/xfs/xfs_utils.c | 2 +- fs/xfs/xfs_utils.h | 2 +- fs/xfs/xfs_vnodeops.c | 8 ++++---- 6 files changed, 13 insertions(+), 10 deletions(-)
fs/xfs/xfs_inode.c +3 -2
@@ -1226,7 +1226,7 @@ xfs_ialloc(umode_t mode, xfs_nlink_t nlink, xfs_dev_t rdev, - prid_t prid, + kprojid_t prid, int okalloc, xfs_buf_t **ialloc_context, xfs_inode_t **ipp)
@@ -1290,7 +1290,8 @@ xfs_ialloc(/* * Project ids won't be stored on disk if we are using a version 1 inode. */ -if ((prid !=0 ) && (ip->i_d.di_version ==1 )) +if (!projid_eq (prid,make_kprojid (&init_user_ns,0 )) && + (ip->i_d.di_version ==1 ))xfs_bump_ino_vers2 (tp, ip);if (pip &&XFS_INHERIT_GID (pip)) {
fs/xfs/xfs_inode.h +1 -1
@@ -516,7 +516,7 @@ int xfs_isilocked(xfs_inode_t *, uint);uint xfs_ilock_map_shared (xfs_inode_t *);void xfs_iunlock_map_shared (xfs_inode_t *,uint );int xfs_ialloc (struct xfs_trans *,xfs_inode_t *,umode_t , -xfs_nlink_t ,xfs_dev_t ,prid_t ,int , +xfs_nlink_t ,xfs_dev_t ,kprojid_t ,int ,struct xfs_buf **,xfs_inode_t **);uint xfs_ip2xflags (struct xfs_inode *);
fs/xfs/xfs_qm.c +3 -1
@@ -777,7 +777,9 @@ xfs_qm_qino_alloc(return error; } - error =xfs_dir_ialloc (&tp,NULL ,S_IFREG ,1 ,0 ,0 ,1 , ip, &committed); + error =xfs_dir_ialloc (&tp,NULL ,S_IFREG ,1 ,0 , +make_kprojid (&init_user_ns,0 ), +1 , ip, &committed);if (error) {xfs_trans_cancel (tp,XFS_TRANS_RELEASE_LOG_RES |XFS_TRANS_ABORT );
fs/xfs/xfs_utils.c +1 -1
@@ -54,7 +54,7 @@ xfs_dir_ialloc(umode_t mode, xfs_nlink_t nlink, xfs_dev_t rdev, - prid_t prid, /* project id */ + kprojid_t prid, /* project id */ int okalloc, /* ok to allocate new space */ xfs_inode_t **ipp, /* pointer to inode; it will be locked. */
fs/xfs/xfs_utils.h +1 -1
@@ -19,7 +19,7 @@#define __XFS_UTILS_H__extern int xfs_dir_ialloc (xfs_trans_t **,xfs_inode_t *,umode_t ,xfs_nlink_t , -xfs_dev_t ,prid_t ,int ,xfs_inode_t **,int *); +xfs_dev_t ,kprojid_t ,int ,xfs_inode_t **,int *);extern int xfs_droplink (xfs_trans_t *,xfs_inode_t *);extern int xfs_bumplink (xfs_trans_t *,xfs_inode_t *);extern void xfs_bump_ino_vers2 (xfs_trans_t *,xfs_inode_t *);
fs/xfs/xfs_vnodeops.c +4 -4
@@ -728,7 +728,7 @@ xfs_create(bool unlock_dp_on_error = false;uint cancel_flags;int committed; -prid_t prid; +kprojid_t prid;struct xfs_dquot *udqp =NULL ;struct xfs_dquot *gdqp =NULL ;uint resblks;
@@ -743,7 +743,7 @@ xfs_create(if (dp->i_d.di_flags &XFS_DIFLAG_PROJINHERIT ) prid = dp->i_d.di_projid;else - prid =XFS_PROJID_DEFAULT ; + prid =make_kprojid (&init_user_ns,XFS_PROJID_DEFAULT );/* * Make sure that we have allocated dquot(s) on disk.
@@ -1379,7 +1379,7 @@ xfs_symlink(int byte_cnt;int n;xfs_buf_t *bp; -prid_t prid; +kprojid_t prid;struct xfs_dquot *udqp, *gdqp;uint resblks;
@@ -1404,7 +1404,7 @@ xfs_symlink(if (dp->i_d.di_flags &XFS_DIFLAG_PROJINHERIT ) prid = dp->i_d.di_projid;else - prid =XFS_PROJID_DEFAULT ; + prid =make_kprojid (&init_user_ns,XFS_PROJID_DEFAULT );/* * Make sure that we have allocated dquot(s) on disk.
Signature · 1 line
1.7.5.4
PATCH 9/14 xfs: Modify xfs_qm_vop_dqalloc to take kuids, kgids, and kprojids.
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
--- fs/xfs/xfs_qm.c | 6 +++--- fs/xfs/xfs_quota.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-)
fs/xfs/xfs_qm.c +3 -3
@@ -1616,9 +1616,9 @@ xfs_qm_write_sb_changes(int xfs_qm_vop_dqalloc (struct xfs_inode *ip, -uid_t uid, -gid_t gid, -prid_t prid, +kuid_t uid, +kgid_t gid, +kprojid_t prid,uint flags,struct xfs_dquot **O_udqpp,struct xfs_dquot **O_gdqpp)
fs/xfs/xfs_quota.h +2 -2
@@ -311,7 +311,7 @@ extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *, struct xfs_mount *, struct xfs_dquot *, struct xfs_dquot *, long, long, uint); -extern int xfs_qm_vop_dqalloc (struct xfs_inode *,uid_t ,gid_t ,prid_t ,uint , +extern int xfs_qm_vop_dqalloc (struct xfs_inode *,kuid_t ,kgid_t ,kprojid_t ,uint ,struct xfs_dquot **,struct xfs_dquot **);extern void xfs_qm_vop_create_dqattach (struct xfs_trans *,struct xfs_inode *,struct xfs_dquot *,struct xfs_dquot *);
@@ -332,7 +332,7 @@ extern void xfs_qm_unmount_quotas(struct xfs_mount *);#else static inline int -xfs_qm_vop_dqalloc (struct xfs_inode *ip,uid_t uid,gid_t gid,prid_t prid, +xfs_qm_vop_dqalloc (struct xfs_inode *ip,kuid_t uid,kgid_t gid,kprojid_t prid,uint flags,struct xfs_dquot **udqp,struct xfs_dquot **gdqp) { *udqp =NULL ;
Signature · 1 line
1.7.5.4
PATCH 10/14 xfs: Push struct kqid into xfs_qm_scall_qmlim and xfs_qm_scall_getquota
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
- In xfs_qm_scall_getquota map the quota id into the callers user namespace in the returned struct fs_disk_quota
- Add a helper is_superquota and use it in xfs_qm_scall_setqlimi to see if we are setting the superusers quota limit. Setting the superuses quota limit on xfs sets the default quota limits for all users.
- Move xfs_quota_type into xfs_qm_syscalls.c where it is now used.
--- fs/xfs/xfs_dquot.h | 6 ++++++ fs/xfs/xfs_qm.h | 4 ++-- fs/xfs/xfs_qm_syscalls.c | 40 +++++++++++++++++++++++++++++----------- fs/xfs/xfs_quotaops.c | 20 ++------------------ 4 files changed, 39 insertions(+), 31 deletions(-)
fs/xfs/xfs_dquot.h +6 -0
@@ -163,4 +163,10 @@ static inline struct xfs_dquot *xfs_qm_dqhold(struct xfs_dquot *dqp)extern const struct xfs_buf_ops xfs_dquot_buf_ops; +/* Is this root's quota in the specified user namespace? */ +static inline bool is_superquota (struct kqid id,struct user_namespace *ns) +{ +return qid_eq (id,make_kqid (ns, id.type,0 )); +} +#endif /* __XFS_DQUOT_H__ */
fs/xfs/xfs_qm.h +2 -2
@@ -114,9 +114,9 @@ extern void xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint);/* quota ops */ extern int xfs_qm_scall_trunc_qfiles (xfs_mount_t *,uint ); -extern int xfs_qm_scall_getquota (xfs_mount_t *,xfs_dqid_t ,uint , +extern int xfs_qm_scall_getquota (xfs_mount_t *,struct kqid ,fs_disk_quota_t *); -extern int xfs_qm_scall_setqlim (xfs_mount_t *,xfs_dqid_t ,uint , +extern int xfs_qm_scall_setqlim (xfs_mount_t *,struct kqid ,fs_disk_quota_t *);extern int xfs_qm_scall_getqstat (xfs_mount_t *,fs_quota_stat_t *);extern int xfs_qm_scall_quotaon (xfs_mount_t *,uint );
fs/xfs/xfs_qm_syscalls.c +29 -11
@@ -48,6 +48,19 @@ STATIC int xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *, STATIC uint xfs_qm_export_flags(uint); STATIC uint xfs_qm_export_qtype_flags(uint); +STATIC int +xfs_quota_type (int type) +{ +switch (type) { +case USRQUOTA : +return XFS_DQ_USER ; +case GRPQUOTA : +return XFS_DQ_GROUP ; +default : +return XFS_DQ_PROJ ; + } +} +/* * Turn off quota accounting and/or enforcement for all udquots and/or * gdquots. Called only at unmount time.
@@ -473,8 +486,7 @@ xfs_qm_scall_getqstat(int xfs_qm_scall_setqlim (xfs_mount_t *mp, -xfs_dqid_t id, -uint type, +struct kqid id,fs_disk_quota_t *newlim) {struct xfs_quotainfo *q = mp->m_quotainfo;
@@ -483,12 +495,16 @@ xfs_qm_scall_setqlim(xfs_trans_t *tp;int error;xfs_qcnt_t hard, soft; +bool superquota;if (newlim->d_fieldmask & ~XFS_DQ_MASK )return EINVAL ;if ((newlim->d_fieldmask &XFS_DQ_MASK ) ==0 )return 0 ; +/* Is this quota id for root? */ + superquota =is_superquota (id, &init_user_ns); + tp =xfs_trans_alloc (mp,XFS_TRANS_QM_SETQLIM ); error =xfs_trans_reserve (tp,0 ,XFS_QM_SETQLIM_LOG_RES (mp),0 ,0 ,XFS_DEFAULT_LOG_COUNT );
@@ -509,7 +525,9 @@ xfs_qm_scall_setqlim(* Get the dquot (locked), and join it to the transaction. * Allocate the dquot if this doesn't exist. */ -if ((error =xfs_qm_dqget (mp,NULL , id, type,XFS_QMOPT_DQALLOC , &dqp))) { +if ((error =xfs_qm_dqget (mp,NULL ,from_kqid (&init_user_ns, id), +xfs_quota_type (id.type), +XFS_QMOPT_DQALLOC , &dqp))) {xfs_trans_cancel (tp,XFS_TRANS_ABORT );ASSERT (error !=ENOENT ); goto out_unlock;
@@ -529,7 +547,7 @@ xfs_qm_scall_setqlim(if (hard ==0 || hard >= soft) { ddq->d_blk_hardlimit =cpu_to_be64 (hard); ddq->d_blk_softlimit =cpu_to_be64 (soft); -if (id ==0 ) { +if (superquota) { q->qi_bhardlimit = hard; q->qi_bsoftlimit = soft; }
@@ -545,7 +563,7 @@ xfs_qm_scall_setqlim(if (hard ==0 || hard >= soft) { ddq->d_rtb_hardlimit =cpu_to_be64 (hard); ddq->d_rtb_softlimit =cpu_to_be64 (soft); -if (id ==0 ) { +if (superquota) { q->qi_rtbhardlimit = hard; q->qi_rtbsoftlimit = soft; }
@@ -562,7 +580,7 @@ xfs_qm_scall_setqlim(if (hard ==0 || hard >= soft) { ddq->d_ino_hardlimit =cpu_to_be64 (hard); ddq->d_ino_softlimit =cpu_to_be64 (soft); -if (id ==0 ) { +if (superquota) { q->qi_ihardlimit = hard; q->qi_isoftlimit = soft; }
@@ -580,7 +598,7 @@ xfs_qm_scall_setqlim(if (newlim->d_fieldmask &FS_DQ_RTBWARNS ) ddq->d_rtbwarns =cpu_to_be16 (newlim->d_rtbwarns); -if (id ==0 ) { +if (superquota) {/* * Timelimits for the super user set the relative time * the other users can be over quota for this file system.
@@ -715,8 +733,7 @@ error0:int xfs_qm_scall_getquota (struct xfs_mount *mp, -xfs_dqid_t id, -uint type, +struct kqid id,struct fs_disk_quota *dst) {struct xfs_dquot *dqp;
@@ -727,7 +744,8 @@ xfs_qm_scall_getquota(* we aren't passing the XFS_QMOPT_DOALLOC flag. If it doesn't * exist, we'll get ENOENT back. */ - error =xfs_qm_dqget (mp,NULL , id, type,0 , &dqp); + error =xfs_qm_dqget (mp,NULL ,from_kqid (&init_user_ns, id), +xfs_quota_type (id.type),0 , &dqp);if (error)return error;
@@ -743,7 +761,7 @@ xfs_qm_scall_getquota(memset (dst,0 ,sizeof (*dst)); dst->d_version =FS_DQUOT_VERSION ; dst->d_flags =xfs_qm_export_qtype_flags (dqp->q_core.d_flags); - dst->d_id =be32_to_cpu (dqp->q_core.d_id); + dst->d_id =from_kqid_munged (current_user_ns (), id); dst->d_blk_hardlimit =XFS_FSB_TO_BB (mp,be64_to_cpu (dqp->q_core.d_blk_hardlimit)); dst->d_blk_softlimit =
fs/xfs/xfs_quotaops.c +2 -18
@@ -27,20 +27,6 @@#include "xfs_qm.h" #include <linux/quota.h> - -STATIC int -xfs_quota_type (int type) -{ -switch (type) { -case USRQUOTA : -return XFS_DQ_USER ; -case GRPQUOTA : -return XFS_DQ_GROUP ; -default : -return XFS_DQ_PROJ ; - } -} - STATIC int xfs_fs_get_xstate( struct super_block *sb,
@@ -107,8 +93,7 @@ xfs_fs_get_dqblk(if (!XFS_IS_QUOTA_ON (mp))return -ESRCH ; -return -xfs_qm_scall_getquota (mp,from_kqid (&init_user_ns, qid), -xfs_quota_type (qid.type), fdq); +return -xfs_qm_scall_getquota (mp, qid, fdq); }STATIC int
@@ -126,8 +111,7 @@ xfs_fs_set_dqblk(if (!XFS_IS_QUOTA_ON (mp))return -ESRCH ; -return -xfs_qm_scall_setqlim (mp,from_kqid (&init_user_ns, qid), -xfs_quota_type (qid.type), fdq); +return -xfs_qm_scall_setqlim (mp, qid, fdq); }const struct quotactl_ops xfs_quotactl_operations = {
Signature · 1 line
1.7.5.4
PATCH 11/14 xfs: Modify xfs_qm_dqget to take a struct kqid.
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
- Modify xfs_qm_dqget, xfs_qm_dqattach_one, and xfs_qm_qutoacheck_dqadjust to take a struct kqid instead of an id and type pair.
- Modify their callers to pass them a struct kqid.
- Move xfs_qutoa_type into xfs_dquot.c where it is now used.
--- fs/xfs/xfs_dquot.c | 24 +++++++++++++++++++----- fs/xfs/xfs_dquot.h | 4 ++-- fs/xfs/xfs_qm.c | 42 +++++++++++++++++++----------------------- fs/xfs/xfs_qm_bhv.c | 2 +- fs/xfs/xfs_qm_syscalls.c | 20 ++------------------ 5 files changed, 43 insertions(+), 49 deletions(-)
fs/xfs/xfs_dquot.c +19 -5
@@ -63,6 +63,19 @@ static struct kmem_zone *xfs_qm_dqzone;static struct lock_class_key xfs_dquot_other_class; +STATIC int +xfs_quota_type (int type) +{ +switch (type) { +case USRQUOTA : +return XFS_DQ_USER ; +case GRPQUOTA : +return XFS_DQ_GROUP ; +default : +return XFS_DQ_PROJ ; + } +} +/* * This is called to free all the memory associated with a dquot */
@@ -696,20 +709,21 @@ intxfs_qm_dqget ( xfs_mount_t *mp, xfs_inode_t *ip,/* locked inode (optional) */ - xfs_dqid_t id, /* uid/projid/gid depending on type */ - uint type, /* XFS_DQ_USER/XFS_DQ_PROJ/XFS_DQ_GROUP */ + struct kqid qid, /* uid/projid/gid depending on type */ uint flags, /* DQALLOC, DQSUSER, DQREPAIR, DOWARN */ xfs_dquot_t **O_dqpp) /* OUT : locked incore dquot */ {struct xfs_quotainfo *qi = mp->m_quotainfo; +uint id =from_kqid (&init_user_ns, qid); +uint type =xfs_quota_type (qid.type);struct radix_tree_root *tree =XFS_DQUOT_TREE (qi, type);struct xfs_dquot *dqp;int error;ASSERT (XFS_IS_QUOTA_RUNNING (mp)); -if ((!XFS_IS_UQUOTA_ON (mp) && type ==XFS_DQ_USER ) || - (!XFS_IS_PQUOTA_ON (mp) && type ==XFS_DQ_PROJ ) || - (!XFS_IS_GQUOTA_ON (mp) && type ==XFS_DQ_GROUP )) { +if ((!XFS_IS_UQUOTA_ON (mp) && qid.type ==USRQUOTA ) || + (!XFS_IS_PQUOTA_ON (mp) && qid.type ==PRJQUOTA ) || + (!XFS_IS_GQUOTA_ON (mp) && qid.type ==GRPQUOTA )) {return (ESRCH ); }
fs/xfs/xfs_dquot.h +2 -2
@@ -147,8 +147,8 @@ extern void xfs_qm_adjust_dqtimers(xfs_mount_t *, xfs_disk_dquot_t *);extern void xfs_qm_adjust_dqlimits (xfs_mount_t *,xfs_disk_dquot_t *); -extern int xfs_qm_dqget (xfs_mount_t *,xfs_inode_t *, -xfs_dqid_t ,uint ,uint ,xfs_dquot_t **); +extern int xfs_qm_dqget (xfs_mount_t *,xfs_inode_t *,struct kqid , +uint ,xfs_dquot_t **);extern void xfs_qm_dqput (xfs_dquot_t *);extern void xfs_dqlock2 (struct xfs_dquot *,struct xfs_dquot *);
fs/xfs/xfs_qm.c +19 -23
126 lines not on this page · raw message
fs/xfs/xfs_qm_bhv.c +1 -1
@@ -79,7 +79,7 @@ xfs_qm_statvfs(xfs_mount_t *mp = ip->i_mount;xfs_dquot_t *dqp; -if (!xfs_qm_dqget (mp,NULL , ip->i_d.di_projid,XFS_DQ_PROJ ,0 , &dqp)) { +if (!xfs_qm_dqget (mp,NULL ,make_kqid_projid (ip->i_d.di_projid),0 , &dqp)) {xfs_fill_statvfs_from_dquot (statp, dqp);xfs_qm_dqput (dqp); }
fs/xfs/xfs_qm_syscalls.c +2 -18
@@ -48,19 +48,6 @@ STATIC int xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *, STATIC uint xfs_qm_export_flags(uint); STATIC uint xfs_qm_export_qtype_flags(uint); -STATIC int -xfs_quota_type (int type) -{ -switch (type) { -case USRQUOTA : -return XFS_DQ_USER ; -case GRPQUOTA : -return XFS_DQ_GROUP ; -default : -return XFS_DQ_PROJ ; - } -} -/* * Turn off quota accounting and/or enforcement for all udquots and/or * gdquots. Called only at unmount time.
@@ -525,9 +512,7 @@ xfs_qm_scall_setqlim(* Get the dquot (locked), and join it to the transaction. * Allocate the dquot if this doesn't exist. */ -if ((error =xfs_qm_dqget (mp,NULL ,from_kqid (&init_user_ns, id), -xfs_quota_type (id.type), -XFS_QMOPT_DQALLOC , &dqp))) { +if ((error =xfs_qm_dqget (mp,NULL , id,XFS_QMOPT_DQALLOC , &dqp))) {xfs_trans_cancel (tp,XFS_TRANS_ABORT );ASSERT (error !=ENOENT ); goto out_unlock;
@@ -744,8 +729,7 @@ xfs_qm_scall_getquota(* we aren't passing the XFS_QMOPT_DOALLOC flag. If it doesn't * exist, we'll get ENOENT back. */ - error =xfs_qm_dqget (mp,NULL ,from_kqid (&init_user_ns, id), -xfs_quota_type (id.type),0 , &dqp); + error =xfs_qm_dqget (mp,NULL , id,0 , &dqp);if (error)return error;
Signature · 1 line
1.7.5.4
PATCH 12/14 xfs: Remember the kqid for a quota
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
- Add q_id to struct xfs_quota
- Modify xfs_qm_dqread to take a struct kqid, allowing xfs_qm_dqread to set q_id on fresh quota structures.
- Modify xfs_qm_dqget and xfs_qm_init_quota_info to pass a kqid to xfs_qm_dqread
--- fs/xfs/xfs_dquot.c | 12 ++++++------ fs/xfs/xfs_dquot.h | 3 ++- fs/xfs/xfs_qm.c | 9 +++++---- 3 files changed, 13 insertions(+), 11 deletions(-)
fs/xfs/xfs_dquot.c +6 -6
@@ -581,8 +581,7 @@ xfs_qm_dqtobp(int xfs_qm_dqread (struct xfs_mount *mp, -xfs_dqid_t id, -uint type, +struct kqid id,uint flags,struct xfs_dquot **O_dqpp) {
@@ -596,8 +595,9 @@ xfs_qm_dqread( dqp =kmem_zone_zalloc (xfs_qm_dqzone,KM_SLEEP ); - dqp->dq_flags = type; - dqp->q_core.d_id =cpu_to_be32 (id); + dqp->q_id = id; + dqp->dq_flags =xfs_quota_type (id.type); + dqp->q_core.d_id =cpu_to_be32 (from_kqid (&init_user_ns, id)); dqp->q_mount = mp;INIT_LIST_HEAD (&dqp->q_lru);mutex_init (&dqp->q_qlock);
@@ -615,7 +615,7 @@ xfs_qm_dqread(* Make sure group quotas have a different lock class than user * quotas. */ -if (!(type &XFS_DQ_USER )) +if (id.type !=USRQUOTA )lockdep_set_class (&dqp->q_qlock, &xfs_dquot_other_class);XFS_STATS_INC (xs_qm_dquot);
@@ -779,7 +779,7 @@ restart:if (ip)xfs_iunlock (ip,XFS_ILOCK_EXCL ); - error =xfs_qm_dqread (mp, id, type, flags, &dqp); + error =xfs_qm_dqread (mp, qid, flags, &dqp);if (ip)xfs_ilock (ip,XFS_ILOCK_EXCL );
fs/xfs/xfs_dquot.h +2 -1
@@ -36,6 +36,7 @@ struct xfs_trans;* The incore dquot structure */ typedef struct xfs_dquot { + struct kqid q_id; /* quota identifier */ uint dq_flags; /* various flags (XFS_DQ_*) */ struct list_head q_lru; /* global free list of dquots */ struct xfs_mount*q_mount; /* filesystem this relates to */
@@ -138,7 +139,7 @@ static inline xfs_dquot_t *xfs_inode_dquot(struct xfs_inode *ip, int type) XFS_DQ_TO_QINF(dqp)->qi_uquotaip : \ XFS_DQ_TO_QINF(dqp)->qi_gquotaip) -extern int xfs_qm_dqread (struct xfs_mount *,xfs_dqid_t ,uint , +extern int xfs_qm_dqread (struct xfs_mount *,struct kqid ,uint ,struct xfs_dquot **);extern void xfs_qm_dqdestroy (xfs_dquot_t *);extern int xfs_qm_dqflush (struct xfs_dquot *,struct xfs_buf **);
fs/xfs/xfs_qm.c +5 -4
@@ -673,10 +673,11 @@ xfs_qm_init_quotainfo(* Since we may not have done a quotacheck by this point, just read * the dquot without attaching it to any hashtables or lists. */ - error =xfs_qm_dqread (mp,0 , -XFS_IS_UQUOTA_RUNNING (mp) ?XFS_DQ_USER : - (XFS_IS_GQUOTA_RUNNING (mp) ?XFS_DQ_GROUP : -XFS_DQ_PROJ ), + error =xfs_qm_dqread (mp, +make_kqid (&init_user_ns, +XFS_IS_UQUOTA_RUNNING (mp) ?USRQUOTA : + (XFS_IS_GQUOTA_RUNNING (mp) ?GRPQUOTA : +PRJQUOTA ),0 ),XFS_QMOPT_DOWARN , &dqp);if (!error) {xfs_disk_dquot_t *ddqp = &dqp->q_core;
Signature · 1 line
1.7.5.4
PATCH 13/14 xfs: Use q_id instead of q_core.d_id.
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
- Use qid_lt on q_id when compariting two quota entries for order.
- Use qid_eq or !qid_eq when comparing a quota entry for equality or inequality.
- Use is_superquota when testing for the magic quota id of 0.
- Use make_kqid_uid, make_kqid_gid, and make_kqid_projid when comparing a quota id against a uids, gids, or projids as appropriate.
- For tracing use from_kqid and map to the init user namespace. Tracers outside of the initial user namespace are not allowed.
- For generating ondisk values continue to use q_core.d_id.
- For cases where we want an index and don't care which quota it is continue to use be32_to_cpu(...->q_core.d_id)
--- fs/xfs/xfs_dquot.c | 3 +-- fs/xfs/xfs_qm.c | 18 +++++++++--------- fs/xfs/xfs_trace.h | 2 +- fs/xfs/xfs_trans_dquot.c | 8 ++------ 4 files changed, 13 insertions(+), 18 deletions(-)
fs/xfs/xfs_dquot.c +1 -2
@@ -1086,8 +1086,7 @@ xfs_dqlock2( {if (d1 && d2) {ASSERT (d1 != d2); -if (be32_to_cpu (d1->q_core.d_id) > -be32_to_cpu (d2->q_core.d_id)) { +if (qid_lt (d2->q_id, d1->q_id)) {mutex_lock (&d2->q_qlock);mutex_lock_nested (&d1->q_qlock,XFS_QLOCK_NESTED ); }else {
fs/xfs/xfs_qm.c +9 -9
@@ -407,7 +407,7 @@ xfs_qm_dqattach_one(* hold the ilock. */ dqp = udqhint->q_gdquot; -if (dqp &&qid_eq (make_kqid (&init_user_ns, id.type,be32_to_cpu (dqp->q_core.d_id)), id)) { +if (dqp &&qid_eq (dqp->q_id, id)) {ASSERT (*IO_idqpp ==NULL ); *IO_idqpp =xfs_qm_dqhold (dqp);
@@ -1057,7 +1057,7 @@ xfs_qm_quotacheck_dqadjust(* * There are no timers for the default values set in the root dquot. */ -if (dqp->q_core.d_id) { +if (!is_superquota (dqp->q_id, &init_user_ns)) {xfs_qm_adjust_dqlimits (mp, &dqp->q_core);xfs_qm_adjust_dqtimers (mp, &dqp->q_core); }
@@ -1804,7 +1804,7 @@ xfs_qm_vop_chown_reserve( XFS_QMOPT_RES_RTBLKS :XFS_QMOPT_RES_REGBLKS ;if (XFS_IS_UQUOTA_ON (mp) && udqp && - !uid_eq (ip->i_d.di_uid, (uid_t )be32_to_cpu (udqp->q_core.d_id))) { + !qid_eq (make_kqid_uid (ip->i_d.di_uid), udqp->q_id)) { delblksudq = udqp;/* * If there are delayed allocation blocks, then we have to
@@ -1818,12 +1818,12 @@ xfs_qm_vop_chown_reserve( }if (XFS_IS_OQUOTA_ON (ip->i_mount) && gdqp) {if (XFS_IS_PQUOTA_ON (ip->i_mount) && - !projid_eq (ip->i_d.di_projid,be32_to_cpu (gdqp->q_core.d_id))) + !qid_eq (make_kqid_projid (ip->i_d.di_projid), gdqp->q_id)) prjflags =XFS_QMOPT_ENOSPC ;if (prjflags || (XFS_IS_GQUOTA_ON (ip->i_mount) && - !gid_eq (ip->i_d.di_gid,be32_to_cpu (gdqp->q_core.d_id)))) { + !qid_eq (make_kqid_gid (ip->i_d.di_gid), gdqp->q_id))) { delblksgdq = gdqp;if (delblks) {ASSERT (ip->i_gdquot);
@@ -1907,7 +1907,7 @@ xfs_qm_vop_create_dqattach(if (udqp) {ASSERT (ip->i_udquot ==NULL );ASSERT (XFS_IS_UQUOTA_ON (mp)); -ASSERT (uid_eq (ip->i_d.di_uid,be32_to_cpu (udqp->q_core.d_id))); +ASSERT (qid_eq (make_kqid_uid (ip->i_d.di_uid), udqp->q_id)); ip->i_udquot =xfs_qm_dqhold (udqp);xfs_trans_mod_dquot (tp, udqp,XFS_TRANS_DQ_ICOUNT ,1 );
@@ -1915,9 +1915,9 @@ xfs_qm_vop_create_dqattach(if (gdqp) {ASSERT (ip->i_gdquot ==NULL );ASSERT (XFS_IS_OQUOTA_ON (mp)); -ASSERT (XFS_IS_GQUOTA_ON (mp) ? -gid_eq (ip->i_d.di_gid,be32_to_cpu (gdqp->q_core.d_id)): -projid_eq (ip->i_d.di_projid,be32_to_cpu (gdqp->q_core.d_id))); +ASSERT (qid_eq (XFS_IS_GQUOTA_ON (mp) ? +make_kqid_gid (ip->i_d.di_gid) : +make_kqid_projid (ip->i_d.di_projid), gdqp->q_id)); ip->i_gdquot =xfs_qm_dqhold (gdqp);xfs_trans_mod_dquot (tp, gdqp,XFS_TRANS_DQ_ICOUNT ,1 );
fs/xfs/xfs_trace.h +1 -1
@@ -713,7 +713,7 @@ DECLARE_EVENT_CLASS(xfs_dquot_class, ), \ TP_fast_assign( __entry->dev = dqp->q_mount->m_super->s_dev; - __entry->id =be32_to_cpu (dqp->q_core.d_id); + __entry->id =from_kqid (&init_user_ns, dqp->q_id); __entry->flags = dqp->dq_flags; __entry->nrefs = dqp->q_nrefs; __entry->res_bcount = dqp->q_res_bcount;
fs/xfs/xfs_trans_dquot.c +2 -6
@@ -578,11 +578,7 @@ xfs_quota_warn(/* no warnings for project quotas - we just return ENOSPC later */ if (dqp->dq_flags &XFS_DQ_PROJ )return ; -quota_send_warning (make_kqid (&init_user_ns, - (dqp->dq_flags &XFS_DQ_USER ) ? -USRQUOTA :GRPQUOTA , -be32_to_cpu (dqp->q_core.d_id)), - mp->m_super->s_dev, type); +quota_send_warning (dqp->q_id, mp->m_super->s_dev, type); }/*
@@ -638,7 +634,7 @@ xfs_trans_dqresv( }if ((flags &XFS_QMOPT_FORCE_RES ) ==0 && - dqp->q_core.d_id && + !is_superquota (dqp->q_id, &init_user_ns) && ((XFS_IS_UQUOTA_ENFORCED (dqp->q_mount) &&XFS_QM_ISUDQ (dqp)) || (XFS_IS_OQUOTA_ENFORCED (dqp->q_mount) && (XFS_QM_ISPDQ (dqp) ||XFS_QM_ISGDQ (dqp))))) {
Signature · 1 line
1.7.5.4
PATCH 14/14 xfs: Enable building with user namespaces enabled.
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Not that all of the types holding uids, gids, and projectids have been converted it is safe to allow users in different user namespaces to access an xfs filesystem.
--- init/Kconfig | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
init/Kconfig +0 -1
@@ -1068,7 +1068,6 @@ config UIDGID_CONVERTED default y # Filesystems - depends on XFS_FS = n config UIDGID_STRICT_TYPE_CHECKS bool "Require conversions between uid/gids and their internal representation"
Signature · 1 line
1.7.5.4
PATCH 2/14 xfs: Separate the in core and the logged inode.
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
Add xfs_inode_from_disk xfs_inode_to_disk and xfs_inode_to_log to handle changes.
Add an extra copy of struct xfs_icdinode into struct xfs_inode_log_item ultimately it will be the only copy but for the moment it is a temporary copy.
In struct xfs_inode change the type of i_d to an anonymous structure with all of the same members as struct xfs_icdinode.
Modify the two places that create a pointer to ip->i_d as a shortcut to get shorter names to use ip->i_d directly.
--- fs/xfs/xfs_icache.c | 2 +- fs/xfs/xfs_inode.c | 138 ++++++++++++++++++++++++++++++++++------------- fs/xfs/xfs_inode.h | 31 ++++++++++- fs/xfs/xfs_inode_item.c | 3 +- fs/xfs/xfs_inode_item.h | 1 + fs/xfs/xfs_itable.c | 45 +++++++-------- 6 files changed, 155 insertions(+), 65 deletions(-)
fs/xfs/xfs_icache.c +1 -1
@@ -82,7 +82,7 @@ xfs_inode_alloc(memset (&ip->i_df,0 ,sizeof (xfs_ifork_t)); ip->i_flags =0 ; ip->i_delayed_blks =0 ; -memset (&ip->i_d,0 ,sizeof (xfs_icdinode_t)); +memset (&ip->i_d,0 ,sizeof (ip->i_d));return ip; }
fs/xfs/xfs_inode.c +101 -39
164 lines not on this page · raw message
fs/xfs/xfs_inode.h +30 -1
@@ -243,7 +243,34 @@ typedef struct xfs_inode {unsigned long i_flags;/* see defined flags below */ unsigned int i_delayed_blks;/* count of delay alloc blks */ -xfs_icdinode_t i_d;/* most of ondisk inode */ +struct { +u16 di_magic;/* inode magic # = XFS_DINODE_MAGIC */ +u16 di_mode;/* mode and type of file */ +s8 di_version;/* inode version */ +s8 di_format;/* format of di_c data */ +u16 di_onlink;/* old number of links to file */ +u32 di_uid;/* owner's user id */ +u32 di_gid;/* owner's group id */ +u32 di_nlink;/* number of links to file */ +u16 di_projid_lo;/* lower part of owner's project id */ +u16 di_projid_hi;/* higher part of owner's project id */ +u8 di_pad[6 ];/* unused, zeroed space */ +u16 di_flushiter;/* incremented on flush */ +xfs_ictimestamp_t di_atime;/* time last accessed */ +xfs_ictimestamp_t di_mtime;/* time last modified */ +xfs_ictimestamp_t di_ctime;/* time created/inode modified */ +xfs_fsize_t di_size;/* number of bytes in file */ +xfs_drfsbno_t di_nblocks;/* # of direct & btree blocks used */ +xfs_extlen_t di_extsize;/* basic/minimum extent size for file */ +xfs_extnum_t di_nextents;/* number of extents in data fork */ +xfs_aextnum_t di_anextents;/* number of extents in attribute fork*/ +u8 di_forkoff;/* attr fork offs, <<3 for 64b align */ +s8 di_aformat;/* format of attr fork's data */ +u32 di_dmevmask;/* DMIG event mask */ +u16 di_dmstate;/* DMIG state info */ +u16 di_flags;/* random flags, XFS_DIFLAG_... */ +u32 di_gen;/* generation number */ + } i_d;/* most of ondisk inode */ /* VFS inode */ struct inode i_vnode;/* embedded VFS inode */
@@ -550,6 +577,8 @@ do { \#define XFS_IGET_UNTRUSTED 0x2#define XFS_IGET_DONTCACHE 0x4 +void xfs_inode_to_log (struct xfs_icdinode *to,struct xfs_inode *from); +int xfs_imap_to_bp (struct xfs_mount *,struct xfs_trans *,struct xfs_imap *,struct xfs_dinode **,struct xfs_buf **,uint ,uint );
fs/xfs/xfs_inode_item.c +2 -1
@@ -178,7 +178,7 @@ xfs_inode_item_format( vecp++; nvecs =1 ; - vecp->i_addr = &ip->i_d; + vecp->i_addr = &iip->ili_d; vecp->i_len =sizeof (struct xfs_icdinode ); vecp->i_type =XLOG_REG_TYPE_ICORE ; vecp++;
@@ -212,6 +212,7 @@ xfs_inode_item_format(memset (&(ip->i_d.di_pad[0 ]),0 ,sizeof (ip->i_d.di_pad)); } } +xfs_inode_to_log (&iip->ili_d, ip);switch (ip->i_d.di_format) {case XFS_DINODE_FMT_EXTENTS :
fs/xfs/xfs_inode_item.h +1 -0
@@ -138,6 +138,7 @@ struct xfs_mount; typedef struct xfs_inode_log_item { xfs_log_item_t ili_item; /* common portion */ struct xfs_inode *ili_inode; /* inode ptr */ + struct xfs_icdinode ili_d; /* most of ondisk inode */ xfs_lsn_t ili_flush_lsn; /* lsn at last flush */ xfs_lsn_t ili_last_lsn; /* lsn at last transaction */ unsigned short ili_lock_flags; /* lock flags */
fs/xfs/xfs_itable.c +21 -24
71 lines not on this page · raw message
Signature · 1 line
1.7.5.4
PATCH 3/14 xfs: Store projectid as a single variable.
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
xfs_get_projid is torturous to read and when you don't have the justification of maintaining an on-disk ABI there is really no point. So merge di_projid_lo and di_projid_hi in xfs_inode into di_projid. That is cheaper to read and cheaper to write and can handle future needs. Update all callers of xfs_get_projid and xfs_set_projid to use i_d.di_projid instead.
--- fs/xfs/xfs_icache.c | 2 +- fs/xfs/xfs_inode.c | 18 +++++++++--------- fs/xfs/xfs_inode.h | 22 +--------------------- fs/xfs/xfs_ioctl.c | 8 ++++---- fs/xfs/xfs_iops.c | 2 +- fs/xfs/xfs_itable.c | 4 ++-- fs/xfs/xfs_qm.c | 10 +++++----- fs/xfs/xfs_qm_bhv.c | 2 +- fs/xfs/xfs_rename.c | 2 +- fs/xfs/xfs_vnodeops.c | 6 +++--- 10 files changed, 28 insertions(+), 48 deletions(-)
fs/xfs/xfs_icache.c +1 -1
@@ -1210,7 +1210,7 @@ xfs_inode_match_id(return 0 ;if (eofb->eof_flags &XFS_EOF_FLAGS_PRID && -xfs_get_projid (ip) != eofb->eof_prid) + ip->i_d.di_projid != eofb->eof_prid)return 0 ;return 1 ;
fs/xfs/xfs_inode.c +9 -9
@@ -842,8 +842,8 @@ static void xfs_inode_from_disk(struct xfs_inode *to, struct xfs_dinode *from) to->i_d.di_uid =be32_to_cpu (from->di_uid); to->i_d.di_gid =be32_to_cpu (from->di_gid); to->i_d.di_nlink =be32_to_cpu (from->di_nlink); - to->i_d.di_projid_lo =be16_to_cpu (from->di_projid_lo); - to->i_d.di_projid_hi =be16_to_cpu (from->di_projid_hi); + to->i_d.di_projid = (((u32 )be16_to_cpu (from->di_projid_hi)) <<16 ) | +be16_to_cpu (from->di_projid_lo);memcpy (to->i_d.di_pad, from->di_pad,sizeof (to->i_d.di_pad)); to->i_d.di_flushiter =be16_to_cpu (from->di_flushiter); to->i_d.di_atime.t_sec =be32_to_cpu (from->di_atime.t_sec);
@@ -875,8 +875,8 @@ static void xfs_inode_to_disk(struct xfs_dinode *to, struct xfs_inode *from) to->di_uid =cpu_to_be32 (from->i_d.di_uid); to->di_gid =cpu_to_be32 (from->i_d.di_gid); to->di_nlink =cpu_to_be32 (from->i_d.di_nlink); - to->di_projid_lo =cpu_to_be16 (from->i_d.di_projid_lo); - to->di_projid_hi =cpu_to_be16 (from->i_d.di_projid_hi); + to->di_projid_lo =cpu_to_be16 (from->i_d.di_projid &0xffff ); + to->di_projid_hi =cpu_to_be16 (from->i_d.di_projid >>16 );memcpy (to->di_pad, from->i_d.di_pad,sizeof (to->di_pad)); to->di_flushiter =cpu_to_be16 (from->i_d.di_flushiter); to->di_atime.t_sec =cpu_to_be32 (from->i_d.di_atime.t_sec);
@@ -909,8 +909,8 @@ void xfs_inode_to_log(struct xfs_icdinode *to, struct xfs_inode *from) to->di_uid = from->i_d.di_uid; to->di_gid = from->i_d.di_gid; to->di_nlink = from->i_d.di_nlink; - to->di_projid_lo = from->i_d.di_projid_lo; - to->di_projid_hi = from->i_d.di_projid_hi; + to->di_projid_lo = from->i_d.di_projid &0xffff ; + to->di_projid_hi = from->i_d.di_projid >>16 ;memcpy (to->di_pad, from->i_d.di_pad,sizeof (to->di_pad)); to->di_flushiter = from->i_d.di_flushiter; to->di_atime.t_sec = from->i_d.di_atime.t_sec;
@@ -1112,7 +1112,7 @@ xfs_iread(if (ip->i_d.di_version ==1 ) { ip->i_d.di_nlink = ip->i_d.di_onlink; ip->i_d.di_onlink =0 ; -xfs_set_projid (ip,0 ); + ip->i_d.di_projid =0 ; } ip->i_delayed_blks =0 ;
@@ -1261,7 +1261,7 @@ xfs_ialloc(ASSERT (ip->i_d.di_nlink == nlink); ip->i_d.di_uid =current_fsuid (); ip->i_d.di_gid =current_fsgid (); -xfs_set_projid (ip, prid); + ip->i_d.di_projid = prid;memset (&(ip->i_d.di_pad[0 ]),0 ,sizeof (ip->i_d.di_pad));/*
@@ -2895,7 +2895,7 @@ xfs_iflush_int(memset (&(ip->i_d.di_pad[0 ]),0 ,sizeof (ip->i_d.di_pad));memset (&(dip->di_pad[0 ]),0 ,sizeof (dip->di_pad)); -ASSERT (xfs_get_projid (ip) ==0 ); +ASSERT (ip->i_d.di_projid ==0 ); } }
fs/xfs/xfs_inode.h +1 -21
@@ -252,8 +252,7 @@ typedef struct xfs_inode {u32 di_uid;/* owner's user id */ u32 di_gid;/* owner's group id */ u32 di_nlink;/* number of links to file */ -u16 di_projid_lo;/* lower part of owner's project id */ -u16 di_projid_hi;/* higher part of owner's project id */ +projid_t di_projid;/* owner's project id */ u8 di_pad[6 ];/* unused, zeroed space */ u16 di_flushiter;/* incremented on flush */ xfs_ictimestamp_t di_atime;/* time last accessed */
@@ -382,25 +381,6 @@ xfs_iflags_test_and_set(xfs_inode_t *ip, unsigned short flags) }/* -* Project quota id helpers (previously projid was 16bit only -* and using two 16bit values to hold new 32bit projid was chosen -* to retain compatibility with "old" filesystems). -*/ -static inline prid_t -xfs_get_projid (struct xfs_inode *ip) -{ -return (prid_t )ip->i_d.di_projid_hi <<16 | ip->i_d.di_projid_lo; -} - -static inline void -xfs_set_projid (struct xfs_inode *ip, -prid_t projid) -{ - ip->i_d.di_projid_hi = (__uint16_t) (projid >>16 ); - ip->i_d.di_projid_lo = (__uint16_t) (projid &0xffff ); -} - -/* * In-core inode flags. */ #define XFS_IRECLAIM (1 << 0)/* started reclaiming this inode */
fs/xfs/xfs_ioctl.c +4 -4
@@ -815,7 +815,7 @@ xfs_ioc_fsgetxattr(xfs_ilock (ip,XFS_ILOCK_SHARED ); fa.fsx_xflags =xfs_ip2xflags (ip); fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog; - fa.fsx_projid =xfs_get_projid (ip); + fa.fsx_projid = ip->i_d.di_projid;if (attr) {if (ip->i_afp) {
@@ -986,7 +986,7 @@ xfs_ioctl_setattr(if (mask &FSX_PROJID ) {if (XFS_IS_QUOTA_RUNNING (mp) &&XFS_IS_PQUOTA_ON (mp) && -xfs_get_projid (ip) != fa->fsx_projid) { + ip->i_d.di_projid != fa->fsx_projid) {ASSERT (tp); code = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp, capable(CAP_FOWNER) ?
@@ -1104,12 +1104,12 @@ xfs_ioctl_setattr(* Change the ownerships and register quota modifications * in the transaction. */ -if (xfs_get_projid (ip) != fa->fsx_projid) { +if (ip->i_d.di_projid != fa->fsx_projid) {if (XFS_IS_QUOTA_RUNNING (mp) &&XFS_IS_PQUOTA_ON (mp)) { olddquot =xfs_qm_vop_chown (tp, ip, &ip->i_gdquot, gdqp); } -xfs_set_projid (ip, fa->fsx_projid); + ip->i_d.di_projid = fa->fsx_projid;/* * We may have to rev the inode as well as
fs/xfs/xfs_iops.c +1 -1
@@ -516,7 +516,7 @@ xfs_setattr_nonsize(*/ ASSERT (udqp ==NULL );ASSERT (gdqp ==NULL ); - error =xfs_qm_vop_dqalloc (ip, uid, gid,xfs_get_projid (ip), + error =xfs_qm_vop_dqalloc (ip, uid, gid, ip->i_d.di_projid, qflags, &udqp, &gdqp);if (error)return error;
fs/xfs/xfs_itable.c +2 -2
@@ -88,8 +88,8 @@ xfs_bulkstat_one_int(* further change. */ buf->bs_nlink = ip->i_d.di_nlink; - buf->bs_projid_lo = ip->i_d.di_projid_lo; - buf->bs_projid_hi = ip->i_d.di_projid_hi; + buf->bs_projid_lo = (u16)(ip->i_d.di_projid &0xffff ); + buf->bs_projid_hi = (u16)(ip->i_d.di_projid >>16 ); buf->bs_ino = ino; buf->bs_mode = ip->i_d.di_mode; buf->bs_uid = ip->i_d.di_uid;
fs/xfs/xfs_qm.c +5 -5
@@ -530,7 +530,7 @@ xfs_qm_dqattach_locked( xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP, flags & XFS_QMOPT_DQALLOC, ip->i_udquot, &ip->i_gdquot) : -xfs_qm_dqattach_one (ip,xfs_get_projid (ip),XFS_DQ_PROJ , +xfs_qm_dqattach_one (ip, ip->i_d.di_projid,XFS_DQ_PROJ , flags &XFS_QMOPT_DQALLOC , ip->i_udquot, &ip->i_gdquot);/*
@@ -1172,7 +1172,7 @@ xfs_qm_dqusage_adjust( }if (XFS_IS_PQUOTA_ON (mp)) { - error =xfs_qm_quotacheck_dqadjust (ip,xfs_get_projid (ip), + error =xfs_qm_quotacheck_dqadjust (ip, ip->i_d.di_projid,XFS_DQ_PROJ , nblks, rtblks);if (error) goto error0;
@@ -1704,7 +1704,7 @@ xfs_qm_vop_dqalloc( gq = xfs_qm_dqhold(ip->i_gdquot); } } else if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) { - if (xfs_get_projid(ip) != prid) { + if (ip->i_d.di_projid != prid) { xfs_iunlock(ip, lockflags); if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid, XFS_DQ_PROJ,
@@ -1819,7 +1819,7 @@ xfs_qm_vop_chown_reserve( }if (XFS_IS_OQUOTA_ON (ip->i_mount) && gdqp) {if (XFS_IS_PQUOTA_ON (ip->i_mount) && -xfs_get_projid (ip) !=be32_to_cpu (gdqp->q_core.d_id)) + ip->i_d.di_projid !=be32_to_cpu (gdqp->q_core.d_id)) prjflags =XFS_QMOPT_ENOSPC ; if (prjflags ||
@@ -1917,7 +1917,7 @@ xfs_qm_vop_create_dqattach(ASSERT (ip->i_gdquot ==NULL );ASSERT (XFS_IS_OQUOTA_ON (mp));ASSERT ((XFS_IS_GQUOTA_ON (mp) ? - ip->i_d.di_gid :xfs_get_projid (ip)) == + ip->i_d.di_gid : ip->i_d.di_projid) ==be32_to_cpu (gdqp->q_core.d_id)); ip->i_gdquot =xfs_qm_dqhold (gdqp);
fs/xfs/xfs_qm_bhv.c +1 -1
@@ -79,7 +79,7 @@ xfs_qm_statvfs(xfs_mount_t *mp = ip->i_mount;xfs_dquot_t *dqp; -if (!xfs_qm_dqget (mp,NULL ,xfs_get_projid (ip),XFS_DQ_PROJ ,0 , &dqp)) { +if (!xfs_qm_dqget (mp,NULL , ip->i_d.di_projid,XFS_DQ_PROJ ,0 , &dqp)) {xfs_fill_statvfs_from_dquot (statp, dqp);xfs_qm_dqput (dqp); }
fs/xfs/xfs_rename.c +1 -1
@@ -171,7 +171,7 @@ xfs_rename(* tree quota mechanism would be circumvented. */ if (unlikely ((target_dp->i_d.di_flags &XFS_DIFLAG_PROJINHERIT ) && - (xfs_get_projid (target_dp) !=xfs_get_projid (src_ip)))) { + (target_dp->i_d.di_projid != src_ip->i_d.di_projid))) { error =XFS_ERROR (EXDEV ); goto error_return; }
fs/xfs/xfs_vnodeops.c +3 -3
@@ -741,7 +741,7 @@ xfs_create(return XFS_ERROR (EIO );if (dp->i_d.di_flags &XFS_DIFLAG_PROJINHERIT ) - prid =xfs_get_projid (dp); + prid = dp->i_d.di_projid;else prid =XFS_PROJID_DEFAULT ;
@@ -1305,7 +1305,7 @@ xfs_link(* the tree quota mechanism could be circumvented. */ if (unlikely ((tdp->i_d.di_flags &XFS_DIFLAG_PROJINHERIT ) && - (xfs_get_projid (tdp) !=xfs_get_projid (sip)))) { + (tdp->i_d.di_projid != sip->i_d.di_projid))) { error =XFS_ERROR (EXDEV ); goto error_return; }
@@ -1402,7 +1402,7 @@ xfs_symlink( udqp = gdqp =NULL ;if (dp->i_d.di_flags &XFS_DIFLAG_PROJINHERIT ) - prid =xfs_get_projid (dp); + prid = dp->i_d.di_projid;else prid =XFS_PROJID_DEFAULT ;
Signature · 6 lines
1.7.5.4 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
PATCH 4/14 xfs: Update inode uids, gids, and projids to be kuids, kgids, and kprojids
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
Update i_projid on struct xfs_inode to be of type kprojid_t.
Update the logic in xfs_inode_from_disk when the values are read from disk to convert their on-disk values into the internal kernel representation.
Update xfs_inode_to_disk and xfs_inode_to_log to convert from the internal kernel representation to the on-disk values when updating the on-disk fields.
Update comparisons against these fields to use uid_eq, gid_eq and projid_eq.
--- fs/xfs/xfs_icache.c | 6 +++--- fs/xfs/xfs_inode.c | 37 +++++++++++++++++++++++-------------- fs/xfs/xfs_inode.h | 6 +++--- fs/xfs/xfs_ioctl.c | 8 ++++---- fs/xfs/xfs_itable.c | 10 ++++++---- fs/xfs/xfs_qm.c | 20 ++++++++++---------- fs/xfs/xfs_rename.c | 2 +- fs/xfs/xfs_vnodeops.c | 2 +- 8 files changed, 51 insertions(+), 40 deletions(-)
fs/xfs/xfs_icache.c +3 -3
@@ -1202,15 +1202,15 @@ xfs_inode_match_id( struct xfs_eofblocks *eofb) {if (eofb->eof_flags &XFS_EOF_FLAGS_UID && - ip->i_d.di_uid != eofb->eof_uid) + !uid_eq (ip->i_d.di_uid, eofb->eof_uid))return 0 ;if (eofb->eof_flags &XFS_EOF_FLAGS_GID && - ip->i_d.di_gid != eofb->eof_gid) + !gid_eq (ip->i_d.di_gid, eofb->eof_gid))return 0 ;if (eofb->eof_flags &XFS_EOF_FLAGS_PRID && - ip->i_d.di_projid != eofb->eof_prid) + !projid_eq (ip->i_d.di_projid, eofb->eof_prid))return 0 ;return 1 ;
fs/xfs/xfs_inode.c +23 -14
@@ -834,16 +834,18 @@ xfs_iformat_btree(static void xfs_inode_from_disk (struct xfs_inode *to,struct xfs_dinode *from) { +projid_t projid; to->i_d.di_magic =be16_to_cpu (from->di_magic); to->i_d.di_mode =be16_to_cpu (from->di_mode); to->i_d.di_version = from ->di_version; to->i_d.di_format = from->di_format; to->i_d.di_onlink =be16_to_cpu (from->di_onlink); - to->i_d.di_uid =be32_to_cpu (from->di_uid); - to->i_d.di_gid =be32_to_cpu (from->di_gid); + to->i_d.di_uid =make_kuid (&init_user_ns,be32_to_cpu (from->di_uid)); + to->i_d.di_gid =make_kgid (&init_user_ns,be32_to_cpu (from->di_gid)); to->i_d.di_nlink =be32_to_cpu (from->di_nlink); - to->i_d.di_projid = (((u32 )be16_to_cpu (from->di_projid_hi)) <<16 ) | + projid = (((u32 )be16_to_cpu (from->di_projid_hi)) <<16 ) |be16_to_cpu (from->di_projid_lo); + to->i_d.di_projid =make_kprojid (&init_user_ns, projid);memcpy (to->i_d.di_pad, from->di_pad,sizeof (to->i_d.di_pad)); to->i_d.di_flushiter =be16_to_cpu (from->di_flushiter); to->i_d.di_atime.t_sec =be32_to_cpu (from->di_atime.t_sec);
@@ -867,16 +869,19 @@ static void xfs_inode_from_disk(struct xfs_inode *to, struct xfs_dinode *from)static void xfs_inode_to_disk (struct xfs_dinode *to,struct xfs_inode *from) { +uid_t uid =from_kuid (&init_user_ns, from->i_d.di_uid); +gid_t gid =from_kgid (&init_user_ns, from->i_d.di_gid); +projid_t projid =from_kprojid (&init_user_ns, from->i_d.di_projid); to->di_magic =cpu_to_be16 (from->i_d.di_magic); to->di_mode =cpu_to_be16 (from->i_d.di_mode); to->di_version = from->i_d.di_version; to->di_format = from->i_d.di_format; to->di_onlink =cpu_to_be16 (from->i_d.di_onlink); - to->di_uid =cpu_to_be32 (from->i_d.di_uid); - to->di_gid =cpu_to_be32 (from->i_d.di_gid); + to->di_uid =cpu_to_be32 (uid); + to->di_gid =cpu_to_be32 (gid); to->di_nlink =cpu_to_be32 (from->i_d.di_nlink); - to->di_projid_lo =cpu_to_be16 (from->i_d.di_projid &0xffff ); - to->di_projid_hi =cpu_to_be16 (from->i_d.di_projid >>16 ); + to->di_projid_lo =cpu_to_be16 (projid &0xffff ); + to->di_projid_hi =cpu_to_be16 (projid >>16 );memcpy (to->di_pad, from->i_d.di_pad,sizeof (to->di_pad)); to->di_flushiter =cpu_to_be16 (from->i_d.di_flushiter); to->di_atime.t_sec =cpu_to_be32 (from->i_d.di_atime.t_sec);
@@ -901,16 +906,19 @@ static void xfs_inode_to_disk(struct xfs_dinode *to, struct xfs_inode *from)void xfs_inode_to_log (struct xfs_icdinode *to,struct xfs_inode *from) {/* xfs_inode_to_disk without the endian changes */ +uid_t uid =from_kuid (&init_user_ns, from->i_d.di_uid); +gid_t gid =from_kgid (&init_user_ns, from->i_d.di_gid); +projid_t projid =from_kprojid (&init_user_ns, from->i_d.di_projid); to->di_magic = from->i_d.di_magic; to->di_mode = from->i_d.di_mode; to->di_version = from->i_d.di_version; to->di_format = from->i_d.di_format; to->di_onlink = from->i_d.di_onlink; - to->di_uid = from->i_d.di_uid; - to->di_gid = from->i_d.di_gid; + to->di_uid = uid; + to->di_gid = gid; to->di_nlink = from->i_d.di_nlink; - to->di_projid_lo = from->i_d.di_projid &0xffff ; - to->di_projid_hi = from->i_d.di_projid >>16 ; + to->di_projid_lo = projid &0xffff ; + to->di_projid_hi = projid >>16 ;memcpy (to->di_pad, from->i_d.di_pad,sizeof (to->di_pad)); to->di_flushiter = from->i_d.di_flushiter; to->di_atime.t_sec = from->i_d.di_atime.t_sec;
@@ -1112,7 +1120,7 @@ xfs_iread(if (ip->i_d.di_version ==1 ) { ip->i_d.di_nlink = ip->i_d.di_onlink; ip->i_d.di_onlink =0 ; - ip->i_d.di_projid =0 ; + ip->i_d.di_projid =make_kprojid (&init_user_ns,0 ); } ip->i_delayed_blks =0 ;
@@ -1299,7 +1307,7 @@ xfs_ialloc(*/ if ((irix_sgid_inherit) && (ip->i_d.di_mode &S_ISGID ) && - (!in_group_p ((gid_t )ip->i_d.di_gid))) { + (!in_group_p (ip->i_d.di_gid))) { ip->i_d.di_mode &= ~S_ISGID ; }
@@ -2895,7 +2903,8 @@ xfs_iflush_int(memset (&(ip->i_d.di_pad[0 ]),0 ,sizeof (ip->i_d.di_pad));memset (&(dip->di_pad[0 ]),0 ,sizeof (dip->di_pad)); -ASSERT (ip->i_d.di_projid ==0 ); +ASSERT (projid_eq (ip->i_d.di_projid, +make_kprojid (&init_user_ns,0 ))); } }
fs/xfs/xfs_inode.h +3 -3
@@ -249,10 +249,10 @@ typedef struct xfs_inode {s8 di_version;/* inode version */ s8 di_format;/* format of di_c data */ u16 di_onlink;/* old number of links to file */ -u32 di_uid;/* owner's user id */ -u32 di_gid;/* owner's group id */ +kuid_t di_uid;/* owner's user id */ +kgid_t di_gid;/* owner's group id */ u32 di_nlink;/* number of links to file */ -projid_t di_projid;/* owner's project id */ +kprojid_t di_projid;/* owner's project id */ u8 di_pad[6 ];/* unused, zeroed space */ u16 di_flushiter;/* incremented on flush */ xfs_ictimestamp_t di_atime;/* time last accessed */
fs/xfs/xfs_ioctl.c +4 -4
@@ -815,7 +815,7 @@ xfs_ioc_fsgetxattr(xfs_ilock (ip,XFS_ILOCK_SHARED ); fa.fsx_xflags =xfs_ip2xflags (ip); fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog; - fa.fsx_projid = ip->i_d.di_projid; + fa.fsx_projid =from_kprojid_munged (current_user_ns (), ip->i_d.di_projid);if (attr) {if (ip->i_afp) {
@@ -975,7 +975,7 @@ xfs_ioctl_setattr(* to the file owner ID, except in cases where the * CAP_FSETID capability is applicable. */ -if (current_fsuid () != ip->i_d.di_uid && !capable (CAP_FOWNER )) { +if (!uid_eq (current_fsuid (), ip->i_d.di_uid) && !capable (CAP_FOWNER )) { code =XFS_ERROR (EPERM ); goto error_return; }
@@ -986,7 +986,7 @@ xfs_ioctl_setattr(if (mask &FSX_PROJID ) {if (XFS_IS_QUOTA_RUNNING (mp) &&XFS_IS_PQUOTA_ON (mp) && - ip->i_d.di_projid != fa->fsx_projid) { + !projid_eq (ip->i_d.di_projid, fa->fsx_projid)) {ASSERT (tp); code = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp, capable(CAP_FOWNER) ?
@@ -1104,7 +1104,7 @@ xfs_ioctl_setattr(* Change the ownerships and register quota modifications * in the transaction. */ -if (ip->i_d.di_projid != fa->fsx_projid) { +if (!projid_eq (ip->i_d.di_projid, fa->fsx_projid)) {if (XFS_IS_QUOTA_RUNNING (mp) &&XFS_IS_PQUOTA_ON (mp)) { olddquot =xfs_qm_vop_chown (tp, ip, &ip->i_gdquot, gdqp);
fs/xfs/xfs_itable.c +6 -4
@@ -63,6 +63,7 @@ xfs_bulkstat_one_int(struct xfs_inode *ip;/* incore inode pointer */ struct xfs_bstat *buf;/* return buffer */ int error =0 ;/* error value */ +projid_t projid; *stat =BULKSTAT_RV_NOTHING ;
@@ -88,12 +89,13 @@ xfs_bulkstat_one_int(* further change. */ buf->bs_nlink = ip->i_d.di_nlink; - buf->bs_projid_lo = (u16)(ip->i_d.di_projid &0xffff ); - buf->bs_projid_hi = (u16)(ip->i_d.di_projid >>16 ); + projid =from_kprojid_munged (current_user_ns (), ip->i_d.di_projid); + buf->bs_projid_lo = projid &0xffff ; + buf->bs_projid_hi = projid >>16 ; buf->bs_ino = ino; buf->bs_mode = ip->i_d.di_mode; - buf->bs_uid = ip->i_d.di_uid; - buf->bs_gid = ip->i_d.di_gid; + buf->bs_uid =from_kuid_munged (current_user_ns (), ip->i_d.di_uid); + buf->bs_gid =from_kgid_munged (current_user_ns (), ip->i_d.di_gid); buf->bs_size = ip->i_d.di_size; buf->bs_atime.tv_sec = ip->i_d.di_atime.t_sec; buf->bs_atime.tv_nsec = ip->i_d.di_atime.t_nsec;
fs/xfs/xfs_qm.c +10 -10
@@ -1649,7 +1649,7 @@ xfs_qm_vop_dqalloc( uq = gq =NULL ;if ((flags &XFS_QMOPT_UQUOTA ) &&XFS_IS_UQUOTA_ON (mp)) { -if (ip->i_d.di_uid != uid) { +if (!uid_eq (ip->i_d.di_uid, uid)) {/* * What we need is the dquot that has this uid, and * if we send the inode to dqget, the uid of the inode
@@ -1684,7 +1684,7 @@ xfs_qm_vop_dqalloc( } } if ((flags & XFS_QMOPT_GQUOTA) && XFS_IS_GQUOTA_ON(mp)) { - if (ip->i_d.di_gid != gid) { + if (!gid_eq(ip->i_d.di_gid, gid)) { xfs_iunlock(ip, lockflags); if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)gid, XFS_DQ_GROUP,
@@ -1704,7 +1704,7 @@ xfs_qm_vop_dqalloc( gq = xfs_qm_dqhold(ip->i_gdquot); } } else if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) { - if (ip->i_d.di_projid != prid) { + if (!projid_eq(ip->i_d.di_projid, prid)) { xfs_iunlock(ip, lockflags); if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid, XFS_DQ_PROJ,
@@ -1805,7 +1805,7 @@ xfs_qm_vop_chown_reserve( XFS_QMOPT_RES_RTBLKS :XFS_QMOPT_RES_REGBLKS ;if (XFS_IS_UQUOTA_ON (mp) && udqp && - ip->i_d.di_uid != (uid_t )be32_to_cpu (udqp->q_core.d_id)) { + !uid_eq (ip->i_d.di_uid, (uid_t )be32_to_cpu (udqp->q_core.d_id))) { delblksudq = udqp;/* * If there are delayed allocation blocks, then we have to
@@ -1819,12 +1819,12 @@ xfs_qm_vop_chown_reserve( }if (XFS_IS_OQUOTA_ON (ip->i_mount) && gdqp) {if (XFS_IS_PQUOTA_ON (ip->i_mount) && - ip->i_d.di_projid !=be32_to_cpu (gdqp->q_core.d_id)) + !projid_eq (ip->i_d.di_projid,be32_to_cpu (gdqp->q_core.d_id))) prjflags =XFS_QMOPT_ENOSPC ;if (prjflags || (XFS_IS_GQUOTA_ON (ip->i_mount) && - ip->i_d.di_gid !=be32_to_cpu (gdqp->q_core.d_id))) { + !gid_eq (ip->i_d.di_gid,be32_to_cpu (gdqp->q_core.d_id)))) { delblksgdq = gdqp;if (delblks) {ASSERT (ip->i_gdquot);
@@ -1908,7 +1908,7 @@ xfs_qm_vop_create_dqattach(if (udqp) {ASSERT (ip->i_udquot ==NULL );ASSERT (XFS_IS_UQUOTA_ON (mp)); -ASSERT (ip->i_d.di_uid ==be32_to_cpu (udqp->q_core.d_id)); +ASSERT (uid_eq (ip->i_d.di_uid,be32_to_cpu (udqp->q_core.d_id))); ip->i_udquot =xfs_qm_dqhold (udqp);xfs_trans_mod_dquot (tp, udqp,XFS_TRANS_DQ_ICOUNT ,1 );
@@ -1916,9 +1916,9 @@ xfs_qm_vop_create_dqattach(if (gdqp) {ASSERT (ip->i_gdquot ==NULL );ASSERT (XFS_IS_OQUOTA_ON (mp)); -ASSERT ((XFS_IS_GQUOTA_ON (mp) ? - ip->i_d.di_gid : ip->i_d.di_projid) == -be32_to_cpu (gdqp->q_core.d_id)); +ASSERT (XFS_IS_GQUOTA_ON (mp) ? +gid_eq (ip->i_d.di_gid,be32_to_cpu (gdqp->q_core.d_id)): +projid_eq (ip->i_d.di_projid,be32_to_cpu (gdqp->q_core.d_id))); ip->i_gdquot =xfs_qm_dqhold (gdqp);xfs_trans_mod_dquot (tp, gdqp,XFS_TRANS_DQ_ICOUNT ,1 );
fs/xfs/xfs_rename.c +1 -1
@@ -171,7 +171,7 @@ xfs_rename(* tree quota mechanism would be circumvented. */ if (unlikely ((target_dp->i_d.di_flags &XFS_DIFLAG_PROJINHERIT ) && - (target_dp->i_d.di_projid != src_ip->i_d.di_projid))) { + !projid_eq (target_dp->i_d.di_projid, src_ip->i_d.di_projid))) { error =XFS_ERROR (EXDEV ); goto error_return; }
fs/xfs/xfs_vnodeops.c +1 -1
@@ -1305,7 +1305,7 @@ xfs_link(* the tree quota mechanism could be circumvented. */ if (unlikely ((tdp->i_d.di_flags &XFS_DIFLAG_PROJINHERIT ) && - (tdp->i_d.di_projid != sip->i_d.di_projid))) { + !projid_eq (tdp->i_d.di_projid, sip->i_d.di_projid))) { error =XFS_ERROR (EXDEV ); goto error_return; }
Signature · 1 line
1.7.5.4
PATCH 5/14 xfs: Update xfs_ioctl_setattr to handle projids in any user namespace
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
- Convert the userspace value in fa->fsx_projid into a kprojid and store it in the variable projid.
- Verify that xfs can store the projid after it is converted into xfs's user namespace.
- Replace uses of fa->fsx_projid with projid throughout xfs_ioctl_setattr.
--- fs/xfs/xfs_ioctl.c | 26 ++++++++++++++++++-------- 1 files changed, 18 insertions(+), 8 deletions(-)
fs/xfs/xfs_ioctl.c +18 -8
@@ -925,6 +925,7 @@ xfs_ioctl_setattr(struct xfs_dquot *gdqp =NULL ;struct xfs_dquot *olddquot =NULL ;int code; +kprojid_t projid =INVALID_PROJID ;trace_xfs_ioctl_setattr (ip);
@@ -934,11 +935,20 @@ xfs_ioctl_setattr(return XFS_ERROR (EIO );/* -* Disallow 32bit project ids when projid32bit feature is not enabled. +* Verify the specifid project id is valid. */ -if ((mask &FSX_PROJID ) && (fa->fsx_projid > (__uint16_t)-1 ) && - !xfs_sb_version_hasprojid32bit (&ip->i_mount->m_sb)) -return XFS_ERROR (EINVAL ); +if (mask &FSX_PROJID ) { + projid =make_kprojid (current_user_ns (), fa->fsx_projid); +if (!projid_valid (projid)) +return XFS_ERROR (EINVAL ); + +/* +* Disallow 32bit project ids when projid32bit feature is not enabled. +*/ +if ((from_kprojid (&init_user_ns, projid) > (__uint16_t)-1 ) && + !xfs_sb_version_hasprojid32bit (&ip->i_mount->m_sb)) +return XFS_ERROR (EINVAL ); + }/* * If disk quotas is on, we make sure that the dquots do exist on disk,
@@ -950,7 +960,7 @@ xfs_ioctl_setattr(*/ if (XFS_IS_QUOTA_ON (mp) && (mask &FSX_PROJID )) { code =xfs_qm_vop_dqalloc (ip, ip->i_d.di_uid, - ip->i_d.di_gid, fa->fsx_projid, + ip->i_d.di_gid, projid,XFS_QMOPT_PQUOTA , &udqp, &gdqp);if (code)return code;
@@ -986,7 +996,7 @@ xfs_ioctl_setattr(if (mask &FSX_PROJID ) {if (XFS_IS_QUOTA_RUNNING (mp) &&XFS_IS_PQUOTA_ON (mp) && - !projid_eq (ip->i_d.di_projid, fa->fsx_projid)) { + !projid_eq (ip->i_d.di_projid, projid)) {ASSERT (tp); code = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp, capable(CAP_FOWNER) ?
@@ -1104,12 +1114,12 @@ xfs_ioctl_setattr(* Change the ownerships and register quota modifications * in the transaction. */ -if (!projid_eq (ip->i_d.di_projid, fa->fsx_projid)) { +if (!projid_eq (ip->i_d.di_projid, projid)) {if (XFS_IS_QUOTA_RUNNING (mp) &&XFS_IS_PQUOTA_ON (mp)) { olddquot =xfs_qm_vop_chown (tp, ip, &ip->i_gdquot, gdqp); } - ip->i_d.di_projid = fa->fsx_projid; + ip->i_d.di_projid = projid;/* * We may have to rev the inode as well as
Signature · 1 line
1.7.5.4
PATCH 7/14 xfs: Update ioctl(XFS_IOC_FREE_EOFBLOCKS) to handle callers in any userspace
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
- Modify the ioctl to convert from uids, gid, and projids in the current user namespace to kuids, kgids, and kprojids, and to report an error if the conversion fails.
- Create struct xfs_internal_eofblocks to hold the same information as struct xfs_eofblocks but with uids, gids, and projids stored as kuids, kgids, and kprojids preventing confusion.
- Pass struct xfs_interanl_eofblocks into xfs_icache_free_eofblocks and it's helpers ensuring there will not be confusing about which user namespace identifiers that need to be compared are in.
--- fs/xfs/xfs_icache.c | 8 ++++---- fs/xfs/xfs_icache.h | 11 ++++++++++- fs/xfs/xfs_ioctl.c | 22 +++++++++++++++++++++- 3 files changed, 35 insertions(+), 6 deletions(-)
fs/xfs/xfs_icache.c +4 -4
@@ -1199,7 +1199,7 @@ xfs_reclaim_inodes_count( STATIC intxfs_inode_match_id (struct xfs_inode *ip, -struct xfs_eofblocks *eofb) +struct xfs_internal_eofblocks *eofb) {if (eofb->eof_flags &XFS_EOF_FLAGS_UID && !uid_eq (ip->i_d.di_uid, eofb->eof_uid))
@@ -1210,7 +1210,7 @@ xfs_inode_match_id(return 0 ;if (eofb->eof_flags &XFS_EOF_FLAGS_PRID && - !projid_eq (ip->i_d.di_projid, eofb->eof_prid)) + !projid_eq (ip->i_d.di_projid, eofb->eof_projid))return 0 ;return 1 ;
@@ -1224,7 +1224,7 @@ xfs_inode_free_eofblocks( void *args) {int ret; -struct xfs_eofblocks *eofb = args; +struct xfs_internal_eofblocks *eofb = args;if (!xfs_can_free_eofblocks (ip, false)) {/* inode could be preallocated or append-only */
@@ -1263,7 +1263,7 @@ xfs_inode_free_eofblocks(int xfs_icache_free_eofblocks (struct xfs_mount *mp, -struct xfs_eofblocks *eofb) +struct xfs_internal_eofblocks *eofb) {int flags =SYNC_TRYLOCK ;
fs/xfs/xfs_icache.h +10 -1
@@ -35,9 +35,18 @@ void xfs_reclaim_inodes_nr(struct xfs_mount *mp, int nr_to_scan);void xfs_inode_set_reclaim_tag (struct xfs_inode *ip); +struct xfs_internal_eofblocks { +u32 eof_version; +u32 eof_flags; +kuid_t eof_uid; +kgid_t eof_gid; +kprojid_t eof_projid; +u64 eof_min_file_size; +}; +void xfs_inode_set_eofblocks_tag (struct xfs_inode *ip);void xfs_inode_clear_eofblocks_tag (struct xfs_inode *ip); -int xfs_icache_free_eofblocks (struct xfs_mount *,struct xfs_eofblocks *); +int xfs_icache_free_eofblocks (struct xfs_mount *,struct xfs_internal_eofblocks *);void xfs_eofblocks_worker (struct work_struct *);int xfs_sync_inode_grab (struct xfs_inode *ip);
fs/xfs/xfs_ioctl.c +21 -1
@@ -1615,6 +1615,7 @@ xfs_file_ioctl(case XFS_IOC_FREE_EOFBLOCKS : {struct xfs_eofblocks eofb; +struct xfs_internal_eofblocks keofb;if (copy_from_user (&eofb, arg,sizeof (eofb)))return -XFS_ERROR (EFAULT );
@@ -1629,7 +1630,26 @@ xfs_file_ioctl( memchr_inv(eofb.pad64, 0, sizeof(eofb.pad64))) return -XFS_ERROR(EINVAL); - error =xfs_icache_free_eofblocks (mp, &eofb); + keofb.eof_version = eofb.eof_version; + keofb.eof_flags = eofb.eof_flags; +if (eofb.eof_flags &XFS_EOF_FLAGS_UID ) { + keofb.eof_uid =make_kuid (current_user_ns (), eofb.eof_uid); +if (!uid_valid (keofb.eof_uid)) +return -XFS_ERROR (EINVAL ); + } +if (eofb.eof_flags &XFS_EOF_FLAGS_GID ) { + keofb.eof_gid =make_kgid (current_user_ns (), eofb.eof_gid); +if (!gid_valid (keofb.eof_gid)) +return -XFS_ERROR (EINVAL ); + } +if (eofb.eof_flags &XFS_EOF_FLAGS_PRID ) { + keofb.eof_projid =make_kprojid (current_user_ns (), eofb.eof_prid); +if (!projid_valid (keofb.eof_projid)) +return -XFS_ERROR (EINVAL ); + } + keofb.eof_min_file_size = eofb.eof_min_file_size; + + error =xfs_icache_free_eofblocks (mp, &keofb);return -error; }
Signature · 1 line
1.7.5.4
PATCH 8/14 xfs: Use kprojids when allocating inodes.
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
In xfs_create and xfs_symlink compute the desired kprojid and pass it down into xfs_ialloc.
--- fs/xfs/xfs_inode.c | 5 +++-- fs/xfs/xfs_inode.h | 2 +- fs/xfs/xfs_qm.c | 4 +++- fs/xfs/xfs_utils.c | 2 +- fs/xfs/xfs_utils.h | 2 +- fs/xfs/xfs_vnodeops.c | 8 ++++---- 6 files changed, 13 insertions(+), 10 deletions(-)
fs/xfs/xfs_inode.c +3 -2
@@ -1226,7 +1226,7 @@ xfs_ialloc(umode_t mode, xfs_nlink_t nlink, xfs_dev_t rdev, - prid_t prid, + kprojid_t prid, int okalloc, xfs_buf_t **ialloc_context, xfs_inode_t **ipp)
@@ -1290,7 +1290,8 @@ xfs_ialloc(/* * Project ids won't be stored on disk if we are using a version 1 inode. */ -if ((prid !=0 ) && (ip->i_d.di_version ==1 )) +if (!projid_eq (prid,make_kprojid (&init_user_ns,0 )) && + (ip->i_d.di_version ==1 ))xfs_bump_ino_vers2 (tp, ip);if (pip &&XFS_INHERIT_GID (pip)) {
fs/xfs/xfs_inode.h +1 -1
@@ -516,7 +516,7 @@ int xfs_isilocked(xfs_inode_t *, uint);uint xfs_ilock_map_shared (xfs_inode_t *);void xfs_iunlock_map_shared (xfs_inode_t *,uint );int xfs_ialloc (struct xfs_trans *,xfs_inode_t *,umode_t , -xfs_nlink_t ,xfs_dev_t ,prid_t ,int , +xfs_nlink_t ,xfs_dev_t ,kprojid_t ,int ,struct xfs_buf **,xfs_inode_t **);uint xfs_ip2xflags (struct xfs_inode *);
fs/xfs/xfs_qm.c +3 -1
@@ -777,7 +777,9 @@ xfs_qm_qino_alloc(return error; } - error =xfs_dir_ialloc (&tp,NULL ,S_IFREG ,1 ,0 ,0 ,1 , ip, &committed); + error =xfs_dir_ialloc (&tp,NULL ,S_IFREG ,1 ,0 , +make_kprojid (&init_user_ns,0 ), +1 , ip, &committed);if (error) {xfs_trans_cancel (tp,XFS_TRANS_RELEASE_LOG_RES |XFS_TRANS_ABORT );
fs/xfs/xfs_utils.c +1 -1
@@ -54,7 +54,7 @@ xfs_dir_ialloc(umode_t mode, xfs_nlink_t nlink, xfs_dev_t rdev, - prid_t prid, /* project id */ + kprojid_t prid, /* project id */ int okalloc, /* ok to allocate new space */ xfs_inode_t **ipp, /* pointer to inode; it will be locked. */
fs/xfs/xfs_utils.h +1 -1
@@ -19,7 +19,7 @@#define __XFS_UTILS_H__extern int xfs_dir_ialloc (xfs_trans_t **,xfs_inode_t *,umode_t ,xfs_nlink_t , -xfs_dev_t ,prid_t ,int ,xfs_inode_t **,int *); +xfs_dev_t ,kprojid_t ,int ,xfs_inode_t **,int *);extern int xfs_droplink (xfs_trans_t *,xfs_inode_t *);extern int xfs_bumplink (xfs_trans_t *,xfs_inode_t *);extern void xfs_bump_ino_vers2 (xfs_trans_t *,xfs_inode_t *);
fs/xfs/xfs_vnodeops.c +4 -4
@@ -728,7 +728,7 @@ xfs_create(bool unlock_dp_on_error = false;uint cancel_flags;int committed; -prid_t prid; +kprojid_t prid;struct xfs_dquot *udqp =NULL ;struct xfs_dquot *gdqp =NULL ;uint resblks;
@@ -743,7 +743,7 @@ xfs_create(if (dp->i_d.di_flags &XFS_DIFLAG_PROJINHERIT ) prid = dp->i_d.di_projid;else - prid =XFS_PROJID_DEFAULT ; + prid =make_kprojid (&init_user_ns,XFS_PROJID_DEFAULT );/* * Make sure that we have allocated dquot(s) on disk.
@@ -1379,7 +1379,7 @@ xfs_symlink(int byte_cnt;int n;xfs_buf_t *bp; -prid_t prid; +kprojid_t prid;struct xfs_dquot *udqp, *gdqp;uint resblks;
@@ -1404,7 +1404,7 @@ xfs_symlink(if (dp->i_d.di_flags &XFS_DIFLAG_PROJINHERIT ) prid = dp->i_d.di_projid;else - prid =XFS_PROJID_DEFAULT ; + prid =make_kprojid (&init_user_ns,XFS_PROJID_DEFAULT );/* * Make sure that we have allocated dquot(s) on disk.
Signature · 1 line
1.7.5.4
PATCH 9/14 xfs: Modify xfs_qm_vop_dqalloc to take kuids, kgids, and kprojids.
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
--- fs/xfs/xfs_qm.c | 6 +++--- fs/xfs/xfs_quota.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-)
fs/xfs/xfs_qm.c +3 -3
@@ -1616,9 +1616,9 @@ xfs_qm_write_sb_changes(int xfs_qm_vop_dqalloc (struct xfs_inode *ip, -uid_t uid, -gid_t gid, -prid_t prid, +kuid_t uid, +kgid_t gid, +kprojid_t prid,uint flags,struct xfs_dquot **O_udqpp,struct xfs_dquot **O_gdqpp)
fs/xfs/xfs_quota.h +2 -2
@@ -311,7 +311,7 @@ extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *, struct xfs_mount *, struct xfs_dquot *, struct xfs_dquot *, long, long, uint); -extern int xfs_qm_vop_dqalloc (struct xfs_inode *,uid_t ,gid_t ,prid_t ,uint , +extern int xfs_qm_vop_dqalloc (struct xfs_inode *,kuid_t ,kgid_t ,kprojid_t ,uint ,struct xfs_dquot **,struct xfs_dquot **);extern void xfs_qm_vop_create_dqattach (struct xfs_trans *,struct xfs_inode *,struct xfs_dquot *,struct xfs_dquot *);
@@ -332,7 +332,7 @@ extern void xfs_qm_unmount_quotas(struct xfs_mount *);#else static inline int -xfs_qm_vop_dqalloc (struct xfs_inode *ip,uid_t uid,gid_t gid,prid_t prid, +xfs_qm_vop_dqalloc (struct xfs_inode *ip,kuid_t uid,kgid_t gid,kprojid_t prid,uint flags,struct xfs_dquot **udqp,struct xfs_dquot **gdqp) { *udqp =NULL ;
Signature · 1 line
1.7.5.4
PATCH 10/14 xfs: Push struct kqid into xfs_qm_scall_qmlim and xfs_qm_scall_getquota
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
- In xfs_qm_scall_getquota map the quota id into the callers user namespace in the returned struct fs_disk_quota
- Add a helper is_superquota and use it in xfs_qm_scall_setqlimi to see if we are setting the superusers quota limit. Setting the superuses quota limit on xfs sets the default quota limits for all users.
- Move xfs_quota_type into xfs_qm_syscalls.c where it is now used.
--- fs/xfs/xfs_dquot.h | 6 ++++++ fs/xfs/xfs_qm.h | 4 ++-- fs/xfs/xfs_qm_syscalls.c | 40 +++++++++++++++++++++++++++++----------- fs/xfs/xfs_quotaops.c | 20 ++------------------ 4 files changed, 39 insertions(+), 31 deletions(-)
fs/xfs/xfs_dquot.h +6 -0
@@ -163,4 +163,10 @@ static inline struct xfs_dquot *xfs_qm_dqhold(struct xfs_dquot *dqp)extern const struct xfs_buf_ops xfs_dquot_buf_ops; +/* Is this root's quota in the specified user namespace? */ +static inline bool is_superquota (struct kqid id,struct user_namespace *ns) +{ +return qid_eq (id,make_kqid (ns, id.type,0 )); +} +#endif /* __XFS_DQUOT_H__ */
fs/xfs/xfs_qm.h +2 -2
@@ -114,9 +114,9 @@ extern void xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint);/* quota ops */ extern int xfs_qm_scall_trunc_qfiles (xfs_mount_t *,uint ); -extern int xfs_qm_scall_getquota (xfs_mount_t *,xfs_dqid_t ,uint , +extern int xfs_qm_scall_getquota (xfs_mount_t *,struct kqid ,fs_disk_quota_t *); -extern int xfs_qm_scall_setqlim (xfs_mount_t *,xfs_dqid_t ,uint , +extern int xfs_qm_scall_setqlim (xfs_mount_t *,struct kqid ,fs_disk_quota_t *);extern int xfs_qm_scall_getqstat (xfs_mount_t *,fs_quota_stat_t *);extern int xfs_qm_scall_quotaon (xfs_mount_t *,uint );
fs/xfs/xfs_qm_syscalls.c +29 -11
@@ -48,6 +48,19 @@ STATIC int xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *, STATIC uint xfs_qm_export_flags(uint); STATIC uint xfs_qm_export_qtype_flags(uint); +STATIC int +xfs_quota_type (int type) +{ +switch (type) { +case USRQUOTA : +return XFS_DQ_USER ; +case GRPQUOTA : +return XFS_DQ_GROUP ; +default : +return XFS_DQ_PROJ ; + } +} +/* * Turn off quota accounting and/or enforcement for all udquots and/or * gdquots. Called only at unmount time.
@@ -473,8 +486,7 @@ xfs_qm_scall_getqstat(int xfs_qm_scall_setqlim (xfs_mount_t *mp, -xfs_dqid_t id, -uint type, +struct kqid id,fs_disk_quota_t *newlim) {struct xfs_quotainfo *q = mp->m_quotainfo;
@@ -483,12 +495,16 @@ xfs_qm_scall_setqlim(xfs_trans_t *tp;int error;xfs_qcnt_t hard, soft; +bool superquota;if (newlim->d_fieldmask & ~XFS_DQ_MASK )return EINVAL ;if ((newlim->d_fieldmask &XFS_DQ_MASK ) ==0 )return 0 ; +/* Is this quota id for root? */ + superquota =is_superquota (id, &init_user_ns); + tp =xfs_trans_alloc (mp,XFS_TRANS_QM_SETQLIM ); error =xfs_trans_reserve (tp,0 ,XFS_QM_SETQLIM_LOG_RES (mp),0 ,0 ,XFS_DEFAULT_LOG_COUNT );
@@ -509,7 +525,9 @@ xfs_qm_scall_setqlim(* Get the dquot (locked), and join it to the transaction. * Allocate the dquot if this doesn't exist. */ -if ((error =xfs_qm_dqget (mp,NULL , id, type,XFS_QMOPT_DQALLOC , &dqp))) { +if ((error =xfs_qm_dqget (mp,NULL ,from_kqid (&init_user_ns, id), +xfs_quota_type (id.type), +XFS_QMOPT_DQALLOC , &dqp))) {xfs_trans_cancel (tp,XFS_TRANS_ABORT );ASSERT (error !=ENOENT ); goto out_unlock;
@@ -529,7 +547,7 @@ xfs_qm_scall_setqlim(if (hard ==0 || hard >= soft) { ddq->d_blk_hardlimit =cpu_to_be64 (hard); ddq->d_blk_softlimit =cpu_to_be64 (soft); -if (id ==0 ) { +if (superquota) { q->qi_bhardlimit = hard; q->qi_bsoftlimit = soft; }
@@ -545,7 +563,7 @@ xfs_qm_scall_setqlim(if (hard ==0 || hard >= soft) { ddq->d_rtb_hardlimit =cpu_to_be64 (hard); ddq->d_rtb_softlimit =cpu_to_be64 (soft); -if (id ==0 ) { +if (superquota) { q->qi_rtbhardlimit = hard; q->qi_rtbsoftlimit = soft; }
@@ -562,7 +580,7 @@ xfs_qm_scall_setqlim(if (hard ==0 || hard >= soft) { ddq->d_ino_hardlimit =cpu_to_be64 (hard); ddq->d_ino_softlimit =cpu_to_be64 (soft); -if (id ==0 ) { +if (superquota) { q->qi_ihardlimit = hard; q->qi_isoftlimit = soft; }
@@ -580,7 +598,7 @@ xfs_qm_scall_setqlim(if (newlim->d_fieldmask &FS_DQ_RTBWARNS ) ddq->d_rtbwarns =cpu_to_be16 (newlim->d_rtbwarns); -if (id ==0 ) { +if (superquota) {/* * Timelimits for the super user set the relative time * the other users can be over quota for this file system.
@@ -715,8 +733,7 @@ error0:int xfs_qm_scall_getquota (struct xfs_mount *mp, -xfs_dqid_t id, -uint type, +struct kqid id,struct fs_disk_quota *dst) {struct xfs_dquot *dqp;
@@ -727,7 +744,8 @@ xfs_qm_scall_getquota(* we aren't passing the XFS_QMOPT_DOALLOC flag. If it doesn't * exist, we'll get ENOENT back. */ - error =xfs_qm_dqget (mp,NULL , id, type,0 , &dqp); + error =xfs_qm_dqget (mp,NULL ,from_kqid (&init_user_ns, id), +xfs_quota_type (id.type),0 , &dqp);if (error)return error;
@@ -743,7 +761,7 @@ xfs_qm_scall_getquota(memset (dst,0 ,sizeof (*dst)); dst->d_version =FS_DQUOT_VERSION ; dst->d_flags =xfs_qm_export_qtype_flags (dqp->q_core.d_flags); - dst->d_id =be32_to_cpu (dqp->q_core.d_id); + dst->d_id =from_kqid_munged (current_user_ns (), id); dst->d_blk_hardlimit =XFS_FSB_TO_BB (mp,be64_to_cpu (dqp->q_core.d_blk_hardlimit)); dst->d_blk_softlimit =
fs/xfs/xfs_quotaops.c +2 -18
@@ -27,20 +27,6 @@#include "xfs_qm.h" #include <linux/quota.h> - -STATIC int -xfs_quota_type (int type) -{ -switch (type) { -case USRQUOTA : -return XFS_DQ_USER ; -case GRPQUOTA : -return XFS_DQ_GROUP ; -default : -return XFS_DQ_PROJ ; - } -} - STATIC int xfs_fs_get_xstate( struct super_block *sb,
@@ -107,8 +93,7 @@ xfs_fs_get_dqblk(if (!XFS_IS_QUOTA_ON (mp))return -ESRCH ; -return -xfs_qm_scall_getquota (mp,from_kqid (&init_user_ns, qid), -xfs_quota_type (qid.type), fdq); +return -xfs_qm_scall_getquota (mp, qid, fdq); }STATIC int
@@ -126,8 +111,7 @@ xfs_fs_set_dqblk(if (!XFS_IS_QUOTA_ON (mp))return -ESRCH ; -return -xfs_qm_scall_setqlim (mp,from_kqid (&init_user_ns, qid), -xfs_quota_type (qid.type), fdq); +return -xfs_qm_scall_setqlim (mp, qid, fdq); }const struct quotactl_ops xfs_quotactl_operations = {
Signature · 1 line
1.7.5.4
PATCH 12/14 xfs: Remember the kqid for a quota
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
- Add q_id to struct xfs_quota
- Modify xfs_qm_dqread to take a struct kqid, allowing xfs_qm_dqread to set q_id on fresh quota structures.
- Modify xfs_qm_dqget and xfs_qm_init_quota_info to pass a kqid to xfs_qm_dqread
--- fs/xfs/xfs_dquot.c | 12 ++++++------ fs/xfs/xfs_dquot.h | 3 ++- fs/xfs/xfs_qm.c | 9 +++++---- 3 files changed, 13 insertions(+), 11 deletions(-)
fs/xfs/xfs_dquot.c +6 -6
@@ -581,8 +581,7 @@ xfs_qm_dqtobp(int xfs_qm_dqread (struct xfs_mount *mp, -xfs_dqid_t id, -uint type, +struct kqid id,uint flags,struct xfs_dquot **O_dqpp) {
@@ -596,8 +595,9 @@ xfs_qm_dqread( dqp =kmem_zone_zalloc (xfs_qm_dqzone,KM_SLEEP ); - dqp->dq_flags = type; - dqp->q_core.d_id =cpu_to_be32 (id); + dqp->q_id = id; + dqp->dq_flags =xfs_quota_type (id.type); + dqp->q_core.d_id =cpu_to_be32 (from_kqid (&init_user_ns, id)); dqp->q_mount = mp;INIT_LIST_HEAD (&dqp->q_lru);mutex_init (&dqp->q_qlock);
@@ -615,7 +615,7 @@ xfs_qm_dqread(* Make sure group quotas have a different lock class than user * quotas. */ -if (!(type &XFS_DQ_USER )) +if (id.type !=USRQUOTA )lockdep_set_class (&dqp->q_qlock, &xfs_dquot_other_class);XFS_STATS_INC (xs_qm_dquot);
@@ -779,7 +779,7 @@ restart:if (ip)xfs_iunlock (ip,XFS_ILOCK_EXCL ); - error =xfs_qm_dqread (mp, id, type, flags, &dqp); + error =xfs_qm_dqread (mp, qid, flags, &dqp);if (ip)xfs_ilock (ip,XFS_ILOCK_EXCL );
fs/xfs/xfs_dquot.h +2 -1
@@ -36,6 +36,7 @@ struct xfs_trans;* The incore dquot structure */ typedef struct xfs_dquot { + struct kqid q_id; /* quota identifier */ uint dq_flags; /* various flags (XFS_DQ_*) */ struct list_head q_lru; /* global free list of dquots */ struct xfs_mount*q_mount; /* filesystem this relates to */
@@ -138,7 +139,7 @@ static inline xfs_dquot_t *xfs_inode_dquot(struct xfs_inode *ip, int type) XFS_DQ_TO_QINF(dqp)->qi_uquotaip : \ XFS_DQ_TO_QINF(dqp)->qi_gquotaip) -extern int xfs_qm_dqread (struct xfs_mount *,xfs_dqid_t ,uint , +extern int xfs_qm_dqread (struct xfs_mount *,struct kqid ,uint ,struct xfs_dquot **);extern void xfs_qm_dqdestroy (xfs_dquot_t *);extern int xfs_qm_dqflush (struct xfs_dquot *,struct xfs_buf **);
fs/xfs/xfs_qm.c +5 -4
@@ -673,10 +673,11 @@ xfs_qm_init_quotainfo(* Since we may not have done a quotacheck by this point, just read * the dquot without attaching it to any hashtables or lists. */ - error =xfs_qm_dqread (mp,0 , -XFS_IS_UQUOTA_RUNNING (mp) ?XFS_DQ_USER : - (XFS_IS_GQUOTA_RUNNING (mp) ?XFS_DQ_GROUP : -XFS_DQ_PROJ ), + error =xfs_qm_dqread (mp, +make_kqid (&init_user_ns, +XFS_IS_UQUOTA_RUNNING (mp) ?USRQUOTA : + (XFS_IS_GQUOTA_RUNNING (mp) ?GRPQUOTA : +PRJQUOTA ),0 ),XFS_QMOPT_DOWARN , &dqp);if (!error) {xfs_disk_dquot_t *ddqp = &dqp->q_core;
Signature · 1 line
1.7.5.4
PATCH 13/14 xfs: Use q_id instead of q_core.d_id.
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
- Use qid_lt on q_id when compariting two quota entries for order.
- Use qid_eq or !qid_eq when comparing a quota entry for equality or inequality.
- Use is_superquota when testing for the magic quota id of 0.
- Use make_kqid_uid, make_kqid_gid, and make_kqid_projid when comparing a quota id against a uids, gids, or projids as appropriate.
- For tracing use from_kqid and map to the init user namespace. Tracers outside of the initial user namespace are not allowed.
- For generating ondisk values continue to use q_core.d_id.
- For cases where we want an index and don't care which quota it is continue to use be32_to_cpu(...->q_core.d_id)
--- fs/xfs/xfs_dquot.c | 3 +-- fs/xfs/xfs_qm.c | 18 +++++++++--------- fs/xfs/xfs_trace.h | 2 +- fs/xfs/xfs_trans_dquot.c | 8 ++------ 4 files changed, 13 insertions(+), 18 deletions(-)
fs/xfs/xfs_dquot.c +1 -2
@@ -1086,8 +1086,7 @@ xfs_dqlock2( {if (d1 && d2) {ASSERT (d1 != d2); -if (be32_to_cpu (d1->q_core.d_id) > -be32_to_cpu (d2->q_core.d_id)) { +if (qid_lt (d2->q_id, d1->q_id)) {mutex_lock (&d2->q_qlock);mutex_lock_nested (&d1->q_qlock,XFS_QLOCK_NESTED ); }else {
fs/xfs/xfs_qm.c +9 -9
@@ -407,7 +407,7 @@ xfs_qm_dqattach_one(* hold the ilock. */ dqp = udqhint->q_gdquot; -if (dqp &&qid_eq (make_kqid (&init_user_ns, id.type,be32_to_cpu (dqp->q_core.d_id)), id)) { +if (dqp &&qid_eq (dqp->q_id, id)) {ASSERT (*IO_idqpp ==NULL ); *IO_idqpp =xfs_qm_dqhold (dqp);
@@ -1057,7 +1057,7 @@ xfs_qm_quotacheck_dqadjust(* * There are no timers for the default values set in the root dquot. */ -if (dqp->q_core.d_id) { +if (!is_superquota (dqp->q_id, &init_user_ns)) {xfs_qm_adjust_dqlimits (mp, &dqp->q_core);xfs_qm_adjust_dqtimers (mp, &dqp->q_core); }
@@ -1804,7 +1804,7 @@ xfs_qm_vop_chown_reserve( XFS_QMOPT_RES_RTBLKS :XFS_QMOPT_RES_REGBLKS ;if (XFS_IS_UQUOTA_ON (mp) && udqp && - !uid_eq (ip->i_d.di_uid, (uid_t )be32_to_cpu (udqp->q_core.d_id))) { + !qid_eq (make_kqid_uid (ip->i_d.di_uid), udqp->q_id)) { delblksudq = udqp;/* * If there are delayed allocation blocks, then we have to
@@ -1818,12 +1818,12 @@ xfs_qm_vop_chown_reserve( }if (XFS_IS_OQUOTA_ON (ip->i_mount) && gdqp) {if (XFS_IS_PQUOTA_ON (ip->i_mount) && - !projid_eq (ip->i_d.di_projid,be32_to_cpu (gdqp->q_core.d_id))) + !qid_eq (make_kqid_projid (ip->i_d.di_projid), gdqp->q_id)) prjflags =XFS_QMOPT_ENOSPC ;if (prjflags || (XFS_IS_GQUOTA_ON (ip->i_mount) && - !gid_eq (ip->i_d.di_gid,be32_to_cpu (gdqp->q_core.d_id)))) { + !qid_eq (make_kqid_gid (ip->i_d.di_gid), gdqp->q_id))) { delblksgdq = gdqp;if (delblks) {ASSERT (ip->i_gdquot);
@@ -1907,7 +1907,7 @@ xfs_qm_vop_create_dqattach(if (udqp) {ASSERT (ip->i_udquot ==NULL );ASSERT (XFS_IS_UQUOTA_ON (mp)); -ASSERT (uid_eq (ip->i_d.di_uid,be32_to_cpu (udqp->q_core.d_id))); +ASSERT (qid_eq (make_kqid_uid (ip->i_d.di_uid), udqp->q_id)); ip->i_udquot =xfs_qm_dqhold (udqp);xfs_trans_mod_dquot (tp, udqp,XFS_TRANS_DQ_ICOUNT ,1 );
@@ -1915,9 +1915,9 @@ xfs_qm_vop_create_dqattach(if (gdqp) {ASSERT (ip->i_gdquot ==NULL );ASSERT (XFS_IS_OQUOTA_ON (mp)); -ASSERT (XFS_IS_GQUOTA_ON (mp) ? -gid_eq (ip->i_d.di_gid,be32_to_cpu (gdqp->q_core.d_id)): -projid_eq (ip->i_d.di_projid,be32_to_cpu (gdqp->q_core.d_id))); +ASSERT (qid_eq (XFS_IS_GQUOTA_ON (mp) ? +make_kqid_gid (ip->i_d.di_gid) : +make_kqid_projid (ip->i_d.di_projid), gdqp->q_id)); ip->i_gdquot =xfs_qm_dqhold (gdqp);xfs_trans_mod_dquot (tp, gdqp,XFS_TRANS_DQ_ICOUNT ,1 );
fs/xfs/xfs_trace.h +1 -1
@@ -713,7 +713,7 @@ DECLARE_EVENT_CLASS(xfs_dquot_class, ), \ TP_fast_assign( __entry->dev = dqp->q_mount->m_super->s_dev; - __entry->id =be32_to_cpu (dqp->q_core.d_id); + __entry->id =from_kqid (&init_user_ns, dqp->q_id); __entry->flags = dqp->dq_flags; __entry->nrefs = dqp->q_nrefs; __entry->res_bcount = dqp->q_res_bcount;
fs/xfs/xfs_trans_dquot.c +2 -6
@@ -578,11 +578,7 @@ xfs_quota_warn(/* no warnings for project quotas - we just return ENOSPC later */ if (dqp->dq_flags &XFS_DQ_PROJ )return ; -quota_send_warning (make_kqid (&init_user_ns, - (dqp->dq_flags &XFS_DQ_USER ) ? -USRQUOTA :GRPQUOTA , -be32_to_cpu (dqp->q_core.d_id)), - mp->m_super->s_dev, type); +quota_send_warning (dqp->q_id, mp->m_super->s_dev, type); }/*
@@ -638,7 +634,7 @@ xfs_trans_dqresv( }if ((flags &XFS_QMOPT_FORCE_RES ) ==0 && - dqp->q_core.d_id && + !is_superquota (dqp->q_id, &init_user_ns) && ((XFS_IS_UQUOTA_ENFORCED (dqp->q_mount) &&XFS_QM_ISUDQ (dqp)) || (XFS_IS_OQUOTA_ENFORCED (dqp->q_mount) && (XFS_QM_ISPDQ (dqp) ||XFS_QM_ISGDQ (dqp))))) {
Signature · 1 line
1.7.5.4
Quoted 10 lines · Eric W. Biederman
Or replace uids, gids, and projids with kuids, kgids, and kprojids
In support of user namespaces I have introduced into the kernel kuids, kgids, and kprojids. The most important characteristic of these ids is that they are not assignment compatible with uids, gids, and projids coming from userspace nor are they assignment compatible with uids, gids or projids stored on disk. This assignment incompatibility makes it easy to ensure that conversions are introduced at the edge of userspace and at the interface between on-disk and in-memory data structures.
TL;DR:
Compared to the last version of this patchset I NACKed, this version increases the per-inode memory footprint by over 100 bytes (i.e. by more than 10%), introduces a double copy of the inode core data into the *hottest path in XFS*, breaks log recovery and fails to address a single NACK I gave for the previous round of the patch set.
So, NACK.
Quoted 2 lines
Converting xfs is an interesting challenge because of the way xfs handles it's inode data is very atypical.
That you have to tell people that find it strange an unusual immediately indicates that you do not really understand the design and structure of the XFS code. This makes your refusal to listen to feedback from someone who is a subject matter expert all the more difficult to understand.
I'll accept that you might forget something mentioned in a review when you post an update, but to ignore a second NACK for the same patch and posting it a third time unchanged is not the best way to make friends and influence people....
And given that you didn't respond to a single review comment I made on the previous version of the patch, well, I have my doubts you are going to respond this time, either. In previous reviews comments I have:
- outlined exactly how to provide a minimally invasive patch set that provides full namespace support as a first step in getting XFS to support namespaces.
- told you where the ondisk/in-memory boundaries are.
- told you that certain IDs are filesystem internal and not subject to namespaces.
- asked questions about how filesystems utilities are supposed to deal with namespaces (i.e. userspace impacts of ioctl interface changes).
And you haven't responded to any of them. You can't selectively ignore review comments you don't like and then magically expect the reviewers to accept an almost-identical-but-even-more-broken patch set the next time around.
Quoted 4 lines
Given the number of ioctls that xfs supports it would be irresponsible to do anything except insist that kuids, kgids, and kprojids are used in all of in memory data structures of xfs, as otherwise it becomes trivially easy to miss a needed conversion with the advent of a new ioctl.
Eric, your rhetoric looks so fine and shiny on the wall, but it is utterly worthless. You're telling us that userspace interface are absolutely necessary, but haven't provided any analysis, description or justification so we can judge the impact of the changes or review why you think the only way such changes can be made is your way.
Nor have you provided any regression tests to verify that this shiny new namespace support is working as the maker has intended. IOWs, I've got no idea what the impact of changing all the ioctls will be, no way to verify it is correct and you sure as hell aren't going out of your way to make it easy for us to understand the impact, either.
Further, I'm pretty sure that you are not even aware of the scope of the issues that namespace awareness raise for some of these XFS ioctls. I've previously asked some questions about behaviours of them, but like most of my other review comments you have ignored those questions.
So, before we go changing anything ioctl related, here's some questions you need to answer:
- if you run bulkstat, what do we do with inodes that contain a ID owned by a namespace outside the current namespace?
- Can we even check the on-disk inode IDs are valid within a specific namespace within the kernel?
- open_by_handle() would appear to allow root in any namespace to open any file in the filesystem it has a valid handle for regardless of the namespace. Is this allowable? The output of bulkstat can be fed directly to open_by_handle(), so if bulkstat can return inodes outside the namespace, open-by-handle can open them and we can do invisible IO on them.
- Further, we can extract and set attributes directly by handle and, IIRC, that includes security/trusted namespace attributes....
- On the same measure, the handles used by XFS handle interfaces are identical to NFS handles and use the same code for decoding and dentry lookup. So, what do handle restrictions mean for NFS servers?
- have you considered that fs/fhandle.c raises many of these same issues?
- and seeing xfsdump and xfs_fsr use bulkstat and handles, what do new limitations on these interfaces mean for these utilities?
- How does xfs_dump/xfs_restore work if we convert all ids based on the current namespace? e.g. dump in one namespace, restore in another.
- How does xfs_dump/xfs_restore work if we *don't* convert all ids (i.e. export the on-disk values)?
- How do we document/communicate all these constraints/ behaviours to users who might be completely unaware of them?
IOWs, simply converting IDs the ioctls take in or emit is only a small part of the larger question of how they are supposed to behave in namespace containers. These questions need to be answered *in detail* and with *regression tests* before we accept any changes to the ioctl interfaces.
Eric, I'm not trying to be difficult here - I'm holding the bar at the same height as it gets held for any significant XFS change that impacts userspace interfaces and behaviour. You don't maintain the XFS code, so you can just walk away once namespaces are "done" and not care that you've left a mess behind.
And if you leave a mess, I'm the person who will have to clean it up. I don't want to have to clean up your mess, so I'm going to keep saying no until you can introduce namespace support without making a mess....
-Dave.
Signature · 2 lines
Dave Chinner [email protected]