diff options
Diffstat (limited to 'fs/quota/quota_v1.c')
| -rw-r--r-- | fs/quota/quota_v1.c | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/fs/quota/quota_v1.c b/fs/quota/quota_v1.c index 8fe79beced5c..6f7f0b4afba9 100644 --- a/fs/quota/quota_v1.c +++ b/fs/quota/quota_v1.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only #include <linux/errno.h> #include <linux/fs.h> #include <linux/quota.h> @@ -56,8 +57,9 @@ static int v1_read_dqblk(struct dquot *dquot) { int type = dquot->dq_id.type; struct v1_disk_dqblk dqblk; + struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); - if (!sb_dqopt(dquot->dq_sb)->files[type]) + if (!dqopt->files[type]) return -EINVAL; /* Set structure to 0s in case read fails/is after end of file */ @@ -126,7 +128,7 @@ static int v1_check_quota_file(struct super_block *sb, int type) { struct inode *inode = sb_dqopt(sb)->files[type]; ulong blocks; - size_t off; + size_t off; struct v2_disk_dqheader dqhead; ssize_t size; loff_t isize; @@ -158,8 +160,11 @@ static int v1_read_file_info(struct super_block *sb, int type) { struct quota_info *dqopt = sb_dqopt(sb); struct v1_disk_dqblk dqblk; + unsigned int memalloc; int ret; + down_read(&dqopt->dqio_sem); + memalloc = memalloc_nofs_save(); ret = sb->s_op->quota_read(sb, type, (char *)&dqblk, sizeof(struct v1_disk_dqblk), v1_dqoff(0)); if (ret != sizeof(struct v1_disk_dqblk)) { @@ -176,6 +181,8 @@ static int v1_read_file_info(struct super_block *sb, int type) dqopt->info[type].dqi_bgrace = dqblk.dqb_btime ? dqblk.dqb_btime : MAX_DQ_TIME; out: + memalloc_nofs_restore(memalloc); + up_read(&dqopt->dqio_sem); return ret; } @@ -183,9 +190,11 @@ static int v1_write_file_info(struct super_block *sb, int type) { struct quota_info *dqopt = sb_dqopt(sb); struct v1_disk_dqblk dqblk; + unsigned int memalloc; int ret; - dqopt->info[type].dqi_flags &= ~DQF_INFO_DIRTY; + down_write(&dqopt->dqio_sem); + memalloc = memalloc_nofs_save(); ret = sb->s_op->quota_read(sb, type, (char *)&dqblk, sizeof(struct v1_disk_dqblk), v1_dqoff(0)); if (ret != sizeof(struct v1_disk_dqblk)) { @@ -193,15 +202,20 @@ static int v1_write_file_info(struct super_block *sb, int type) ret = -EIO; goto out; } + spin_lock(&dq_data_lock); + dqopt->info[type].dqi_flags &= ~DQF_INFO_DIRTY; dqblk.dqb_itime = dqopt->info[type].dqi_igrace; dqblk.dqb_btime = dqopt->info[type].dqi_bgrace; + spin_unlock(&dq_data_lock); ret = sb->s_op->quota_write(sb, type, (char *)&dqblk, sizeof(struct v1_disk_dqblk), v1_dqoff(0)); if (ret == sizeof(struct v1_disk_dqblk)) ret = 0; - else if (ret > 0) + else if (ret >= 0) ret = -EIO; out: + memalloc_nofs_restore(memalloc); + up_write(&dqopt->dqio_sem); return ret; } @@ -209,7 +223,6 @@ static const struct quota_format_ops v1_format_ops = { .check_quota_file = v1_check_quota_file, .read_file_info = v1_read_file_info, .write_file_info = v1_write_file_info, - .free_file_info = NULL, .read_dqblk = v1_read_dqblk, .commit_dqblk = v1_commit_dqblk, }; @@ -222,7 +235,8 @@ static struct quota_format_type v1_quota_format = { static int __init init_v1_quota_format(void) { - return register_quota_format(&v1_quota_format); + register_quota_format(&v1_quota_format); + return 0; } static void __exit exit_v1_quota_format(void) |
