// SPDX-License-Identifier: GPL-2.0-only /* * In memory quota format relies on quota infrastructure to store dquot * information for us. While conventional quota formats for file systems * with persistent storage can load quota information into dquot from the * storage on-demand and hence quota dquot shrinker can free any dquot * that is not currently being used, it must be avoided here. Otherwise we * can lose valuable information, user provided limits, because there is * no persistent storage to load the information from afterwards. * * One information that in-memory quota format needs to keep track of is * a sorted list of ids for each quota type. This is done by utilizing * an rb tree which root is stored in mem_dqinfo->dqi_priv for each quota * type. * * This format can be used to support quota on file system without persistent * storage such as tmpfs. * * Author: Lukas Czerner <lczerner@redhat.com> * Carlos Maiolino <cmaiolino@redhat.com> * * Copyright (C) 2023 Red Hat, Inc.
*/ #include <linux/errno.h> #include <linux/fs.h> #include <linux/mount.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/rbtree.h> #include <linux/shmem_fs.h>
/* * The following constants define the amount of time given a user * before the soft limits are treated as hard limits (usually resulting * in an allocation failure). The timer is started when the user crosses * their soft limit, it is reset when they go below their soft limit.
*/ #define SHMEM_MAX_IQ_TIME 604800 /* (7*24*60*60) 1 week */ #define SHMEM_MAX_DQ_TIME 604800 /* (7*24*60*60) 1 week */
staticint shmem_check_quota_file(struct super_block *sb, int type)
{ /* There is no real quota file, nothing to do */ return 1;
}
/* * There is no real quota file. Just allocate rb_root for quota ids and * set limits
*/ staticint shmem_read_file_info(struct super_block *sb, int type)
{ struct quota_info *dqopt = sb_dqopt(sb); struct mem_dqinfo *info = &dqopt->info[type];
info->dqi_priv = kzalloc(sizeof(struct rb_root), GFP_NOFS); if (!info->dqi_priv) return -ENOMEM;
if (id < entry->id)
n = &(*n)->rb_left; elseif (id > entry->id)
n = &(*n)->rb_right; else goto found;
}
/* We don't have entry for this id yet, create it */
new_entry = kzalloc(sizeof(struct quota_id), GFP_NOFS); if (!new_entry) {
ret = -ENOMEM; goto out_unlock;
}
/* Make sure flags update is visible after dquot has been filled */
smp_mb__before_atomic();
set_bit(DQ_ACTIVE_B, &dquot->dq_flags);
out_unlock:
up_write(&dqopt->dqio_sem);
mutex_unlock(&dquot->dq_lock); return ret;
}
returnfalse;
} /* * Store limits from dquot in the tree unless it's fake. If it is fake * remove the id from the tree since there is no useful information in * there.
*/ staticint shmem_release_dquot(struct dquot *dquot)
{ struct mem_dqinfo *info = sb_dqinfo(dquot->dq_sb, dquot->dq_id.type); struct rb_node *node;
qid_t id = from_kqid(&init_user_ns, dquot->dq_id); struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); struct quota_id *entry = NULL;
mutex_lock(&dquot->dq_lock); /* Check whether we are not racing with some other dqget() */ if (dquot_is_busy(dquot)) goto out_dqlock;
if (id < entry->id)
node = node->rb_left; elseif (id > entry->id)
node = node->rb_right; else goto found;
}
/* We should always find the entry in the rb tree */
WARN_ONCE(1, "quota id %u from dquot %p, not in rb tree!\n", id, dquot);
up_write(&dqopt->dqio_sem);
mutex_unlock(&dquot->dq_lock); return -ENOENT;
found: if (shmem_is_empty_dquot(dquot)) { /* Remove entry from the tree */
rb_erase(&entry->node, info->dqi_priv);
kfree(entry);
} else { /* Store the limits in the tree */
spin_lock(&dquot->dq_dqb_lock);
entry->bhardlimit = dquot->dq_dqb.dqb_bhardlimit;
entry->bsoftlimit = dquot->dq_dqb.dqb_bsoftlimit;
entry->ihardlimit = dquot->dq_dqb.dqb_ihardlimit;
entry->isoftlimit = dquot->dq_dqb.dqb_isoftlimit;
spin_unlock(&dquot->dq_dqb_lock);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.