1eafc474eSCarlos Maiolino // SPDX-License-Identifier: GPL-2.0-only
2eafc474eSCarlos Maiolino /*
3eafc474eSCarlos Maiolino * In memory quota format relies on quota infrastructure to store dquot
4eafc474eSCarlos Maiolino * information for us. While conventional quota formats for file systems
5eafc474eSCarlos Maiolino * with persistent storage can load quota information into dquot from the
6eafc474eSCarlos Maiolino * storage on-demand and hence quota dquot shrinker can free any dquot
7eafc474eSCarlos Maiolino * that is not currently being used, it must be avoided here. Otherwise we
8eafc474eSCarlos Maiolino * can lose valuable information, user provided limits, because there is
9eafc474eSCarlos Maiolino * no persistent storage to load the information from afterwards.
10eafc474eSCarlos Maiolino *
11eafc474eSCarlos Maiolino * One information that in-memory quota format needs to keep track of is
12eafc474eSCarlos Maiolino * a sorted list of ids for each quota type. This is done by utilizing
13eafc474eSCarlos Maiolino * an rb tree which root is stored in mem_dqinfo->dqi_priv for each quota
14eafc474eSCarlos Maiolino * type.
15eafc474eSCarlos Maiolino *
16eafc474eSCarlos Maiolino * This format can be used to support quota on file system without persistent
17eafc474eSCarlos Maiolino * storage such as tmpfs.
18eafc474eSCarlos Maiolino *
19eafc474eSCarlos Maiolino * Author: Lukas Czerner <lczerner@redhat.com>
20eafc474eSCarlos Maiolino * Carlos Maiolino <cmaiolino@redhat.com>
21eafc474eSCarlos Maiolino *
22eafc474eSCarlos Maiolino * Copyright (C) 2023 Red Hat, Inc.
23eafc474eSCarlos Maiolino */
24eafc474eSCarlos Maiolino #include <linux/errno.h>
25eafc474eSCarlos Maiolino #include <linux/fs.h>
26eafc474eSCarlos Maiolino #include <linux/mount.h>
27eafc474eSCarlos Maiolino #include <linux/kernel.h>
28eafc474eSCarlos Maiolino #include <linux/init.h>
29eafc474eSCarlos Maiolino #include <linux/module.h>
30eafc474eSCarlos Maiolino #include <linux/slab.h>
31eafc474eSCarlos Maiolino #include <linux/rbtree.h>
32eafc474eSCarlos Maiolino #include <linux/shmem_fs.h>
33eafc474eSCarlos Maiolino
34eafc474eSCarlos Maiolino #include <linux/quotaops.h>
35eafc474eSCarlos Maiolino #include <linux/quota.h>
36eafc474eSCarlos Maiolino
37eafc474eSCarlos Maiolino /*
38eafc474eSCarlos Maiolino * The following constants define the amount of time given a user
39eafc474eSCarlos Maiolino * before the soft limits are treated as hard limits (usually resulting
40eafc474eSCarlos Maiolino * in an allocation failure). The timer is started when the user crosses
41eafc474eSCarlos Maiolino * their soft limit, it is reset when they go below their soft limit.
42eafc474eSCarlos Maiolino */
43eafc474eSCarlos Maiolino #define SHMEM_MAX_IQ_TIME 604800 /* (7*24*60*60) 1 week */
44eafc474eSCarlos Maiolino #define SHMEM_MAX_DQ_TIME 604800 /* (7*24*60*60) 1 week */
45eafc474eSCarlos Maiolino
46eafc474eSCarlos Maiolino struct quota_id {
47eafc474eSCarlos Maiolino struct rb_node node;
48eafc474eSCarlos Maiolino qid_t id;
49eafc474eSCarlos Maiolino qsize_t bhardlimit;
50eafc474eSCarlos Maiolino qsize_t bsoftlimit;
51eafc474eSCarlos Maiolino qsize_t ihardlimit;
52eafc474eSCarlos Maiolino qsize_t isoftlimit;
53eafc474eSCarlos Maiolino };
54eafc474eSCarlos Maiolino
shmem_check_quota_file(struct super_block * sb,int type)55eafc474eSCarlos Maiolino static int shmem_check_quota_file(struct super_block *sb, int type)
56eafc474eSCarlos Maiolino {
57eafc474eSCarlos Maiolino /* There is no real quota file, nothing to do */
58eafc474eSCarlos Maiolino return 1;
59eafc474eSCarlos Maiolino }
60eafc474eSCarlos Maiolino
61eafc474eSCarlos Maiolino /*
62eafc474eSCarlos Maiolino * There is no real quota file. Just allocate rb_root for quota ids and
63eafc474eSCarlos Maiolino * set limits
64eafc474eSCarlos Maiolino */
shmem_read_file_info(struct super_block * sb,int type)65eafc474eSCarlos Maiolino static int shmem_read_file_info(struct super_block *sb, int type)
66eafc474eSCarlos Maiolino {
67eafc474eSCarlos Maiolino struct quota_info *dqopt = sb_dqopt(sb);
68eafc474eSCarlos Maiolino struct mem_dqinfo *info = &dqopt->info[type];
69eafc474eSCarlos Maiolino
70*69050f8dSKees Cook info->dqi_priv = kzalloc_obj(struct rb_root, GFP_NOFS);
71eafc474eSCarlos Maiolino if (!info->dqi_priv)
72eafc474eSCarlos Maiolino return -ENOMEM;
73eafc474eSCarlos Maiolino
74eafc474eSCarlos Maiolino info->dqi_max_spc_limit = SHMEM_QUOTA_MAX_SPC_LIMIT;
75eafc474eSCarlos Maiolino info->dqi_max_ino_limit = SHMEM_QUOTA_MAX_INO_LIMIT;
76eafc474eSCarlos Maiolino
77eafc474eSCarlos Maiolino info->dqi_bgrace = SHMEM_MAX_DQ_TIME;
78eafc474eSCarlos Maiolino info->dqi_igrace = SHMEM_MAX_IQ_TIME;
79eafc474eSCarlos Maiolino info->dqi_flags = 0;
80eafc474eSCarlos Maiolino
81eafc474eSCarlos Maiolino return 0;
82eafc474eSCarlos Maiolino }
83eafc474eSCarlos Maiolino
shmem_write_file_info(struct super_block * sb,int type)84eafc474eSCarlos Maiolino static int shmem_write_file_info(struct super_block *sb, int type)
85eafc474eSCarlos Maiolino {
86eafc474eSCarlos Maiolino /* There is no real quota file, nothing to do */
87eafc474eSCarlos Maiolino return 0;
88eafc474eSCarlos Maiolino }
89eafc474eSCarlos Maiolino
90eafc474eSCarlos Maiolino /*
91eafc474eSCarlos Maiolino * Free all the quota_id entries in the rb tree and rb_root.
92eafc474eSCarlos Maiolino */
shmem_free_file_info(struct super_block * sb,int type)93eafc474eSCarlos Maiolino static int shmem_free_file_info(struct super_block *sb, int type)
94eafc474eSCarlos Maiolino {
95eafc474eSCarlos Maiolino struct mem_dqinfo *info = &sb_dqopt(sb)->info[type];
96eafc474eSCarlos Maiolino struct rb_root *root = info->dqi_priv;
97eafc474eSCarlos Maiolino struct quota_id *entry;
98eafc474eSCarlos Maiolino struct rb_node *node;
99eafc474eSCarlos Maiolino
100eafc474eSCarlos Maiolino info->dqi_priv = NULL;
101eafc474eSCarlos Maiolino node = rb_first(root);
102eafc474eSCarlos Maiolino while (node) {
103eafc474eSCarlos Maiolino entry = rb_entry(node, struct quota_id, node);
104eafc474eSCarlos Maiolino node = rb_next(&entry->node);
105eafc474eSCarlos Maiolino
106eafc474eSCarlos Maiolino rb_erase(&entry->node, root);
107eafc474eSCarlos Maiolino kfree(entry);
108eafc474eSCarlos Maiolino }
109eafc474eSCarlos Maiolino
110eafc474eSCarlos Maiolino kfree(root);
111eafc474eSCarlos Maiolino return 0;
112eafc474eSCarlos Maiolino }
113eafc474eSCarlos Maiolino
shmem_get_next_id(struct super_block * sb,struct kqid * qid)114eafc474eSCarlos Maiolino static int shmem_get_next_id(struct super_block *sb, struct kqid *qid)
115eafc474eSCarlos Maiolino {
116eafc474eSCarlos Maiolino struct mem_dqinfo *info = sb_dqinfo(sb, qid->type);
1170a69b6b3SCarlos Maiolino struct rb_node *node;
118eafc474eSCarlos Maiolino qid_t id = from_kqid(&init_user_ns, *qid);
119eafc474eSCarlos Maiolino struct quota_info *dqopt = sb_dqopt(sb);
120eafc474eSCarlos Maiolino struct quota_id *entry = NULL;
121eafc474eSCarlos Maiolino int ret = 0;
122eafc474eSCarlos Maiolino
123eafc474eSCarlos Maiolino if (!sb_has_quota_active(sb, qid->type))
124eafc474eSCarlos Maiolino return -ESRCH;
125eafc474eSCarlos Maiolino
126eafc474eSCarlos Maiolino down_read(&dqopt->dqio_sem);
1270a69b6b3SCarlos Maiolino node = ((struct rb_root *)info->dqi_priv)->rb_node;
128eafc474eSCarlos Maiolino while (node) {
129eafc474eSCarlos Maiolino entry = rb_entry(node, struct quota_id, node);
130eafc474eSCarlos Maiolino
131eafc474eSCarlos Maiolino if (id < entry->id)
132eafc474eSCarlos Maiolino node = node->rb_left;
133eafc474eSCarlos Maiolino else if (id > entry->id)
134eafc474eSCarlos Maiolino node = node->rb_right;
135eafc474eSCarlos Maiolino else
136eafc474eSCarlos Maiolino goto got_next_id;
137eafc474eSCarlos Maiolino }
138eafc474eSCarlos Maiolino
139eafc474eSCarlos Maiolino if (!entry) {
140eafc474eSCarlos Maiolino ret = -ENOENT;
141eafc474eSCarlos Maiolino goto out_unlock;
142eafc474eSCarlos Maiolino }
143eafc474eSCarlos Maiolino
144eafc474eSCarlos Maiolino if (id > entry->id) {
145eafc474eSCarlos Maiolino node = rb_next(&entry->node);
146eafc474eSCarlos Maiolino if (!node) {
147eafc474eSCarlos Maiolino ret = -ENOENT;
148eafc474eSCarlos Maiolino goto out_unlock;
149eafc474eSCarlos Maiolino }
150eafc474eSCarlos Maiolino entry = rb_entry(node, struct quota_id, node);
151eafc474eSCarlos Maiolino }
152eafc474eSCarlos Maiolino
153eafc474eSCarlos Maiolino got_next_id:
154eafc474eSCarlos Maiolino *qid = make_kqid(&init_user_ns, qid->type, entry->id);
155eafc474eSCarlos Maiolino out_unlock:
156eafc474eSCarlos Maiolino up_read(&dqopt->dqio_sem);
157eafc474eSCarlos Maiolino return ret;
158eafc474eSCarlos Maiolino }
159eafc474eSCarlos Maiolino
160eafc474eSCarlos Maiolino /*
161eafc474eSCarlos Maiolino * Load dquot with limits from existing entry, or create the new entry if
162eafc474eSCarlos Maiolino * it does not exist.
163eafc474eSCarlos Maiolino */
shmem_acquire_dquot(struct dquot * dquot)164eafc474eSCarlos Maiolino static int shmem_acquire_dquot(struct dquot *dquot)
165eafc474eSCarlos Maiolino {
166eafc474eSCarlos Maiolino struct mem_dqinfo *info = sb_dqinfo(dquot->dq_sb, dquot->dq_id.type);
1670a69b6b3SCarlos Maiolino struct rb_node **n;
168de4c0e7cSLukas Czerner struct shmem_sb_info *sbinfo = dquot->dq_sb->s_fs_info;
169eafc474eSCarlos Maiolino struct rb_node *parent = NULL, *new_node = NULL;
170eafc474eSCarlos Maiolino struct quota_id *new_entry, *entry;
171eafc474eSCarlos Maiolino qid_t id = from_kqid(&init_user_ns, dquot->dq_id);
172eafc474eSCarlos Maiolino struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
173eafc474eSCarlos Maiolino int ret = 0;
174eafc474eSCarlos Maiolino
175eafc474eSCarlos Maiolino mutex_lock(&dquot->dq_lock);
176eafc474eSCarlos Maiolino
177eafc474eSCarlos Maiolino down_write(&dqopt->dqio_sem);
1780a69b6b3SCarlos Maiolino n = &((struct rb_root *)info->dqi_priv)->rb_node;
1790a69b6b3SCarlos Maiolino
180eafc474eSCarlos Maiolino while (*n) {
181eafc474eSCarlos Maiolino parent = *n;
182eafc474eSCarlos Maiolino entry = rb_entry(parent, struct quota_id, node);
183eafc474eSCarlos Maiolino
184eafc474eSCarlos Maiolino if (id < entry->id)
185eafc474eSCarlos Maiolino n = &(*n)->rb_left;
186eafc474eSCarlos Maiolino else if (id > entry->id)
187eafc474eSCarlos Maiolino n = &(*n)->rb_right;
188eafc474eSCarlos Maiolino else
189eafc474eSCarlos Maiolino goto found;
190eafc474eSCarlos Maiolino }
191eafc474eSCarlos Maiolino
192eafc474eSCarlos Maiolino /* We don't have entry for this id yet, create it */
193*69050f8dSKees Cook new_entry = kzalloc_obj(struct quota_id, GFP_NOFS);
194eafc474eSCarlos Maiolino if (!new_entry) {
195eafc474eSCarlos Maiolino ret = -ENOMEM;
196eafc474eSCarlos Maiolino goto out_unlock;
197eafc474eSCarlos Maiolino }
198eafc474eSCarlos Maiolino
199eafc474eSCarlos Maiolino new_entry->id = id;
200de4c0e7cSLukas Czerner if (dquot->dq_id.type == USRQUOTA) {
201de4c0e7cSLukas Czerner new_entry->bhardlimit = sbinfo->qlimits.usrquota_bhardlimit;
202de4c0e7cSLukas Czerner new_entry->ihardlimit = sbinfo->qlimits.usrquota_ihardlimit;
203de4c0e7cSLukas Czerner } else if (dquot->dq_id.type == GRPQUOTA) {
204de4c0e7cSLukas Czerner new_entry->bhardlimit = sbinfo->qlimits.grpquota_bhardlimit;
205de4c0e7cSLukas Czerner new_entry->ihardlimit = sbinfo->qlimits.grpquota_ihardlimit;
206de4c0e7cSLukas Czerner }
207de4c0e7cSLukas Czerner
208eafc474eSCarlos Maiolino new_node = &new_entry->node;
209eafc474eSCarlos Maiolino rb_link_node(new_node, parent, n);
210eafc474eSCarlos Maiolino rb_insert_color(new_node, (struct rb_root *)info->dqi_priv);
211eafc474eSCarlos Maiolino entry = new_entry;
212eafc474eSCarlos Maiolino
213eafc474eSCarlos Maiolino found:
214eafc474eSCarlos Maiolino /* Load the stored limits from the tree */
215eafc474eSCarlos Maiolino spin_lock(&dquot->dq_dqb_lock);
216eafc474eSCarlos Maiolino dquot->dq_dqb.dqb_bhardlimit = entry->bhardlimit;
217eafc474eSCarlos Maiolino dquot->dq_dqb.dqb_bsoftlimit = entry->bsoftlimit;
218eafc474eSCarlos Maiolino dquot->dq_dqb.dqb_ihardlimit = entry->ihardlimit;
219eafc474eSCarlos Maiolino dquot->dq_dqb.dqb_isoftlimit = entry->isoftlimit;
220eafc474eSCarlos Maiolino
221eafc474eSCarlos Maiolino if (!dquot->dq_dqb.dqb_bhardlimit &&
222eafc474eSCarlos Maiolino !dquot->dq_dqb.dqb_bsoftlimit &&
223eafc474eSCarlos Maiolino !dquot->dq_dqb.dqb_ihardlimit &&
224eafc474eSCarlos Maiolino !dquot->dq_dqb.dqb_isoftlimit)
225eafc474eSCarlos Maiolino set_bit(DQ_FAKE_B, &dquot->dq_flags);
226eafc474eSCarlos Maiolino spin_unlock(&dquot->dq_dqb_lock);
227eafc474eSCarlos Maiolino
228eafc474eSCarlos Maiolino /* Make sure flags update is visible after dquot has been filled */
229eafc474eSCarlos Maiolino smp_mb__before_atomic();
230eafc474eSCarlos Maiolino set_bit(DQ_ACTIVE_B, &dquot->dq_flags);
231eafc474eSCarlos Maiolino out_unlock:
232eafc474eSCarlos Maiolino up_write(&dqopt->dqio_sem);
233eafc474eSCarlos Maiolino mutex_unlock(&dquot->dq_lock);
234eafc474eSCarlos Maiolino return ret;
235eafc474eSCarlos Maiolino }
236eafc474eSCarlos Maiolino
shmem_is_empty_dquot(struct dquot * dquot)237de4c0e7cSLukas Czerner static bool shmem_is_empty_dquot(struct dquot *dquot)
238de4c0e7cSLukas Czerner {
239de4c0e7cSLukas Czerner struct shmem_sb_info *sbinfo = dquot->dq_sb->s_fs_info;
240de4c0e7cSLukas Czerner qsize_t bhardlimit;
241de4c0e7cSLukas Czerner qsize_t ihardlimit;
242de4c0e7cSLukas Czerner
243de4c0e7cSLukas Czerner if (dquot->dq_id.type == USRQUOTA) {
244de4c0e7cSLukas Czerner bhardlimit = sbinfo->qlimits.usrquota_bhardlimit;
245de4c0e7cSLukas Czerner ihardlimit = sbinfo->qlimits.usrquota_ihardlimit;
246de4c0e7cSLukas Czerner } else if (dquot->dq_id.type == GRPQUOTA) {
247de4c0e7cSLukas Czerner bhardlimit = sbinfo->qlimits.grpquota_bhardlimit;
248de4c0e7cSLukas Czerner ihardlimit = sbinfo->qlimits.grpquota_ihardlimit;
249de4c0e7cSLukas Czerner }
250de4c0e7cSLukas Czerner
251de4c0e7cSLukas Czerner if (test_bit(DQ_FAKE_B, &dquot->dq_flags) ||
252de4c0e7cSLukas Czerner (dquot->dq_dqb.dqb_curspace == 0 &&
253de4c0e7cSLukas Czerner dquot->dq_dqb.dqb_curinodes == 0 &&
254de4c0e7cSLukas Czerner dquot->dq_dqb.dqb_bhardlimit == bhardlimit &&
255de4c0e7cSLukas Czerner dquot->dq_dqb.dqb_ihardlimit == ihardlimit))
256de4c0e7cSLukas Czerner return true;
257de4c0e7cSLukas Czerner
258de4c0e7cSLukas Czerner return false;
259de4c0e7cSLukas Czerner }
260eafc474eSCarlos Maiolino /*
261eafc474eSCarlos Maiolino * Store limits from dquot in the tree unless it's fake. If it is fake
262eafc474eSCarlos Maiolino * remove the id from the tree since there is no useful information in
263eafc474eSCarlos Maiolino * there.
264eafc474eSCarlos Maiolino */
shmem_release_dquot(struct dquot * dquot)265eafc474eSCarlos Maiolino static int shmem_release_dquot(struct dquot *dquot)
266eafc474eSCarlos Maiolino {
267eafc474eSCarlos Maiolino struct mem_dqinfo *info = sb_dqinfo(dquot->dq_sb, dquot->dq_id.type);
2680a69b6b3SCarlos Maiolino struct rb_node *node;
269eafc474eSCarlos Maiolino qid_t id = from_kqid(&init_user_ns, dquot->dq_id);
270eafc474eSCarlos Maiolino struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
271eafc474eSCarlos Maiolino struct quota_id *entry = NULL;
272eafc474eSCarlos Maiolino
273eafc474eSCarlos Maiolino mutex_lock(&dquot->dq_lock);
274eafc474eSCarlos Maiolino /* Check whether we are not racing with some other dqget() */
275eafc474eSCarlos Maiolino if (dquot_is_busy(dquot))
276eafc474eSCarlos Maiolino goto out_dqlock;
277eafc474eSCarlos Maiolino
278eafc474eSCarlos Maiolino down_write(&dqopt->dqio_sem);
2790a69b6b3SCarlos Maiolino node = ((struct rb_root *)info->dqi_priv)->rb_node;
280eafc474eSCarlos Maiolino while (node) {
281eafc474eSCarlos Maiolino entry = rb_entry(node, struct quota_id, node);
282eafc474eSCarlos Maiolino
283eafc474eSCarlos Maiolino if (id < entry->id)
284eafc474eSCarlos Maiolino node = node->rb_left;
285eafc474eSCarlos Maiolino else if (id > entry->id)
286eafc474eSCarlos Maiolino node = node->rb_right;
287eafc474eSCarlos Maiolino else
288eafc474eSCarlos Maiolino goto found;
289eafc474eSCarlos Maiolino }
290eafc474eSCarlos Maiolino
291eafc474eSCarlos Maiolino /* We should always find the entry in the rb tree */
292eafc474eSCarlos Maiolino WARN_ONCE(1, "quota id %u from dquot %p, not in rb tree!\n", id, dquot);
293eafc474eSCarlos Maiolino up_write(&dqopt->dqio_sem);
294eafc474eSCarlos Maiolino mutex_unlock(&dquot->dq_lock);
295eafc474eSCarlos Maiolino return -ENOENT;
296eafc474eSCarlos Maiolino
297eafc474eSCarlos Maiolino found:
298de4c0e7cSLukas Czerner if (shmem_is_empty_dquot(dquot)) {
299eafc474eSCarlos Maiolino /* Remove entry from the tree */
300eafc474eSCarlos Maiolino rb_erase(&entry->node, info->dqi_priv);
301eafc474eSCarlos Maiolino kfree(entry);
302eafc474eSCarlos Maiolino } else {
303eafc474eSCarlos Maiolino /* Store the limits in the tree */
304eafc474eSCarlos Maiolino spin_lock(&dquot->dq_dqb_lock);
305eafc474eSCarlos Maiolino entry->bhardlimit = dquot->dq_dqb.dqb_bhardlimit;
306eafc474eSCarlos Maiolino entry->bsoftlimit = dquot->dq_dqb.dqb_bsoftlimit;
307eafc474eSCarlos Maiolino entry->ihardlimit = dquot->dq_dqb.dqb_ihardlimit;
308eafc474eSCarlos Maiolino entry->isoftlimit = dquot->dq_dqb.dqb_isoftlimit;
309eafc474eSCarlos Maiolino spin_unlock(&dquot->dq_dqb_lock);
310eafc474eSCarlos Maiolino }
311eafc474eSCarlos Maiolino
312eafc474eSCarlos Maiolino clear_bit(DQ_ACTIVE_B, &dquot->dq_flags);
313eafc474eSCarlos Maiolino up_write(&dqopt->dqio_sem);
314eafc474eSCarlos Maiolino
315eafc474eSCarlos Maiolino out_dqlock:
316eafc474eSCarlos Maiolino mutex_unlock(&dquot->dq_lock);
317eafc474eSCarlos Maiolino return 0;
318eafc474eSCarlos Maiolino }
319eafc474eSCarlos Maiolino
shmem_mark_dquot_dirty(struct dquot * dquot)320eafc474eSCarlos Maiolino static int shmem_mark_dquot_dirty(struct dquot *dquot)
321eafc474eSCarlos Maiolino {
322eafc474eSCarlos Maiolino return 0;
323eafc474eSCarlos Maiolino }
324eafc474eSCarlos Maiolino
shmem_dquot_write_info(struct super_block * sb,int type)325eafc474eSCarlos Maiolino static int shmem_dquot_write_info(struct super_block *sb, int type)
326eafc474eSCarlos Maiolino {
327eafc474eSCarlos Maiolino return 0;
328eafc474eSCarlos Maiolino }
329eafc474eSCarlos Maiolino
330eafc474eSCarlos Maiolino static const struct quota_format_ops shmem_format_ops = {
331eafc474eSCarlos Maiolino .check_quota_file = shmem_check_quota_file,
332eafc474eSCarlos Maiolino .read_file_info = shmem_read_file_info,
333eafc474eSCarlos Maiolino .write_file_info = shmem_write_file_info,
334eafc474eSCarlos Maiolino .free_file_info = shmem_free_file_info,
335eafc474eSCarlos Maiolino };
336eafc474eSCarlos Maiolino
337eafc474eSCarlos Maiolino struct quota_format_type shmem_quota_format = {
338eafc474eSCarlos Maiolino .qf_fmt_id = QFMT_SHMEM,
339eafc474eSCarlos Maiolino .qf_ops = &shmem_format_ops,
340eafc474eSCarlos Maiolino .qf_owner = THIS_MODULE
341eafc474eSCarlos Maiolino };
342eafc474eSCarlos Maiolino
343eafc474eSCarlos Maiolino const struct dquot_operations shmem_quota_operations = {
344eafc474eSCarlos Maiolino .acquire_dquot = shmem_acquire_dquot,
345eafc474eSCarlos Maiolino .release_dquot = shmem_release_dquot,
346eafc474eSCarlos Maiolino .alloc_dquot = dquot_alloc,
347eafc474eSCarlos Maiolino .destroy_dquot = dquot_destroy,
348eafc474eSCarlos Maiolino .write_info = shmem_dquot_write_info,
349eafc474eSCarlos Maiolino .mark_dirty = shmem_mark_dquot_dirty,
350eafc474eSCarlos Maiolino .get_next_id = shmem_get_next_id,
351eafc474eSCarlos Maiolino };
352