1 // SPDX-License-Identifier: GPL-2.0-only
3 * In memory quota format relies on quota infrastructure to store dquot
4 * information for us. While conventional quota formats for file systems
5 * with persistent storage can load quota information into dquot from the
6 * storage on-demand and hence quota dquot shrinker can free any dquot
7 * that is not currently being used, it must be avoided here. Otherwise we
8 * can lose valuable information, user provided limits, because there is
9 * no persistent storage to load the information from afterwards.
11 * One information that in-memory quota format needs to keep track of is
12 * a sorted list of ids for each quota type. This is done by utilizing
13 * an rb tree which root is stored in mem_dqinfo->dqi_priv for each quota
16 * This format can be used to support quota on file system without persistent
17 * storage such as tmpfs.
19 * Author: Lukas Czerner <lczerner@redhat.com>
20 * Carlos Maiolino <cmaiolino@redhat.com>
22 * Copyright (C) 2023 Red Hat, Inc.
24 #include <linux/errno.h>
26 #include <linux/mount.h>
27 #include <linux/kernel.h>
28 #include <linux/init.h>
29 #include <linux/module.h>
30 #include <linux/slab.h>
31 #include <linux/rbtree.h>
32 #include <linux/shmem_fs.h>
34 #include <linux/quotaops.h>
35 #include <linux/quota.h>
38 * The following constants define the amount of time given a user
39 * before the soft limits are treated as hard limits (usually resulting
40 * in an allocation failure). The timer is started when the user crosses
41 * their soft limit, it is reset when they go below their soft limit.
43 #define SHMEM_MAX_IQ_TIME 604800 /* (7*24*60*60) 1 week */
44 #define SHMEM_MAX_DQ_TIME 604800 /* (7*24*60*60) 1 week */
55 static int shmem_check_quota_file(struct super_block
*sb
, int type
)
57 /* There is no real quota file, nothing to do */
62 * There is no real quota file. Just allocate rb_root for quota ids and
65 static int shmem_read_file_info(struct super_block
*sb
, int type
)
67 struct quota_info
*dqopt
= sb_dqopt(sb
);
68 struct mem_dqinfo
*info
= &dqopt
->info
[type
];
70 info
->dqi_priv
= kzalloc(sizeof(struct rb_root
), GFP_NOFS
);
74 info
->dqi_max_spc_limit
= SHMEM_QUOTA_MAX_SPC_LIMIT
;
75 info
->dqi_max_ino_limit
= SHMEM_QUOTA_MAX_INO_LIMIT
;
77 info
->dqi_bgrace
= SHMEM_MAX_DQ_TIME
;
78 info
->dqi_igrace
= SHMEM_MAX_IQ_TIME
;
84 static int shmem_write_file_info(struct super_block
*sb
, int type
)
86 /* There is no real quota file, nothing to do */
91 * Free all the quota_id entries in the rb tree and rb_root.
93 static int shmem_free_file_info(struct super_block
*sb
, int type
)
95 struct mem_dqinfo
*info
= &sb_dqopt(sb
)->info
[type
];
96 struct rb_root
*root
= info
->dqi_priv
;
97 struct quota_id
*entry
;
100 info
->dqi_priv
= NULL
;
101 node
= rb_first(root
);
103 entry
= rb_entry(node
, struct quota_id
, node
);
104 node
= rb_next(&entry
->node
);
106 rb_erase(&entry
->node
, root
);
114 static int shmem_get_next_id(struct super_block
*sb
, struct kqid
*qid
)
116 struct mem_dqinfo
*info
= sb_dqinfo(sb
, qid
->type
);
117 struct rb_node
*node
;
118 qid_t id
= from_kqid(&init_user_ns
, *qid
);
119 struct quota_info
*dqopt
= sb_dqopt(sb
);
120 struct quota_id
*entry
= NULL
;
123 if (!sb_has_quota_active(sb
, qid
->type
))
126 down_read(&dqopt
->dqio_sem
);
127 node
= ((struct rb_root
*)info
->dqi_priv
)->rb_node
;
129 entry
= rb_entry(node
, struct quota_id
, node
);
132 node
= node
->rb_left
;
133 else if (id
> entry
->id
)
134 node
= node
->rb_right
;
144 if (id
> entry
->id
) {
145 node
= rb_next(&entry
->node
);
150 entry
= rb_entry(node
, struct quota_id
, node
);
154 *qid
= make_kqid(&init_user_ns
, qid
->type
, entry
->id
);
156 up_read(&dqopt
->dqio_sem
);
161 * Load dquot with limits from existing entry, or create the new entry if
164 static int shmem_acquire_dquot(struct dquot
*dquot
)
166 struct mem_dqinfo
*info
= sb_dqinfo(dquot
->dq_sb
, dquot
->dq_id
.type
);
168 struct shmem_sb_info
*sbinfo
= dquot
->dq_sb
->s_fs_info
;
169 struct rb_node
*parent
= NULL
, *new_node
= NULL
;
170 struct quota_id
*new_entry
, *entry
;
171 qid_t id
= from_kqid(&init_user_ns
, dquot
->dq_id
);
172 struct quota_info
*dqopt
= sb_dqopt(dquot
->dq_sb
);
175 mutex_lock(&dquot
->dq_lock
);
177 down_write(&dqopt
->dqio_sem
);
178 n
= &((struct rb_root
*)info
->dqi_priv
)->rb_node
;
182 entry
= rb_entry(parent
, struct quota_id
, node
);
186 else if (id
> entry
->id
)
192 /* We don't have entry for this id yet, create it */
193 new_entry
= kzalloc(sizeof(struct quota_id
), GFP_NOFS
);
200 if (dquot
->dq_id
.type
== USRQUOTA
) {
201 new_entry
->bhardlimit
= sbinfo
->qlimits
.usrquota_bhardlimit
;
202 new_entry
->ihardlimit
= sbinfo
->qlimits
.usrquota_ihardlimit
;
203 } else if (dquot
->dq_id
.type
== GRPQUOTA
) {
204 new_entry
->bhardlimit
= sbinfo
->qlimits
.grpquota_bhardlimit
;
205 new_entry
->ihardlimit
= sbinfo
->qlimits
.grpquota_ihardlimit
;
208 new_node
= &new_entry
->node
;
209 rb_link_node(new_node
, parent
, n
);
210 rb_insert_color(new_node
, (struct rb_root
*)info
->dqi_priv
);
214 /* Load the stored limits from the tree */
215 spin_lock(&dquot
->dq_dqb_lock
);
216 dquot
->dq_dqb
.dqb_bhardlimit
= entry
->bhardlimit
;
217 dquot
->dq_dqb
.dqb_bsoftlimit
= entry
->bsoftlimit
;
218 dquot
->dq_dqb
.dqb_ihardlimit
= entry
->ihardlimit
;
219 dquot
->dq_dqb
.dqb_isoftlimit
= entry
->isoftlimit
;
221 if (!dquot
->dq_dqb
.dqb_bhardlimit
&&
222 !dquot
->dq_dqb
.dqb_bsoftlimit
&&
223 !dquot
->dq_dqb
.dqb_ihardlimit
&&
224 !dquot
->dq_dqb
.dqb_isoftlimit
)
225 set_bit(DQ_FAKE_B
, &dquot
->dq_flags
);
226 spin_unlock(&dquot
->dq_dqb_lock
);
228 /* Make sure flags update is visible after dquot has been filled */
229 smp_mb__before_atomic();
230 set_bit(DQ_ACTIVE_B
, &dquot
->dq_flags
);
232 up_write(&dqopt
->dqio_sem
);
233 mutex_unlock(&dquot
->dq_lock
);
237 static bool shmem_is_empty_dquot(struct dquot
*dquot
)
239 struct shmem_sb_info
*sbinfo
= dquot
->dq_sb
->s_fs_info
;
243 if (dquot
->dq_id
.type
== USRQUOTA
) {
244 bhardlimit
= sbinfo
->qlimits
.usrquota_bhardlimit
;
245 ihardlimit
= sbinfo
->qlimits
.usrquota_ihardlimit
;
246 } else if (dquot
->dq_id
.type
== GRPQUOTA
) {
247 bhardlimit
= sbinfo
->qlimits
.grpquota_bhardlimit
;
248 ihardlimit
= sbinfo
->qlimits
.grpquota_ihardlimit
;
251 if (test_bit(DQ_FAKE_B
, &dquot
->dq_flags
) ||
252 (dquot
->dq_dqb
.dqb_curspace
== 0 &&
253 dquot
->dq_dqb
.dqb_curinodes
== 0 &&
254 dquot
->dq_dqb
.dqb_bhardlimit
== bhardlimit
&&
255 dquot
->dq_dqb
.dqb_ihardlimit
== ihardlimit
))
261 * Store limits from dquot in the tree unless it's fake. If it is fake
262 * remove the id from the tree since there is no useful information in
265 static int shmem_release_dquot(struct dquot
*dquot
)
267 struct mem_dqinfo
*info
= sb_dqinfo(dquot
->dq_sb
, dquot
->dq_id
.type
);
268 struct rb_node
*node
;
269 qid_t id
= from_kqid(&init_user_ns
, dquot
->dq_id
);
270 struct quota_info
*dqopt
= sb_dqopt(dquot
->dq_sb
);
271 struct quota_id
*entry
= NULL
;
273 mutex_lock(&dquot
->dq_lock
);
274 /* Check whether we are not racing with some other dqget() */
275 if (dquot_is_busy(dquot
))
278 down_write(&dqopt
->dqio_sem
);
279 node
= ((struct rb_root
*)info
->dqi_priv
)->rb_node
;
281 entry
= rb_entry(node
, struct quota_id
, node
);
284 node
= node
->rb_left
;
285 else if (id
> entry
->id
)
286 node
= node
->rb_right
;
291 /* We should always find the entry in the rb tree */
292 WARN_ONCE(1, "quota id %u from dquot %p, not in rb tree!\n", id
, dquot
);
293 up_write(&dqopt
->dqio_sem
);
294 mutex_unlock(&dquot
->dq_lock
);
298 if (shmem_is_empty_dquot(dquot
)) {
299 /* Remove entry from the tree */
300 rb_erase(&entry
->node
, info
->dqi_priv
);
303 /* Store the limits in the tree */
304 spin_lock(&dquot
->dq_dqb_lock
);
305 entry
->bhardlimit
= dquot
->dq_dqb
.dqb_bhardlimit
;
306 entry
->bsoftlimit
= dquot
->dq_dqb
.dqb_bsoftlimit
;
307 entry
->ihardlimit
= dquot
->dq_dqb
.dqb_ihardlimit
;
308 entry
->isoftlimit
= dquot
->dq_dqb
.dqb_isoftlimit
;
309 spin_unlock(&dquot
->dq_dqb_lock
);
312 clear_bit(DQ_ACTIVE_B
, &dquot
->dq_flags
);
313 up_write(&dqopt
->dqio_sem
);
316 mutex_unlock(&dquot
->dq_lock
);
320 static int shmem_mark_dquot_dirty(struct dquot
*dquot
)
325 static int shmem_dquot_write_info(struct super_block
*sb
, int type
)
330 static const struct quota_format_ops shmem_format_ops
= {
331 .check_quota_file
= shmem_check_quota_file
,
332 .read_file_info
= shmem_read_file_info
,
333 .write_file_info
= shmem_write_file_info
,
334 .free_file_info
= shmem_free_file_info
,
337 struct quota_format_type shmem_quota_format
= {
338 .qf_fmt_id
= QFMT_SHMEM
,
339 .qf_ops
= &shmem_format_ops
,
340 .qf_owner
= THIS_MODULE
343 const struct dquot_operations shmem_quota_operations
= {
344 .acquire_dquot
= shmem_acquire_dquot
,
345 .release_dquot
= shmem_release_dquot
,
346 .alloc_dquot
= dquot_alloc
,
347 .destroy_dquot
= dquot_destroy
,
348 .write_info
= shmem_dquot_write_info
,
349 .mark_dirty
= shmem_mark_dquot_dirty
,
350 .get_next_id
= shmem_get_next_id
,