* [PATCH] ext4: prevent ext4_quota_write() from failing due to ENOSPC
@ 2015-06-21 5:27 Theodore Ts'o
2015-06-23 14:25 ` Theodore Ts'o
0 siblings, 1 reply; 5+ messages in thread
From: Theodore Ts'o @ 2015-06-21 5:27 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Theodore Ts'o
In order to prevent quota block tracking to be inaccurate when
ext4_quota_write() fails with ENOSPC, we make two changes. The quota
file can now use the reserved block (since the quota file is arguably
file system metadata), and ext4_quota_write() now uses
ext4_should_retry_alloc() to retry the block allocation after a commit
has completed and released some blocks for allocation.
This fixes failures of xfstests generic/270:
Quota error (device vdc): write_blk: dquota write failed
Quota error (device vdc): qtree_write_dquot: Error -28 occurred while creating quota
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
---
fs/ext4/extents.c | 2 ++
fs/ext4/indirect.c | 2 ++
fs/ext4/inode.c | 10 +++++-----
fs/ext4/namei.c | 2 +-
fs/ext4/super.c | 8 +++++++-
5 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 338473b..a1a54f5 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4456,6 +4456,8 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
ar.flags |= EXT4_MB_HINT_NOPREALLOC;
if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
ar.flags |= EXT4_MB_DELALLOC_RESERVED;
+ if (flags & EXT4_GET_BLOCKS_METADATA_NOFAIL)
+ ar.flags |= EXT4_MB_USE_RESERVED;
newblock = ext4_mb_new_blocks(handle, &ar, &err);
if (!newblock)
goto out2;
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
index 9588240..9962d57 100644
--- a/fs/ext4/indirect.c
+++ b/fs/ext4/indirect.c
@@ -576,6 +576,8 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
ar.flags = EXT4_MB_HINT_DATA;
if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
ar.flags |= EXT4_MB_DELALLOC_RESERVED;
+ if (flags & EXT4_GET_BLOCKS_METADATA_NOFAIL)
+ ar.flags |= EXT4_MB_USE_RESERVED;
ar.goal = ext4_find_goal(inode, map->m_lblk, partial);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 263a46c..e8a67b8 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -731,18 +731,18 @@ int ext4_get_block(struct inode *inode, sector_t iblock,
* `handle' can be NULL if create is zero
*/
struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
- ext4_lblk_t block, int create)
+ ext4_lblk_t block, int map_flags)
{
struct ext4_map_blocks map;
struct buffer_head *bh;
+ int create = map_flags & EXT4_GET_BLOCKS_CREATE;
int err;
J_ASSERT(handle != NULL || create == 0);
map.m_lblk = block;
map.m_len = 1;
- err = ext4_map_blocks(handle, inode, &map,
- create ? EXT4_GET_BLOCKS_CREATE : 0);
+ err = ext4_map_blocks(handle, inode, &map, map_flags);
if (err == 0)
return create ? ERR_PTR(-ENOSPC) : NULL;
@@ -788,11 +788,11 @@ errout:
}
struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode,
- ext4_lblk_t block, int create)
+ ext4_lblk_t block, int map_flags)
{
struct buffer_head *bh;
- bh = ext4_getblk(handle, inode, block, create);
+ bh = ext4_getblk(handle, inode, block, map_flags);
if (IS_ERR(bh))
return bh;
if (!bh || buffer_uptodate(bh))
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 5e7676f..e230b31 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -61,7 +61,7 @@ static struct buffer_head *ext4_append(handle_t *handle,
*block = inode->i_size >> inode->i_sb->s_blocksize_bits;
- bh = ext4_bread(handle, inode, *block, 1);
+ bh = ext4_bread(handle, inode, *block, EXT4_GET_BLOCKS_CREATE);
if (IS_ERR(bh))
return bh;
inode->i_size += inode->i_sb->s_blocksize;
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 2858ac0..bd4df9d 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -5438,6 +5438,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
struct inode *inode = sb_dqopt(sb)->files[type];
ext4_lblk_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb);
int err, offset = off & (sb->s_blocksize - 1);
+ int retries = 0;
struct buffer_head *bh;
handle_t *handle = journal_current_handle();
@@ -5458,7 +5459,12 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
return -EIO;
}
- bh = ext4_bread(handle, inode, blk, 1);
+ do {
+ bh = ext4_bread(handle, inode, blk,
+ EXT4_GET_BLOCKS_CREATE |
+ EXT4_GET_BLOCKS_METADATA_NOFAIL);
+ } while (IS_ERR(bh) && (PTR_ERR(bh) == -ENOSPC) &&
+ ext4_should_retry_alloc(inode->i_sb, &retries));
if (IS_ERR(bh))
return PTR_ERR(bh);
if (!bh)
--
2.3.0
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] ext4: prevent ext4_quota_write() from failing due to ENOSPC
2015-06-21 5:27 [PATCH] ext4: prevent ext4_quota_write() from failing due to ENOSPC Theodore Ts'o
@ 2015-06-23 14:25 ` Theodore Ts'o
2015-06-23 16:29 ` Jan Kara
0 siblings, 1 reply; 5+ messages in thread
From: Theodore Ts'o @ 2015-06-23 14:25 UTC (permalink / raw)
To: Ext4 Developers List; +Cc: Jan Kara
On Sun, Jun 21, 2015 at 01:27:42AM -0400, Theodore Ts'o wrote:
> In order to prevent quota block tracking to be inaccurate when
> ext4_quota_write() fails with ENOSPC, we make two changes. The quota
> file can now use the reserved block (since the quota file is arguably
> file system metadata), and ext4_quota_write() now uses
> ext4_should_retry_alloc() to retry the block allocation after a commit
> has completed and released some blocks for allocation.
>
> This fixes failures of xfstests generic/270:
>
> Quota error (device vdc): write_blk: dquota write failed
> Quota error (device vdc): qtree_write_dquot: Error -28 occurred while creating quota
>
> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This patch significantly reduces the incidence of generic/270 failing,
but it doesn't completely eliminate them, especially when using a 1k
block size. This makes sense, because what this generic/270 does is
to chown files to random uid's using an ENOSPC hitter as an
antagonist. This means the quota system needs to allocate a huge
number of blocks, and with a 1k block, it's doing 4x the number
allocations.
Something we could do that would help this situation is if there was
an interface in the quota system that initialized the quota records
for a particular uid or gid, which we could call from ext4_setattr()
or ext4_open() *before* we actually need to allocate a block quota
record for the file.
(We do check the error return from dquot_transfer() and abort if it
fails, but either the allocation qtree_write_dquot() isn't getting
perculated all the way up to dquot_transfer(), or the quota mismatch
is taking place because we're doing the chown on an empty file, and
then when we subsequently write to the file, that's when the quota
record is created and by the time we try to resolve the quota file
update, it's too late to back out the delayed allocation write.)
Jan, does that make sense to you as a way to solve this issue?
- Ted
P.S. BTW, have you had a chance to take a look at the various
competing project quota patches and do you have an opinion about their
disposition? Project quota hasn't been high priority for me, to be
honest, but there are people who seem to care about it, and I've been
waiting to see what you think about the patchsets from Li Xi and
Konstantin Khlebnikov. Thanks!!
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] ext4: prevent ext4_quota_write() from failing due to ENOSPC
2015-06-23 14:25 ` Theodore Ts'o
@ 2015-06-23 16:29 ` Jan Kara
2015-06-26 15:00 ` Jan Kara
0 siblings, 1 reply; 5+ messages in thread
From: Jan Kara @ 2015-06-23 16:29 UTC (permalink / raw)
To: Theodore Ts'o; +Cc: Ext4 Developers List, Jan Kara
On Tue 23-06-15 10:25:45, Ted Tso wrote:
> On Sun, Jun 21, 2015 at 01:27:42AM -0400, Theodore Ts'o wrote:
> > In order to prevent quota block tracking to be inaccurate when
> > ext4_quota_write() fails with ENOSPC, we make two changes. The quota
> > file can now use the reserved block (since the quota file is arguably
> > file system metadata), and ext4_quota_write() now uses
> > ext4_should_retry_alloc() to retry the block allocation after a commit
> > has completed and released some blocks for allocation.
> >
> > This fixes failures of xfstests generic/270:
> >
> > Quota error (device vdc): write_blk: dquota write failed
> > Quota error (device vdc): qtree_write_dquot: Error -28 occurred while creating quota
> >
> > Signed-off-by: Theodore Ts'o <tytso@mit.edu>
>
> This patch significantly reduces the incidence of generic/270 failing,
> but it doesn't completely eliminate them, especially when using a 1k
> block size. This makes sense, because what this generic/270 does is
> to chown files to random uid's using an ENOSPC hitter as an
> antagonist. This means the quota system needs to allocate a huge
> number of blocks, and with a 1k block, it's doing 4x the number
> allocations.
>
> Something we could do that would help this situation is if there was
> an interface in the quota system that initialized the quota records
> for a particular uid or gid, which we could call from ext4_setattr()
> or ext4_open() *before* we actually need to allocate a block quota
> record for the file.
So quota record is actually first written from dquot_acquire() function
which gets called (through ->acquire_dquot() callback) when we get the
first reference to a quota structure in dqget() (called from
dquot_initialize() / dquot_transfer()). So the problem really is in the
lack of error propagation from dqget() up through dquot_initialize() /
dquot_transfer() to the filesystem.
Doing the propagation for dquot_transfer() should be pretty easy since that
already reports other errors. With dquot_initialize() it is more difficult
since that doesn't return any errors currently so we have to add error
handling into filesystems to the inode creation path.
I'll look into this.
> P.S. BTW, have you had a chance to take a look at the various
> competing project quota patches and do you have an opinion about their
> disposition? Project quota hasn't been high priority for me, to be
> honest, but there are people who seem to care about it, and I've been
> waiting to see what you think about the patchsets from Li Xi and
> Konstantin Khlebnikov. Thanks!!
Yes, patches from Li Xi look good to me and I think I've added my
Reviewed-by tags to all of them. The only missing piece was that Dave
wanted Li Xi to run xfstests for ext4 & xfs with them and Li Xi got somehow
stuck with that.
Honza
--
Jan Kara <jack@suse.cz>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] ext4: prevent ext4_quota_write() from failing due to ENOSPC
2015-06-23 16:29 ` Jan Kara
@ 2015-06-26 15:00 ` Jan Kara
2015-06-26 23:44 ` Theodore Ts'o
0 siblings, 1 reply; 5+ messages in thread
From: Jan Kara @ 2015-06-26 15:00 UTC (permalink / raw)
To: Theodore Ts'o; +Cc: Ext4 Developers List, Jan Kara
[-- Attachment #1: Type: text/plain, Size: 2758 bytes --]
On Tue 23-06-15 18:29:17, Jan Kara wrote:
> On Tue 23-06-15 10:25:45, Ted Tso wrote:
> > On Sun, Jun 21, 2015 at 01:27:42AM -0400, Theodore Ts'o wrote:
> > > In order to prevent quota block tracking to be inaccurate when
> > > ext4_quota_write() fails with ENOSPC, we make two changes. The quota
> > > file can now use the reserved block (since the quota file is arguably
> > > file system metadata), and ext4_quota_write() now uses
> > > ext4_should_retry_alloc() to retry the block allocation after a commit
> > > has completed and released some blocks for allocation.
> > >
> > > This fixes failures of xfstests generic/270:
> > >
> > > Quota error (device vdc): write_blk: dquota write failed
> > > Quota error (device vdc): qtree_write_dquot: Error -28 occurred while creating quota
> > >
> > > Signed-off-by: Theodore Ts'o <tytso@mit.edu>
> >
> > This patch significantly reduces the incidence of generic/270 failing,
> > but it doesn't completely eliminate them, especially when using a 1k
> > block size. This makes sense, because what this generic/270 does is
> > to chown files to random uid's using an ENOSPC hitter as an
> > antagonist. This means the quota system needs to allocate a huge
> > number of blocks, and with a 1k block, it's doing 4x the number
> > allocations.
> >
> > Something we could do that would help this situation is if there was
> > an interface in the quota system that initialized the quota records
> > for a particular uid or gid, which we could call from ext4_setattr()
> > or ext4_open() *before* we actually need to allocate a block quota
> > record for the file.
>
> So quota record is actually first written from dquot_acquire() function
> which gets called (through ->acquire_dquot() callback) when we get the
> first reference to a quota structure in dqget() (called from
> dquot_initialize() / dquot_transfer()). So the problem really is in the
> lack of error propagation from dqget() up through dquot_initialize() /
> dquot_transfer() to the filesystem.
>
> Doing the propagation for dquot_transfer() should be pretty easy since that
> already reports other errors. With dquot_initialize() it is more difficult
> since that doesn't return any errors currently so we have to add error
> handling into filesystems to the inode creation path.
>
> I'll look into this.
The attached patch propagates errors from quota creation up into the caller
so now chown will return ENOSPC... The patch seems to work for me. Can you
check whether it fixes the failures you are seeing? If yes, I'll merge the
patch through my tree.
Missing is still handling of errors from dquot_initialize() in filesystems.
I'll add that on top if this patch works for you.
Honza
--
Jan Kara <jack@suse.cz>
SUSE Labs, CR
[-- Attachment #2: 0001-quota-Propagate-error-from-acquire_dquot.patch --]
[-- Type: text/x-patch, Size: 8457 bytes --]
>From 727cbcbb7776efb7185fd8835c79737b4387dcae Mon Sep 17 00:00:00 2001
From: Jan Kara <jack@suse.cz>
Date: Wed, 24 Jun 2015 18:07:02 +0200
Subject: [PATCH] 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>
---
fs/ocfs2/file.c | 8 ++---
fs/ocfs2/quota_local.c | 4 +--
fs/quota/dquot.c | 88 ++++++++++++++++++++++++++++++++++--------------
include/linux/quotaops.h | 2 +-
4 files changed, 70 insertions(+), 32 deletions(-)
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index d8b670cbd909..474176b35ffb 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -1208,8 +1208,8 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
&& OCFS2_HAS_RO_COMPAT_FEATURE(sb,
OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) {
transfer_to[USRQUOTA] = dqget(sb, make_kqid_uid(attr->ia_uid));
- if (!transfer_to[USRQUOTA]) {
- status = -ESRCH;
+ if (IS_ERR(transfer_to[USRQUOTA])) {
+ status = PTR_ERR(transfer_to[USRQUOTA]);
goto bail_unlock;
}
}
@@ -1217,8 +1217,8 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
&& OCFS2_HAS_RO_COMPAT_FEATURE(sb,
OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)) {
transfer_to[GRPQUOTA] = dqget(sb, make_kqid_gid(attr->ia_gid));
- if (!transfer_to[GRPQUOTA]) {
- status = -ESRCH;
+ if (IS_ERR(transfer_to[GRPQUOTA])) {
+ status = PTR_ERR(transfer_to[GRPQUOTA]);
goto bail_unlock;
}
}
diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c
index 3d0b63d34225..bb07004df72a 100644
--- a/fs/ocfs2/quota_local.c
+++ b/fs/ocfs2/quota_local.c
@@ -499,8 +499,8 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode,
dquot = dqget(sb,
make_kqid(&init_user_ns, type,
le64_to_cpu(dqblk->dqb_id)));
- if (!dquot) {
- status = -EIO;
+ if (IS_ERR(dquot)) {
+ status = PTR_ERR(dquot);
mlog(ML_ERROR, "Failed to get quota structure "
"for id %u, type %d. Cannot finish quota "
"file recovery.\n",
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 20d1f74561cf..c61ed126fa4c 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -247,7 +247,7 @@ struct dqstats dqstats;
EXPORT_SYMBOL(dqstats);
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
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)
{
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))
- return NULL;
+ return ERR_PTR(-ESRCH);
we_slept:
spin_lock(&dq_list_lock);
spin_lock(&dq_state_lock);
if (!sb_has_quota_active(sb, qid.type)) {
spin_unlock(&dq_state_lock);
spin_unlock(&dq_list_lock);
+ dquot = ERR_PTR(-ESRCH);
goto out;
}
spin_unlock(&dq_state_lock);
@@ -876,11 +877,15 @@ we_slept:
* already finished or it will be canceled due to dq_count > 1 test */
wait_on_dquot(dquot);
/* Read the dquot / allocate space in quota file */
- if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) &&
- sb->dq_op->acquire_dquot(dquot) < 0) {
- dqput(dquot);
- dquot = NULL;
- goto out;
+ if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {
+ int err;
+
+ err = sb->dq_op->acquire_dquot(dquot);
+ if (err < 0) {
+ dqput(dquot);
+ dquot = ERR_PTR(err);
+ goto out;
+ }
}
#ifdef CONFIG_QUOTA_DEBUG
BUG_ON(!dquot->dq_sb); /* Has somebody invalidated entry under us? */
@@ -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
* 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;
struct dquot **dquots, *got[MAXQUOTAS];
struct super_block *sb = inode->i_sb;
qsize_t rsv;
+ int ret = 0;
if (!dquot_active(inode))
- return;
+ return 0;
dquots = i_dquot(inode);
@@ -1407,6 +1413,7 @@ static void __dquot_initialize(struct inode *inode, int type)
struct kqid qid;
kprojid_t projid;
int rc;
+ struct dquot *dquot;
got[cnt] = NULL;
if (type != -1 && cnt != type)
@@ -1438,16 +1445,25 @@ static void __dquot_initialize(struct inode *inode, int type)
qid = make_kqid_projid(projid);
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 */
if (!init_needed)
- return;
+ return 0;
spin_lock(&dq_data_lock);
if (IS_NOQUOTA(inode))
- goto out_err;
+ goto out_lock;
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
if (type != -1 && cnt != type)
continue;
@@ -1469,15 +1485,18 @@ static void __dquot_initialize(struct inode *inode, int type)
dquot_resv_space(dquots[cnt], rsv);
}
}
-out_err:
+out_lock:
spin_unlock(&dq_data_lock);
+out_put:
/* Drop unused references */
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);
@@ -1961,18 +1980,37 @@ EXPORT_SYMBOL(__dquot_transfer);
int dquot_transfer(struct inode *inode, struct iattr *iattr)
{
struct dquot *transfer_to[MAXQUOTAS] = {};
+ struct dquot *dquot;
struct super_block *sb = inode->i_sb;
int ret;
if (!dquot_active(inode))
return 0;
- 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));
- if (iattr->ia_valid & ATTR_GID && !gid_eq(iattr->ia_gid, inode->i_gid))
- transfer_to[GRPQUOTA] = dqget(sb, make_kqid_gid(iattr->ia_gid));
-
+ if (iattr->ia_valid & ATTR_UID && !uid_eq(iattr->ia_uid, inode->i_uid)){
+ dquot = dqget(sb, make_kqid_uid(iattr->ia_uid));
+ if (IS_ERR(dquot)) {
+ 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);
+out_put:
dqput_all(transfer_to);
return ret;
}
@@ -2518,8 +2556,8 @@ int dquot_get_dqblk(struct super_block *sb, struct kqid qid,
struct dquot *dquot;
dquot = dqget(sb, qid);
- if (!dquot)
- return -ESRCH;
+ if (IS_ERR(dquot))
+ return PTR_ERR(dquot);
do_get_dqblk(dquot, di);
dqput(dquot);
@@ -2631,8 +2669,8 @@ int dquot_set_dqblk(struct super_block *sb, struct kqid qid,
int rc;
dquot = dqget(sb, qid);
- if (!dquot) {
- rc = -ESRCH;
+ if (!IS_ERR(dquot)) {
+ rc = PTR_ERR(dquot);
goto out;
}
rc = do_set_dqblk(dquot, di);
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index 77ca6601ff25..06c9ea8971fb 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -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_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);
struct dquot *dqget(struct super_block *sb, struct kqid qid);
static inline struct dquot *dqgrab(struct dquot *dquot)
--
2.1.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] ext4: prevent ext4_quota_write() from failing due to ENOSPC
2015-06-26 15:00 ` Jan Kara
@ 2015-06-26 23:44 ` Theodore Ts'o
0 siblings, 0 replies; 5+ messages in thread
From: Theodore Ts'o @ 2015-06-26 23:44 UTC (permalink / raw)
To: Jan Kara; +Cc: Ext4 Developers List
On Fri, Jun 26, 2015 at 05:00:41PM +0200, Jan Kara wrote:
>
> The attached patch propagates errors from quota creation up into the caller
> so now chown will return ENOSPC... The patch seems to work for me. Can you
> check whether it fixes the failures you are seeing? If yes, I'll merge the
> patch through my tree.
I ran "kvm-xfstests -C 5 generic/270" with this patch applied and I'm
not seeing any failures. So this seems to solve the issue!
- Ted
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2015-06-26 23:44 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-06-21 5:27 [PATCH] ext4: prevent ext4_quota_write() from failing due to ENOSPC Theodore Ts'o
2015-06-23 14:25 ` Theodore Ts'o
2015-06-23 16:29 ` Jan Kara
2015-06-26 15:00 ` Jan Kara
2015-06-26 23:44 ` Theodore Ts'o
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).