diff options
Diffstat (limited to 'fs/jffs2/write.c')
-rw-r--r-- | fs/jffs2/write.c | 71 |
1 files changed, 21 insertions, 50 deletions
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index 0e12b7561b71..67176792e138 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c | |||
@@ -61,7 +61,6 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 | |||
61 | uint32_t datalen, int alloc_mode) | 61 | uint32_t datalen, int alloc_mode) |
62 | 62 | ||
63 | { | 63 | { |
64 | struct jffs2_raw_node_ref *raw; | ||
65 | struct jffs2_full_dnode *fn; | 64 | struct jffs2_full_dnode *fn; |
66 | size_t retlen; | 65 | size_t retlen; |
67 | uint32_t flash_ofs; | 66 | uint32_t flash_ofs; |
@@ -83,27 +82,16 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 | |||
83 | if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) { | 82 | if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) { |
84 | printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08zx) + datalen (0x%08x)\n", je32_to_cpu(ri->totlen), sizeof(*ri), datalen); | 83 | printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08zx) + datalen (0x%08x)\n", je32_to_cpu(ri->totlen), sizeof(*ri), datalen); |
85 | } | 84 | } |
86 | raw = jffs2_alloc_raw_node_ref(); | ||
87 | if (!raw) | ||
88 | return ERR_PTR(-ENOMEM); | ||
89 | 85 | ||
90 | fn = jffs2_alloc_full_dnode(); | 86 | fn = jffs2_alloc_full_dnode(); |
91 | if (!fn) { | 87 | if (!fn) |
92 | jffs2_free_raw_node_ref(raw); | ||
93 | return ERR_PTR(-ENOMEM); | 88 | return ERR_PTR(-ENOMEM); |
94 | } | ||
95 | |||
96 | fn->ofs = je32_to_cpu(ri->offset); | ||
97 | fn->size = je32_to_cpu(ri->dsize); | ||
98 | fn->frags = 0; | ||
99 | 89 | ||
100 | /* check number of valid vecs */ | 90 | /* check number of valid vecs */ |
101 | if (!datalen || !data) | 91 | if (!datalen || !data) |
102 | cnt = 1; | 92 | cnt = 1; |
103 | retry: | 93 | retry: |
104 | fn->raw = raw; | 94 | flash_ofs = write_ofs(c); |
105 | |||
106 | raw->flash_offset = flash_ofs = write_ofs(c); | ||
107 | 95 | ||
108 | jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); | 96 | jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); |
109 | 97 | ||
@@ -130,14 +118,11 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 | |||
130 | seem corrupted, in which case the scan would skip over | 118 | seem corrupted, in which case the scan would skip over |
131 | any node we write before the original intended end of | 119 | any node we write before the original intended end of |
132 | this node */ | 120 | this node */ |
133 | raw->flash_offset |= REF_OBSOLETE; | 121 | jffs2_add_physical_node_ref(c, flash_ofs | REF_OBSOLETE, PAD(sizeof(*ri)+datalen), NULL); |
134 | jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*ri)+datalen), NULL); | ||
135 | jffs2_mark_node_obsolete(c, raw); | ||
136 | } else { | 122 | } else { |
137 | printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); | 123 | printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", flash_ofs); |
138 | jffs2_free_raw_node_ref(raw); | ||
139 | } | 124 | } |
140 | if (!retried && alloc_mode != ALLOC_NORETRY && (raw = jffs2_alloc_raw_node_ref())) { | 125 | if (!retried && alloc_mode != ALLOC_NORETRY) { |
141 | /* Try to reallocate space and retry */ | 126 | /* Try to reallocate space and retry */ |
142 | uint32_t dummy; | 127 | uint32_t dummy; |
143 | struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; | 128 | struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; |
@@ -172,7 +157,6 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 | |||
172 | goto retry; | 157 | goto retry; |
173 | } | 158 | } |
174 | D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); | 159 | D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); |
175 | jffs2_free_raw_node_ref(raw); | ||
176 | } | 160 | } |
177 | /* Release the full_dnode which is now useless, and return */ | 161 | /* Release the full_dnode which is now useless, and return */ |
178 | jffs2_free_full_dnode(fn); | 162 | jffs2_free_full_dnode(fn); |
@@ -186,14 +170,17 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 | |||
186 | if ((je32_to_cpu(ri->dsize) >= PAGE_CACHE_SIZE) || | 170 | if ((je32_to_cpu(ri->dsize) >= PAGE_CACHE_SIZE) || |
187 | ( ((je32_to_cpu(ri->offset)&(PAGE_CACHE_SIZE-1))==0) && | 171 | ( ((je32_to_cpu(ri->offset)&(PAGE_CACHE_SIZE-1))==0) && |
188 | (je32_to_cpu(ri->dsize)+je32_to_cpu(ri->offset) == je32_to_cpu(ri->isize)))) { | 172 | (je32_to_cpu(ri->dsize)+je32_to_cpu(ri->offset) == je32_to_cpu(ri->isize)))) { |
189 | raw->flash_offset |= REF_PRISTINE; | 173 | flash_ofs |= REF_PRISTINE; |
190 | } else { | 174 | } else { |
191 | raw->flash_offset |= REF_NORMAL; | 175 | flash_ofs |= REF_NORMAL; |
192 | } | 176 | } |
193 | jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*ri)+datalen), f->inocache); | 177 | fn->raw = jffs2_add_physical_node_ref(c, flash_ofs, PAD(sizeof(*ri)+datalen), f->inocache); |
178 | fn->ofs = je32_to_cpu(ri->offset); | ||
179 | fn->size = je32_to_cpu(ri->dsize); | ||
180 | fn->frags = 0; | ||
194 | 181 | ||
195 | D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x(%d) with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n", | 182 | D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x(%d) with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n", |
196 | flash_ofs, ref_flags(raw), je32_to_cpu(ri->dsize), | 183 | flash_ofs & ~3, flash_ofs & 3, je32_to_cpu(ri->dsize), |
197 | je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc), | 184 | je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc), |
198 | je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen))); | 185 | je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen))); |
199 | 186 | ||
@@ -208,11 +195,10 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff | |||
208 | struct jffs2_raw_dirent *rd, const unsigned char *name, | 195 | struct jffs2_raw_dirent *rd, const unsigned char *name, |
209 | uint32_t namelen, int alloc_mode) | 196 | uint32_t namelen, int alloc_mode) |
210 | { | 197 | { |
211 | struct jffs2_raw_node_ref *raw; | ||
212 | struct jffs2_full_dirent *fd; | 198 | struct jffs2_full_dirent *fd; |
213 | size_t retlen; | 199 | size_t retlen; |
214 | struct kvec vecs[2]; | 200 | struct kvec vecs[2]; |
215 | uint32_t flash_ofs = write_ofs(c); | 201 | uint32_t flash_ofs; |
216 | int retried = 0; | 202 | int retried = 0; |
217 | int ret; | 203 | int ret; |
218 | 204 | ||
@@ -223,26 +209,16 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff | |||
223 | D1(if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) { | 209 | D1(if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) { |
224 | printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dirent()\n"); | 210 | printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dirent()\n"); |
225 | BUG(); | 211 | BUG(); |
226 | } | 212 | }); |
227 | ); | ||
228 | 213 | ||
229 | vecs[0].iov_base = rd; | 214 | vecs[0].iov_base = rd; |
230 | vecs[0].iov_len = sizeof(*rd); | 215 | vecs[0].iov_len = sizeof(*rd); |
231 | vecs[1].iov_base = (unsigned char *)name; | 216 | vecs[1].iov_base = (unsigned char *)name; |
232 | vecs[1].iov_len = namelen; | 217 | vecs[1].iov_len = namelen; |
233 | 218 | ||
234 | jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); | ||
235 | |||
236 | raw = jffs2_alloc_raw_node_ref(); | ||
237 | |||
238 | if (!raw) | ||
239 | return ERR_PTR(-ENOMEM); | ||
240 | |||
241 | fd = jffs2_alloc_full_dirent(namelen+1); | 219 | fd = jffs2_alloc_full_dirent(namelen+1); |
242 | if (!fd) { | 220 | if (!fd) |
243 | jffs2_free_raw_node_ref(raw); | ||
244 | return ERR_PTR(-ENOMEM); | 221 | return ERR_PTR(-ENOMEM); |
245 | } | ||
246 | 222 | ||
247 | fd->version = je32_to_cpu(rd->version); | 223 | fd->version = je32_to_cpu(rd->version); |
248 | fd->ino = je32_to_cpu(rd->ino); | 224 | fd->ino = je32_to_cpu(rd->ino); |
@@ -252,9 +228,9 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff | |||
252 | fd->name[namelen]=0; | 228 | fd->name[namelen]=0; |
253 | 229 | ||
254 | retry: | 230 | retry: |
255 | fd->raw = raw; | 231 | flash_ofs = write_ofs(c); |
256 | 232 | ||
257 | raw->flash_offset = flash_ofs; | 233 | jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); |
258 | 234 | ||
259 | if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(rd->version) < f->highest_version)) { | 235 | if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(rd->version) < f->highest_version)) { |
260 | BUG_ON(!retried); | 236 | BUG_ON(!retried); |
@@ -273,14 +249,11 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff | |||
273 | sizeof(*rd)+namelen, flash_ofs, ret, retlen); | 249 | sizeof(*rd)+namelen, flash_ofs, ret, retlen); |
274 | /* Mark the space as dirtied */ | 250 | /* Mark the space as dirtied */ |
275 | if (retlen) { | 251 | if (retlen) { |
276 | raw->flash_offset |= REF_OBSOLETE; | 252 | jffs2_add_physical_node_ref(c, flash_ofs | REF_OBSOLETE, PAD(sizeof(*rd)+namelen), NULL); |
277 | jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*rd)+namelen), NULL); | ||
278 | jffs2_mark_node_obsolete(c, raw); | ||
279 | } else { | 253 | } else { |
280 | printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); | 254 | printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", flash_ofs); |
281 | jffs2_free_raw_node_ref(raw); | ||
282 | } | 255 | } |
283 | if (!retried && (raw = jffs2_alloc_raw_node_ref())) { | 256 | if (!retried) { |
284 | /* Try to reallocate space and retry */ | 257 | /* Try to reallocate space and retry */ |
285 | uint32_t dummy; | 258 | uint32_t dummy; |
286 | struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; | 259 | struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; |
@@ -313,15 +286,13 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff | |||
313 | goto retry; | 286 | goto retry; |
314 | } | 287 | } |
315 | D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); | 288 | D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); |
316 | jffs2_free_raw_node_ref(raw); | ||
317 | } | 289 | } |
318 | /* Release the full_dnode which is now useless, and return */ | 290 | /* Release the full_dnode which is now useless, and return */ |
319 | jffs2_free_full_dirent(fd); | 291 | jffs2_free_full_dirent(fd); |
320 | return ERR_PTR(ret?ret:-EIO); | 292 | return ERR_PTR(ret?ret:-EIO); |
321 | } | 293 | } |
322 | /* Mark the space used */ | 294 | /* Mark the space used */ |
323 | raw->flash_offset |= REF_PRISTINE; | 295 | fd->raw = jffs2_add_physical_node_ref(c, flash_ofs | REF_PRISTINE, PAD(sizeof(*rd)+namelen), f->inocache); |
324 | jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*rd)+namelen), f->inocache); | ||
325 | 296 | ||
326 | if (retried) { | 297 | if (retried) { |
327 | jffs2_dbg_acct_sanity_check(c,NULL); | 298 | jffs2_dbg_acct_sanity_check(c,NULL); |