On Thu 20-04-23 10:03:59, cem@xxxxxxxxxx wrote: > From: Lukas Czerner <lczerner@xxxxxxxxxx> > > Allow system administrator to set default global quota limits at tmpfs > mount time. > > Signed-off-by: Lukas Czerner <lczerner@xxxxxxxxxx> > Signed-off-by: Carlos Maiolino <cmaiolino@xxxxxxxxxx> > --- > Documentation/filesystems/tmpfs.rst | 34 ++++++++++---- > include/linux/shmem_fs.h | 8 ++++ > mm/shmem.c | 69 +++++++++++++++++++++++++++++ > mm/shmem_quota.c | 9 ++++ > 4 files changed, 111 insertions(+), 9 deletions(-) > > diff --git a/Documentation/filesystems/tmpfs.rst b/Documentation/filesystems/tmpfs.rst > index 1d4ef4f7cca7e..241c11f86cd73 100644 > --- a/Documentation/filesystems/tmpfs.rst > +++ b/Documentation/filesystems/tmpfs.rst > @@ -88,15 +88,31 @@ that instance in a system with many CPUs making intensive use of it. > > tmpfs also supports quota with the following mount options > > -======== ============================================================= > -quota User and group quota accounting and enforcement is enabled on > - the mount. Tmpfs is using hidden system quota files that are > - initialized on mount. > -usrquota User quota accounting and enforcement is enabled on the > - mount. > -grpquota Group quota accounting and enforcement is enabled on the > - mount. > -======== ============================================================= > +======================== ================================================= > +quota User and group quota accounting and enforcement > + is enabled on the mount. Tmpfs is using hidden > + system quota files that are initialized on mount. > +usrquota User quota accounting and enforcement is enabled > + on the mount. > +grpquota Group quota accounting and enforcement is enabled > + on the mount. > +usrquota_block_hardlimit Set global user quota block hard limit. > +usrquota_inode_hardlimit Set global user quota inode hard limit. > +grpquota_block_hardlimit Set global group quota block hard limit. > +grpquota_inode_hardlimit Set global group quota inode hard limit. > +======================== ================================================= > + > +None of the quota related mount options can be set or changed on remount. > + > +Quota limit parameters accept a suffix k, m or g for kilo, mega and giga > +and can't be changed on remount. Default global quota limits are taking > +effect for any and all user/group/project except root the first time the > +quota entry for user/group/project id is being accessed - typically the > +first time an inode with a particular id ownership is being created after > +the mount. In other words, instead of the limits being initialized to zero, > +they are initialized with the particular value provided with these mount > +options. The limits can be changed for any user/group id at any time as it ^^ they > +normally can. ^^^ can be > @@ -3714,6 +3723,50 @@ static int shmem_parse_one(struct fs_context *fc, struct fs_parameter *param) > ctx->seen |= SHMEM_SEEN_QUOTA; > ctx->quota_types |= QTYPE_MASK_GRP; > break; > + case Opt_usrquota_block_hardlimit: > + size = memparse(param->string, &rest); > + if (*rest || !size) > + goto bad_value; > + if (size > SHMEM_QUOTA_MAX_SPC_LIMIT) > + return invalfc(fc, > + "User quota block hardlimit too large."); > + ctx->qlimits.usrquota_bhardlimit = size; > + ctx->seen |= SHMEM_SEEN_QUOTA; > + ctx->quota_types |= QTYPE_MASK_USR; So if I get it right, the intention here is that if usrquota_block_hardlimit=value option is used, it automatically enables user quota accounting and enforcement. I guess it is logical but it is not documented and I'd prefer to require explicit usrquota mount option to enable accounting & enforcement - it is then e.g. easier to parse mount options (in userspace) for finding out whether enforcement is enabled or not. Also I can imagine we would allow changing the default limits on remount but it isn't easy to enable quota accounting on remount etc. > diff --git a/mm/shmem_quota.c b/mm/shmem_quota.c > index c0b531e2ef688..3cc53f2c35e2c 100644 > --- a/mm/shmem_quota.c > +++ b/mm/shmem_quota.c > @@ -166,6 +166,7 @@ static int shmem_acquire_dquot(struct dquot *dquot) > { > struct mem_dqinfo *info = sb_dqinfo(dquot->dq_sb, dquot->dq_id.type); > struct rb_node **n = &((struct rb_root *)info->dqi_priv)->rb_node; > + struct shmem_sb_info *sbinfo = dquot->dq_sb->s_fs_info; > struct rb_node *parent = NULL, *new_node = NULL; > struct quota_id *new_entry, *entry; > qid_t id = from_kqid(&init_user_ns, dquot->dq_id); > @@ -195,6 +196,14 @@ static int shmem_acquire_dquot(struct dquot *dquot) > } > > new_entry->id = id; > + if (dquot->dq_id.type == USRQUOTA) { > + new_entry->bhardlimit = sbinfo->qlimits.usrquota_bhardlimit; > + new_entry->ihardlimit = sbinfo->qlimits.usrquota_ihardlimit; > + } else if (dquot->dq_id.type == GRPQUOTA) { > + new_entry->bhardlimit = sbinfo->qlimits.grpquota_bhardlimit; > + new_entry->ihardlimit = sbinfo->qlimits.grpquota_ihardlimit; > + } > + > new_node = &new_entry->node; > rb_link_node(new_node, parent, n); > rb_insert_color(new_node, (struct rb_root *)info->dqi_priv); Maybe in shmem_dquot_release() when usage is 0 and limits are at default limits, we can free the structure? Honza -- Jan Kara <jack@xxxxxxxx> SUSE Labs, CR