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 <jack@suse.cz>
This commit is contained in:
parent
d725e66c06
commit
6184fc0b8d
|
@ -1209,8 +1209,8 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
|
||||||
&& OCFS2_HAS_RO_COMPAT_FEATURE(sb,
|
&& OCFS2_HAS_RO_COMPAT_FEATURE(sb,
|
||||||
OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) {
|
OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) {
|
||||||
transfer_to[USRQUOTA] = dqget(sb, make_kqid_uid(attr->ia_uid));
|
transfer_to[USRQUOTA] = dqget(sb, make_kqid_uid(attr->ia_uid));
|
||||||
if (!transfer_to[USRQUOTA]) {
|
if (IS_ERR(transfer_to[USRQUOTA])) {
|
||||||
status = -ESRCH;
|
status = PTR_ERR(transfer_to[USRQUOTA]);
|
||||||
goto bail_unlock;
|
goto bail_unlock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1218,8 +1218,8 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
|
||||||
&& OCFS2_HAS_RO_COMPAT_FEATURE(sb,
|
&& OCFS2_HAS_RO_COMPAT_FEATURE(sb,
|
||||||
OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)) {
|
OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)) {
|
||||||
transfer_to[GRPQUOTA] = dqget(sb, make_kqid_gid(attr->ia_gid));
|
transfer_to[GRPQUOTA] = dqget(sb, make_kqid_gid(attr->ia_gid));
|
||||||
if (!transfer_to[GRPQUOTA]) {
|
if (IS_ERR(transfer_to[GRPQUOTA])) {
|
||||||
status = -ESRCH;
|
status = PTR_ERR(transfer_to[GRPQUOTA]);
|
||||||
goto bail_unlock;
|
goto bail_unlock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -499,8 +499,8 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode,
|
||||||
dquot = dqget(sb,
|
dquot = dqget(sb,
|
||||||
make_kqid(&init_user_ns, type,
|
make_kqid(&init_user_ns, type,
|
||||||
le64_to_cpu(dqblk->dqb_id)));
|
le64_to_cpu(dqblk->dqb_id)));
|
||||||
if (!dquot) {
|
if (IS_ERR(dquot)) {
|
||||||
status = -EIO;
|
status = PTR_ERR(dquot);
|
||||||
mlog(ML_ERROR, "Failed to get quota structure "
|
mlog(ML_ERROR, "Failed to get quota structure "
|
||||||
"for id %u, type %d. Cannot finish quota "
|
"for id %u, type %d. Cannot finish quota "
|
||||||
"file recovery.\n",
|
"file recovery.\n",
|
||||||
|
|
|
@ -247,7 +247,7 @@ struct dqstats dqstats;
|
||||||
EXPORT_SYMBOL(dqstats);
|
EXPORT_SYMBOL(dqstats);
|
||||||
|
|
||||||
static qsize_t inode_get_rsv_space(struct inode *inode);
|
static qsize_t inode_get_rsv_space(struct inode *inode);
|
||||||
static void __dquot_initialize(struct inode *inode, int type);
|
static int __dquot_initialize(struct inode *inode, int type);
|
||||||
|
|
||||||
static inline unsigned int
|
static inline unsigned int
|
||||||
hashfn(const struct super_block *sb, struct kqid qid)
|
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)
|
||||||
struct dquot *dqget(struct super_block *sb, struct kqid qid)
|
struct dquot *dqget(struct super_block *sb, struct kqid qid)
|
||||||
{
|
{
|
||||||
unsigned int hashent = hashfn(sb, qid);
|
unsigned int hashent = hashfn(sb, qid);
|
||||||
struct dquot *dquot = NULL, *empty = NULL;
|
struct dquot *dquot, *empty = NULL;
|
||||||
|
|
||||||
if (!sb_has_quota_active(sb, qid.type))
|
if (!sb_has_quota_active(sb, qid.type))
|
||||||
return NULL;
|
return ERR_PTR(-ESRCH);
|
||||||
we_slept:
|
we_slept:
|
||||||
spin_lock(&dq_list_lock);
|
spin_lock(&dq_list_lock);
|
||||||
spin_lock(&dq_state_lock);
|
spin_lock(&dq_state_lock);
|
||||||
if (!sb_has_quota_active(sb, qid.type)) {
|
if (!sb_has_quota_active(sb, qid.type)) {
|
||||||
spin_unlock(&dq_state_lock);
|
spin_unlock(&dq_state_lock);
|
||||||
spin_unlock(&dq_list_lock);
|
spin_unlock(&dq_list_lock);
|
||||||
|
dquot = ERR_PTR(-ESRCH);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
spin_unlock(&dq_state_lock);
|
spin_unlock(&dq_state_lock);
|
||||||
|
@ -876,12 +877,16 @@ we_slept:
|
||||||
* already finished or it will be canceled due to dq_count > 1 test */
|
* already finished or it will be canceled due to dq_count > 1 test */
|
||||||
wait_on_dquot(dquot);
|
wait_on_dquot(dquot);
|
||||||
/* Read the dquot / allocate space in quota file */
|
/* Read the dquot / allocate space in quota file */
|
||||||
if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) &&
|
if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {
|
||||||
sb->dq_op->acquire_dquot(dquot) < 0) {
|
int err;
|
||||||
|
|
||||||
|
err = sb->dq_op->acquire_dquot(dquot);
|
||||||
|
if (err < 0) {
|
||||||
dqput(dquot);
|
dqput(dquot);
|
||||||
dquot = NULL;
|
dquot = ERR_PTR(err);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#ifdef CONFIG_QUOTA_DEBUG
|
#ifdef CONFIG_QUOTA_DEBUG
|
||||||
BUG_ON(!dquot->dq_sb); /* Has somebody invalidated entry under us? */
|
BUG_ON(!dquot->dq_sb); /* Has somebody invalidated entry under us? */
|
||||||
#endif
|
#endif
|
||||||
|
@ -1390,15 +1395,16 @@ static int dquot_active(const struct inode *inode)
|
||||||
* It is better to call this function outside of any transaction as it
|
* It is better to call this function outside of any transaction as it
|
||||||
* might need a lot of space in journal for dquot structure allocation.
|
* might need a lot of space in journal for dquot structure allocation.
|
||||||
*/
|
*/
|
||||||
static void __dquot_initialize(struct inode *inode, int type)
|
static int __dquot_initialize(struct inode *inode, int type)
|
||||||
{
|
{
|
||||||
int cnt, init_needed = 0;
|
int cnt, init_needed = 0;
|
||||||
struct dquot **dquots, *got[MAXQUOTAS];
|
struct dquot **dquots, *got[MAXQUOTAS];
|
||||||
struct super_block *sb = inode->i_sb;
|
struct super_block *sb = inode->i_sb;
|
||||||
qsize_t rsv;
|
qsize_t rsv;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
if (!dquot_active(inode))
|
if (!dquot_active(inode))
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
dquots = i_dquot(inode);
|
dquots = i_dquot(inode);
|
||||||
|
|
||||||
|
@ -1407,6 +1413,7 @@ static void __dquot_initialize(struct inode *inode, int type)
|
||||||
struct kqid qid;
|
struct kqid qid;
|
||||||
kprojid_t projid;
|
kprojid_t projid;
|
||||||
int rc;
|
int rc;
|
||||||
|
struct dquot *dquot;
|
||||||
|
|
||||||
got[cnt] = NULL;
|
got[cnt] = NULL;
|
||||||
if (type != -1 && cnt != type)
|
if (type != -1 && cnt != type)
|
||||||
|
@ -1438,16 +1445,25 @@ static void __dquot_initialize(struct inode *inode, int type)
|
||||||
qid = make_kqid_projid(projid);
|
qid = make_kqid_projid(projid);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
got[cnt] = dqget(sb, qid);
|
dquot = dqget(sb, qid);
|
||||||
|
if (IS_ERR(dquot)) {
|
||||||
|
/* We raced with somebody turning quotas off... */
|
||||||
|
if (PTR_ERR(dquot) != -ESRCH) {
|
||||||
|
ret = PTR_ERR(dquot);
|
||||||
|
goto out_put;
|
||||||
|
}
|
||||||
|
dquot = NULL;
|
||||||
|
}
|
||||||
|
got[cnt] = dquot;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* All required i_dquot has been initialized */
|
/* All required i_dquot has been initialized */
|
||||||
if (!init_needed)
|
if (!init_needed)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
spin_lock(&dq_data_lock);
|
spin_lock(&dq_data_lock);
|
||||||
if (IS_NOQUOTA(inode))
|
if (IS_NOQUOTA(inode))
|
||||||
goto out_err;
|
goto out_lock;
|
||||||
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
||||||
if (type != -1 && cnt != type)
|
if (type != -1 && cnt != type)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1469,15 +1485,18 @@ static void __dquot_initialize(struct inode *inode, int type)
|
||||||
dquot_resv_space(dquots[cnt], rsv);
|
dquot_resv_space(dquots[cnt], rsv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out_err:
|
out_lock:
|
||||||
spin_unlock(&dq_data_lock);
|
spin_unlock(&dq_data_lock);
|
||||||
|
out_put:
|
||||||
/* Drop unused references */
|
/* Drop unused references */
|
||||||
dqput_all(got);
|
dqput_all(got);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dquot_initialize(struct inode *inode)
|
int dquot_initialize(struct inode *inode)
|
||||||
{
|
{
|
||||||
__dquot_initialize(inode, -1);
|
return __dquot_initialize(inode, -1);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(dquot_initialize);
|
EXPORT_SYMBOL(dquot_initialize);
|
||||||
|
|
||||||
|
@ -1961,18 +1980,37 @@ EXPORT_SYMBOL(__dquot_transfer);
|
||||||
int dquot_transfer(struct inode *inode, struct iattr *iattr)
|
int dquot_transfer(struct inode *inode, struct iattr *iattr)
|
||||||
{
|
{
|
||||||
struct dquot *transfer_to[MAXQUOTAS] = {};
|
struct dquot *transfer_to[MAXQUOTAS] = {};
|
||||||
|
struct dquot *dquot;
|
||||||
struct super_block *sb = inode->i_sb;
|
struct super_block *sb = inode->i_sb;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!dquot_active(inode))
|
if (!dquot_active(inode))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (iattr->ia_valid & ATTR_UID && !uid_eq(iattr->ia_uid, inode->i_uid))
|
if (iattr->ia_valid & ATTR_UID && !uid_eq(iattr->ia_uid, inode->i_uid)){
|
||||||
transfer_to[USRQUOTA] = dqget(sb, make_kqid_uid(iattr->ia_uid));
|
dquot = dqget(sb, make_kqid_uid(iattr->ia_uid));
|
||||||
if (iattr->ia_valid & ATTR_GID && !gid_eq(iattr->ia_gid, inode->i_gid))
|
if (IS_ERR(dquot)) {
|
||||||
transfer_to[GRPQUOTA] = dqget(sb, make_kqid_gid(iattr->ia_gid));
|
if (PTR_ERR(dquot) != -ESRCH) {
|
||||||
|
ret = PTR_ERR(dquot);
|
||||||
|
goto out_put;
|
||||||
|
}
|
||||||
|
dquot = NULL;
|
||||||
|
}
|
||||||
|
transfer_to[USRQUOTA] = dquot;
|
||||||
|
}
|
||||||
|
if (iattr->ia_valid & ATTR_GID && !gid_eq(iattr->ia_gid, inode->i_gid)){
|
||||||
|
dquot = dqget(sb, make_kqid_gid(iattr->ia_gid));
|
||||||
|
if (IS_ERR(dquot)) {
|
||||||
|
if (PTR_ERR(dquot) != -ESRCH) {
|
||||||
|
ret = PTR_ERR(dquot);
|
||||||
|
goto out_put;
|
||||||
|
}
|
||||||
|
dquot = NULL;
|
||||||
|
}
|
||||||
|
transfer_to[GRPQUOTA] = dquot;
|
||||||
|
}
|
||||||
ret = __dquot_transfer(inode, transfer_to);
|
ret = __dquot_transfer(inode, transfer_to);
|
||||||
|
out_put:
|
||||||
dqput_all(transfer_to);
|
dqput_all(transfer_to);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -2518,8 +2556,8 @@ int dquot_get_dqblk(struct super_block *sb, struct kqid qid,
|
||||||
struct dquot *dquot;
|
struct dquot *dquot;
|
||||||
|
|
||||||
dquot = dqget(sb, qid);
|
dquot = dqget(sb, qid);
|
||||||
if (!dquot)
|
if (IS_ERR(dquot))
|
||||||
return -ESRCH;
|
return PTR_ERR(dquot);
|
||||||
do_get_dqblk(dquot, di);
|
do_get_dqblk(dquot, di);
|
||||||
dqput(dquot);
|
dqput(dquot);
|
||||||
|
|
||||||
|
@ -2631,8 +2669,8 @@ int dquot_set_dqblk(struct super_block *sb, struct kqid qid,
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
dquot = dqget(sb, qid);
|
dquot = dqget(sb, qid);
|
||||||
if (!dquot) {
|
if (IS_ERR(dquot)) {
|
||||||
rc = -ESRCH;
|
rc = PTR_ERR(dquot);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
rc = do_set_dqblk(dquot, di);
|
rc = do_set_dqblk(dquot, di);
|
||||||
|
|
|
@ -43,7 +43,7 @@ void inode_claim_rsv_space(struct inode *inode, qsize_t number);
|
||||||
void inode_sub_rsv_space(struct inode *inode, qsize_t number);
|
void inode_sub_rsv_space(struct inode *inode, qsize_t number);
|
||||||
void inode_reclaim_rsv_space(struct inode *inode, qsize_t number);
|
void inode_reclaim_rsv_space(struct inode *inode, qsize_t number);
|
||||||
|
|
||||||
void dquot_initialize(struct inode *inode);
|
int dquot_initialize(struct inode *inode);
|
||||||
void dquot_drop(struct inode *inode);
|
void dquot_drop(struct inode *inode);
|
||||||
struct dquot *dqget(struct super_block *sb, struct kqid qid);
|
struct dquot *dqget(struct super_block *sb, struct kqid qid);
|
||||||
static inline struct dquot *dqgrab(struct dquot *dquot)
|
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)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void dquot_initialize(struct inode *inode)
|
static inline int dquot_initialize(struct inode *inode)
|
||||||
{
|
{
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void dquot_drop(struct inode *inode)
|
static inline void dquot_drop(struct inode *inode)
|
||||||
|
|
Loading…
Reference in New Issue