aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jffs2')
-rw-r--r--fs/jffs2/erase.c19
-rw-r--r--fs/jffs2/gc.c5
-rw-r--r--fs/jffs2/jffs2_fs_sb.h3
-rw-r--r--fs/jffs2/malloc.c2
-rw-r--r--fs/jffs2/nodemgmt.c21
-rw-r--r--fs/jffs2/scan.c57
-rw-r--r--fs/jffs2/summary.c39
-rw-r--r--fs/jffs2/xattr.c736
-rw-r--r--fs/jffs2/xattr.h40
9 files changed, 583 insertions, 339 deletions
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index 1862e8bc101d..1644e3408852 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -230,7 +230,6 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
230 at the end of the linked list. Stash it and continue 230 at the end of the linked list. Stash it and continue
231 from the beginning of the list */ 231 from the beginning of the list */
232 ic = (struct jffs2_inode_cache *)(*prev); 232 ic = (struct jffs2_inode_cache *)(*prev);
233 BUG_ON(ic->class != RAWNODE_CLASS_INODE_CACHE);
234 prev = &ic->nodes; 233 prev = &ic->nodes;
235 continue; 234 continue;
236 } 235 }
@@ -254,7 +253,8 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
254 253
255 /* PARANOIA */ 254 /* PARANOIA */
256 if (!ic) { 255 if (!ic) {
257 printk(KERN_WARNING "inode_cache not found in remove_node_refs()!!\n"); 256 JFFS2_WARNING("inode_cache/xattr_datum/xattr_ref"
257 " not found in remove_node_refs()!!\n");
258 return; 258 return;
259 } 259 }
260 260
@@ -279,8 +279,19 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
279 printk("\n"); 279 printk("\n");
280 }); 280 });
281 281
282 if (ic->nodes == (void *)ic && ic->nlink == 0) 282 switch (ic->class) {
283 jffs2_del_ino_cache(c, ic); 283#ifdef CONFIG_JFFS2_FS_XATTR
284 case RAWNODE_CLASS_XATTR_DATUM:
285 jffs2_release_xattr_datum(c, (struct jffs2_xattr_datum *)ic);
286 break;
287 case RAWNODE_CLASS_XATTR_REF:
288 jffs2_release_xattr_ref(c, (struct jffs2_xattr_ref *)ic);
289 break;
290#endif
291 default:
292 if (ic->nodes == (void *)ic && ic->nlink == 0)
293 jffs2_del_ino_cache(c, ic);
294 }
284} 295}
285 296
286void jffs2_free_jeb_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) 297void jffs2_free_jeb_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index 477c526d638b..f59b147661c9 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -275,13 +275,12 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
275 * We can decide whether this node is inode or xattr by ic->class. */ 275 * We can decide whether this node is inode or xattr by ic->class. */
276 if (ic->class == RAWNODE_CLASS_XATTR_DATUM 276 if (ic->class == RAWNODE_CLASS_XATTR_DATUM
277 || ic->class == RAWNODE_CLASS_XATTR_REF) { 277 || ic->class == RAWNODE_CLASS_XATTR_REF) {
278 BUG_ON(raw->next_in_ino != (void *)ic);
279 spin_unlock(&c->erase_completion_lock); 278 spin_unlock(&c->erase_completion_lock);
280 279
281 if (ic->class == RAWNODE_CLASS_XATTR_DATUM) { 280 if (ic->class == RAWNODE_CLASS_XATTR_DATUM) {
282 ret = jffs2_garbage_collect_xattr_datum(c, (struct jffs2_xattr_datum *)ic); 281 ret = jffs2_garbage_collect_xattr_datum(c, (struct jffs2_xattr_datum *)ic, raw);
283 } else { 282 } else {
284 ret = jffs2_garbage_collect_xattr_ref(c, (struct jffs2_xattr_ref *)ic); 283 ret = jffs2_garbage_collect_xattr_ref(c, (struct jffs2_xattr_ref *)ic, raw);
285 } 284 }
286 goto release_sem; 285 goto release_sem;
287 } 286 }
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
index 935fec1b1201..b98594992eed 100644
--- a/fs/jffs2/jffs2_fs_sb.h
+++ b/fs/jffs2/jffs2_fs_sb.h
@@ -119,8 +119,11 @@ struct jffs2_sb_info {
119#ifdef CONFIG_JFFS2_FS_XATTR 119#ifdef CONFIG_JFFS2_FS_XATTR
120#define XATTRINDEX_HASHSIZE (57) 120#define XATTRINDEX_HASHSIZE (57)
121 uint32_t highest_xid; 121 uint32_t highest_xid;
122 uint32_t highest_xseqno;
122 struct list_head xattrindex[XATTRINDEX_HASHSIZE]; 123 struct list_head xattrindex[XATTRINDEX_HASHSIZE];
123 struct list_head xattr_unchecked; 124 struct list_head xattr_unchecked;
125 struct list_head xattr_dead_list;
126 struct jffs2_xattr_ref *xref_dead_list;
124 struct jffs2_xattr_ref *xref_temp; 127 struct jffs2_xattr_ref *xref_temp;
125 struct rw_semaphore xattr_sem; 128 struct rw_semaphore xattr_sem;
126 uint32_t xdatum_mem_usage; 129 uint32_t xdatum_mem_usage;
diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c
index 4889d0700c0e..8310c95478e9 100644
--- a/fs/jffs2/malloc.c
+++ b/fs/jffs2/malloc.c
@@ -291,6 +291,7 @@ struct jffs2_xattr_datum *jffs2_alloc_xattr_datum(void)
291 291
292 memset(xd, 0, sizeof(struct jffs2_xattr_datum)); 292 memset(xd, 0, sizeof(struct jffs2_xattr_datum));
293 xd->class = RAWNODE_CLASS_XATTR_DATUM; 293 xd->class = RAWNODE_CLASS_XATTR_DATUM;
294 xd->node = (void *)xd;
294 INIT_LIST_HEAD(&xd->xindex); 295 INIT_LIST_HEAD(&xd->xindex);
295 return xd; 296 return xd;
296} 297}
@@ -309,6 +310,7 @@ struct jffs2_xattr_ref *jffs2_alloc_xattr_ref(void)
309 310
310 memset(ref, 0, sizeof(struct jffs2_xattr_ref)); 311 memset(ref, 0, sizeof(struct jffs2_xattr_ref));
311 ref->class = RAWNODE_CLASS_XATTR_REF; 312 ref->class = RAWNODE_CLASS_XATTR_REF;
313 ref->node = (void *)ref;
312 return ref; 314 return ref;
313} 315}
314 316
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
index 8bedfd2ff689..01594a2256eb 100644
--- a/fs/jffs2/nodemgmt.c
+++ b/fs/jffs2/nodemgmt.c
@@ -684,19 +684,26 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
684 spin_lock(&c->erase_completion_lock); 684 spin_lock(&c->erase_completion_lock);
685 685
686 ic = jffs2_raw_ref_to_ic(ref); 686 ic = jffs2_raw_ref_to_ic(ref);
687 /* It seems we should never call jffs2_mark_node_obsolete() for
688 XATTR nodes.... yet. Make sure we notice if/when we change
689 that :) */
690 BUG_ON(ic->class != RAWNODE_CLASS_INODE_CACHE);
691 for (p = &ic->nodes; (*p) != ref; p = &((*p)->next_in_ino)) 687 for (p = &ic->nodes; (*p) != ref; p = &((*p)->next_in_ino))
692 ; 688 ;
693 689
694 *p = ref->next_in_ino; 690 *p = ref->next_in_ino;
695 ref->next_in_ino = NULL; 691 ref->next_in_ino = NULL;
696 692
697 if (ic->nodes == (void *)ic && ic->nlink == 0) 693 switch (ic->class) {
698 jffs2_del_ino_cache(c, ic); 694#ifdef CONFIG_JFFS2_FS_XATTR
699 695 case RAWNODE_CLASS_XATTR_DATUM:
696 jffs2_release_xattr_datum(c, (struct jffs2_xattr_datum *)ic);
697 break;
698 case RAWNODE_CLASS_XATTR_REF:
699 jffs2_release_xattr_ref(c, (struct jffs2_xattr_ref *)ic);
700 break;
701#endif
702 default:
703 if (ic->nodes == (void *)ic && ic->nlink == 0)
704 jffs2_del_ino_cache(c, ic);
705 break;
706 }
700 spin_unlock(&c->erase_completion_lock); 707 spin_unlock(&c->erase_completion_lock);
701 } 708 }
702 709
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 61618080b86f..79638f56c5ea 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -317,20 +317,25 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
317 struct jffs2_summary *s) 317 struct jffs2_summary *s)
318{ 318{
319 struct jffs2_xattr_datum *xd; 319 struct jffs2_xattr_datum *xd;
320 uint32_t totlen, crc; 320 uint32_t xid, version, totlen, crc;
321 int err; 321 int err;
322 322
323 crc = crc32(0, rx, sizeof(struct jffs2_raw_xattr) - 4); 323 crc = crc32(0, rx, sizeof(struct jffs2_raw_xattr) - 4);
324 if (crc != je32_to_cpu(rx->node_crc)) { 324 if (crc != je32_to_cpu(rx->node_crc)) {
325 if (je32_to_cpu(rx->node_crc) != 0xffffffff) 325 JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
326 JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", 326 ofs, je32_to_cpu(rx->node_crc), crc);
327 ofs, je32_to_cpu(rx->node_crc), crc);
328 if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rx->totlen)))) 327 if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rx->totlen))))
329 return err; 328 return err;
330 return 0; 329 return 0;
331 } 330 }
332 331
333 totlen = PAD(sizeof(*rx) + rx->name_len + 1 + je16_to_cpu(rx->value_len)); 332 xid = je32_to_cpu(rx->xid);
333 version = je32_to_cpu(rx->version);
334
335 totlen = sizeof(struct jffs2_raw_xattr);
336 if (version != XDATUM_DELETE_MARKER)
337 totlen += rx->name_len + 1 + je16_to_cpu(rx->value_len);
338 totlen = PAD(totlen);
334 if (totlen != je32_to_cpu(rx->totlen)) { 339 if (totlen != je32_to_cpu(rx->totlen)) {
335 JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%u\n", 340 JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%u\n",
336 ofs, je32_to_cpu(rx->totlen), totlen); 341 ofs, je32_to_cpu(rx->totlen), totlen);
@@ -339,22 +344,24 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
339 return 0; 344 return 0;
340 } 345 }
341 346
342 xd = jffs2_setup_xattr_datum(c, je32_to_cpu(rx->xid), je32_to_cpu(rx->version)); 347 xd = jffs2_setup_xattr_datum(c, xid, version);
343 if (IS_ERR(xd)) { 348 if (IS_ERR(xd))
344 if (PTR_ERR(xd) == -EEXIST) {
345 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rx->totlen)))))
346 return err;
347 return 0;
348 }
349 return PTR_ERR(xd); 349 return PTR_ERR(xd);
350 }
351 xd->xprefix = rx->xprefix;
352 xd->name_len = rx->name_len;
353 xd->value_len = je16_to_cpu(rx->value_len);
354 xd->data_crc = je32_to_cpu(rx->data_crc);
355 350
356 xd->node = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, NULL); 351 if (xd->version > version) {
357 /* FIXME */ xd->node->next_in_ino = (void *)xd; 352 struct jffs2_raw_node_ref *raw
353 = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, NULL);
354 raw->next_in_ino = xd->node->next_in_ino;
355 xd->node->next_in_ino = raw;
356 } else {
357 xd->version = version;
358 xd->xprefix = rx->xprefix;
359 xd->name_len = rx->name_len;
360 xd->value_len = je16_to_cpu(rx->value_len);
361 xd->data_crc = je32_to_cpu(rx->data_crc);
362
363 jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, (void *)xd);
364 }
358 365
359 if (jffs2_sum_active()) 366 if (jffs2_sum_active())
360 jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset); 367 jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset);
@@ -373,9 +380,8 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock
373 380
374 crc = crc32(0, rr, sizeof(*rr) - 4); 381 crc = crc32(0, rr, sizeof(*rr) - 4);
375 if (crc != je32_to_cpu(rr->node_crc)) { 382 if (crc != je32_to_cpu(rr->node_crc)) {
376 if (je32_to_cpu(rr->node_crc) != 0xffffffff) 383 JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
377 JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", 384 ofs, je32_to_cpu(rr->node_crc), crc);
378 ofs, je32_to_cpu(rr->node_crc), crc);
379 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rr->totlen))))) 385 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rr->totlen)))))
380 return err; 386 return err;
381 return 0; 387 return 0;
@@ -395,6 +401,7 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock
395 return -ENOMEM; 401 return -ENOMEM;
396 402
397 /* BEFORE jffs2_build_xattr_subsystem() called, 403 /* BEFORE jffs2_build_xattr_subsystem() called,
404 * and AFTER xattr_ref is marked as a dead xref,
398 * ref->xid is used to store 32bit xid, xd is not used 405 * ref->xid is used to store 32bit xid, xd is not used
399 * ref->ino is used to store 32bit inode-number, ic is not used 406 * ref->ino is used to store 32bit inode-number, ic is not used
400 * Thoes variables are declared as union, thus using those 407 * Thoes variables are declared as union, thus using those
@@ -404,11 +411,13 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock
404 */ 411 */
405 ref->ino = je32_to_cpu(rr->ino); 412 ref->ino = je32_to_cpu(rr->ino);
406 ref->xid = je32_to_cpu(rr->xid); 413 ref->xid = je32_to_cpu(rr->xid);
414 ref->xseqno = je32_to_cpu(rr->xseqno);
415 if (ref->xseqno > c->highest_xseqno)
416 c->highest_xseqno = (ref->xseqno & ~XREF_DELETE_MARKER);
407 ref->next = c->xref_temp; 417 ref->next = c->xref_temp;
408 c->xref_temp = ref; 418 c->xref_temp = ref;
409 419
410 ref->node = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rr->totlen)), NULL); 420 jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rr->totlen)), (void *)ref);
411 /* FIXME */ ref->node->next_in_ino = (void *)ref;
412 421
413 if (jffs2_sum_active()) 422 if (jffs2_sum_active())
414 jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset); 423 jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset);
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
index 0b02fc79e4d1..c430f1d217e2 100644
--- a/fs/jffs2/summary.c
+++ b/fs/jffs2/summary.c
@@ -310,8 +310,6 @@ int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs,
310#ifdef CONFIG_JFFS2_FS_XATTR 310#ifdef CONFIG_JFFS2_FS_XATTR
311 case JFFS2_NODETYPE_XATTR: { 311 case JFFS2_NODETYPE_XATTR: {
312 struct jffs2_sum_xattr_mem *temp; 312 struct jffs2_sum_xattr_mem *temp;
313 if (je32_to_cpu(node->x.version) == 0xffffffff)
314 return 0;
315 temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL); 313 temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL);
316 if (!temp) 314 if (!temp)
317 goto no_mem; 315 goto no_mem;
@@ -327,10 +325,6 @@ int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs,
327 } 325 }
328 case JFFS2_NODETYPE_XREF: { 326 case JFFS2_NODETYPE_XREF: {
329 struct jffs2_sum_xref_mem *temp; 327 struct jffs2_sum_xref_mem *temp;
330
331 if (je32_to_cpu(node->r.ino) == 0xffffffff
332 && je32_to_cpu(node->r.xid) == 0xffffffff)
333 return 0;
334 temp = kmalloc(sizeof(struct jffs2_sum_xref_mem), GFP_KERNEL); 328 temp = kmalloc(sizeof(struct jffs2_sum_xref_mem), GFP_KERNEL);
335 if (!temp) 329 if (!temp)
336 goto no_mem; 330 goto no_mem;
@@ -483,22 +477,20 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
483 477
484 xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid), 478 xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid),
485 je32_to_cpu(spx->version)); 479 je32_to_cpu(spx->version));
486 if (IS_ERR(xd)) { 480 if (IS_ERR(xd))
487 if (PTR_ERR(xd) == -EEXIST) {
488 /* a newer version of xd exists */
489 if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(spx->totlen))))
490 return err;
491 sp += JFFS2_SUMMARY_XATTR_SIZE;
492 break;
493 }
494 JFFS2_NOTICE("allocation of xattr_datum failed\n");
495 return PTR_ERR(xd); 481 return PTR_ERR(xd);
482 if (xd->version > je32_to_cpu(spx->version)) {
483 /* node is not the newest one */
484 struct jffs2_raw_node_ref *raw
485 = sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED,
486 PAD(je32_to_cpu(spx->totlen)), NULL);
487 raw->next_in_ino = xd->node->next_in_ino;
488 xd->node->next_in_ino = raw;
489 } else {
490 xd->version = je32_to_cpu(spx->version);
491 sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED,
492 PAD(je32_to_cpu(spx->totlen)), (void *)xd);
496 } 493 }
497
498 xd->node = sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED,
499 PAD(je32_to_cpu(spx->totlen)), NULL);
500 /* FIXME */ xd->node->next_in_ino = (void *)xd;
501
502 *pseudo_random += je32_to_cpu(spx->xid); 494 *pseudo_random += je32_to_cpu(spx->xid);
503 sp += JFFS2_SUMMARY_XATTR_SIZE; 495 sp += JFFS2_SUMMARY_XATTR_SIZE;
504 496
@@ -519,14 +511,11 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
519 JFFS2_NOTICE("allocation of xattr_datum failed\n"); 511 JFFS2_NOTICE("allocation of xattr_datum failed\n");
520 return -ENOMEM; 512 return -ENOMEM;
521 } 513 }
522 ref->ino = 0xfffffffe;
523 ref->xid = 0xfffffffd;
524 ref->next = c->xref_temp; 514 ref->next = c->xref_temp;
525 c->xref_temp = ref; 515 c->xref_temp = ref;
526 516
527 ref->node = sum_link_node_ref(c, jeb, je32_to_cpu(spr->offset) | REF_UNCHECKED, 517 sum_link_node_ref(c, jeb, je32_to_cpu(spr->offset) | REF_UNCHECKED,
528 PAD(sizeof(struct jffs2_raw_xref)), NULL); 518 PAD(sizeof(struct jffs2_raw_xref)), (void *)ref);
529 /* FIXME */ ref->node->next_in_ino = (void *)ref;
530 519
531 *pseudo_random += ref->node->flash_offset; 520 *pseudo_random += ref->node->flash_offset;
532 sp += JFFS2_SUMMARY_XREF_SIZE; 521 sp += JFFS2_SUMMARY_XREF_SIZE;
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
index 2d82e250be34..03871ab7c26d 100644
--- a/fs/jffs2/xattr.c
+++ b/fs/jffs2/xattr.c
@@ -23,18 +23,15 @@
23 * xattr_datum_hashkey(xprefix, xname, xvalue, xsize) 23 * xattr_datum_hashkey(xprefix, xname, xvalue, xsize)
24 * is used to calcurate xdatum hashkey. The reminder of hashkey into XATTRINDEX_HASHSIZE is 24 * is used to calcurate xdatum hashkey. The reminder of hashkey into XATTRINDEX_HASHSIZE is
25 * the index of the xattr name/value pair cache (c->xattrindex). 25 * the index of the xattr name/value pair cache (c->xattrindex).
26 * is_xattr_datum_unchecked(c, xd)
27 * returns 1, if xdatum contains any unchecked raw nodes. if all raw nodes are not
28 * unchecked, it returns 0.
26 * unload_xattr_datum(c, xd) 29 * unload_xattr_datum(c, xd)
27 * is used to release xattr name/value pair and detach from c->xattrindex. 30 * is used to release xattr name/value pair and detach from c->xattrindex.
28 * reclaim_xattr_datum(c) 31 * reclaim_xattr_datum(c)
29 * is used to reclaim xattr name/value pairs on the xattr name/value pair cache when 32 * is used to reclaim xattr name/value pairs on the xattr name/value pair cache when
30 * memory usage by cache is over c->xdatum_mem_threshold. Currentry, this threshold 33 * memory usage by cache is over c->xdatum_mem_threshold. Currentry, this threshold
31 * is hard coded as 32KiB. 34 * is hard coded as 32KiB.
32 * delete_xattr_datum_node(c, xd)
33 * is used to delete a jffs2 node is dominated by xdatum. When EBS(Erase Block Summary) is
34 * enabled, it overwrites the obsolete node by myself.
35 * delete_xattr_datum(c, xd)
36 * is used to delete jffs2_xattr_datum object. It must be called with 0-value of reference
37 * counter. (It means how many jffs2_xattr_ref object refers this xdatum.)
38 * do_verify_xattr_datum(c, xd) 35 * do_verify_xattr_datum(c, xd)
39 * is used to load the xdatum informations without name/value pair from the medium. 36 * is used to load the xdatum informations without name/value pair from the medium.
40 * It's necessary once, because those informations are not collected during mounting 37 * It's necessary once, because those informations are not collected during mounting
@@ -53,8 +50,13 @@
53 * is used to write xdatum to medium. xd->version will be incremented. 50 * is used to write xdatum to medium. xd->version will be incremented.
54 * create_xattr_datum(c, xprefix, xname, xvalue, xsize) 51 * create_xattr_datum(c, xprefix, xname, xvalue, xsize)
55 * is used to create new xdatum and write to medium. 52 * is used to create new xdatum and write to medium.
53 * delete_xattr_datum_delay(c, xd)
54 * is used to delete a xdatum without 'delete marker'. It has a possibility to detect
55 * orphan xdatum on next mounting.
56 * delete_xattr_datum(c, xd)
57 * is used to delete a xdatum with 'delete marker'. Calling jffs2_reserve_space() is
58 * necessary before this function.
56 * -------------------------------------------------- */ 59 * -------------------------------------------------- */
57
58static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *xvalue, int xsize) 60static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *xvalue, int xsize)
59{ 61{
60 int name_len = strlen(xname); 62 int name_len = strlen(xname);
@@ -62,6 +64,22 @@ static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *
62 return crc32(xprefix, xname, name_len) ^ crc32(xprefix, xvalue, xsize); 64 return crc32(xprefix, xname, name_len) ^ crc32(xprefix, xvalue, xsize);
63} 65}
64 66
67static int is_xattr_datum_unchecked(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
68{
69 struct jffs2_raw_node_ref *raw;
70 int rc = 0;
71
72 spin_lock(&c->erase_completion_lock);
73 for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) {
74 if (ref_flags(raw) == REF_UNCHECKED) {
75 rc = 1;
76 break;
77 }
78 }
79 spin_unlock(&c->erase_completion_lock);
80 return rc;
81}
82
65static void unload_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) 83static void unload_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
66{ 84{
67 /* must be called under down_write(xattr_sem) */ 85 /* must be called under down_write(xattr_sem) */
@@ -107,80 +125,39 @@ static void reclaim_xattr_datum(struct jffs2_sb_info *c)
107 before, c->xdatum_mem_usage, before - c->xdatum_mem_usage); 125 before, c->xdatum_mem_usage, before - c->xdatum_mem_usage);
108} 126}
109 127
110static void delete_xattr_datum_node(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
111{
112 /* must be called under down_write(xattr_sem) */
113 struct jffs2_raw_xattr rx;
114 size_t length;
115 int rc;
116
117 if (!xd->node) {
118 JFFS2_WARNING("xdatum (xid=%u) is removed twice.\n", xd->xid);
119 return;
120 }
121 if (jffs2_sum_active()) {
122 memset(&rx, 0xff, sizeof(struct jffs2_raw_xattr));
123 rc = jffs2_flash_read(c, ref_offset(xd->node),
124 sizeof(struct jffs2_unknown_node),
125 &length, (char *)&rx);
126 if (rc || length != sizeof(struct jffs2_unknown_node)) {
127 JFFS2_ERROR("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n",
128 rc, sizeof(struct jffs2_unknown_node),
129 length, ref_offset(xd->node));
130 }
131 rc = jffs2_flash_write(c, ref_offset(xd->node), sizeof(rx),
132 &length, (char *)&rx);
133 if (rc || length != sizeof(struct jffs2_raw_xattr)) {
134 JFFS2_ERROR("jffs2_flash_write()=%d, req=%zu, wrote=%zu ar %#08x\n",
135 rc, sizeof(rx), length, ref_offset(xd->node));
136 }
137 }
138 spin_lock(&c->erase_completion_lock);
139 xd->node->next_in_ino = NULL;
140 spin_unlock(&c->erase_completion_lock);
141 jffs2_mark_node_obsolete(c, xd->node);
142 xd->node = NULL;
143}
144
145static void delete_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
146{
147 /* must be called under down_write(xattr_sem) */
148 BUG_ON(xd->refcnt);
149
150 unload_xattr_datum(c, xd);
151 if (xd->node) {
152 delete_xattr_datum_node(c, xd);
153 xd->node = NULL;
154 }
155 jffs2_free_xattr_datum(xd);
156}
157
158static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) 128static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
159{ 129{
160 /* must be called under down_write(xattr_sem) */ 130 /* must be called under down_write(xattr_sem) */
161 struct jffs2_eraseblock *jeb; 131 struct jffs2_eraseblock *jeb;
132 struct jffs2_raw_node_ref *raw;
162 struct jffs2_raw_xattr rx; 133 struct jffs2_raw_xattr rx;
163 size_t readlen; 134 size_t readlen;
164 uint32_t crc, totlen; 135 uint32_t crc, offset, totlen;
165 int rc; 136 int rc;
166 137
167 BUG_ON(!xd->node); 138 spin_lock(&c->erase_completion_lock);
168 BUG_ON(ref_flags(xd->node) != REF_UNCHECKED); 139 offset = ref_offset(xd->node);
140 if (ref_flags(xd->node) == REF_PRISTINE)
141 goto complete;
142 spin_unlock(&c->erase_completion_lock);
169 143
170 rc = jffs2_flash_read(c, ref_offset(xd->node), sizeof(rx), &readlen, (char *)&rx); 144 rc = jffs2_flash_read(c, offset, sizeof(rx), &readlen, (char *)&rx);
171 if (rc || readlen != sizeof(rx)) { 145 if (rc || readlen != sizeof(rx)) {
172 JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n", 146 JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n",
173 rc, sizeof(rx), readlen, ref_offset(xd->node)); 147 rc, sizeof(rx), readlen, offset);
174 return rc ? rc : -EIO; 148 return rc ? rc : -EIO;
175 } 149 }
176 crc = crc32(0, &rx, sizeof(rx) - 4); 150 crc = crc32(0, &rx, sizeof(rx) - 4);
177 if (crc != je32_to_cpu(rx.node_crc)) { 151 if (crc != je32_to_cpu(rx.node_crc)) {
178 if (je32_to_cpu(rx.node_crc) != 0xffffffff) 152 JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
179 JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", 153 offset, je32_to_cpu(rx.hdr_crc), crc);
180 ref_offset(xd->node), je32_to_cpu(rx.hdr_crc), crc); 154 xd->flags |= JFFS2_XFLAGS_INVALID;
181 return EIO; 155 return EIO;
182 } 156 }
183 totlen = PAD(sizeof(rx) + rx.name_len + 1 + je16_to_cpu(rx.value_len)); 157 totlen = sizeof(rx);
158 if (xd->version != XDATUM_DELETE_MARKER)
159 totlen += rx.name_len + 1 + je16_to_cpu(rx.value_len);
160 totlen = PAD(totlen);
184 if (je16_to_cpu(rx.magic) != JFFS2_MAGIC_BITMASK 161 if (je16_to_cpu(rx.magic) != JFFS2_MAGIC_BITMASK
185 || je16_to_cpu(rx.nodetype) != JFFS2_NODETYPE_XATTR 162 || je16_to_cpu(rx.nodetype) != JFFS2_NODETYPE_XATTR
186 || je32_to_cpu(rx.totlen) != totlen 163 || je32_to_cpu(rx.totlen) != totlen
@@ -188,11 +165,12 @@ static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_dat
188 || je32_to_cpu(rx.version) != xd->version) { 165 || je32_to_cpu(rx.version) != xd->version) {
189 JFFS2_ERROR("inconsistent xdatum at %#08x, magic=%#04x/%#04x, " 166 JFFS2_ERROR("inconsistent xdatum at %#08x, magic=%#04x/%#04x, "
190 "nodetype=%#04x/%#04x, totlen=%u/%u, xid=%u/%u, version=%u/%u\n", 167 "nodetype=%#04x/%#04x, totlen=%u/%u, xid=%u/%u, version=%u/%u\n",
191 ref_offset(xd->node), je16_to_cpu(rx.magic), JFFS2_MAGIC_BITMASK, 168 offset, je16_to_cpu(rx.magic), JFFS2_MAGIC_BITMASK,
192 je16_to_cpu(rx.nodetype), JFFS2_NODETYPE_XATTR, 169 je16_to_cpu(rx.nodetype), JFFS2_NODETYPE_XATTR,
193 je32_to_cpu(rx.totlen), totlen, 170 je32_to_cpu(rx.totlen), totlen,
194 je32_to_cpu(rx.xid), xd->xid, 171 je32_to_cpu(rx.xid), xd->xid,
195 je32_to_cpu(rx.version), xd->version); 172 je32_to_cpu(rx.version), xd->version);
173 xd->flags |= JFFS2_XFLAGS_INVALID;
196 return EIO; 174 return EIO;
197 } 175 }
198 xd->xprefix = rx.xprefix; 176 xd->xprefix = rx.xprefix;
@@ -200,14 +178,17 @@ static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_dat
200 xd->value_len = je16_to_cpu(rx.value_len); 178 xd->value_len = je16_to_cpu(rx.value_len);
201 xd->data_crc = je32_to_cpu(rx.data_crc); 179 xd->data_crc = je32_to_cpu(rx.data_crc);
202 180
203 /* This JFFS2_NODETYPE_XATTR node is checked */
204 jeb = &c->blocks[ref_offset(xd->node) / c->sector_size];
205 totlen = PAD(je32_to_cpu(rx.totlen));
206
207 spin_lock(&c->erase_completion_lock); 181 spin_lock(&c->erase_completion_lock);
208 c->unchecked_size -= totlen; c->used_size += totlen; 182 complete:
209 jeb->unchecked_size -= totlen; jeb->used_size += totlen; 183 for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) {
210 xd->node->flash_offset = ref_offset(xd->node) | REF_PRISTINE; 184 jeb = &c->blocks[ref_offset(raw) / c->sector_size];
185 totlen = PAD(ref_totlen(c, jeb, raw));
186 if (ref_flags(raw) == REF_UNCHECKED) {
187 c->unchecked_size -= totlen; c->used_size += totlen;
188 jeb->unchecked_size -= totlen; jeb->used_size += totlen;
189 }
190 raw->flash_offset = ref_offset(raw) | ((xd->node==raw) ? REF_PRISTINE : REF_NORMAL);
191 }
211 spin_unlock(&c->erase_completion_lock); 192 spin_unlock(&c->erase_completion_lock);
212 193
213 /* unchecked xdatum is chained with c->xattr_unchecked */ 194 /* unchecked xdatum is chained with c->xattr_unchecked */
@@ -227,7 +208,6 @@ static int do_load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum
227 uint32_t crc, length; 208 uint32_t crc, length;
228 int i, ret, retry = 0; 209 int i, ret, retry = 0;
229 210
230 BUG_ON(!xd->node);
231 BUG_ON(ref_flags(xd->node) != REF_PRISTINE); 211 BUG_ON(ref_flags(xd->node) != REF_PRISTINE);
232 BUG_ON(!list_empty(&xd->xindex)); 212 BUG_ON(!list_empty(&xd->xindex));
233 retry: 213 retry:
@@ -253,6 +233,7 @@ static int do_load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum
253 " at %#08x, read: 0x%08x calculated: 0x%08x\n", 233 " at %#08x, read: 0x%08x calculated: 0x%08x\n",
254 ref_offset(xd->node), xd->data_crc, crc); 234 ref_offset(xd->node), xd->data_crc, crc);
255 kfree(data); 235 kfree(data);
236 xd->flags |= JFFS2_XFLAGS_INVALID;
256 return EIO; 237 return EIO;
257 } 238 }
258 239
@@ -286,16 +267,13 @@ static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x
286 * rc > 0 : Unrecoverable error, this node should be deleted. 267 * rc > 0 : Unrecoverable error, this node should be deleted.
287 */ 268 */
288 int rc = 0; 269 int rc = 0;
289 BUG_ON(xd->xname); 270
290 if (!xd->node) 271 if (xd->xname)
272 return 0;
273 if (xd->flags & JFFS2_XFLAGS_INVALID)
291 return EIO; 274 return EIO;
292 if (unlikely(ref_flags(xd->node) != REF_PRISTINE)) { 275 if (unlikely(is_xattr_datum_unchecked(c, xd)))
293 rc = do_verify_xattr_datum(c, xd); 276 rc = do_verify_xattr_datum(c, xd);
294 if (rc > 0) {
295 list_del_init(&xd->xindex);
296 delete_xattr_datum_node(c, xd);
297 }
298 }
299 if (!rc) 277 if (!rc)
300 rc = do_load_xattr_datum(c, xd); 278 rc = do_load_xattr_datum(c, xd);
301 return rc; 279 return rc;
@@ -304,36 +282,43 @@ static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x
304static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) 282static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
305{ 283{
306 /* must be called under down_write(xattr_sem) */ 284 /* must be called under down_write(xattr_sem) */
307 struct jffs2_raw_node_ref *raw;
308 struct jffs2_raw_xattr rx; 285 struct jffs2_raw_xattr rx;
309 struct kvec vecs[2]; 286 struct kvec vecs[2];
310 size_t length; 287 size_t length;
311 int rc, totlen; 288 int rc, totlen, nvecs = 1;
312 uint32_t phys_ofs = write_ofs(c); 289 uint32_t phys_ofs = write_ofs(c);
313 290
314 BUG_ON(!xd->xname); 291 BUG_ON(is_xattr_datum_dead(xd) || (xd->flags & JFFS2_XFLAGS_INVALID)
292 ? !!xd->xname : !xd->xname);
315 293
316 vecs[0].iov_base = ℞ 294 vecs[0].iov_base = ℞
317 vecs[0].iov_len = PAD(sizeof(rx)); 295 vecs[0].iov_len = totlen = sizeof(rx);
318 vecs[1].iov_base = xd->xname; 296 if (!is_xattr_datum_dead(xd) && !(xd->flags & JFFS2_XFLAGS_INVALID)) {
319 vecs[1].iov_len = xd->name_len + 1 + xd->value_len; 297 nvecs++;
320 totlen = vecs[0].iov_len + vecs[1].iov_len; 298 vecs[1].iov_base = xd->xname;
321 299 vecs[1].iov_len = xd->name_len + 1 + xd->value_len;
300 totlen += vecs[1].iov_len;
301 }
322 /* Setup raw-xattr */ 302 /* Setup raw-xattr */
303 memset(&rx, 0, sizeof(rx));
323 rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 304 rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
324 rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR); 305 rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR);
325 rx.totlen = cpu_to_je32(PAD(totlen)); 306 rx.totlen = cpu_to_je32(PAD(totlen));
326 rx.hdr_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_unknown_node) - 4)); 307 rx.hdr_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_unknown_node) - 4));
327 308
328 rx.xid = cpu_to_je32(xd->xid); 309 rx.xid = cpu_to_je32(xd->xid);
329 rx.version = cpu_to_je32(++xd->version); 310 if (!is_xattr_datum_dead(xd) && !(xd->flags & JFFS2_XFLAGS_INVALID)) {
330 rx.xprefix = xd->xprefix; 311 rx.version = cpu_to_je32(++xd->version);
331 rx.name_len = xd->name_len; 312 rx.xprefix = xd->xprefix;
332 rx.value_len = cpu_to_je16(xd->value_len); 313 rx.name_len = xd->name_len;
333 rx.data_crc = cpu_to_je32(crc32(0, vecs[1].iov_base, vecs[1].iov_len)); 314 rx.value_len = cpu_to_je16(xd->value_len);
315 rx.data_crc = cpu_to_je32(crc32(0, vecs[1].iov_base, vecs[1].iov_len));
316 } else {
317 rx.version = cpu_to_je32(XDATUM_DELETE_MARKER);
318 }
334 rx.node_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_raw_xattr) - 4)); 319 rx.node_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_raw_xattr) - 4));
335 320
336 rc = jffs2_flash_writev(c, vecs, 2, phys_ofs, &length, 0); 321 rc = jffs2_flash_writev(c, vecs, nvecs, phys_ofs, &length, 0);
337 if (rc || totlen != length) { 322 if (rc || totlen != length) {
338 JFFS2_WARNING("jffs2_flash_writev()=%d, req=%u, wrote=%zu, at %#08x\n", 323 JFFS2_WARNING("jffs2_flash_writev()=%d, req=%u, wrote=%zu, at %#08x\n",
339 rc, totlen, length, phys_ofs); 324 rc, totlen, length, phys_ofs);
@@ -343,14 +328,8 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x
343 328
344 return rc; 329 return rc;
345 } 330 }
346
347 /* success */ 331 /* success */
348 raw = jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(totlen), NULL); 332 jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(totlen), (void *)xd);
349 /* FIXME */ raw->next_in_ino = (void *)xd;
350
351 if (xd->node)
352 delete_xattr_datum_node(c, xd);
353 xd->node = raw;
354 333
355 dbg_xattr("success on saving xdatum (xid=%u, version=%u, xprefix=%u, xname='%s')\n", 334 dbg_xattr("success on saving xdatum (xid=%u, version=%u, xprefix=%u, xname='%s')\n",
356 xd->xid, xd->version, xd->xprefix, xd->xname); 335 xd->xid, xd->version, xd->xprefix, xd->xname);
@@ -426,6 +405,39 @@ static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c,
426 return xd; 405 return xd;
427} 406}
428 407
408static void delete_xattr_datum_delay(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
409{
410 /* must be called under down_write(xattr_sem) */
411 BUG_ON(xd->refcnt);
412
413 unload_xattr_datum(c, xd);
414 set_xattr_datum_dead(xd);
415 spin_lock(&c->erase_completion_lock);
416 list_add(&xd->xindex, &c->xattr_dead_list);
417 spin_unlock(&c->erase_completion_lock);
418 JFFS2_NOTICE("xdatum(xid=%u) was removed without delete marker. "
419 "An orphan xdatum may be detected on next mounting.\n", xd->xid);
420}
421
422static void delete_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
423{
424 /* must be called under jffs2_reserve_space() and down_write(xattr_sem) */
425 int rc;
426 BUG_ON(xd->refcnt);
427
428 unload_xattr_datum(c, xd);
429 set_xattr_datum_dead(xd);
430 rc = save_xattr_datum(c, xd);
431 if (rc) {
432 JFFS2_NOTICE("xdatum(xid=%u) was removed without delete marker. "
433 "An orphan xdatum may be detected on next mounting.\n",
434 xd->xid);
435 }
436 spin_lock(&c->erase_completion_lock);
437 list_add(&xd->xindex, &c->xattr_dead_list);
438 spin_unlock(&c->erase_completion_lock);
439}
440
429/* -------- xref related functions ------------------ 441/* -------- xref related functions ------------------
430 * verify_xattr_ref(c, ref) 442 * verify_xattr_ref(c, ref)
431 * is used to load xref information from medium. Because summary data does not 443 * is used to load xref information from medium. Because summary data does not
@@ -450,25 +462,29 @@ static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c,
450static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) 462static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
451{ 463{
452 struct jffs2_eraseblock *jeb; 464 struct jffs2_eraseblock *jeb;
465 struct jffs2_raw_node_ref *raw;
453 struct jffs2_raw_xref rr; 466 struct jffs2_raw_xref rr;
454 size_t readlen; 467 size_t readlen;
455 uint32_t crc, totlen; 468 uint32_t crc, offset, totlen;
456 int rc; 469 int rc;
457 470
458 BUG_ON(ref_flags(ref->node) != REF_UNCHECKED); 471 spin_lock(&c->erase_completion_lock);
472 if (ref_flags(ref->node) != REF_UNCHECKED)
473 goto complete;
474 offset = ref_offset(ref->node);
475 spin_unlock(&c->erase_completion_lock);
459 476
460 rc = jffs2_flash_read(c, ref_offset(ref->node), sizeof(rr), &readlen, (char *)&rr); 477 rc = jffs2_flash_read(c, offset, sizeof(rr), &readlen, (char *)&rr);
461 if (rc || sizeof(rr) != readlen) { 478 if (rc || sizeof(rr) != readlen) {
462 JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu, at %#08x\n", 479 JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu, at %#08x\n",
463 rc, sizeof(rr), readlen, ref_offset(ref->node)); 480 rc, sizeof(rr), readlen, offset);
464 return rc ? rc : -EIO; 481 return rc ? rc : -EIO;
465 } 482 }
466 /* obsolete node */ 483 /* obsolete node */
467 crc = crc32(0, &rr, sizeof(rr) - 4); 484 crc = crc32(0, &rr, sizeof(rr) - 4);
468 if (crc != je32_to_cpu(rr.node_crc)) { 485 if (crc != je32_to_cpu(rr.node_crc)) {
469 if (je32_to_cpu(rr.node_crc) != 0xffffffff) 486 JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
470 JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", 487 offset, je32_to_cpu(rr.node_crc), crc);
471 ref_offset(ref->node), je32_to_cpu(rr.node_crc), crc);
472 return EIO; 488 return EIO;
473 } 489 }
474 if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK 490 if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK
@@ -476,22 +492,28 @@ static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref
476 || je32_to_cpu(rr.totlen) != PAD(sizeof(rr))) { 492 || je32_to_cpu(rr.totlen) != PAD(sizeof(rr))) {
477 JFFS2_ERROR("inconsistent xref at %#08x, magic=%#04x/%#04x, " 493 JFFS2_ERROR("inconsistent xref at %#08x, magic=%#04x/%#04x, "
478 "nodetype=%#04x/%#04x, totlen=%u/%zu\n", 494 "nodetype=%#04x/%#04x, totlen=%u/%zu\n",
479 ref_offset(ref->node), je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK, 495 offset, je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK,
480 je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF, 496 je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF,
481 je32_to_cpu(rr.totlen), PAD(sizeof(rr))); 497 je32_to_cpu(rr.totlen), PAD(sizeof(rr)));
482 return EIO; 498 return EIO;
483 } 499 }
484 ref->ino = je32_to_cpu(rr.ino); 500 ref->ino = je32_to_cpu(rr.ino);
485 ref->xid = je32_to_cpu(rr.xid); 501 ref->xid = je32_to_cpu(rr.xid);
486 502 ref->xseqno = je32_to_cpu(rr.xseqno);
487 /* fixup superblock/eraseblock info */ 503 if (ref->xseqno > c->highest_xseqno)
488 jeb = &c->blocks[ref_offset(ref->node) / c->sector_size]; 504 c->highest_xseqno = (ref->xseqno & ~XREF_DELETE_MARKER);
489 totlen = PAD(sizeof(rr));
490 505
491 spin_lock(&c->erase_completion_lock); 506 spin_lock(&c->erase_completion_lock);
492 c->unchecked_size -= totlen; c->used_size += totlen; 507 complete:
493 jeb->unchecked_size -= totlen; jeb->used_size += totlen; 508 for (raw=ref->node; raw != (void *)ref; raw=raw->next_in_ino) {
494 ref->node->flash_offset = ref_offset(ref->node) | REF_PRISTINE; 509 jeb = &c->blocks[ref_offset(raw) / c->sector_size];
510 totlen = PAD(ref_totlen(c, jeb, raw));
511 if (ref_flags(raw) == REF_UNCHECKED) {
512 c->unchecked_size -= totlen; c->used_size += totlen;
513 jeb->unchecked_size -= totlen; jeb->used_size += totlen;
514 }
515 raw->flash_offset = ref_offset(raw) | ((ref->node==raw) ? REF_PRISTINE : REF_NORMAL);
516 }
495 spin_unlock(&c->erase_completion_lock); 517 spin_unlock(&c->erase_completion_lock);
496 518
497 dbg_xattr("success on verifying xref (ino=%u, xid=%u) at %#08x\n", 519 dbg_xattr("success on verifying xref (ino=%u, xid=%u) at %#08x\n",
@@ -499,58 +521,12 @@ static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref
499 return 0; 521 return 0;
500} 522}
501 523
502static void delete_xattr_ref_node(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
503{
504 struct jffs2_raw_xref rr;
505 size_t length;
506 int rc;
507
508 if (jffs2_sum_active()) {
509 memset(&rr, 0xff, sizeof(rr));
510 rc = jffs2_flash_read(c, ref_offset(ref->node),
511 sizeof(struct jffs2_unknown_node),
512 &length, (char *)&rr);
513 if (rc || length != sizeof(struct jffs2_unknown_node)) {
514 JFFS2_ERROR("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n",
515 rc, sizeof(struct jffs2_unknown_node),
516 length, ref_offset(ref->node));
517 }
518 rc = jffs2_flash_write(c, ref_offset(ref->node), sizeof(rr),
519 &length, (char *)&rr);
520 if (rc || length != sizeof(struct jffs2_raw_xref)) {
521 JFFS2_ERROR("jffs2_flash_write()=%d, req=%zu, wrote=%zu at %#08x\n",
522 rc, sizeof(rr), length, ref_offset(ref->node));
523 }
524 }
525 spin_lock(&c->erase_completion_lock);
526 ref->node->next_in_ino = NULL;
527 spin_unlock(&c->erase_completion_lock);
528 jffs2_mark_node_obsolete(c, ref->node);
529 ref->node = NULL;
530}
531
532static void delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
533{
534 /* must be called under down_write(xattr_sem) */
535 struct jffs2_xattr_datum *xd;
536
537 BUG_ON(!ref->node);
538 delete_xattr_ref_node(c, ref);
539
540 xd = ref->xd;
541 xd->refcnt--;
542 if (!xd->refcnt)
543 delete_xattr_datum(c, xd);
544 jffs2_free_xattr_ref(ref);
545}
546
547static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) 524static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
548{ 525{
549 /* must be called under down_write(xattr_sem) */ 526 /* must be called under down_write(xattr_sem) */
550 struct jffs2_raw_node_ref *raw;
551 struct jffs2_raw_xref rr; 527 struct jffs2_raw_xref rr;
552 size_t length; 528 size_t length;
553 uint32_t phys_ofs = write_ofs(c); 529 uint32_t xseqno, phys_ofs = write_ofs(c);
554 int ret; 530 int ret;
555 531
556 rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 532 rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -558,8 +534,16 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
558 rr.totlen = cpu_to_je32(PAD(sizeof(rr))); 534 rr.totlen = cpu_to_je32(PAD(sizeof(rr)));
559 rr.hdr_crc = cpu_to_je32(crc32(0, &rr, sizeof(struct jffs2_unknown_node) - 4)); 535 rr.hdr_crc = cpu_to_je32(crc32(0, &rr, sizeof(struct jffs2_unknown_node) - 4));
560 536
561 rr.ino = cpu_to_je32(ref->ic->ino); 537 xseqno = (c->highest_xseqno += 2);
562 rr.xid = cpu_to_je32(ref->xd->xid); 538 if (is_xattr_ref_dead(ref)) {
539 xseqno |= XREF_DELETE_MARKER;
540 rr.ino = cpu_to_je32(ref->ino);
541 rr.xid = cpu_to_je32(ref->xid);
542 } else {
543 rr.ino = cpu_to_je32(ref->ic->ino);
544 rr.xid = cpu_to_je32(ref->xd->xid);
545 }
546 rr.xseqno = cpu_to_je32(xseqno);
563 rr.node_crc = cpu_to_je32(crc32(0, &rr, sizeof(rr) - 4)); 547 rr.node_crc = cpu_to_je32(crc32(0, &rr, sizeof(rr) - 4));
564 548
565 ret = jffs2_flash_write(c, phys_ofs, sizeof(rr), &length, (char *)&rr); 549 ret = jffs2_flash_write(c, phys_ofs, sizeof(rr), &length, (char *)&rr);
@@ -572,12 +556,9 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
572 556
573 return ret; 557 return ret;
574 } 558 }
575 559 /* success */
576 raw = jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(sizeof(rr)), NULL); 560 ref->xseqno = xseqno;
577 /* FIXME */ raw->next_in_ino = (void *)ref; 561 jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(sizeof(rr)), (void *)ref);
578 if (ref->node)
579 delete_xattr_ref_node(c, ref);
580 ref->node = raw;
581 562
582 dbg_xattr("success on saving xref (ino=%u, xid=%u)\n", ref->ic->ino, ref->xd->xid); 563 dbg_xattr("success on saving xref (ino=%u, xid=%u)\n", ref->ic->ino, ref->xd->xid);
583 564
@@ -610,22 +591,116 @@ static struct jffs2_xattr_ref *create_xattr_ref(struct jffs2_sb_info *c, struct
610 return ref; /* success */ 591 return ref; /* success */
611} 592}
612 593
594static void delete_xattr_ref_delay(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
595{
596 /* must be called under down_write(xattr_sem) */
597 struct jffs2_xattr_datum *xd;
598
599 set_xattr_ref_dead(ref);
600 xd = ref->xd;
601 ref->ino = ref->ic->ino;
602 ref->xid = ref->xd->xid;
603 spin_lock(&c->erase_completion_lock);
604 ref->next = c->xref_dead_list;
605 c->xref_dead_list = ref;
606 spin_unlock(&c->erase_completion_lock);
607
608 JFFS2_NOTICE("xref(ino=%u, xid=%u) was removed without delete marker. "
609 "An orphan xref may be detected on next mounting.\n",
610 ref->ino, ref->xid);
611
612 if (!--xd->refcnt)
613 delete_xattr_datum_delay(c, xd);
614}
615
616static int delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref, int enforce)
617{
618 /* must be called under jffs2_reserve_space() and down_write(xattr_sem) */
619 struct jffs2_inode_cache *ic;
620 struct jffs2_xattr_datum *xd;
621 uint32_t length;
622 int rc;
623
624 set_xattr_ref_dead(ref);
625 ic = ref->ic;
626 xd = ref->xd;
627 ref->ino = ic->ino;
628 ref->xid = xd->xid;
629 rc = save_xattr_ref(c, ref);
630 if (rc) {
631 if (!enforce) {
632 clr_xattr_ref_dead(ref);
633 ref->ic = ic;
634 ref->xd = xd;
635 return rc;
636 }
637 JFFS2_WARNING("could not write delete marker of xref(ino=%u, xid=%u). "
638 "An orphan xref may be detected on next mounting.\n",
639 ref->ic->ino, ref->xd->xid);
640 }
641 spin_lock(&c->erase_completion_lock);
642 ref->next = c->xref_dead_list;
643 c->xref_dead_list = ref;
644 spin_unlock(&c->erase_completion_lock);
645
646 xd->refcnt--;
647 if (xd->refcnt)
648 return 0;
649
650 /* delete xdatum */
651 unload_xattr_datum(c, xd);
652 up_write(&c->xattr_sem);
653 jffs2_complete_reservation(c);
654
655 rc = jffs2_reserve_space(c, PAD(sizeof(struct jffs2_raw_xattr)), &length,
656 ALLOC_DELETION, JFFS2_SUMMARY_XATTR_SIZE);
657 if (rc) {
658 down(&c->alloc_sem);
659 down_write(&c->xattr_sem);
660 delete_xattr_datum_delay(c, xd);
661 } else {
662 down_write(&c->xattr_sem);
663 delete_xattr_datum(c, xd);
664 }
665 return 0;
666}
667
613void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) 668void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
614{ 669{
615 /* It's called from jffs2_clear_inode() on inode removing. 670 /* It's called from jffs2_clear_inode() on inode removing.
616 When an inode with XATTR is removed, those XATTRs must be removed. */ 671 When an inode with XATTR is removed, those XATTRs must be removed. */
617 struct jffs2_xattr_ref *ref, *_ref; 672 struct jffs2_xattr_ref *ref;
673 uint32_t length;
674 int rc, retry;
618 675
619 if (!ic || ic->nlink > 0) 676 if (!ic || ic->nlink > 0)
620 return; 677 return;
621 678
679 down_read(&c->xattr_sem);
680 if (!ic->xref) {
681 up_read(&c->xattr_sem);
682 return;
683 }
684 up_read(&c->xattr_sem);
685 retry:
686 rc = jffs2_reserve_space(c, PAD(sizeof(struct jffs2_raw_xref)), &length,
687 ALLOC_DELETION, JFFS2_SUMMARY_XREF_SIZE);
622 down_write(&c->xattr_sem); 688 down_write(&c->xattr_sem);
623 for (ref = ic->xref; ref; ref = _ref) { 689 if (ic->xref) {
624 _ref = ref->next; 690 ref = ic->xref;
625 delete_xattr_ref(c, ref); 691 ic->xref = ref->next;
692 if (rc) {
693 delete_xattr_ref_delay(c, ref);
694 } else {
695 delete_xattr_ref(c, ref, 1);
696 }
626 } 697 }
627 ic->xref = NULL; 698 retry = ic->xref ? 1 : 0;
628 up_write(&c->xattr_sem); 699 up_write(&c->xattr_sem);
700 if (!rc)
701 jffs2_complete_reservation(c);
702 if (retry)
703 goto retry;
629} 704}
630 705
631void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) 706void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
@@ -655,7 +730,7 @@ static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cac
655 * duplicate name/value pairs. If duplicate name/value pair would be found, 730 * duplicate name/value pairs. If duplicate name/value pair would be found,
656 * one will be removed. 731 * one will be removed.
657 */ 732 */
658 struct jffs2_xattr_ref *ref, *cmp, **pref; 733 struct jffs2_xattr_ref *ref, *cmp, **pref, **pcmp;
659 int rc = 0; 734 int rc = 0;
660 735
661 if (likely(ic->flags & INO_FLAGS_XATTR_CHECKED)) 736 if (likely(ic->flags & INO_FLAGS_XATTR_CHECKED))
@@ -668,27 +743,32 @@ static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cac
668 rc = load_xattr_datum(c, ref->xd); 743 rc = load_xattr_datum(c, ref->xd);
669 if (unlikely(rc > 0)) { 744 if (unlikely(rc > 0)) {
670 *pref = ref->next; 745 *pref = ref->next;
671 delete_xattr_ref(c, ref); 746 delete_xattr_ref_delay(c, ref);
672 goto retry; 747 goto retry;
673 } else if (unlikely(rc < 0)) 748 } else if (unlikely(rc < 0))
674 goto out; 749 goto out;
675 } 750 }
676 for (cmp=ref->next, pref=&ref->next; cmp; pref=&cmp->next, cmp=cmp->next) { 751 for (cmp=ref->next, pcmp=&ref->next; cmp; pcmp=&cmp->next, cmp=cmp->next) {
677 if (!cmp->xd->xname) { 752 if (!cmp->xd->xname) {
678 ref->xd->flags |= JFFS2_XFLAGS_BIND; 753 ref->xd->flags |= JFFS2_XFLAGS_BIND;
679 rc = load_xattr_datum(c, cmp->xd); 754 rc = load_xattr_datum(c, cmp->xd);
680 ref->xd->flags &= ~JFFS2_XFLAGS_BIND; 755 ref->xd->flags &= ~JFFS2_XFLAGS_BIND;
681 if (unlikely(rc > 0)) { 756 if (unlikely(rc > 0)) {
682 *pref = cmp->next; 757 *pcmp = cmp->next;
683 delete_xattr_ref(c, cmp); 758 delete_xattr_ref_delay(c, cmp);
684 goto retry; 759 goto retry;
685 } else if (unlikely(rc < 0)) 760 } else if (unlikely(rc < 0))
686 goto out; 761 goto out;
687 } 762 }
688 if (ref->xd->xprefix == cmp->xd->xprefix 763 if (ref->xd->xprefix == cmp->xd->xprefix
689 && !strcmp(ref->xd->xname, cmp->xd->xname)) { 764 && !strcmp(ref->xd->xname, cmp->xd->xname)) {
690 *pref = cmp->next; 765 if (ref->xseqno > cmp->xseqno) {
691 delete_xattr_ref(c, cmp); 766 *pcmp = cmp->next;
767 delete_xattr_ref_delay(c, cmp);
768 } else {
769 *pref = ref->next;
770 delete_xattr_ref_delay(c, ref);
771 }
692 goto retry; 772 goto retry;
693 } 773 }
694 } 774 }
@@ -719,9 +799,13 @@ void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c)
719 for (i=0; i < XATTRINDEX_HASHSIZE; i++) 799 for (i=0; i < XATTRINDEX_HASHSIZE; i++)
720 INIT_LIST_HEAD(&c->xattrindex[i]); 800 INIT_LIST_HEAD(&c->xattrindex[i]);
721 INIT_LIST_HEAD(&c->xattr_unchecked); 801 INIT_LIST_HEAD(&c->xattr_unchecked);
802 INIT_LIST_HEAD(&c->xattr_dead_list);
803 c->xref_dead_list = NULL;
722 c->xref_temp = NULL; 804 c->xref_temp = NULL;
723 805
724 init_rwsem(&c->xattr_sem); 806 init_rwsem(&c->xattr_sem);
807 c->highest_xid = 0;
808 c->highest_xseqno = 0;
725 c->xdatum_mem_usage = 0; 809 c->xdatum_mem_usage = 0;
726 c->xdatum_mem_threshold = 32 * 1024; /* Default 32KB */ 810 c->xdatum_mem_threshold = 32 * 1024; /* Default 32KB */
727} 811}
@@ -751,7 +835,11 @@ void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c)
751 _ref = ref->next; 835 _ref = ref->next;
752 jffs2_free_xattr_ref(ref); 836 jffs2_free_xattr_ref(ref);
753 } 837 }
754 c->xref_temp = NULL; 838
839 for (ref=c->xref_dead_list; ref; ref = _ref) {
840 _ref = ref->next;
841 jffs2_free_xattr_ref(ref);
842 }
755 843
756 for (i=0; i < XATTRINDEX_HASHSIZE; i++) { 844 for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
757 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) { 845 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
@@ -761,64 +849,120 @@ void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c)
761 jffs2_free_xattr_datum(xd); 849 jffs2_free_xattr_datum(xd);
762 } 850 }
763 } 851 }
852
853 list_for_each_entry_safe(xd, _xd, &c->xattr_dead_list, xindex) {
854 list_del(&xd->xindex);
855 jffs2_free_xattr_datum(xd);
856 }
764} 857}
765 858
859#define XREF_TMPHASH_SIZE (128)
766void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c) 860void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
767{ 861{
768 struct jffs2_xattr_ref *ref, *_ref; 862 struct jffs2_xattr_ref *ref, *_ref;
863 struct jffs2_xattr_ref *xref_tmphash[XREF_TMPHASH_SIZE];
769 struct jffs2_xattr_datum *xd, *_xd; 864 struct jffs2_xattr_datum *xd, *_xd;
770 struct jffs2_inode_cache *ic; 865 struct jffs2_inode_cache *ic;
771 int i, xdatum_count =0, xdatum_unchecked_count = 0, xref_count = 0; 866 struct jffs2_raw_node_ref *raw;
867 int i, xdatum_count = 0, xdatum_unchecked_count = 0, xref_count = 0;
772 868
773 BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING)); 869 BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING));
870 /* Phase.1 : Drop dead xdatum */
871 for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
872 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
873 BUG_ON(xd->node == (void *)xd);
874 if (is_xattr_datum_dead(xd)) {
875 list_del_init(&xd->xindex);
876 list_add(&xd->xindex, &c->xattr_unchecked);
877 }
878 }
879 }
774 880
775 /* Phase.1 */ 881 /* Phase.2 : Merge same xref */
882 for (i=0; i < XREF_TMPHASH_SIZE; i++)
883 xref_tmphash[i] = NULL;
776 for (ref=c->xref_temp; ref; ref=_ref) { 884 for (ref=c->xref_temp; ref; ref=_ref) {
885 struct jffs2_xattr_ref *tmp;
886
777 _ref = ref->next; 887 _ref = ref->next;
778 /* checking REF_UNCHECKED nodes */
779 if (ref_flags(ref->node) != REF_PRISTINE) { 888 if (ref_flags(ref->node) != REF_PRISTINE) {
780 if (verify_xattr_ref(c, ref)) { 889 if (verify_xattr_ref(c, ref)) {
781 delete_xattr_ref_node(c, ref); 890 BUG_ON(ref->node->next_in_ino != (void *)ref);
891 ref->node->next_in_ino = NULL;
892 jffs2_mark_node_obsolete(c, ref->node);
782 jffs2_free_xattr_ref(ref); 893 jffs2_free_xattr_ref(ref);
783 continue; 894 continue;
784 } 895 }
785 } 896 }
786 /* At this point, ref->xid and ref->ino contain XID and inode number. 897
787 ref->xd and ref->ic are not valid yet. */ 898 i = (ref->ino ^ ref->xid) % XREF_TMPHASH_SIZE;
788 xd = jffs2_find_xattr_datum(c, ref->xid); 899 for (tmp=xref_tmphash[i]; tmp; tmp=tmp->next) {
789 ic = jffs2_get_ino_cache(c, ref->ino); 900 if (tmp->ino == ref->ino && tmp->xid == ref->xid)
790 if (!xd || !ic) { 901 break;
791 if (ref_flags(ref->node) != REF_UNCHECKED) 902 }
792 JFFS2_WARNING("xref(ino=%u, xid=%u) is orphan. \n", 903 if (tmp) {
793 ref->ino, ref->xid); 904 raw = ref->node;
794 delete_xattr_ref_node(c, ref); 905 if (ref->xseqno > tmp->xseqno) {
906 tmp->xseqno = ref->xseqno;
907 raw->next_in_ino = tmp->node;
908 tmp->node = raw;
909 } else {
910 raw->next_in_ino = tmp->node->next_in_ino;
911 tmp->node->next_in_ino = raw;
912 }
795 jffs2_free_xattr_ref(ref); 913 jffs2_free_xattr_ref(ref);
796 continue; 914 continue;
915 } else {
916 ref->next = xref_tmphash[i];
917 xref_tmphash[i] = ref;
797 } 918 }
798 ref->xd = xd;
799 ref->ic = ic;
800 xd->refcnt++;
801 ref->next = ic->xref;
802 ic->xref = ref;
803 xref_count++;
804 } 919 }
805 c->xref_temp = NULL; 920 c->xref_temp = NULL;
806 /* After this, ref->xid/ino are NEVER used. */
807 921
808 /* Phase.2 */ 922 /* Phase.3 : Bind xref with inode_cache and xattr_datum */
923 for (i=0; i < XREF_TMPHASH_SIZE; i++) {
924 for (ref=xref_tmphash[i]; ref; ref=_ref) {
925 _ref = ref->next;
926 if (is_xattr_ref_dead(ref)) {
927 ref->next = c->xref_dead_list;
928 c->xref_dead_list = ref;
929 continue;
930 }
931 /* At this point, ref->xid and ref->ino contain XID and inode number.
932 ref->xd and ref->ic are not valid yet. */
933 xd = jffs2_find_xattr_datum(c, ref->xid);
934 ic = jffs2_get_ino_cache(c, ref->ino);
935 if (!xd || !ic) {
936 JFFS2_WARNING("xref(ino=%u, xid=%u, xseqno=%u) is orphan. \n",
937 ref->ino, ref->xid, ref->xseqno);
938 set_xattr_ref_dead(ref);
939 ref->next = c->xref_dead_list;
940 c->xref_dead_list = ref;
941 continue;
942 }
943 ref->xd = xd;
944 ref->ic = ic;
945 xd->refcnt++;
946 ref->next = ic->xref;
947 ic->xref = ref;
948 xref_count++;
949 }
950 }
951
952 /* Phase.4 : Link unchecked xdatum to xattr_unchecked list */
809 for (i=0; i < XATTRINDEX_HASHSIZE; i++) { 953 for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
810 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) { 954 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
811 list_del_init(&xd->xindex); 955 list_del_init(&xd->xindex);
812 if (!xd->refcnt) { 956 if (!xd->refcnt) {
813 if (ref_flags(xd->node) != REF_UNCHECKED) 957 JFFS2_WARNING("orphan xdatum(xid=%u, version=%u)\n",
814 JFFS2_WARNING("orphan xdatum(xid=%u, version=%u) at %#08x\n", 958 xd->xid, xd->version);
815 xd->xid, xd->version, ref_offset(xd->node)); 959 set_xattr_datum_dead(xd);
816 delete_xattr_datum(c, xd); 960 list_add(&xd->xindex, &c->xattr_unchecked);
817 continue; 961 continue;
818 } 962 }
819 if (ref_flags(xd->node) != REF_PRISTINE) { 963 if (is_xattr_datum_unchecked(c, xd)) {
820 dbg_xattr("unchecked xdatum(xid=%u) at %#08x\n", 964 dbg_xattr("unchecked xdatum(xid=%u, version=%u)\n",
821 xd->xid, ref_offset(xd->node)); 965 xd->xid, xd->version);
822 list_add(&xd->xindex, &c->xattr_unchecked); 966 list_add(&xd->xindex, &c->xattr_unchecked);
823 xdatum_unchecked_count++; 967 xdatum_unchecked_count++;
824 } 968 }
@@ -833,28 +977,18 @@ void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
833struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c, 977struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
834 uint32_t xid, uint32_t version) 978 uint32_t xid, uint32_t version)
835{ 979{
836 struct jffs2_xattr_datum *xd, *_xd; 980 struct jffs2_xattr_datum *xd;
837 981
838 _xd = jffs2_find_xattr_datum(c, xid); 982 xd = jffs2_find_xattr_datum(c, xid);
839 if (_xd) { 983 if (!xd) {
840 dbg_xattr("duplicate xdatum (xid=%u, version=%u/%u) at %#08x\n", 984 xd = jffs2_alloc_xattr_datum();
841 xid, version, _xd->version, ref_offset(_xd->node)); 985 if (!xd)
842 if (version < _xd->version) 986 return ERR_PTR(-ENOMEM);
843 return ERR_PTR(-EEXIST); 987 xd->xid = xid;
844 } 988 xd->version = version;
845 xd = jffs2_alloc_xattr_datum(); 989 if (xd->xid > c->highest_xid)
846 if (!xd) 990 c->highest_xid = xd->xid;
847 return ERR_PTR(-ENOMEM); 991 list_add_tail(&xd->xindex, &c->xattrindex[xid % XATTRINDEX_HASHSIZE]);
848 xd->xid = xid;
849 xd->version = version;
850 if (xd->xid > c->highest_xid)
851 c->highest_xid = xd->xid;
852 list_add_tail(&xd->xindex, &c->xattrindex[xid % XATTRINDEX_HASHSIZE]);
853
854 if (_xd) {
855 list_del_init(&_xd->xindex);
856 delete_xattr_datum_node(c, _xd);
857 jffs2_free_xattr_datum(_xd);
858 } 992 }
859 return xd; 993 return xd;
860} 994}
@@ -945,7 +1079,7 @@ ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
945 rc = load_xattr_datum(c, xd); 1079 rc = load_xattr_datum(c, xd);
946 if (unlikely(rc > 0)) { 1080 if (unlikely(rc > 0)) {
947 *pref = ref->next; 1081 *pref = ref->next;
948 delete_xattr_ref(c, ref); 1082 delete_xattr_ref_delay(c, ref);
949 goto retry; 1083 goto retry;
950 } else if (unlikely(rc < 0)) 1084 } else if (unlikely(rc < 0))
951 goto out; 1085 goto out;
@@ -1006,7 +1140,7 @@ int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname,
1006 rc = load_xattr_datum(c, xd); 1140 rc = load_xattr_datum(c, xd);
1007 if (unlikely(rc > 0)) { 1141 if (unlikely(rc > 0)) {
1008 *pref = ref->next; 1142 *pref = ref->next;
1009 delete_xattr_ref(c, ref); 1143 delete_xattr_ref_delay(c, ref);
1010 goto retry; 1144 goto retry;
1011 } else if (unlikely(rc < 0)) { 1145 } else if (unlikely(rc < 0)) {
1012 goto out; 1146 goto out;
@@ -1069,7 +1203,7 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1069 rc = load_xattr_datum(c, xd); 1203 rc = load_xattr_datum(c, xd);
1070 if (unlikely(rc > 0)) { 1204 if (unlikely(rc > 0)) {
1071 *pref = ref->next; 1205 *pref = ref->next;
1072 delete_xattr_ref(c, ref); 1206 delete_xattr_ref_delay(c, ref);
1073 goto retry; 1207 goto retry;
1074 } else if (unlikely(rc < 0)) 1208 } else if (unlikely(rc < 0))
1075 goto out; 1209 goto out;
@@ -1081,8 +1215,7 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1081 } 1215 }
1082 if (!buffer) { 1216 if (!buffer) {
1083 *pref = ref->next; 1217 *pref = ref->next;
1084 delete_xattr_ref(c, ref); 1218 rc = delete_xattr_ref(c, ref, 0);
1085 rc = 0;
1086 goto out; 1219 goto out;
1087 } 1220 }
1088 goto found; 1221 goto found;
@@ -1094,7 +1227,7 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1094 goto out; 1227 goto out;
1095 } 1228 }
1096 if (!buffer) { 1229 if (!buffer) {
1097 rc = -EINVAL; 1230 rc = -ENODATA;
1098 goto out; 1231 goto out;
1099 } 1232 }
1100 found: 1233 found:
@@ -1110,16 +1243,15 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1110 request = PAD(sizeof(struct jffs2_raw_xref)); 1243 request = PAD(sizeof(struct jffs2_raw_xref));
1111 rc = jffs2_reserve_space(c, request, &length, 1244 rc = jffs2_reserve_space(c, request, &length,
1112 ALLOC_NORMAL, JFFS2_SUMMARY_XREF_SIZE); 1245 ALLOC_NORMAL, JFFS2_SUMMARY_XREF_SIZE);
1246 down_write(&c->xattr_sem);
1113 if (rc) { 1247 if (rc) {
1114 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request); 1248 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request);
1115 down_write(&c->xattr_sem);
1116 xd->refcnt--; 1249 xd->refcnt--;
1117 if (!xd->refcnt) 1250 if (!xd->refcnt)
1118 delete_xattr_datum(c, xd); 1251 delete_xattr_datum_delay(c, xd);
1119 up_write(&c->xattr_sem); 1252 up_write(&c->xattr_sem);
1120 return rc; 1253 return rc;
1121 } 1254 }
1122 down_write(&c->xattr_sem);
1123 if (ref) 1255 if (ref)
1124 *pref = ref->next; 1256 *pref = ref->next;
1125 newref = create_xattr_ref(c, ic, xd); 1257 newref = create_xattr_ref(c, ic, xd);
@@ -1131,9 +1263,21 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1131 rc = PTR_ERR(newref); 1263 rc = PTR_ERR(newref);
1132 xd->refcnt--; 1264 xd->refcnt--;
1133 if (!xd->refcnt) 1265 if (!xd->refcnt)
1134 delete_xattr_datum(c, xd); 1266 delete_xattr_datum_delay(c, xd);
1135 } else if (ref) { 1267 } else if (ref) {
1136 delete_xattr_ref(c, ref); 1268 up_write(&c->xattr_sem);
1269 jffs2_complete_reservation(c);
1270
1271 rc = jffs2_reserve_space(c, request, &length,
1272 ALLOC_DELETION, JFFS2_SUMMARY_XREF_SIZE);
1273 down_write(&c->xattr_sem);
1274 if (rc) {
1275 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request);
1276 delete_xattr_ref_delay(c, ref);
1277 up_write(&c->xattr_sem);
1278 return 0;
1279 }
1280 delete_xattr_ref(c, ref, 1);
1137 } 1281 }
1138 out: 1282 out:
1139 up_write(&c->xattr_sem); 1283 up_write(&c->xattr_sem);
@@ -1142,38 +1286,37 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1142} 1286}
1143 1287
1144/* -------- garbage collector functions ------------- 1288/* -------- garbage collector functions -------------
1145 * jffs2_garbage_collect_xattr_datum(c, xd) 1289 * jffs2_garbage_collect_xattr_datum(c, xd, raw)
1146 * is used to move xdatum into new node. 1290 * is used to move xdatum into new node.
1147 * jffs2_garbage_collect_xattr_ref(c, ref) 1291 * jffs2_garbage_collect_xattr_ref(c, ref, raw)
1148 * is used to move xref into new node. 1292 * is used to move xref into new node.
1149 * jffs2_verify_xattr(c) 1293 * jffs2_verify_xattr(c)
1150 * is used to call do_verify_xattr_datum() before garbage collecting. 1294 * is used to call do_verify_xattr_datum() before garbage collecting.
1151 * -------------------------------------------------- */ 1295 * -------------------------------------------------- */
1152int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) 1296int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd,
1297 struct jffs2_raw_node_ref *raw)
1153{ 1298{
1154 uint32_t totlen, length, old_ofs; 1299 uint32_t totlen, length, old_ofs;
1155 int rc = -EINVAL; 1300 int rc = 0;
1156 1301
1157 down_write(&c->xattr_sem); 1302 down_write(&c->xattr_sem);
1158 BUG_ON(!xd->node); 1303 if (xd->node != raw)
1304 goto out;
1305 if (is_xattr_datum_dead(xd) && (raw->next_in_ino == (void *)xd))
1306 goto out;
1159 1307
1160 old_ofs = ref_offset(xd->node); 1308 old_ofs = ref_offset(xd->node);
1161 totlen = ref_totlen(c, c->gcblock, xd->node); 1309 totlen = ref_totlen(c, c->gcblock, xd->node);
1162 if (totlen < sizeof(struct jffs2_raw_xattr))
1163 goto out;
1164 1310
1165 if (!xd->xname) { 1311 if (!is_xattr_datum_dead(xd)) {
1166 rc = load_xattr_datum(c, xd); 1312 rc = load_xattr_datum(c, xd);
1167 if (unlikely(rc > 0)) { 1313 if (unlikely(rc < 0))
1168 delete_xattr_datum_node(c, xd);
1169 rc = 0;
1170 goto out;
1171 } else if (unlikely(rc < 0))
1172 goto out; 1314 goto out;
1173 } 1315 }
1316
1174 rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE); 1317 rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE);
1175 if (rc || length < totlen) { 1318 if (rc) {
1176 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, totlen); 1319 JFFS2_WARNING("jffs2_reserve_space_gc()=%d, request=%u\n", rc, totlen);
1177 rc = rc ? rc : -EBADFD; 1320 rc = rc ? rc : -EBADFD;
1178 goto out; 1321 goto out;
1179 } 1322 }
@@ -1182,27 +1325,33 @@ int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xatt
1182 dbg_xattr("xdatum (xid=%u, version=%u) GC'ed from %#08x to %08x\n", 1325 dbg_xattr("xdatum (xid=%u, version=%u) GC'ed from %#08x to %08x\n",
1183 xd->xid, xd->version, old_ofs, ref_offset(xd->node)); 1326 xd->xid, xd->version, old_ofs, ref_offset(xd->node));
1184 out: 1327 out:
1328 if (!rc)
1329 jffs2_mark_node_obsolete(c, raw);
1185 up_write(&c->xattr_sem); 1330 up_write(&c->xattr_sem);
1186 return rc; 1331 return rc;
1187} 1332}
1188 1333
1189 1334
1190int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) 1335int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref,
1336 struct jffs2_raw_node_ref *raw)
1191{ 1337{
1192 uint32_t totlen, length, old_ofs; 1338 uint32_t totlen, length, old_ofs;
1193 int rc = -EINVAL; 1339 int rc = 0;
1194 1340
1195 down_write(&c->xattr_sem); 1341 down_write(&c->xattr_sem);
1196 BUG_ON(!ref->node); 1342 BUG_ON(!ref->node);
1197 1343
1344 if (ref->node != raw)
1345 goto out;
1346 if (is_xattr_ref_dead(ref) && (raw->next_in_ino == (void *)ref))
1347 goto out;
1348
1198 old_ofs = ref_offset(ref->node); 1349 old_ofs = ref_offset(ref->node);
1199 totlen = ref_totlen(c, c->gcblock, ref->node); 1350 totlen = ref_totlen(c, c->gcblock, ref->node);
1200 if (totlen != sizeof(struct jffs2_raw_xref))
1201 goto out;
1202 1351
1203 rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XREF_SIZE); 1352 rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XREF_SIZE);
1204 if (rc || length < totlen) { 1353 if (rc) {
1205 JFFS2_WARNING("%s: jffs2_reserve_space() = %d, request = %u\n", 1354 JFFS2_WARNING("%s: jffs2_reserve_space_gc() = %d, request = %u\n",
1206 __FUNCTION__, rc, totlen); 1355 __FUNCTION__, rc, totlen);
1207 rc = rc ? rc : -EBADFD; 1356 rc = rc ? rc : -EBADFD;
1208 goto out; 1357 goto out;
@@ -1212,6 +1361,8 @@ int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_
1212 dbg_xattr("xref (ino=%u, xid=%u) GC'ed from %#08x to %08x\n", 1361 dbg_xattr("xref (ino=%u, xid=%u) GC'ed from %#08x to %08x\n",
1213 ref->ic->ino, ref->xd->xid, old_ofs, ref_offset(ref->node)); 1362 ref->ic->ino, ref->xd->xid, old_ofs, ref_offset(ref->node));
1214 out: 1363 out:
1364 if (!rc)
1365 jffs2_mark_node_obsolete(c, raw);
1215 up_write(&c->xattr_sem); 1366 up_write(&c->xattr_sem);
1216 return rc; 1367 return rc;
1217} 1368}
@@ -1219,20 +1370,59 @@ int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_
1219int jffs2_verify_xattr(struct jffs2_sb_info *c) 1370int jffs2_verify_xattr(struct jffs2_sb_info *c)
1220{ 1371{
1221 struct jffs2_xattr_datum *xd, *_xd; 1372 struct jffs2_xattr_datum *xd, *_xd;
1373 struct jffs2_eraseblock *jeb;
1374 struct jffs2_raw_node_ref *raw;
1375 uint32_t totlen;
1222 int rc; 1376 int rc;
1223 1377
1224 down_write(&c->xattr_sem); 1378 down_write(&c->xattr_sem);
1225 list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) { 1379 list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) {
1226 rc = do_verify_xattr_datum(c, xd); 1380 rc = do_verify_xattr_datum(c, xd);
1227 if (rc == 0) { 1381 if (rc < 0)
1228 list_del_init(&xd->xindex); 1382 continue;
1229 break; 1383 list_del_init(&xd->xindex);
1230 } else if (rc > 0) { 1384 spin_lock(&c->erase_completion_lock);
1231 list_del_init(&xd->xindex); 1385 for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) {
1232 delete_xattr_datum_node(c, xd); 1386 if (ref_flags(raw) != REF_UNCHECKED)
1387 continue;
1388 jeb = &c->blocks[ref_offset(raw) / c->sector_size];
1389 totlen = PAD(ref_totlen(c, jeb, raw));
1390 c->unchecked_size -= totlen; c->used_size += totlen;
1391 jeb->unchecked_size -= totlen; jeb->used_size += totlen;
1392 raw->flash_offset = ref_offset(raw)
1393 | ((xd->node == (void *)raw) ? REF_PRISTINE : REF_NORMAL);
1233 } 1394 }
1395 if (is_xattr_datum_dead(xd))
1396 list_add(&xd->xindex, &c->xattr_dead_list);
1397 spin_unlock(&c->erase_completion_lock);
1234 } 1398 }
1235 up_write(&c->xattr_sem); 1399 up_write(&c->xattr_sem);
1236
1237 return list_empty(&c->xattr_unchecked) ? 1 : 0; 1400 return list_empty(&c->xattr_unchecked) ? 1 : 0;
1238} 1401}
1402
1403void jffs2_release_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
1404{
1405 /* must be called under spin_lock(&c->erase_completion_lock) */
1406 if (xd->node != (void *)xd)
1407 return;
1408
1409 list_del(&xd->xindex);
1410 jffs2_free_xattr_datum(xd);
1411}
1412
1413void jffs2_release_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
1414{
1415 /* must be called under spin_lock(&c->erase_completion_lock) */
1416 struct jffs2_xattr_ref *tmp, **ptmp;
1417
1418 if (ref->node != (void *)ref)
1419 return;
1420
1421 for (tmp=c->xref_dead_list, ptmp=&c->xref_dead_list; tmp; ptmp=&tmp->next, tmp=tmp->next) {
1422 if (ref == tmp) {
1423 *ptmp = tmp->next;
1424 jffs2_free_xattr_ref(ref);
1425 break;
1426 }
1427 }
1428}
diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h
index 2c199856c582..06ab7b880212 100644
--- a/fs/jffs2/xattr.h
+++ b/fs/jffs2/xattr.h
@@ -16,6 +16,7 @@
16 16
17#define JFFS2_XFLAGS_HOT (0x01) /* This datum is HOT */ 17#define JFFS2_XFLAGS_HOT (0x01) /* This datum is HOT */
18#define JFFS2_XFLAGS_BIND (0x02) /* This datum is not reclaimed */ 18#define JFFS2_XFLAGS_BIND (0x02) /* This datum is not reclaimed */
19#define JFFS2_XFLAGS_INVALID (0x80) /* This datum contains crc error */
19 20
20struct jffs2_xattr_datum 21struct jffs2_xattr_datum
21{ 22{
@@ -23,7 +24,7 @@ struct jffs2_xattr_datum
23 struct jffs2_raw_node_ref *node; 24 struct jffs2_raw_node_ref *node;
24 uint8_t class; 25 uint8_t class;
25 uint8_t flags; 26 uint8_t flags;
26 uint16_t xprefix; /* see JFFS2_XATTR_PREFIX_* */ 27 uint16_t xprefix; /* see JFFS2_XATTR_PREFIX_* */
27 28
28 struct list_head xindex; /* chained from c->xattrindex[n] */ 29 struct list_head xindex; /* chained from c->xattrindex[n] */
29 uint32_t refcnt; /* # of xattr_ref refers this */ 30 uint32_t refcnt; /* # of xattr_ref refers this */
@@ -47,6 +48,7 @@ struct jffs2_xattr_ref
47 uint8_t flags; /* Currently unused */ 48 uint8_t flags; /* Currently unused */
48 u16 unused; 49 u16 unused;
49 50
51 uint32_t xseqno;
50 union { 52 union {
51 struct jffs2_inode_cache *ic; /* reference to jffs2_inode_cache */ 53 struct jffs2_inode_cache *ic; /* reference to jffs2_inode_cache */
52 uint32_t ino; /* only used in scanning/building */ 54 uint32_t ino; /* only used in scanning/building */
@@ -58,6 +60,34 @@ struct jffs2_xattr_ref
58 struct jffs2_xattr_ref *next; /* chained from ic->xref_list */ 60 struct jffs2_xattr_ref *next; /* chained from ic->xref_list */
59}; 61};
60 62
63#define XDATUM_DELETE_MARKER (0xffffffff)
64#define XREF_DELETE_MARKER (0x00000001)
65static inline int is_xattr_datum_dead(struct jffs2_xattr_datum *xd)
66{
67 return (xd->version == XDATUM_DELETE_MARKER);
68}
69
70static inline void set_xattr_datum_dead(struct jffs2_xattr_datum *xd)
71{
72 xd->version = XDATUM_DELETE_MARKER;
73}
74
75static inline int is_xattr_ref_dead(struct jffs2_xattr_ref *ref)
76{
77 return ((ref->xseqno & XREF_DELETE_MARKER) != 0);
78}
79
80static inline void set_xattr_ref_dead(struct jffs2_xattr_ref *ref)
81{
82 ref->xseqno |= XREF_DELETE_MARKER;
83}
84
85static inline void clr_xattr_ref_dead(struct jffs2_xattr_ref *ref)
86{
87 ref->xseqno &= ~XREF_DELETE_MARKER;
88}
89
90
61#ifdef CONFIG_JFFS2_FS_XATTR 91#ifdef CONFIG_JFFS2_FS_XATTR
62 92
63extern void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c); 93extern void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c);
@@ -70,9 +100,13 @@ extern struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c
70extern void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); 100extern void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
71extern void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); 101extern void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
72 102
73extern int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd); 103extern int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd,
74extern int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref); 104 struct jffs2_raw_node_ref *raw);
105extern int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref,
106 struct jffs2_raw_node_ref *raw);
75extern int jffs2_verify_xattr(struct jffs2_sb_info *c); 107extern int jffs2_verify_xattr(struct jffs2_sb_info *c);
108extern void jffs2_release_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd);
109extern void jffs2_release_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref);
76 110
77extern int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname, 111extern int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname,
78 char *buffer, size_t size); 112 char *buffer, size_t size);