Skip to content

Commit

Permalink
UBIFS: fix zero-length truncations
Browse files Browse the repository at this point in the history
Always allow truncations to zero, even if budgeting thinks there
is no space. UBIFS reserves some space for deletions anyway.

Otherwise, the following happans:
1. create a file, and write as much as possible there, until ENOSPC
2. truncate the file, which fails with ENOSPC, which is not good.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
  • Loading branch information
Artem Bityutskiy authored and Artem Bityutskiy committed Aug 21, 2008
1 parent 6a55617 commit 04da11b
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 5 deletions.
1 change: 0 additions & 1 deletion fs/ubifs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,6 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry)
if (err) {
if (err != -ENOSPC)
return err;
err = 0;
budgeted = 0;
}

Expand Down
20 changes: 16 additions & 4 deletions fs/ubifs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,7 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode,
int err;
struct ubifs_budget_req req;
loff_t old_size = inode->i_size, new_size = attr->ia_size;
int offset = new_size & (UBIFS_BLOCK_SIZE - 1);
int offset = new_size & (UBIFS_BLOCK_SIZE - 1), budgeted = 1;
struct ubifs_inode *ui = ubifs_inode(inode);

dbg_gen("ino %lu, size %lld -> %lld", inode->i_ino, old_size, new_size);
Expand All @@ -811,8 +811,15 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode,
/* A funny way to budget for truncation node */
req.dirtied_ino_d = UBIFS_TRUN_NODE_SZ;
err = ubifs_budget_space(c, &req);
if (err)
return err;
if (err) {
/*
* Treat truncations to zero as deletion and always allow them,
* just like we do for '->unlink()'.
*/
if (new_size || err != -ENOSPC)
return err;
budgeted = 0;
}

err = vmtruncate(inode, new_size);
if (err)
Expand Down Expand Up @@ -869,7 +876,12 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode,
err = ubifs_jnl_truncate(c, inode, old_size, new_size);
mutex_unlock(&ui->ui_mutex);
out_budg:
ubifs_release_budget(c, &req);
if (budgeted)
ubifs_release_budget(c, &req);
else {
c->nospace = c->nospace_rp = 0;
smp_wmb();
}
return err;
}

Expand Down

0 comments on commit 04da11b

Please sign in to comment.