mirror of https://gitee.com/openkylin/linux.git
quota_v2: Implement get_next_id() for V2 quota format
Implement functions to get id of next existing quota structure in quota file for quota tree based formats and thus for V2 quota format. Signed-off-by: Jan Kara <jack@suse.cz>
This commit is contained in:
parent
be6257b251
commit
0066373d9f
|
@ -22,10 +22,9 @@ MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
#define __QUOTA_QT_PARANOIA
|
#define __QUOTA_QT_PARANOIA
|
||||||
|
|
||||||
static int get_index(struct qtree_mem_dqinfo *info, struct kqid qid, int depth)
|
static int __get_index(struct qtree_mem_dqinfo *info, qid_t id, int depth)
|
||||||
{
|
{
|
||||||
unsigned int epb = info->dqi_usable_bs >> 2;
|
unsigned int epb = info->dqi_usable_bs >> 2;
|
||||||
qid_t id = from_kqid(&init_user_ns, qid);
|
|
||||||
|
|
||||||
depth = info->dqi_qtree_depth - depth - 1;
|
depth = info->dqi_qtree_depth - depth - 1;
|
||||||
while (depth--)
|
while (depth--)
|
||||||
|
@ -33,6 +32,13 @@ static int get_index(struct qtree_mem_dqinfo *info, struct kqid qid, int depth)
|
||||||
return id % epb;
|
return id % epb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int get_index(struct qtree_mem_dqinfo *info, struct kqid qid, int depth)
|
||||||
|
{
|
||||||
|
qid_t id = from_kqid(&init_user_ns, qid);
|
||||||
|
|
||||||
|
return __get_index(info, id, depth);
|
||||||
|
}
|
||||||
|
|
||||||
/* Number of entries in one blocks */
|
/* Number of entries in one blocks */
|
||||||
static int qtree_dqstr_in_blk(struct qtree_mem_dqinfo *info)
|
static int qtree_dqstr_in_blk(struct qtree_mem_dqinfo *info)
|
||||||
{
|
{
|
||||||
|
@ -668,3 +674,60 @@ int qtree_release_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(qtree_release_dquot);
|
EXPORT_SYMBOL(qtree_release_dquot);
|
||||||
|
|
||||||
|
static int find_next_id(struct qtree_mem_dqinfo *info, qid_t *id,
|
||||||
|
unsigned int blk, int depth)
|
||||||
|
{
|
||||||
|
char *buf = getdqbuf(info->dqi_usable_bs);
|
||||||
|
__le32 *ref = (__le32 *)buf;
|
||||||
|
ssize_t ret;
|
||||||
|
unsigned int epb = info->dqi_usable_bs >> 2;
|
||||||
|
unsigned int level_inc = 1;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!buf)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
for (i = depth; i < info->dqi_qtree_depth - 1; i++)
|
||||||
|
level_inc *= epb;
|
||||||
|
|
||||||
|
ret = read_blk(info, blk, buf);
|
||||||
|
if (ret < 0) {
|
||||||
|
quota_error(info->dqi_sb,
|
||||||
|
"Can't read quota tree block %u", blk);
|
||||||
|
goto out_buf;
|
||||||
|
}
|
||||||
|
for (i = __get_index(info, *id, depth); i < epb; i++) {
|
||||||
|
if (ref[i] == cpu_to_le32(0)) {
|
||||||
|
*id += level_inc;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (depth == info->dqi_qtree_depth - 1) {
|
||||||
|
ret = 0;
|
||||||
|
goto out_buf;
|
||||||
|
}
|
||||||
|
ret = find_next_id(info, id, le32_to_cpu(ref[i]), depth + 1);
|
||||||
|
if (ret != -ENOENT)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == epb) {
|
||||||
|
ret = -ENOENT;
|
||||||
|
goto out_buf;
|
||||||
|
}
|
||||||
|
out_buf:
|
||||||
|
kfree(buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int qtree_get_next_id(struct qtree_mem_dqinfo *info, struct kqid *qid)
|
||||||
|
{
|
||||||
|
qid_t id = from_kqid(&init_user_ns, *qid);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = find_next_id(info, &id, QT_TREEOFF, 0);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
*qid = make_kqid(&init_user_ns, qid->type, id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(qtree_get_next_id);
|
||||||
|
|
|
@ -304,6 +304,11 @@ static int v2_free_file_info(struct super_block *sb, int type)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int v2_get_next_id(struct super_block *sb, struct kqid *qid)
|
||||||
|
{
|
||||||
|
return qtree_get_next_id(sb_dqinfo(sb, qid->type)->dqi_priv, qid);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct quota_format_ops v2_format_ops = {
|
static const struct quota_format_ops v2_format_ops = {
|
||||||
.check_quota_file = v2_check_quota_file,
|
.check_quota_file = v2_check_quota_file,
|
||||||
.read_file_info = v2_read_file_info,
|
.read_file_info = v2_read_file_info,
|
||||||
|
@ -312,6 +317,7 @@ static const struct quota_format_ops v2_format_ops = {
|
||||||
.read_dqblk = v2_read_dquot,
|
.read_dqblk = v2_read_dquot,
|
||||||
.commit_dqblk = v2_write_dquot,
|
.commit_dqblk = v2_write_dquot,
|
||||||
.release_dqblk = v2_release_dquot,
|
.release_dqblk = v2_release_dquot,
|
||||||
|
.get_next_id = v2_get_next_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct quota_format_type v2r0_quota_format = {
|
static struct quota_format_type v2r0_quota_format = {
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#define QTREE_DEL_REWRITE 6
|
#define QTREE_DEL_REWRITE 6
|
||||||
|
|
||||||
struct dquot;
|
struct dquot;
|
||||||
|
struct kqid;
|
||||||
|
|
||||||
/* Operations */
|
/* Operations */
|
||||||
struct qtree_fmt_operations {
|
struct qtree_fmt_operations {
|
||||||
|
@ -52,5 +53,6 @@ static inline int qtree_depth(struct qtree_mem_dqinfo *info)
|
||||||
entries *= epb;
|
entries *= epb;
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
int qtree_get_next_id(struct qtree_mem_dqinfo *info, struct kqid *qid);
|
||||||
|
|
||||||
#endif /* _LINUX_DQBLK_QTREE_H */
|
#endif /* _LINUX_DQBLK_QTREE_H */
|
||||||
|
|
Loading…
Reference in New Issue