summaryrefslogtreecommitdiffstats
path: root/fs/ubifs/file.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-10-12 12:39:30 +0200
committerIngo Molnar <mingo@elte.hu>2008-10-12 12:39:50 +0200
commit4c7145a1ec1bb789d5f07e47510e8bda546a7c4a (patch)
treee2767b77e5413473a3bba302237f4669a203f183 /fs/ubifs/file.c
parent74e91604b2452c15bbe72d77b37cf47ed0310d13 (diff)
parentfd048088306656824958e7783ffcee27e241b361 (diff)
Merge branch 'linus' into x86/spinlocks
Done to prevent this failure of an Octopus merge: Added arch/arm/include/asm/byteorder.h in both, but differently. ERROR: Merge conflict in arch/arm/include/asm/byteorder.h Auto-merging include/asm-x86/spinlock.h ERROR: Merge conflict in include/asm-x86/spinlock.h fatal: merge program failed
Diffstat (limited to 'fs/ubifs/file.c')
-rw-r--r--fs/ubifs/file.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index 4071d1cae29..3d698e2022b 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -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);
@@ -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)
@@ -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;
}