Skip to content

Commit 6184fc0

Browse files
jankaraJan Kara
authored andcommitted
quota: Propagate error from ->acquire_dquot()
Currently when some error happened in ->acquire_dquot(), dqget() just returned NULL. That was indistinguishable from a case when e.g. someone run quotaoff and so was generally silently ignored. However ->acquire_dquot() can fail because of ENOSPC or EIO in which case user should better know. So propagate error up from ->acquire_dquot properly. Signed-off-by: Jan Kara <[email protected]>
1 parent d725e66 commit 6184fc0

File tree

4 files changed

+72
-33
lines changed

4 files changed

+72
-33
lines changed

fs/ocfs2/file.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,17 +1209,17 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
12091209
&& OCFS2_HAS_RO_COMPAT_FEATURE(sb,
12101210
OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) {
12111211
transfer_to[USRQUOTA] = dqget(sb, make_kqid_uid(attr->ia_uid));
1212-
if (!transfer_to[USRQUOTA]) {
1213-
status = -ESRCH;
1212+
if (IS_ERR(transfer_to[USRQUOTA])) {
1213+
status = PTR_ERR(transfer_to[USRQUOTA]);
12141214
goto bail_unlock;
12151215
}
12161216
}
12171217
if (attr->ia_valid & ATTR_GID && !gid_eq(attr->ia_gid, inode->i_gid)
12181218
&& OCFS2_HAS_RO_COMPAT_FEATURE(sb,
12191219
OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)) {
12201220
transfer_to[GRPQUOTA] = dqget(sb, make_kqid_gid(attr->ia_gid));
1221-
if (!transfer_to[GRPQUOTA]) {
1222-
status = -ESRCH;
1221+
if (IS_ERR(transfer_to[GRPQUOTA])) {
1222+
status = PTR_ERR(transfer_to[GRPQUOTA]);
12231223
goto bail_unlock;
12241224
}
12251225
}

fs/ocfs2/quota_local.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -499,8 +499,8 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode,
499499
dquot = dqget(sb,
500500
make_kqid(&init_user_ns, type,
501501
le64_to_cpu(dqblk->dqb_id)));
502-
if (!dquot) {
503-
status = -EIO;
502+
if (IS_ERR(dquot)) {
503+
status = PTR_ERR(dquot);
504504
mlog(ML_ERROR, "Failed to get quota structure "
505505
"for id %u, type %d. Cannot finish quota "
506506
"file recovery.\n",

fs/quota/dquot.c

Lines changed: 63 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ struct dqstats dqstats;
247247
EXPORT_SYMBOL(dqstats);
248248

249249
static qsize_t inode_get_rsv_space(struct inode *inode);
250-
static void __dquot_initialize(struct inode *inode, int type);
250+
static int __dquot_initialize(struct inode *inode, int type);
251251

252252
static inline unsigned int
253253
hashfn(const struct super_block *sb, struct kqid qid)
@@ -832,16 +832,17 @@ static struct dquot *get_empty_dquot(struct super_block *sb, int type)
832832
struct dquot *dqget(struct super_block *sb, struct kqid qid)
833833
{
834834
unsigned int hashent = hashfn(sb, qid);
835-
struct dquot *dquot = NULL, *empty = NULL;
835+
struct dquot *dquot, *empty = NULL;
836836

837837
if (!sb_has_quota_active(sb, qid.type))
838-
return NULL;
838+
return ERR_PTR(-ESRCH);
839839
we_slept:
840840
spin_lock(&dq_list_lock);
841841
spin_lock(&dq_state_lock);
842842
if (!sb_has_quota_active(sb, qid.type)) {
843843
spin_unlock(&dq_state_lock);
844844
spin_unlock(&dq_list_lock);
845+
dquot = ERR_PTR(-ESRCH);
845846
goto out;
846847
}
847848
spin_unlock(&dq_state_lock);
@@ -876,11 +877,15 @@ struct dquot *dqget(struct super_block *sb, struct kqid qid)
876877
* already finished or it will be canceled due to dq_count > 1 test */
877878
wait_on_dquot(dquot);
878879
/* Read the dquot / allocate space in quota file */
879-
if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) &&
880-
sb->dq_op->acquire_dquot(dquot) < 0) {
881-
dqput(dquot);
882-
dquot = NULL;
883-
goto out;
880+
if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {
881+
int err;
882+
883+
err = sb->dq_op->acquire_dquot(dquot);
884+
if (err < 0) {
885+
dqput(dquot);
886+
dquot = ERR_PTR(err);
887+
goto out;
888+
}
884889
}
885890
#ifdef CONFIG_QUOTA_DEBUG
886891
BUG_ON(!dquot->dq_sb); /* Has somebody invalidated entry under us? */
@@ -1390,15 +1395,16 @@ static int dquot_active(const struct inode *inode)
13901395
* It is better to call this function outside of any transaction as it
13911396
* might need a lot of space in journal for dquot structure allocation.
13921397
*/
1393-
static void __dquot_initialize(struct inode *inode, int type)
1398+
static int __dquot_initialize(struct inode *inode, int type)
13941399
{
13951400
int cnt, init_needed = 0;
13961401
struct dquot **dquots, *got[MAXQUOTAS];
13971402
struct super_block *sb = inode->i_sb;
13981403
qsize_t rsv;
1404+
int ret = 0;
13991405

14001406
if (!dquot_active(inode))
1401-
return;
1407+
return 0;
14021408

14031409
dquots = i_dquot(inode);
14041410

@@ -1407,6 +1413,7 @@ static void __dquot_initialize(struct inode *inode, int type)
14071413
struct kqid qid;
14081414
kprojid_t projid;
14091415
int rc;
1416+
struct dquot *dquot;
14101417

14111418
got[cnt] = NULL;
14121419
if (type != -1 && cnt != type)
@@ -1438,16 +1445,25 @@ static void __dquot_initialize(struct inode *inode, int type)
14381445
qid = make_kqid_projid(projid);
14391446
break;
14401447
}
1441-
got[cnt] = dqget(sb, qid);
1448+
dquot = dqget(sb, qid);
1449+
if (IS_ERR(dquot)) {
1450+
/* We raced with somebody turning quotas off... */
1451+
if (PTR_ERR(dquot) != -ESRCH) {
1452+
ret = PTR_ERR(dquot);
1453+
goto out_put;
1454+
}
1455+
dquot = NULL;
1456+
}
1457+
got[cnt] = dquot;
14421458
}
14431459

14441460
/* All required i_dquot has been initialized */
14451461
if (!init_needed)
1446-
return;
1462+
return 0;
14471463

14481464
spin_lock(&dq_data_lock);
14491465
if (IS_NOQUOTA(inode))
1450-
goto out_err;
1466+
goto out_lock;
14511467
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
14521468
if (type != -1 && cnt != type)
14531469
continue;
@@ -1469,15 +1485,18 @@ static void __dquot_initialize(struct inode *inode, int type)
14691485
dquot_resv_space(dquots[cnt], rsv);
14701486
}
14711487
}
1472-
out_err:
1488+
out_lock:
14731489
spin_unlock(&dq_data_lock);
1490+
out_put:
14741491
/* Drop unused references */
14751492
dqput_all(got);
1493+
1494+
return ret;
14761495
}
14771496

1478-
void dquot_initialize(struct inode *inode)
1497+
int dquot_initialize(struct inode *inode)
14791498
{
1480-
__dquot_initialize(inode, -1);
1499+
return __dquot_initialize(inode, -1);
14811500
}
14821501
EXPORT_SYMBOL(dquot_initialize);
14831502

@@ -1961,18 +1980,37 @@ EXPORT_SYMBOL(__dquot_transfer);
19611980
int dquot_transfer(struct inode *inode, struct iattr *iattr)
19621981
{
19631982
struct dquot *transfer_to[MAXQUOTAS] = {};
1983+
struct dquot *dquot;
19641984
struct super_block *sb = inode->i_sb;
19651985
int ret;
19661986

19671987
if (!dquot_active(inode))
19681988
return 0;
19691989

1970-
if (iattr->ia_valid & ATTR_UID && !uid_eq(iattr->ia_uid, inode->i_uid))
1971-
transfer_to[USRQUOTA] = dqget(sb, make_kqid_uid(iattr->ia_uid));
1972-
if (iattr->ia_valid & ATTR_GID && !gid_eq(iattr->ia_gid, inode->i_gid))
1973-
transfer_to[GRPQUOTA] = dqget(sb, make_kqid_gid(iattr->ia_gid));
1974-
1990+
if (iattr->ia_valid & ATTR_UID && !uid_eq(iattr->ia_uid, inode->i_uid)){
1991+
dquot = dqget(sb, make_kqid_uid(iattr->ia_uid));
1992+
if (IS_ERR(dquot)) {
1993+
if (PTR_ERR(dquot) != -ESRCH) {
1994+
ret = PTR_ERR(dquot);
1995+
goto out_put;
1996+
}
1997+
dquot = NULL;
1998+
}
1999+
transfer_to[USRQUOTA] = dquot;
2000+
}
2001+
if (iattr->ia_valid & ATTR_GID && !gid_eq(iattr->ia_gid, inode->i_gid)){
2002+
dquot = dqget(sb, make_kqid_gid(iattr->ia_gid));
2003+
if (IS_ERR(dquot)) {
2004+
if (PTR_ERR(dquot) != -ESRCH) {
2005+
ret = PTR_ERR(dquot);
2006+
goto out_put;
2007+
}
2008+
dquot = NULL;
2009+
}
2010+
transfer_to[GRPQUOTA] = dquot;
2011+
}
19752012
ret = __dquot_transfer(inode, transfer_to);
2013+
out_put:
19762014
dqput_all(transfer_to);
19772015
return ret;
19782016
}
@@ -2518,8 +2556,8 @@ int dquot_get_dqblk(struct super_block *sb, struct kqid qid,
25182556
struct dquot *dquot;
25192557

25202558
dquot = dqget(sb, qid);
2521-
if (!dquot)
2522-
return -ESRCH;
2559+
if (IS_ERR(dquot))
2560+
return PTR_ERR(dquot);
25232561
do_get_dqblk(dquot, di);
25242562
dqput(dquot);
25252563

@@ -2631,8 +2669,8 @@ int dquot_set_dqblk(struct super_block *sb, struct kqid qid,
26312669
int rc;
26322670

26332671
dquot = dqget(sb, qid);
2634-
if (!dquot) {
2635-
rc = -ESRCH;
2672+
if (IS_ERR(dquot)) {
2673+
rc = PTR_ERR(dquot);
26362674
goto out;
26372675
}
26382676
rc = do_set_dqblk(dquot, di);

include/linux/quotaops.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ void inode_claim_rsv_space(struct inode *inode, qsize_t number);
4343
void inode_sub_rsv_space(struct inode *inode, qsize_t number);
4444
void inode_reclaim_rsv_space(struct inode *inode, qsize_t number);
4545

46-
void dquot_initialize(struct inode *inode);
46+
int dquot_initialize(struct inode *inode);
4747
void dquot_drop(struct inode *inode);
4848
struct dquot *dqget(struct super_block *sb, struct kqid qid);
4949
static inline struct dquot *dqgrab(struct dquot *dquot)
@@ -200,8 +200,9 @@ static inline int sb_has_quota_active(struct super_block *sb, int type)
200200
return 0;
201201
}
202202

203-
static inline void dquot_initialize(struct inode *inode)
203+
static inline int dquot_initialize(struct inode *inode)
204204
{
205+
return 0;
205206
}
206207

207208
static inline void dquot_drop(struct inode *inode)

0 commit comments

Comments
 (0)