Skip to content

Commit 3da22d0

Browse files
jankaragregkh
authored andcommitted
quota: Factor out setup of quota inode
[ Upstream commit c7d3d28 ] Factor out setting up of quota inode and eventual error cleanup from vfs_load_quota_inode(). This will simplify situation for filesystems that don't have any quota inodes. Signed-off-by: Jan Kara <[email protected]> Stable-dep-of: d323877 ("ext4: fix bug_on in __es_tree_search caused by bad quota inode") Signed-off-by: Sasha Levin <[email protected]>
1 parent ecb9d0d commit 3da22d0

File tree

2 files changed

+69
-41
lines changed

2 files changed

+69
-41
lines changed

fs/quota/dquot.c

Lines changed: 67 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2306,28 +2306,60 @@ EXPORT_SYMBOL(dquot_quota_off);
23062306
* Turn quotas on on a device
23072307
*/
23082308

2309-
/*
2310-
* Helper function to turn quotas on when we already have the inode of
2311-
* quota file and no quota information is loaded.
2312-
*/
2313-
static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
2309+
static int vfs_setup_quota_inode(struct inode *inode, int type)
2310+
{
2311+
struct super_block *sb = inode->i_sb;
2312+
struct quota_info *dqopt = sb_dqopt(sb);
2313+
2314+
if (!S_ISREG(inode->i_mode))
2315+
return -EACCES;
2316+
if (IS_RDONLY(inode))
2317+
return -EROFS;
2318+
if (sb_has_quota_loaded(sb, type))
2319+
return -EBUSY;
2320+
2321+
dqopt->files[type] = igrab(inode);
2322+
if (!dqopt->files[type])
2323+
return -EIO;
2324+
if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) {
2325+
/* We don't want quota and atime on quota files (deadlocks
2326+
* possible) Also nobody should write to the file - we use
2327+
* special IO operations which ignore the immutable bit. */
2328+
inode_lock(inode);
2329+
inode->i_flags |= S_NOQUOTA;
2330+
inode_unlock(inode);
2331+
/*
2332+
* When S_NOQUOTA is set, remove dquot references as no more
2333+
* references can be added
2334+
*/
2335+
__dquot_drop(inode);
2336+
}
2337+
return 0;
2338+
}
2339+
2340+
static void vfs_cleanup_quota_inode(struct super_block *sb, int type)
2341+
{
2342+
struct quota_info *dqopt = sb_dqopt(sb);
2343+
struct inode *inode = dqopt->files[type];
2344+
2345+
if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) {
2346+
inode_lock(inode);
2347+
inode->i_flags &= ~S_NOQUOTA;
2348+
inode_unlock(inode);
2349+
}
2350+
dqopt->files[type] = NULL;
2351+
iput(inode);
2352+
}
2353+
2354+
int dquot_load_quota_sb(struct super_block *sb, int type, int format_id,
23142355
unsigned int flags)
23152356
{
23162357
struct quota_format_type *fmt = find_quota_format(format_id);
2317-
struct super_block *sb = inode->i_sb;
23182358
struct quota_info *dqopt = sb_dqopt(sb);
23192359
int error;
23202360

23212361
if (!fmt)
23222362
return -ESRCH;
2323-
if (!S_ISREG(inode->i_mode)) {
2324-
error = -EACCES;
2325-
goto out_fmt;
2326-
}
2327-
if (IS_RDONLY(inode)) {
2328-
error = -EROFS;
2329-
goto out_fmt;
2330-
}
23312363
if (!sb->s_op->quota_write || !sb->s_op->quota_read ||
23322364
(type == PRJQUOTA && sb->dq_op->get_projid == NULL)) {
23332365
error = -EINVAL;
@@ -2359,35 +2391,17 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
23592391
invalidate_bdev(sb->s_bdev);
23602392
}
23612393

2362-
if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) {
2363-
/* We don't want quota and atime on quota files (deadlocks
2364-
* possible) Also nobody should write to the file - we use
2365-
* special IO operations which ignore the immutable bit. */
2366-
inode_lock(inode);
2367-
inode->i_flags |= S_NOQUOTA;
2368-
inode_unlock(inode);
2369-
/*
2370-
* When S_NOQUOTA is set, remove dquot references as no more
2371-
* references can be added
2372-
*/
2373-
__dquot_drop(inode);
2374-
}
2375-
2376-
error = -EIO;
2377-
dqopt->files[type] = igrab(inode);
2378-
if (!dqopt->files[type])
2379-
goto out_file_flags;
23802394
error = -EINVAL;
23812395
if (!fmt->qf_ops->check_quota_file(sb, type))
2382-
goto out_file_init;
2396+
goto out_fmt;
23832397

23842398
dqopt->ops[type] = fmt->qf_ops;
23852399
dqopt->info[type].dqi_format = fmt;
23862400
dqopt->info[type].dqi_fmt_id = format_id;
23872401
INIT_LIST_HEAD(&dqopt->info[type].dqi_dirty_list);
23882402
error = dqopt->ops[type]->read_file_info(sb, type);
23892403
if (error < 0)
2390-
goto out_file_init;
2404+
goto out_fmt;
23912405
if (dqopt->flags & DQUOT_QUOTA_SYS_FILE) {
23922406
spin_lock(&dq_data_lock);
23932407
dqopt->info[type].dqi_flags |= DQF_SYS_FILE;
@@ -2402,18 +2416,30 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
24022416
dquot_disable(sb, type, flags);
24032417

24042418
return error;
2405-
out_file_init:
2406-
dqopt->files[type] = NULL;
2407-
iput(inode);
2408-
out_file_flags:
2409-
inode_lock(inode);
2410-
inode->i_flags &= ~S_NOQUOTA;
2411-
inode_unlock(inode);
24122419
out_fmt:
24132420
put_quota_format(fmt);
24142421

24152422
return error;
24162423
}
2424+
EXPORT_SYMBOL(dquot_load_quota_sb);
2425+
2426+
/*
2427+
* Helper function to turn quotas on when we already have the inode of
2428+
* quota file and no quota information is loaded.
2429+
*/
2430+
static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
2431+
unsigned int flags)
2432+
{
2433+
int err;
2434+
2435+
err = vfs_setup_quota_inode(inode, type);
2436+
if (err < 0)
2437+
return err;
2438+
err = dquot_load_quota_sb(inode->i_sb, type, format_id, flags);
2439+
if (err < 0)
2440+
vfs_cleanup_quota_inode(inode->i_sb, type);
2441+
return err;
2442+
}
24172443

24182444
/* Reenable quotas on remount RW */
24192445
int dquot_resume(struct super_block *sb, int type)

include/linux/quotaops.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ int dquot_file_open(struct inode *inode, struct file *file);
9999

100100
int dquot_enable(struct inode *inode, int type, int format_id,
101101
unsigned int flags);
102+
int dquot_load_quota_sb(struct super_block *sb, int type, int format_id,
103+
unsigned int flags);
102104
int dquot_quota_on(struct super_block *sb, int type, int format_id,
103105
const struct path *path);
104106
int dquot_quota_on_mount(struct super_block *sb, char *qf_name,

0 commit comments

Comments
 (0)