162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * In memory quota format relies on quota infrastructure to store dquot
462306a36Sopenharmony_ci * information for us. While conventional quota formats for file systems
562306a36Sopenharmony_ci * with persistent storage can load quota information into dquot from the
662306a36Sopenharmony_ci * storage on-demand and hence quota dquot shrinker can free any dquot
762306a36Sopenharmony_ci * that is not currently being used, it must be avoided here. Otherwise we
862306a36Sopenharmony_ci * can lose valuable information, user provided limits, because there is
962306a36Sopenharmony_ci * no persistent storage to load the information from afterwards.
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * One information that in-memory quota format needs to keep track of is
1262306a36Sopenharmony_ci * a sorted list of ids for each quota type. This is done by utilizing
1362306a36Sopenharmony_ci * an rb tree which root is stored in mem_dqinfo->dqi_priv for each quota
1462306a36Sopenharmony_ci * type.
1562306a36Sopenharmony_ci *
1662306a36Sopenharmony_ci * This format can be used to support quota on file system without persistent
1762306a36Sopenharmony_ci * storage such as tmpfs.
1862306a36Sopenharmony_ci *
1962306a36Sopenharmony_ci * Author:	Lukas Czerner <lczerner@redhat.com>
2062306a36Sopenharmony_ci *		Carlos Maiolino <cmaiolino@redhat.com>
2162306a36Sopenharmony_ci *
2262306a36Sopenharmony_ci * Copyright (C) 2023 Red Hat, Inc.
2362306a36Sopenharmony_ci */
2462306a36Sopenharmony_ci#include <linux/errno.h>
2562306a36Sopenharmony_ci#include <linux/fs.h>
2662306a36Sopenharmony_ci#include <linux/mount.h>
2762306a36Sopenharmony_ci#include <linux/kernel.h>
2862306a36Sopenharmony_ci#include <linux/init.h>
2962306a36Sopenharmony_ci#include <linux/module.h>
3062306a36Sopenharmony_ci#include <linux/slab.h>
3162306a36Sopenharmony_ci#include <linux/rbtree.h>
3262306a36Sopenharmony_ci#include <linux/shmem_fs.h>
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#include <linux/quotaops.h>
3562306a36Sopenharmony_ci#include <linux/quota.h>
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#ifdef CONFIG_TMPFS_QUOTA
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci/*
4062306a36Sopenharmony_ci * The following constants define the amount of time given a user
4162306a36Sopenharmony_ci * before the soft limits are treated as hard limits (usually resulting
4262306a36Sopenharmony_ci * in an allocation failure). The timer is started when the user crosses
4362306a36Sopenharmony_ci * their soft limit, it is reset when they go below their soft limit.
4462306a36Sopenharmony_ci */
4562306a36Sopenharmony_ci#define SHMEM_MAX_IQ_TIME 604800	/* (7*24*60*60) 1 week */
4662306a36Sopenharmony_ci#define SHMEM_MAX_DQ_TIME 604800	/* (7*24*60*60) 1 week */
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_cistruct quota_id {
4962306a36Sopenharmony_ci	struct rb_node	node;
5062306a36Sopenharmony_ci	qid_t		id;
5162306a36Sopenharmony_ci	qsize_t		bhardlimit;
5262306a36Sopenharmony_ci	qsize_t		bsoftlimit;
5362306a36Sopenharmony_ci	qsize_t		ihardlimit;
5462306a36Sopenharmony_ci	qsize_t		isoftlimit;
5562306a36Sopenharmony_ci};
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_cistatic int shmem_check_quota_file(struct super_block *sb, int type)
5862306a36Sopenharmony_ci{
5962306a36Sopenharmony_ci	/* There is no real quota file, nothing to do */
6062306a36Sopenharmony_ci	return 1;
6162306a36Sopenharmony_ci}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci/*
6462306a36Sopenharmony_ci * There is no real quota file. Just allocate rb_root for quota ids and
6562306a36Sopenharmony_ci * set limits
6662306a36Sopenharmony_ci */
6762306a36Sopenharmony_cistatic int shmem_read_file_info(struct super_block *sb, int type)
6862306a36Sopenharmony_ci{
6962306a36Sopenharmony_ci	struct quota_info *dqopt = sb_dqopt(sb);
7062306a36Sopenharmony_ci	struct mem_dqinfo *info = &dqopt->info[type];
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	info->dqi_priv = kzalloc(sizeof(struct rb_root), GFP_NOFS);
7362306a36Sopenharmony_ci	if (!info->dqi_priv)
7462306a36Sopenharmony_ci		return -ENOMEM;
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	info->dqi_max_spc_limit = SHMEM_QUOTA_MAX_SPC_LIMIT;
7762306a36Sopenharmony_ci	info->dqi_max_ino_limit = SHMEM_QUOTA_MAX_INO_LIMIT;
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	info->dqi_bgrace = SHMEM_MAX_DQ_TIME;
8062306a36Sopenharmony_ci	info->dqi_igrace = SHMEM_MAX_IQ_TIME;
8162306a36Sopenharmony_ci	info->dqi_flags = 0;
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	return 0;
8462306a36Sopenharmony_ci}
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_cistatic int shmem_write_file_info(struct super_block *sb, int type)
8762306a36Sopenharmony_ci{
8862306a36Sopenharmony_ci	/* There is no real quota file, nothing to do */
8962306a36Sopenharmony_ci	return 0;
9062306a36Sopenharmony_ci}
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci/*
9362306a36Sopenharmony_ci * Free all the quota_id entries in the rb tree and rb_root.
9462306a36Sopenharmony_ci */
9562306a36Sopenharmony_cistatic int shmem_free_file_info(struct super_block *sb, int type)
9662306a36Sopenharmony_ci{
9762306a36Sopenharmony_ci	struct mem_dqinfo *info = &sb_dqopt(sb)->info[type];
9862306a36Sopenharmony_ci	struct rb_root *root = info->dqi_priv;
9962306a36Sopenharmony_ci	struct quota_id *entry;
10062306a36Sopenharmony_ci	struct rb_node *node;
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	info->dqi_priv = NULL;
10362306a36Sopenharmony_ci	node = rb_first(root);
10462306a36Sopenharmony_ci	while (node) {
10562306a36Sopenharmony_ci		entry = rb_entry(node, struct quota_id, node);
10662306a36Sopenharmony_ci		node = rb_next(&entry->node);
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci		rb_erase(&entry->node, root);
10962306a36Sopenharmony_ci		kfree(entry);
11062306a36Sopenharmony_ci	}
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	kfree(root);
11362306a36Sopenharmony_ci	return 0;
11462306a36Sopenharmony_ci}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_cistatic int shmem_get_next_id(struct super_block *sb, struct kqid *qid)
11762306a36Sopenharmony_ci{
11862306a36Sopenharmony_ci	struct mem_dqinfo *info = sb_dqinfo(sb, qid->type);
11962306a36Sopenharmony_ci	struct rb_node *node = ((struct rb_root *)info->dqi_priv)->rb_node;
12062306a36Sopenharmony_ci	qid_t id = from_kqid(&init_user_ns, *qid);
12162306a36Sopenharmony_ci	struct quota_info *dqopt = sb_dqopt(sb);
12262306a36Sopenharmony_ci	struct quota_id *entry = NULL;
12362306a36Sopenharmony_ci	int ret = 0;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	if (!sb_has_quota_active(sb, qid->type))
12662306a36Sopenharmony_ci		return -ESRCH;
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci	down_read(&dqopt->dqio_sem);
12962306a36Sopenharmony_ci	while (node) {
13062306a36Sopenharmony_ci		entry = rb_entry(node, struct quota_id, node);
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci		if (id < entry->id)
13362306a36Sopenharmony_ci			node = node->rb_left;
13462306a36Sopenharmony_ci		else if (id > entry->id)
13562306a36Sopenharmony_ci			node = node->rb_right;
13662306a36Sopenharmony_ci		else
13762306a36Sopenharmony_ci			goto got_next_id;
13862306a36Sopenharmony_ci	}
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	if (!entry) {
14162306a36Sopenharmony_ci		ret = -ENOENT;
14262306a36Sopenharmony_ci		goto out_unlock;
14362306a36Sopenharmony_ci	}
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	if (id > entry->id) {
14662306a36Sopenharmony_ci		node = rb_next(&entry->node);
14762306a36Sopenharmony_ci		if (!node) {
14862306a36Sopenharmony_ci			ret = -ENOENT;
14962306a36Sopenharmony_ci			goto out_unlock;
15062306a36Sopenharmony_ci		}
15162306a36Sopenharmony_ci		entry = rb_entry(node, struct quota_id, node);
15262306a36Sopenharmony_ci	}
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_cigot_next_id:
15562306a36Sopenharmony_ci	*qid = make_kqid(&init_user_ns, qid->type, entry->id);
15662306a36Sopenharmony_ciout_unlock:
15762306a36Sopenharmony_ci	up_read(&dqopt->dqio_sem);
15862306a36Sopenharmony_ci	return ret;
15962306a36Sopenharmony_ci}
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci/*
16262306a36Sopenharmony_ci * Load dquot with limits from existing entry, or create the new entry if
16362306a36Sopenharmony_ci * it does not exist.
16462306a36Sopenharmony_ci */
16562306a36Sopenharmony_cistatic int shmem_acquire_dquot(struct dquot *dquot)
16662306a36Sopenharmony_ci{
16762306a36Sopenharmony_ci	struct mem_dqinfo *info = sb_dqinfo(dquot->dq_sb, dquot->dq_id.type);
16862306a36Sopenharmony_ci	struct rb_node **n = &((struct rb_root *)info->dqi_priv)->rb_node;
16962306a36Sopenharmony_ci	struct shmem_sb_info *sbinfo = dquot->dq_sb->s_fs_info;
17062306a36Sopenharmony_ci	struct rb_node *parent = NULL, *new_node = NULL;
17162306a36Sopenharmony_ci	struct quota_id *new_entry, *entry;
17262306a36Sopenharmony_ci	qid_t id = from_kqid(&init_user_ns, dquot->dq_id);
17362306a36Sopenharmony_ci	struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
17462306a36Sopenharmony_ci	int ret = 0;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	mutex_lock(&dquot->dq_lock);
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	down_write(&dqopt->dqio_sem);
17962306a36Sopenharmony_ci	while (*n) {
18062306a36Sopenharmony_ci		parent = *n;
18162306a36Sopenharmony_ci		entry = rb_entry(parent, struct quota_id, node);
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci		if (id < entry->id)
18462306a36Sopenharmony_ci			n = &(*n)->rb_left;
18562306a36Sopenharmony_ci		else if (id > entry->id)
18662306a36Sopenharmony_ci			n = &(*n)->rb_right;
18762306a36Sopenharmony_ci		else
18862306a36Sopenharmony_ci			goto found;
18962306a36Sopenharmony_ci	}
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	/* We don't have entry for this id yet, create it */
19262306a36Sopenharmony_ci	new_entry = kzalloc(sizeof(struct quota_id), GFP_NOFS);
19362306a36Sopenharmony_ci	if (!new_entry) {
19462306a36Sopenharmony_ci		ret = -ENOMEM;
19562306a36Sopenharmony_ci		goto out_unlock;
19662306a36Sopenharmony_ci	}
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	new_entry->id = id;
19962306a36Sopenharmony_ci	if (dquot->dq_id.type == USRQUOTA) {
20062306a36Sopenharmony_ci		new_entry->bhardlimit = sbinfo->qlimits.usrquota_bhardlimit;
20162306a36Sopenharmony_ci		new_entry->ihardlimit = sbinfo->qlimits.usrquota_ihardlimit;
20262306a36Sopenharmony_ci	} else if (dquot->dq_id.type == GRPQUOTA) {
20362306a36Sopenharmony_ci		new_entry->bhardlimit = sbinfo->qlimits.grpquota_bhardlimit;
20462306a36Sopenharmony_ci		new_entry->ihardlimit = sbinfo->qlimits.grpquota_ihardlimit;
20562306a36Sopenharmony_ci	}
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	new_node = &new_entry->node;
20862306a36Sopenharmony_ci	rb_link_node(new_node, parent, n);
20962306a36Sopenharmony_ci	rb_insert_color(new_node, (struct rb_root *)info->dqi_priv);
21062306a36Sopenharmony_ci	entry = new_entry;
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_cifound:
21362306a36Sopenharmony_ci	/* Load the stored limits from the tree */
21462306a36Sopenharmony_ci	spin_lock(&dquot->dq_dqb_lock);
21562306a36Sopenharmony_ci	dquot->dq_dqb.dqb_bhardlimit = entry->bhardlimit;
21662306a36Sopenharmony_ci	dquot->dq_dqb.dqb_bsoftlimit = entry->bsoftlimit;
21762306a36Sopenharmony_ci	dquot->dq_dqb.dqb_ihardlimit = entry->ihardlimit;
21862306a36Sopenharmony_ci	dquot->dq_dqb.dqb_isoftlimit = entry->isoftlimit;
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	if (!dquot->dq_dqb.dqb_bhardlimit &&
22162306a36Sopenharmony_ci	    !dquot->dq_dqb.dqb_bsoftlimit &&
22262306a36Sopenharmony_ci	    !dquot->dq_dqb.dqb_ihardlimit &&
22362306a36Sopenharmony_ci	    !dquot->dq_dqb.dqb_isoftlimit)
22462306a36Sopenharmony_ci		set_bit(DQ_FAKE_B, &dquot->dq_flags);
22562306a36Sopenharmony_ci	spin_unlock(&dquot->dq_dqb_lock);
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	/* Make sure flags update is visible after dquot has been filled */
22862306a36Sopenharmony_ci	smp_mb__before_atomic();
22962306a36Sopenharmony_ci	set_bit(DQ_ACTIVE_B, &dquot->dq_flags);
23062306a36Sopenharmony_ciout_unlock:
23162306a36Sopenharmony_ci	up_write(&dqopt->dqio_sem);
23262306a36Sopenharmony_ci	mutex_unlock(&dquot->dq_lock);
23362306a36Sopenharmony_ci	return ret;
23462306a36Sopenharmony_ci}
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_cistatic bool shmem_is_empty_dquot(struct dquot *dquot)
23762306a36Sopenharmony_ci{
23862306a36Sopenharmony_ci	struct shmem_sb_info *sbinfo = dquot->dq_sb->s_fs_info;
23962306a36Sopenharmony_ci	qsize_t bhardlimit;
24062306a36Sopenharmony_ci	qsize_t ihardlimit;
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci	if (dquot->dq_id.type == USRQUOTA) {
24362306a36Sopenharmony_ci		bhardlimit = sbinfo->qlimits.usrquota_bhardlimit;
24462306a36Sopenharmony_ci		ihardlimit = sbinfo->qlimits.usrquota_ihardlimit;
24562306a36Sopenharmony_ci	} else if (dquot->dq_id.type == GRPQUOTA) {
24662306a36Sopenharmony_ci		bhardlimit = sbinfo->qlimits.grpquota_bhardlimit;
24762306a36Sopenharmony_ci		ihardlimit = sbinfo->qlimits.grpquota_ihardlimit;
24862306a36Sopenharmony_ci	}
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	if (test_bit(DQ_FAKE_B, &dquot->dq_flags) ||
25162306a36Sopenharmony_ci		(dquot->dq_dqb.dqb_curspace == 0 &&
25262306a36Sopenharmony_ci		 dquot->dq_dqb.dqb_curinodes == 0 &&
25362306a36Sopenharmony_ci		 dquot->dq_dqb.dqb_bhardlimit == bhardlimit &&
25462306a36Sopenharmony_ci		 dquot->dq_dqb.dqb_ihardlimit == ihardlimit))
25562306a36Sopenharmony_ci		return true;
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	return false;
25862306a36Sopenharmony_ci}
25962306a36Sopenharmony_ci/*
26062306a36Sopenharmony_ci * Store limits from dquot in the tree unless it's fake. If it is fake
26162306a36Sopenharmony_ci * remove the id from the tree since there is no useful information in
26262306a36Sopenharmony_ci * there.
26362306a36Sopenharmony_ci */
26462306a36Sopenharmony_cistatic int shmem_release_dquot(struct dquot *dquot)
26562306a36Sopenharmony_ci{
26662306a36Sopenharmony_ci	struct mem_dqinfo *info = sb_dqinfo(dquot->dq_sb, dquot->dq_id.type);
26762306a36Sopenharmony_ci	struct rb_node *node = ((struct rb_root *)info->dqi_priv)->rb_node;
26862306a36Sopenharmony_ci	qid_t id = from_kqid(&init_user_ns, dquot->dq_id);
26962306a36Sopenharmony_ci	struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
27062306a36Sopenharmony_ci	struct quota_id *entry = NULL;
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	mutex_lock(&dquot->dq_lock);
27362306a36Sopenharmony_ci	/* Check whether we are not racing with some other dqget() */
27462306a36Sopenharmony_ci	if (dquot_is_busy(dquot))
27562306a36Sopenharmony_ci		goto out_dqlock;
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	down_write(&dqopt->dqio_sem);
27862306a36Sopenharmony_ci	while (node) {
27962306a36Sopenharmony_ci		entry = rb_entry(node, struct quota_id, node);
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci		if (id < entry->id)
28262306a36Sopenharmony_ci			node = node->rb_left;
28362306a36Sopenharmony_ci		else if (id > entry->id)
28462306a36Sopenharmony_ci			node = node->rb_right;
28562306a36Sopenharmony_ci		else
28662306a36Sopenharmony_ci			goto found;
28762306a36Sopenharmony_ci	}
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci	/* We should always find the entry in the rb tree */
29062306a36Sopenharmony_ci	WARN_ONCE(1, "quota id %u from dquot %p, not in rb tree!\n", id, dquot);
29162306a36Sopenharmony_ci	up_write(&dqopt->dqio_sem);
29262306a36Sopenharmony_ci	mutex_unlock(&dquot->dq_lock);
29362306a36Sopenharmony_ci	return -ENOENT;
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_cifound:
29662306a36Sopenharmony_ci	if (shmem_is_empty_dquot(dquot)) {
29762306a36Sopenharmony_ci		/* Remove entry from the tree */
29862306a36Sopenharmony_ci		rb_erase(&entry->node, info->dqi_priv);
29962306a36Sopenharmony_ci		kfree(entry);
30062306a36Sopenharmony_ci	} else {
30162306a36Sopenharmony_ci		/* Store the limits in the tree */
30262306a36Sopenharmony_ci		spin_lock(&dquot->dq_dqb_lock);
30362306a36Sopenharmony_ci		entry->bhardlimit = dquot->dq_dqb.dqb_bhardlimit;
30462306a36Sopenharmony_ci		entry->bsoftlimit = dquot->dq_dqb.dqb_bsoftlimit;
30562306a36Sopenharmony_ci		entry->ihardlimit = dquot->dq_dqb.dqb_ihardlimit;
30662306a36Sopenharmony_ci		entry->isoftlimit = dquot->dq_dqb.dqb_isoftlimit;
30762306a36Sopenharmony_ci		spin_unlock(&dquot->dq_dqb_lock);
30862306a36Sopenharmony_ci	}
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci	clear_bit(DQ_ACTIVE_B, &dquot->dq_flags);
31162306a36Sopenharmony_ci	up_write(&dqopt->dqio_sem);
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ciout_dqlock:
31462306a36Sopenharmony_ci	mutex_unlock(&dquot->dq_lock);
31562306a36Sopenharmony_ci	return 0;
31662306a36Sopenharmony_ci}
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_cistatic int shmem_mark_dquot_dirty(struct dquot *dquot)
31962306a36Sopenharmony_ci{
32062306a36Sopenharmony_ci	return 0;
32162306a36Sopenharmony_ci}
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_cistatic int shmem_dquot_write_info(struct super_block *sb, int type)
32462306a36Sopenharmony_ci{
32562306a36Sopenharmony_ci	return 0;
32662306a36Sopenharmony_ci}
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_cistatic const struct quota_format_ops shmem_format_ops = {
32962306a36Sopenharmony_ci	.check_quota_file	= shmem_check_quota_file,
33062306a36Sopenharmony_ci	.read_file_info		= shmem_read_file_info,
33162306a36Sopenharmony_ci	.write_file_info	= shmem_write_file_info,
33262306a36Sopenharmony_ci	.free_file_info		= shmem_free_file_info,
33362306a36Sopenharmony_ci};
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_cistruct quota_format_type shmem_quota_format = {
33662306a36Sopenharmony_ci	.qf_fmt_id = QFMT_SHMEM,
33762306a36Sopenharmony_ci	.qf_ops = &shmem_format_ops,
33862306a36Sopenharmony_ci	.qf_owner = THIS_MODULE
33962306a36Sopenharmony_ci};
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ciconst struct dquot_operations shmem_quota_operations = {
34262306a36Sopenharmony_ci	.acquire_dquot		= shmem_acquire_dquot,
34362306a36Sopenharmony_ci	.release_dquot		= shmem_release_dquot,
34462306a36Sopenharmony_ci	.alloc_dquot		= dquot_alloc,
34562306a36Sopenharmony_ci	.destroy_dquot		= dquot_destroy,
34662306a36Sopenharmony_ci	.write_info		= shmem_dquot_write_info,
34762306a36Sopenharmony_ci	.mark_dirty		= shmem_mark_dquot_dirty,
34862306a36Sopenharmony_ci	.get_next_id		= shmem_get_next_id,
34962306a36Sopenharmony_ci};
35062306a36Sopenharmony_ci#endif /* CONFIG_TMPFS_QUOTA */
351