diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-07 13:11:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-07 13:11:22 +0000 |
commit | b20732900e4636a467c0183a47f7396700f5f743 (patch) | |
tree | 42f079ff82e701ebcb76829974b4caca3e5b6798 /fs/quota/quota_v2.c | |
parent | Adding upstream version 6.8.12. (diff) | |
download | linux-b20732900e4636a467c0183a47f7396700f5f743.tar.xz linux-b20732900e4636a467c0183a47f7396700f5f743.zip |
Adding upstream version 6.9.7.upstream/6.9.7
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'fs/quota/quota_v2.c')
-rw-r--r-- | fs/quota/quota_v2.c | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/fs/quota/quota_v2.c b/fs/quota/quota_v2.c index ae99e7b882..c48c233f3b 100644 --- a/fs/quota/quota_v2.c +++ b/fs/quota/quota_v2.c @@ -96,9 +96,11 @@ static int v2_read_file_info(struct super_block *sb, int type) struct qtree_mem_dqinfo *qinfo; ssize_t size; unsigned int version; + unsigned int memalloc; int ret; down_read(&dqopt->dqio_sem); + memalloc = memalloc_nofs_save(); ret = v2_read_header(sb, type, &dqhead); if (ret < 0) goto out; @@ -119,7 +121,7 @@ static int v2_read_file_info(struct super_block *sb, int type) ret = -EIO; goto out; } - info->dqi_priv = kmalloc(sizeof(struct qtree_mem_dqinfo), GFP_NOFS); + info->dqi_priv = kmalloc(sizeof(struct qtree_mem_dqinfo), GFP_KERNEL); if (!info->dqi_priv) { ret = -ENOMEM; goto out; @@ -166,14 +168,17 @@ static int v2_read_file_info(struct super_block *sb, int type) i_size_read(sb_dqopt(sb)->files[type])); goto out_free; } - if (qinfo->dqi_free_blk >= qinfo->dqi_blocks) { - quota_error(sb, "Free block number too big (%u >= %u).", - qinfo->dqi_free_blk, qinfo->dqi_blocks); + if (qinfo->dqi_free_blk && (qinfo->dqi_free_blk <= QT_TREEOFF || + qinfo->dqi_free_blk >= qinfo->dqi_blocks)) { + quota_error(sb, "Free block number %u out of range (%u, %u).", + qinfo->dqi_free_blk, QT_TREEOFF, qinfo->dqi_blocks); goto out_free; } - if (qinfo->dqi_free_entry >= qinfo->dqi_blocks) { - quota_error(sb, "Block with free entry too big (%u >= %u).", - qinfo->dqi_free_entry, qinfo->dqi_blocks); + if (qinfo->dqi_free_entry && (qinfo->dqi_free_entry <= QT_TREEOFF || + qinfo->dqi_free_entry >= qinfo->dqi_blocks)) { + quota_error(sb, "Block with free entry %u out of range (%u, %u).", + qinfo->dqi_free_entry, QT_TREEOFF, + qinfo->dqi_blocks); goto out_free; } ret = 0; @@ -183,6 +188,7 @@ out_free: info->dqi_priv = NULL; } out: + memalloc_nofs_restore(memalloc); up_read(&dqopt->dqio_sem); return ret; } @@ -195,8 +201,10 @@ static int v2_write_file_info(struct super_block *sb, int type) struct mem_dqinfo *info = &dqopt->info[type]; struct qtree_mem_dqinfo *qinfo = info->dqi_priv; ssize_t size; + unsigned int memalloc; down_write(&dqopt->dqio_sem); + memalloc = memalloc_nofs_save(); spin_lock(&dq_data_lock); info->dqi_flags &= ~DQF_INFO_DIRTY; dinfo.dqi_bgrace = cpu_to_le32(info->dqi_bgrace); @@ -209,6 +217,7 @@ static int v2_write_file_info(struct super_block *sb, int type) dinfo.dqi_free_entry = cpu_to_le32(qinfo->dqi_free_entry); size = sb->s_op->quota_write(sb, type, (char *)&dinfo, sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF); + memalloc_nofs_restore(memalloc); up_write(&dqopt->dqio_sem); if (size != sizeof(struct v2_disk_dqinfo)) { quota_error(sb, "Can't write info structure"); @@ -328,11 +337,14 @@ static int v2_read_dquot(struct dquot *dquot) { struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); int ret; + unsigned int memalloc; down_read(&dqopt->dqio_sem); + memalloc = memalloc_nofs_save(); ret = qtree_read_dquot( sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv, dquot); + memalloc_nofs_restore(memalloc); up_read(&dqopt->dqio_sem); return ret; } @@ -342,6 +354,7 @@ static int v2_write_dquot(struct dquot *dquot) struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); int ret; bool alloc = false; + unsigned int memalloc; /* * If space for dquot is already allocated, we don't need any @@ -355,9 +368,11 @@ static int v2_write_dquot(struct dquot *dquot) } else { down_read(&dqopt->dqio_sem); } + memalloc = memalloc_nofs_save(); ret = qtree_write_dquot( sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv, dquot); + memalloc_nofs_restore(memalloc); if (alloc) up_write(&dqopt->dqio_sem); else @@ -368,10 +383,13 @@ static int v2_write_dquot(struct dquot *dquot) static int v2_release_dquot(struct dquot *dquot) { struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); + unsigned int memalloc; int ret; down_write(&dqopt->dqio_sem); + memalloc = memalloc_nofs_save(); ret = qtree_release_dquot(sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv, dquot); + memalloc_nofs_restore(memalloc); up_write(&dqopt->dqio_sem); return ret; @@ -386,10 +404,13 @@ static int v2_free_file_info(struct super_block *sb, int type) static int v2_get_next_id(struct super_block *sb, struct kqid *qid) { struct quota_info *dqopt = sb_dqopt(sb); + unsigned int memalloc; int ret; down_read(&dqopt->dqio_sem); + memalloc = memalloc_nofs_save(); ret = qtree_get_next_id(sb_dqinfo(sb, qid->type)->dqi_priv, qid); + memalloc_nofs_restore(memalloc); up_read(&dqopt->dqio_sem); return ret; } |