summaryrefslogtreecommitdiffstats
path: root/fs/jffs2
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2006-05-21 13:15:59 +0100
committerDavid Woodhouse <dwmw2@infradead.org>2006-05-21 13:15:59 +0100
commit010b06d6d07d9fa5ea6070aa72bb3e0de1761ab7 (patch)
tree96c6ceddfec1aa6ddcdd0efcb39f903b284203c2 /fs/jffs2
parent9167e0f811cbe28564c44a99c2f07b0ce5b368cf (diff)
downloadlinux-010b06d6d07d9fa5ea6070aa72bb3e0de1761ab7.tar.gz
linux-010b06d6d07d9fa5ea6070aa72bb3e0de1761ab7.tar.bz2
linux-010b06d6d07d9fa5ea6070aa72bb3e0de1761ab7.zip
[JFFS2] Locking issues in summary write code.
We can't use jffs2_scan_dirty_space() because it doesn't do any locking; it's only for use at scan time -- hence the 'scan' in the name. Also, don't allocate refs while we have c->erase_completion_lock held. Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'fs/jffs2')
-rw-r--r--fs/jffs2/summary.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
index 5a59c6188407..1451732e1fa7 100644
--- a/fs/jffs2/summary.c
+++ b/fs/jffs2/summary.c
@@ -835,19 +835,32 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
spin_unlock(&c->erase_completion_lock);
ret = jffs2_flash_writev(c, vecs, 2, jeb->offset + c->sector_size -
jeb->free_size, &retlen, 0);
- spin_lock(&c->erase_completion_lock);
-
if (ret || (retlen != infosize)) {
+ struct jffs2_raw_node_ref *ref;
+
JFFS2_WARNING("Write of %u bytes at 0x%08x failed. returned %d, retlen %zd\n",
infosize, jeb->offset + c->sector_size - jeb->free_size, ret, retlen);
+ /* Waste remaining space */
+ ref = jffs2_alloc_raw_node_ref();
+ if (ref) {
+ spin_lock(&c->erase_completion_lock);
+
+ ref->flash_offset = jeb->offset + c->sector_size - jeb->free_size;
+ ref->flash_offset |= REF_OBSOLETE;
+ ref->next_in_ino = 0;
+
+ jffs2_link_node_ref(c, jeb, ref, c->sector_size - jeb->free_size);
+ }
+
c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE;
- jffs2_scan_dirty_space(c, jeb, infosize);
return 1;
}
+ spin_lock(&c->erase_completion_lock);
+
return 0;
}
@@ -890,7 +903,6 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c)
/* for ACCT_PARANOIA_CHECK */
spin_unlock(&c->erase_completion_lock);
summary_ref = jffs2_alloc_raw_node_ref();
- spin_lock(&c->erase_completion_lock);
if (!summary_ref) {
JFFS2_NOTICE("Failed to allocate node ref for summary\n");
@@ -900,6 +912,7 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c)
summary_ref->next_in_ino = NULL;
summary_ref->flash_offset = (jeb->offset + c->sector_size - jeb->free_size) | REF_NORMAL;
+ spin_lock(&c->erase_completion_lock);
jffs2_link_node_ref(c, jeb, summary_ref, infosize);
return 0;