diff options
author | David Woodhouse <dwmw2@infradead.org> | 2006-05-21 08:15:59 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2006-05-21 08:15:59 -0400 |
commit | 010b06d6d07d9fa5ea6070aa72bb3e0de1761ab7 (patch) | |
tree | 96c6ceddfec1aa6ddcdd0efcb39f903b284203c2 /fs/jffs2 | |
parent | 9167e0f811cbe28564c44a99c2f07b0ce5b368cf (diff) |
[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.c | 21 |
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 | |||
835 | spin_unlock(&c->erase_completion_lock); | 835 | spin_unlock(&c->erase_completion_lock); |
836 | ret = jffs2_flash_writev(c, vecs, 2, jeb->offset + c->sector_size - | 836 | ret = jffs2_flash_writev(c, vecs, 2, jeb->offset + c->sector_size - |
837 | jeb->free_size, &retlen, 0); | 837 | jeb->free_size, &retlen, 0); |
838 | spin_lock(&c->erase_completion_lock); | ||
839 | |||
840 | 838 | ||
841 | if (ret || (retlen != infosize)) { | 839 | if (ret || (retlen != infosize)) { |
840 | struct jffs2_raw_node_ref *ref; | ||
841 | |||
842 | JFFS2_WARNING("Write of %u bytes at 0x%08x failed. returned %d, retlen %zd\n", | 842 | JFFS2_WARNING("Write of %u bytes at 0x%08x failed. returned %d, retlen %zd\n", |
843 | infosize, jeb->offset + c->sector_size - jeb->free_size, ret, retlen); | 843 | infosize, jeb->offset + c->sector_size - jeb->free_size, ret, retlen); |
844 | 844 | ||
845 | /* Waste remaining space */ | ||
846 | ref = jffs2_alloc_raw_node_ref(); | ||
847 | if (ref) { | ||
848 | spin_lock(&c->erase_completion_lock); | ||
849 | |||
850 | ref->flash_offset = jeb->offset + c->sector_size - jeb->free_size; | ||
851 | ref->flash_offset |= REF_OBSOLETE; | ||
852 | ref->next_in_ino = 0; | ||
853 | |||
854 | jffs2_link_node_ref(c, jeb, ref, c->sector_size - jeb->free_size); | ||
855 | } | ||
856 | |||
845 | c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; | 857 | c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; |
846 | jffs2_scan_dirty_space(c, jeb, infosize); | ||
847 | 858 | ||
848 | return 1; | 859 | return 1; |
849 | } | 860 | } |
850 | 861 | ||
862 | spin_lock(&c->erase_completion_lock); | ||
863 | |||
851 | return 0; | 864 | return 0; |
852 | } | 865 | } |
853 | 866 | ||
@@ -890,7 +903,6 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) | |||
890 | /* for ACCT_PARANOIA_CHECK */ | 903 | /* for ACCT_PARANOIA_CHECK */ |
891 | spin_unlock(&c->erase_completion_lock); | 904 | spin_unlock(&c->erase_completion_lock); |
892 | summary_ref = jffs2_alloc_raw_node_ref(); | 905 | summary_ref = jffs2_alloc_raw_node_ref(); |
893 | spin_lock(&c->erase_completion_lock); | ||
894 | 906 | ||
895 | if (!summary_ref) { | 907 | if (!summary_ref) { |
896 | JFFS2_NOTICE("Failed to allocate node ref for summary\n"); | 908 | JFFS2_NOTICE("Failed to allocate node ref for summary\n"); |
@@ -900,6 +912,7 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) | |||
900 | summary_ref->next_in_ino = NULL; | 912 | summary_ref->next_in_ino = NULL; |
901 | summary_ref->flash_offset = (jeb->offset + c->sector_size - jeb->free_size) | REF_NORMAL; | 913 | summary_ref->flash_offset = (jeb->offset + c->sector_size - jeb->free_size) | REF_NORMAL; |
902 | 914 | ||
915 | spin_lock(&c->erase_completion_lock); | ||
903 | jffs2_link_node_ref(c, jeb, summary_ref, infosize); | 916 | jffs2_link_node_ref(c, jeb, summary_ref, infosize); |
904 | 917 | ||
905 | return 0; | 918 | return 0; |