aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/Kconfig2
-rw-r--r--fs/jffs2/acl.c2
-rw-r--r--fs/jffs2/erase.c19
-rw-r--r--fs/jffs2/fs.c2
-rw-r--r--fs/jffs2/gc.c6
-rw-r--r--fs/jffs2/jffs2_fs_sb.h3
-rw-r--r--fs/jffs2/malloc.c2
-rw-r--r--fs/jffs2/nodelist.c3
-rw-r--r--fs/jffs2/nodemgmt.c21
-rw-r--r--fs/jffs2/readinode.c1
-rw-r--r--fs/jffs2/scan.c55
-rw-r--r--fs/jffs2/summary.c41
-rw-r--r--fs/jffs2/xattr.c632
-rw-r--r--fs/jffs2/xattr.h21
14 files changed, 467 insertions, 343 deletions
diff --git a/fs/Kconfig b/fs/Kconfig
index 00aa3d5c5a83..6dc8cfd6d80c 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1116,7 +1116,7 @@ config JFFS2_SUMMARY
1116 1116
1117config JFFS2_FS_XATTR 1117config JFFS2_FS_XATTR
1118 bool "JFFS2 XATTR support (EXPERIMENTAL)" 1118 bool "JFFS2 XATTR support (EXPERIMENTAL)"
1119 depends on JFFS2_FS && EXPERIMENTAL && !JFFS2_FS_WRITEBUFFER 1119 depends on JFFS2_FS && EXPERIMENTAL
1120 default n 1120 default n
1121 help 1121 help
1122 Extended attributes are name:value pairs associated with inodes by 1122 Extended attributes are name:value pairs associated with inodes by
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
index 320dd48b834e..9c2077e7e081 100644
--- a/fs/jffs2/acl.c
+++ b/fs/jffs2/acl.c
@@ -267,6 +267,8 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
267 } 267 }
268 268
269 rc = do_jffs2_setxattr(inode, xprefix, "", value, size, 0); 269 rc = do_jffs2_setxattr(inode, xprefix, "", value, size, 0);
270 if (!value && rc == -ENODATA)
271 rc = 0;
270 if (value) 272 if (value)
271 kfree(value); 273 kfree(value);
272 if (!rc) { 274 if (!rc) {
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index b8886f048eaa..ad0121088dde 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -225,7 +225,6 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
225 at the end of the linked list. Stash it and continue 225 at the end of the linked list. Stash it and continue
226 from the beginning of the list */ 226 from the beginning of the list */
227 ic = (struct jffs2_inode_cache *)(*prev); 227 ic = (struct jffs2_inode_cache *)(*prev);
228 BUG_ON(ic->class != RAWNODE_CLASS_INODE_CACHE);
229 prev = &ic->nodes; 228 prev = &ic->nodes;
230 continue; 229 continue;
231 } 230 }
@@ -249,7 +248,8 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
249 248
250 /* PARANOIA */ 249 /* PARANOIA */
251 if (!ic) { 250 if (!ic) {
252 printk(KERN_WARNING "inode_cache not found in remove_node_refs()!!\n"); 251 JFFS2_WARNING("inode_cache/xattr_datum/xattr_ref"
252 " not found in remove_node_refs()!!\n");
253 return; 253 return;
254 } 254 }
255 255
@@ -274,8 +274,19 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
274 printk("\n"); 274 printk("\n");
275 }); 275 });
276 276
277 if (ic->nodes == (void *)ic && ic->nlink == 0) 277 switch (ic->class) {
278 jffs2_del_ino_cache(c, ic); 278#ifdef CONFIG_JFFS2_FS_XATTR
279 case RAWNODE_CLASS_XATTR_DATUM:
280 jffs2_release_xattr_datum(c, (struct jffs2_xattr_datum *)ic);
281 break;
282 case RAWNODE_CLASS_XATTR_REF:
283 jffs2_release_xattr_ref(c, (struct jffs2_xattr_ref *)ic);
284 break;
285#endif
286 default:
287 if (ic->nodes == (void *)ic && ic->nlink == 0)
288 jffs2_del_ino_cache(c, ic);
289 }
279} 290}
280 291
281void jffs2_free_jeb_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) 292void jffs2_free_jeb_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 2900ec3ec3af..97caa77d60cf 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -227,8 +227,6 @@ void jffs2_clear_inode (struct inode *inode)
227 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); 227 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
228 228
229 D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode)); 229 D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode));
230
231 jffs2_xattr_delete_inode(c, f->inocache);
232 jffs2_do_clear_inode(c, f); 230 jffs2_do_clear_inode(c, f);
233} 231}
234 232
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index 477c526d638b..daff3341ff92 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -165,6 +165,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
165 D1(printk(KERN_DEBUG "Skipping check of ino #%d with nlink zero\n", 165 D1(printk(KERN_DEBUG "Skipping check of ino #%d with nlink zero\n",
166 ic->ino)); 166 ic->ino));
167 spin_unlock(&c->inocache_lock); 167 spin_unlock(&c->inocache_lock);
168 jffs2_xattr_delete_inode(c, ic);
168 continue; 169 continue;
169 } 170 }
170 switch(ic->state) { 171 switch(ic->state) {
@@ -275,13 +276,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. */ 276 * We can decide whether this node is inode or xattr by ic->class. */
276 if (ic->class == RAWNODE_CLASS_XATTR_DATUM 277 if (ic->class == RAWNODE_CLASS_XATTR_DATUM
277 || ic->class == RAWNODE_CLASS_XATTR_REF) { 278 || ic->class == RAWNODE_CLASS_XATTR_REF) {
278 BUG_ON(raw->next_in_ino != (void *)ic);
279 spin_unlock(&c->erase_completion_lock); 279 spin_unlock(&c->erase_completion_lock);
280 280
281 if (ic->class == RAWNODE_CLASS_XATTR_DATUM) { 281 if (ic->class == RAWNODE_CLASS_XATTR_DATUM) {
282 ret = jffs2_garbage_collect_xattr_datum(c, (struct jffs2_xattr_datum *)ic); 282 ret = jffs2_garbage_collect_xattr_datum(c, (struct jffs2_xattr_datum *)ic, raw);
283 } else { 283 } else {
284 ret = jffs2_garbage_collect_xattr_ref(c, (struct jffs2_xattr_ref *)ic); 284 ret = jffs2_garbage_collect_xattr_ref(c, (struct jffs2_xattr_ref *)ic, raw);
285 } 285 }
286 goto release_sem; 286 goto release_sem;
287 } 287 }
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/nodelist.c b/fs/jffs2/nodelist.c
index 927dfe42ba76..7675b33396c7 100644
--- a/fs/jffs2/nodelist.c
+++ b/fs/jffs2/nodelist.c
@@ -906,6 +906,9 @@ void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old)
906{ 906{
907 struct jffs2_inode_cache **prev; 907 struct jffs2_inode_cache **prev;
908 908
909#ifdef CONFIG_JFFS2_FS_XATTR
910 BUG_ON(old->xref);
911#endif
909 dbg_inocache("del %p (ino #%u)\n", old, old->ino); 912 dbg_inocache("del %p (ino #%u)\n", old, old->ino);
910 spin_lock(&c->inocache_lock); 913 spin_lock(&c->inocache_lock);
911 914
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
index ac0c350ed7d7..d88376992ed9 100644
--- a/fs/jffs2/nodemgmt.c
+++ b/fs/jffs2/nodemgmt.c
@@ -683,19 +683,26 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
683 spin_lock(&c->erase_completion_lock); 683 spin_lock(&c->erase_completion_lock);
684 684
685 ic = jffs2_raw_ref_to_ic(ref); 685 ic = jffs2_raw_ref_to_ic(ref);
686 /* It seems we should never call jffs2_mark_node_obsolete() for
687 XATTR nodes.... yet. Make sure we notice if/when we change
688 that :) */
689 BUG_ON(ic->class != RAWNODE_CLASS_INODE_CACHE);
690 for (p = &ic->nodes; (*p) != ref; p = &((*p)->next_in_ino)) 686 for (p = &ic->nodes; (*p) != ref; p = &((*p)->next_in_ino))
691 ; 687 ;
692 688
693 *p = ref->next_in_ino; 689 *p = ref->next_in_ino;
694 ref->next_in_ino = NULL; 690 ref->next_in_ino = NULL;
695 691
696 if (ic->nodes == (void *)ic && ic->nlink == 0) 692 switch (ic->class) {
697 jffs2_del_ino_cache(c, ic); 693#ifdef CONFIG_JFFS2_FS_XATTR
698 694 case RAWNODE_CLASS_XATTR_DATUM:
695 jffs2_release_xattr_datum(c, (struct jffs2_xattr_datum *)ic);
696 break;
697 case RAWNODE_CLASS_XATTR_REF:
698 jffs2_release_xattr_ref(c, (struct jffs2_xattr_ref *)ic);
699 break;
700#endif
701 default:
702 if (ic->nodes == (void *)ic && ic->nlink == 0)
703 jffs2_del_ino_cache(c, ic);
704 break;
705 }
699 spin_unlock(&c->erase_completion_lock); 706 spin_unlock(&c->erase_completion_lock);
700 } 707 }
701 708
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 5fec012b02ed..cc1899268c43 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -968,6 +968,7 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
968 struct jffs2_full_dirent *fd, *fds; 968 struct jffs2_full_dirent *fd, *fds;
969 int deleted; 969 int deleted;
970 970
971 jffs2_xattr_delete_inode(c, f->inocache);
971 down(&f->sem); 972 down(&f->sem);
972 deleted = f->inocache && !f->inocache->nlink; 973 deleted = f->inocache && !f->inocache->nlink;
973 974
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 61618080b86f..2bfdc33752d3 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -317,20 +317,23 @@ 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 = PAD(sizeof(struct jffs2_raw_xattr)
336 + rx->name_len + 1 + je16_to_cpu(rx->value_len));
334 if (totlen != je32_to_cpu(rx->totlen)) { 337 if (totlen != je32_to_cpu(rx->totlen)) {
335 JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%u\n", 338 JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%u\n",
336 ofs, je32_to_cpu(rx->totlen), totlen); 339 ofs, je32_to_cpu(rx->totlen), totlen);
@@ -339,22 +342,24 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
339 return 0; 342 return 0;
340 } 343 }
341 344
342 xd = jffs2_setup_xattr_datum(c, je32_to_cpu(rx->xid), je32_to_cpu(rx->version)); 345 xd = jffs2_setup_xattr_datum(c, xid, version);
343 if (IS_ERR(xd)) { 346 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); 347 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 348
356 xd->node = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, NULL); 349 if (xd->version > version) {
357 /* FIXME */ xd->node->next_in_ino = (void *)xd; 350 struct jffs2_raw_node_ref *raw
351 = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, NULL);
352 raw->next_in_ino = xd->node->next_in_ino;
353 xd->node->next_in_ino = raw;
354 } else {
355 xd->version = version;
356 xd->xprefix = rx->xprefix;
357 xd->name_len = rx->name_len;
358 xd->value_len = je16_to_cpu(rx->value_len);
359 xd->data_crc = je32_to_cpu(rx->data_crc);
360
361 jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, (void *)xd);
362 }
358 363
359 if (jffs2_sum_active()) 364 if (jffs2_sum_active())
360 jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset); 365 jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset);
@@ -373,9 +378,8 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock
373 378
374 crc = crc32(0, rr, sizeof(*rr) - 4); 379 crc = crc32(0, rr, sizeof(*rr) - 4);
375 if (crc != je32_to_cpu(rr->node_crc)) { 380 if (crc != je32_to_cpu(rr->node_crc)) {
376 if (je32_to_cpu(rr->node_crc) != 0xffffffff) 381 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", 382 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))))) 383 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rr->totlen)))))
380 return err; 384 return err;
381 return 0; 385 return 0;
@@ -395,6 +399,7 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock
395 return -ENOMEM; 399 return -ENOMEM;
396 400
397 /* BEFORE jffs2_build_xattr_subsystem() called, 401 /* BEFORE jffs2_build_xattr_subsystem() called,
402 * and AFTER xattr_ref is marked as a dead xref,
398 * ref->xid is used to store 32bit xid, xd is not used 403 * 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 404 * ref->ino is used to store 32bit inode-number, ic is not used
400 * Thoes variables are declared as union, thus using those 405 * Thoes variables are declared as union, thus using those
@@ -404,11 +409,13 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock
404 */ 409 */
405 ref->ino = je32_to_cpu(rr->ino); 410 ref->ino = je32_to_cpu(rr->ino);
406 ref->xid = je32_to_cpu(rr->xid); 411 ref->xid = je32_to_cpu(rr->xid);
412 ref->xseqno = je32_to_cpu(rr->xseqno);
413 if (ref->xseqno > c->highest_xseqno)
414 c->highest_xseqno = (ref->xseqno & ~XREF_DELETE_MARKER);
407 ref->next = c->xref_temp; 415 ref->next = c->xref_temp;
408 c->xref_temp = ref; 416 c->xref_temp = ref;
409 417
410 ref->node = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rr->totlen)), NULL); 418 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 419
413 if (jffs2_sum_active()) 420 if (jffs2_sum_active())
414 jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset); 421 jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset);
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
index be1acc3dad97..c19bd476e8ec 100644
--- a/fs/jffs2/summary.c
+++ b/fs/jffs2/summary.c
@@ -5,7 +5,7 @@
5 * Zoltan Sogor <weth@inf.u-szeged.hu>, 5 * Zoltan Sogor <weth@inf.u-szeged.hu>,
6 * Patrik Kluba <pajko@halom.u-szeged.hu>, 6 * Patrik Kluba <pajko@halom.u-szeged.hu>,
7 * University of Szeged, Hungary 7 * University of Szeged, Hungary
8 * 2005 KaiGai Kohei <kaigai@ak.jp.nec.com> 8 * 2006 KaiGai Kohei <kaigai@ak.jp.nec.com>
9 * 9 *
10 * For licensing information, see the file 'LICENCE' in this directory. 10 * For licensing information, see the file 'LICENCE' in this directory.
11 * 11 *
@@ -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..18e66dbf23b4 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,10 @@
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(c, xd)
54 * is used to delete a xdatum. It marks xd JFFS2_XFLAGS_DEAD, and allows
55 * GC to reclaim those physical nodes.
56 * -------------------------------------------------- */ 56 * -------------------------------------------------- */
57
58static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *xvalue, int xsize) 57static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *xvalue, int xsize)
59{ 58{
60 int name_len = strlen(xname); 59 int name_len = strlen(xname);
@@ -62,6 +61,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); 61 return crc32(xprefix, xname, name_len) ^ crc32(xprefix, xvalue, xsize);
63} 62}
64 63
64static int is_xattr_datum_unchecked(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
65{
66 struct jffs2_raw_node_ref *raw;
67 int rc = 0;
68
69 spin_lock(&c->erase_completion_lock);
70 for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) {
71 if (ref_flags(raw) == REF_UNCHECKED) {
72 rc = 1;
73 break;
74 }
75 }
76 spin_unlock(&c->erase_completion_lock);
77 return rc;
78}
79
65static void unload_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) 80static void unload_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
66{ 81{
67 /* must be called under down_write(xattr_sem) */ 82 /* must be called under down_write(xattr_sem) */
@@ -107,77 +122,33 @@ static void reclaim_xattr_datum(struct jffs2_sb_info *c)
107 before, c->xdatum_mem_usage, before - c->xdatum_mem_usage); 122 before, c->xdatum_mem_usage, before - c->xdatum_mem_usage);
108} 123}
109 124
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) 125static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
159{ 126{
160 /* must be called under down_write(xattr_sem) */ 127 /* must be called under down_write(xattr_sem) */
161 struct jffs2_eraseblock *jeb; 128 struct jffs2_eraseblock *jeb;
129 struct jffs2_raw_node_ref *raw;
162 struct jffs2_raw_xattr rx; 130 struct jffs2_raw_xattr rx;
163 size_t readlen; 131 size_t readlen;
164 uint32_t crc, totlen; 132 uint32_t crc, offset, totlen;
165 int rc; 133 int rc;
166 134
167 BUG_ON(!xd->node); 135 spin_lock(&c->erase_completion_lock);
168 BUG_ON(ref_flags(xd->node) != REF_UNCHECKED); 136 offset = ref_offset(xd->node);
137 if (ref_flags(xd->node) == REF_PRISTINE)
138 goto complete;
139 spin_unlock(&c->erase_completion_lock);
169 140
170 rc = jffs2_flash_read(c, ref_offset(xd->node), sizeof(rx), &readlen, (char *)&rx); 141 rc = jffs2_flash_read(c, offset, sizeof(rx), &readlen, (char *)&rx);
171 if (rc || readlen != sizeof(rx)) { 142 if (rc || readlen != sizeof(rx)) {
172 JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n", 143 JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n",
173 rc, sizeof(rx), readlen, ref_offset(xd->node)); 144 rc, sizeof(rx), readlen, offset);
174 return rc ? rc : -EIO; 145 return rc ? rc : -EIO;
175 } 146 }
176 crc = crc32(0, &rx, sizeof(rx) - 4); 147 crc = crc32(0, &rx, sizeof(rx) - 4);
177 if (crc != je32_to_cpu(rx.node_crc)) { 148 if (crc != je32_to_cpu(rx.node_crc)) {
178 if (je32_to_cpu(rx.node_crc) != 0xffffffff) 149 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", 150 offset, je32_to_cpu(rx.hdr_crc), crc);
180 ref_offset(xd->node), je32_to_cpu(rx.hdr_crc), crc); 151 xd->flags |= JFFS2_XFLAGS_INVALID;
181 return EIO; 152 return EIO;
182 } 153 }
183 totlen = PAD(sizeof(rx) + rx.name_len + 1 + je16_to_cpu(rx.value_len)); 154 totlen = PAD(sizeof(rx) + rx.name_len + 1 + je16_to_cpu(rx.value_len));
@@ -188,11 +159,12 @@ static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_dat
188 || je32_to_cpu(rx.version) != xd->version) { 159 || je32_to_cpu(rx.version) != xd->version) {
189 JFFS2_ERROR("inconsistent xdatum at %#08x, magic=%#04x/%#04x, " 160 JFFS2_ERROR("inconsistent xdatum at %#08x, magic=%#04x/%#04x, "
190 "nodetype=%#04x/%#04x, totlen=%u/%u, xid=%u/%u, version=%u/%u\n", 161 "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, 162 offset, je16_to_cpu(rx.magic), JFFS2_MAGIC_BITMASK,
192 je16_to_cpu(rx.nodetype), JFFS2_NODETYPE_XATTR, 163 je16_to_cpu(rx.nodetype), JFFS2_NODETYPE_XATTR,
193 je32_to_cpu(rx.totlen), totlen, 164 je32_to_cpu(rx.totlen), totlen,
194 je32_to_cpu(rx.xid), xd->xid, 165 je32_to_cpu(rx.xid), xd->xid,
195 je32_to_cpu(rx.version), xd->version); 166 je32_to_cpu(rx.version), xd->version);
167 xd->flags |= JFFS2_XFLAGS_INVALID;
196 return EIO; 168 return EIO;
197 } 169 }
198 xd->xprefix = rx.xprefix; 170 xd->xprefix = rx.xprefix;
@@ -200,14 +172,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); 172 xd->value_len = je16_to_cpu(rx.value_len);
201 xd->data_crc = je32_to_cpu(rx.data_crc); 173 xd->data_crc = je32_to_cpu(rx.data_crc);
202 174
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); 175 spin_lock(&c->erase_completion_lock);
208 c->unchecked_size -= totlen; c->used_size += totlen; 176 complete:
209 jeb->unchecked_size -= totlen; jeb->used_size += totlen; 177 for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) {
210 xd->node->flash_offset = ref_offset(xd->node) | REF_PRISTINE; 178 jeb = &c->blocks[ref_offset(raw) / c->sector_size];
179 totlen = PAD(ref_totlen(c, jeb, raw));
180 if (ref_flags(raw) == REF_UNCHECKED) {
181 c->unchecked_size -= totlen; c->used_size += totlen;
182 jeb->unchecked_size -= totlen; jeb->used_size += totlen;
183 }
184 raw->flash_offset = ref_offset(raw) | ((xd->node==raw) ? REF_PRISTINE : REF_NORMAL);
185 }
211 spin_unlock(&c->erase_completion_lock); 186 spin_unlock(&c->erase_completion_lock);
212 187
213 /* unchecked xdatum is chained with c->xattr_unchecked */ 188 /* unchecked xdatum is chained with c->xattr_unchecked */
@@ -227,7 +202,6 @@ static int do_load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum
227 uint32_t crc, length; 202 uint32_t crc, length;
228 int i, ret, retry = 0; 203 int i, ret, retry = 0;
229 204
230 BUG_ON(!xd->node);
231 BUG_ON(ref_flags(xd->node) != REF_PRISTINE); 205 BUG_ON(ref_flags(xd->node) != REF_PRISTINE);
232 BUG_ON(!list_empty(&xd->xindex)); 206 BUG_ON(!list_empty(&xd->xindex));
233 retry: 207 retry:
@@ -253,6 +227,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", 227 " at %#08x, read: 0x%08x calculated: 0x%08x\n",
254 ref_offset(xd->node), xd->data_crc, crc); 228 ref_offset(xd->node), xd->data_crc, crc);
255 kfree(data); 229 kfree(data);
230 xd->flags |= JFFS2_XFLAGS_INVALID;
256 return EIO; 231 return EIO;
257 } 232 }
258 233
@@ -286,16 +261,14 @@ 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. 261 * rc > 0 : Unrecoverable error, this node should be deleted.
287 */ 262 */
288 int rc = 0; 263 int rc = 0;
289 BUG_ON(xd->xname); 264
290 if (!xd->node) 265 BUG_ON(xd->flags & JFFS2_XFLAGS_DEAD);
266 if (xd->xname)
267 return 0;
268 if (xd->flags & JFFS2_XFLAGS_INVALID)
291 return EIO; 269 return EIO;
292 if (unlikely(ref_flags(xd->node) != REF_PRISTINE)) { 270 if (unlikely(is_xattr_datum_unchecked(c, xd)))
293 rc = do_verify_xattr_datum(c, xd); 271 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) 272 if (!rc)
300 rc = do_load_xattr_datum(c, xd); 273 rc = do_load_xattr_datum(c, xd);
301 return rc; 274 return rc;
@@ -304,7 +277,6 @@ 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) 277static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
305{ 278{
306 /* must be called under down_write(xattr_sem) */ 279 /* must be called under down_write(xattr_sem) */
307 struct jffs2_raw_node_ref *raw;
308 struct jffs2_raw_xattr rx; 280 struct jffs2_raw_xattr rx;
309 struct kvec vecs[2]; 281 struct kvec vecs[2];
310 size_t length; 282 size_t length;
@@ -312,14 +284,16 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x
312 uint32_t phys_ofs = write_ofs(c); 284 uint32_t phys_ofs = write_ofs(c);
313 285
314 BUG_ON(!xd->xname); 286 BUG_ON(!xd->xname);
287 BUG_ON(xd->flags & (JFFS2_XFLAGS_DEAD|JFFS2_XFLAGS_INVALID));
315 288
316 vecs[0].iov_base = &rx; 289 vecs[0].iov_base = &rx;
317 vecs[0].iov_len = PAD(sizeof(rx)); 290 vecs[0].iov_len = sizeof(rx);
318 vecs[1].iov_base = xd->xname; 291 vecs[1].iov_base = xd->xname;
319 vecs[1].iov_len = xd->name_len + 1 + xd->value_len; 292 vecs[1].iov_len = xd->name_len + 1 + xd->value_len;
320 totlen = vecs[0].iov_len + vecs[1].iov_len; 293 totlen = vecs[0].iov_len + vecs[1].iov_len;
321 294
322 /* Setup raw-xattr */ 295 /* Setup raw-xattr */
296 memset(&rx, 0, sizeof(rx));
323 rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 297 rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
324 rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR); 298 rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR);
325 rx.totlen = cpu_to_je32(PAD(totlen)); 299 rx.totlen = cpu_to_je32(PAD(totlen));
@@ -343,14 +317,8 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x
343 317
344 return rc; 318 return rc;
345 } 319 }
346
347 /* success */ 320 /* success */
348 raw = jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(totlen), NULL); 321 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 322
355 dbg_xattr("success on saving xdatum (xid=%u, version=%u, xprefix=%u, xname='%s')\n", 323 dbg_xattr("success on saving xdatum (xid=%u, version=%u, xprefix=%u, xname='%s')\n",
356 xd->xid, xd->version, xd->xprefix, xd->xname); 324 xd->xid, xd->version, xd->xprefix, xd->xname);
@@ -377,7 +345,7 @@ static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c,
377 && xd->value_len==xsize 345 && xd->value_len==xsize
378 && !strcmp(xd->xname, xname) 346 && !strcmp(xd->xname, xname)
379 && !memcmp(xd->xvalue, xvalue, xsize)) { 347 && !memcmp(xd->xvalue, xvalue, xsize)) {
380 xd->refcnt++; 348 atomic_inc(&xd->refcnt);
381 return xd; 349 return xd;
382 } 350 }
383 } 351 }
@@ -397,7 +365,7 @@ static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c,
397 strcpy(data, xname); 365 strcpy(data, xname);
398 memcpy(data + name_len + 1, xvalue, xsize); 366 memcpy(data + name_len + 1, xvalue, xsize);
399 367
400 xd->refcnt = 1; 368 atomic_set(&xd->refcnt, 1);
401 xd->xid = ++c->highest_xid; 369 xd->xid = ++c->highest_xid;
402 xd->flags |= JFFS2_XFLAGS_HOT; 370 xd->flags |= JFFS2_XFLAGS_HOT;
403 xd->xprefix = xprefix; 371 xd->xprefix = xprefix;
@@ -426,20 +394,36 @@ static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c,
426 return xd; 394 return xd;
427} 395}
428 396
397static void delete_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
398{
399 /* must be called under down_write(xattr_sem) */
400 BUG_ON(atomic_read(&xd->refcnt));
401
402 unload_xattr_datum(c, xd);
403 xd->flags |= JFFS2_XFLAGS_DEAD;
404 spin_lock(&c->erase_completion_lock);
405 if (xd->node == (void *)xd) {
406 BUG_ON(!(xd->flags & JFFS2_XFLAGS_INVALID));
407 jffs2_free_xattr_datum(xd);
408 } else {
409 list_add(&xd->xindex, &c->xattr_dead_list);
410 }
411 spin_unlock(&c->erase_completion_lock);
412 dbg_xattr("xdatum(xid=%u, version=%u) was removed.\n", xd->xid, xd->version);
413}
414
429/* -------- xref related functions ------------------ 415/* -------- xref related functions ------------------
430 * verify_xattr_ref(c, ref) 416 * verify_xattr_ref(c, ref)
431 * is used to load xref information from medium. Because summary data does not 417 * is used to load xref information from medium. Because summary data does not
432 * contain xid/ino, it's necessary to verify once while mounting process. 418 * contain xid/ino, it's necessary to verify once while mounting process.
433 * delete_xattr_ref_node(c, ref)
434 * is used to delete a jffs2 node is dominated by xref. When EBS is enabled,
435 * it overwrites the obsolete node by myself.
436 * delete_xattr_ref(c, ref)
437 * is used to delete jffs2_xattr_ref object. If the reference counter of xdatum
438 * is refered by this xref become 0, delete_xattr_datum() is called later.
439 * save_xattr_ref(c, ref) 419 * save_xattr_ref(c, ref)
440 * is used to write xref to medium. 420 * is used to write xref to medium. If delete marker is marked, it write
421 * a delete marker of xref into medium.
441 * create_xattr_ref(c, ic, xd) 422 * create_xattr_ref(c, ic, xd)
442 * is used to create a new xref and write to medium. 423 * is used to create a new xref and write to medium.
424 * delete_xattr_ref(c, ref)
425 * is used to delete jffs2_xattr_ref. It marks xref XREF_DELETE_MARKER,
426 * and allows GC to reclaim those physical nodes.
443 * jffs2_xattr_delete_inode(c, ic) 427 * jffs2_xattr_delete_inode(c, ic)
444 * is called to remove xrefs related to obsolete inode when inode is unlinked. 428 * is called to remove xrefs related to obsolete inode when inode is unlinked.
445 * jffs2_xattr_free_inode(c, ic) 429 * jffs2_xattr_free_inode(c, ic)
@@ -450,25 +434,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) 434static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
451{ 435{
452 struct jffs2_eraseblock *jeb; 436 struct jffs2_eraseblock *jeb;
437 struct jffs2_raw_node_ref *raw;
453 struct jffs2_raw_xref rr; 438 struct jffs2_raw_xref rr;
454 size_t readlen; 439 size_t readlen;
455 uint32_t crc, totlen; 440 uint32_t crc, offset, totlen;
456 int rc; 441 int rc;
457 442
458 BUG_ON(ref_flags(ref->node) != REF_UNCHECKED); 443 spin_lock(&c->erase_completion_lock);
444 if (ref_flags(ref->node) != REF_UNCHECKED)
445 goto complete;
446 offset = ref_offset(ref->node);
447 spin_unlock(&c->erase_completion_lock);
459 448
460 rc = jffs2_flash_read(c, ref_offset(ref->node), sizeof(rr), &readlen, (char *)&rr); 449 rc = jffs2_flash_read(c, offset, sizeof(rr), &readlen, (char *)&rr);
461 if (rc || sizeof(rr) != readlen) { 450 if (rc || sizeof(rr) != readlen) {
462 JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu, at %#08x\n", 451 JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu, at %#08x\n",
463 rc, sizeof(rr), readlen, ref_offset(ref->node)); 452 rc, sizeof(rr), readlen, offset);
464 return rc ? rc : -EIO; 453 return rc ? rc : -EIO;
465 } 454 }
466 /* obsolete node */ 455 /* obsolete node */
467 crc = crc32(0, &rr, sizeof(rr) - 4); 456 crc = crc32(0, &rr, sizeof(rr) - 4);
468 if (crc != je32_to_cpu(rr.node_crc)) { 457 if (crc != je32_to_cpu(rr.node_crc)) {
469 if (je32_to_cpu(rr.node_crc) != 0xffffffff) 458 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", 459 offset, je32_to_cpu(rr.node_crc), crc);
471 ref_offset(ref->node), je32_to_cpu(rr.node_crc), crc);
472 return EIO; 460 return EIO;
473 } 461 }
474 if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK 462 if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK
@@ -476,22 +464,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))) { 464 || je32_to_cpu(rr.totlen) != PAD(sizeof(rr))) {
477 JFFS2_ERROR("inconsistent xref at %#08x, magic=%#04x/%#04x, " 465 JFFS2_ERROR("inconsistent xref at %#08x, magic=%#04x/%#04x, "
478 "nodetype=%#04x/%#04x, totlen=%u/%zu\n", 466 "nodetype=%#04x/%#04x, totlen=%u/%zu\n",
479 ref_offset(ref->node), je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK, 467 offset, je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK,
480 je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF, 468 je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF,
481 je32_to_cpu(rr.totlen), PAD(sizeof(rr))); 469 je32_to_cpu(rr.totlen), PAD(sizeof(rr)));
482 return EIO; 470 return EIO;
483 } 471 }
484 ref->ino = je32_to_cpu(rr.ino); 472 ref->ino = je32_to_cpu(rr.ino);
485 ref->xid = je32_to_cpu(rr.xid); 473 ref->xid = je32_to_cpu(rr.xid);
486 474 ref->xseqno = je32_to_cpu(rr.xseqno);
487 /* fixup superblock/eraseblock info */ 475 if (ref->xseqno > c->highest_xseqno)
488 jeb = &c->blocks[ref_offset(ref->node) / c->sector_size]; 476 c->highest_xseqno = (ref->xseqno & ~XREF_DELETE_MARKER);
489 totlen = PAD(sizeof(rr));
490 477
491 spin_lock(&c->erase_completion_lock); 478 spin_lock(&c->erase_completion_lock);
492 c->unchecked_size -= totlen; c->used_size += totlen; 479 complete:
493 jeb->unchecked_size -= totlen; jeb->used_size += totlen; 480 for (raw=ref->node; raw != (void *)ref; raw=raw->next_in_ino) {
494 ref->node->flash_offset = ref_offset(ref->node) | REF_PRISTINE; 481 jeb = &c->blocks[ref_offset(raw) / c->sector_size];
482 totlen = PAD(ref_totlen(c, jeb, raw));
483 if (ref_flags(raw) == REF_UNCHECKED) {
484 c->unchecked_size -= totlen; c->used_size += totlen;
485 jeb->unchecked_size -= totlen; jeb->used_size += totlen;
486 }
487 raw->flash_offset = ref_offset(raw) | ((ref->node==raw) ? REF_PRISTINE : REF_NORMAL);
488 }
495 spin_unlock(&c->erase_completion_lock); 489 spin_unlock(&c->erase_completion_lock);
496 490
497 dbg_xattr("success on verifying xref (ino=%u, xid=%u) at %#08x\n", 491 dbg_xattr("success on verifying xref (ino=%u, xid=%u) at %#08x\n",
@@ -499,58 +493,12 @@ static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref
499 return 0; 493 return 0;
500} 494}
501 495
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) 496static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
548{ 497{
549 /* must be called under down_write(xattr_sem) */ 498 /* must be called under down_write(xattr_sem) */
550 struct jffs2_raw_node_ref *raw;
551 struct jffs2_raw_xref rr; 499 struct jffs2_raw_xref rr;
552 size_t length; 500 size_t length;
553 uint32_t phys_ofs = write_ofs(c); 501 uint32_t xseqno, phys_ofs = write_ofs(c);
554 int ret; 502 int ret;
555 503
556 rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 504 rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -558,8 +506,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))); 506 rr.totlen = cpu_to_je32(PAD(sizeof(rr)));
559 rr.hdr_crc = cpu_to_je32(crc32(0, &rr, sizeof(struct jffs2_unknown_node) - 4)); 507 rr.hdr_crc = cpu_to_je32(crc32(0, &rr, sizeof(struct jffs2_unknown_node) - 4));
560 508
561 rr.ino = cpu_to_je32(ref->ic->ino); 509 xseqno = (c->highest_xseqno += 2);
562 rr.xid = cpu_to_je32(ref->xd->xid); 510 if (is_xattr_ref_dead(ref)) {
511 xseqno |= XREF_DELETE_MARKER;
512 rr.ino = cpu_to_je32(ref->ino);
513 rr.xid = cpu_to_je32(ref->xid);
514 } else {
515 rr.ino = cpu_to_je32(ref->ic->ino);
516 rr.xid = cpu_to_je32(ref->xd->xid);
517 }
518 rr.xseqno = cpu_to_je32(xseqno);
563 rr.node_crc = cpu_to_je32(crc32(0, &rr, sizeof(rr) - 4)); 519 rr.node_crc = cpu_to_je32(crc32(0, &rr, sizeof(rr) - 4));
564 520
565 ret = jffs2_flash_write(c, phys_ofs, sizeof(rr), &length, (char *)&rr); 521 ret = jffs2_flash_write(c, phys_ofs, sizeof(rr), &length, (char *)&rr);
@@ -572,12 +528,9 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
572 528
573 return ret; 529 return ret;
574 } 530 }
575 531 /* success */
576 raw = jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(sizeof(rr)), NULL); 532 ref->xseqno = xseqno;
577 /* FIXME */ raw->next_in_ino = (void *)ref; 533 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 534
582 dbg_xattr("success on saving xref (ino=%u, xid=%u)\n", ref->ic->ino, ref->xd->xid); 535 dbg_xattr("success on saving xref (ino=%u, xid=%u)\n", ref->ic->ino, ref->xd->xid);
583 536
@@ -610,6 +563,27 @@ static struct jffs2_xattr_ref *create_xattr_ref(struct jffs2_sb_info *c, struct
610 return ref; /* success */ 563 return ref; /* success */
611} 564}
612 565
566static void delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
567{
568 /* must be called under down_write(xattr_sem) */
569 struct jffs2_xattr_datum *xd;
570
571 xd = ref->xd;
572 ref->xseqno |= XREF_DELETE_MARKER;
573 ref->ino = ref->ic->ino;
574 ref->xid = ref->xd->xid;
575 spin_lock(&c->erase_completion_lock);
576 ref->next = c->xref_dead_list;
577 c->xref_dead_list = ref;
578 spin_unlock(&c->erase_completion_lock);
579
580 dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) was removed.\n",
581 ref->ino, ref->xid, ref->xseqno);
582
583 if (atomic_dec_and_test(&xd->refcnt))
584 delete_xattr_datum(c, xd);
585}
586
613void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) 587void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
614{ 588{
615 /* It's called from jffs2_clear_inode() on inode removing. 589 /* It's called from jffs2_clear_inode() on inode removing.
@@ -638,8 +612,7 @@ void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *i
638 for (ref = ic->xref; ref; ref = _ref) { 612 for (ref = ic->xref; ref; ref = _ref) {
639 _ref = ref->next; 613 _ref = ref->next;
640 xd = ref->xd; 614 xd = ref->xd;
641 xd->refcnt--; 615 if (atomic_dec_and_test(&xd->refcnt)) {
642 if (!xd->refcnt) {
643 unload_xattr_datum(c, xd); 616 unload_xattr_datum(c, xd);
644 jffs2_free_xattr_datum(xd); 617 jffs2_free_xattr_datum(xd);
645 } 618 }
@@ -655,7 +628,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, 628 * duplicate name/value pairs. If duplicate name/value pair would be found,
656 * one will be removed. 629 * one will be removed.
657 */ 630 */
658 struct jffs2_xattr_ref *ref, *cmp, **pref; 631 struct jffs2_xattr_ref *ref, *cmp, **pref, **pcmp;
659 int rc = 0; 632 int rc = 0;
660 633
661 if (likely(ic->flags & INO_FLAGS_XATTR_CHECKED)) 634 if (likely(ic->flags & INO_FLAGS_XATTR_CHECKED))
@@ -673,13 +646,13 @@ static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cac
673 } else if (unlikely(rc < 0)) 646 } else if (unlikely(rc < 0))
674 goto out; 647 goto out;
675 } 648 }
676 for (cmp=ref->next, pref=&ref->next; cmp; pref=&cmp->next, cmp=cmp->next) { 649 for (cmp=ref->next, pcmp=&ref->next; cmp; pcmp=&cmp->next, cmp=cmp->next) {
677 if (!cmp->xd->xname) { 650 if (!cmp->xd->xname) {
678 ref->xd->flags |= JFFS2_XFLAGS_BIND; 651 ref->xd->flags |= JFFS2_XFLAGS_BIND;
679 rc = load_xattr_datum(c, cmp->xd); 652 rc = load_xattr_datum(c, cmp->xd);
680 ref->xd->flags &= ~JFFS2_XFLAGS_BIND; 653 ref->xd->flags &= ~JFFS2_XFLAGS_BIND;
681 if (unlikely(rc > 0)) { 654 if (unlikely(rc > 0)) {
682 *pref = cmp->next; 655 *pcmp = cmp->next;
683 delete_xattr_ref(c, cmp); 656 delete_xattr_ref(c, cmp);
684 goto retry; 657 goto retry;
685 } else if (unlikely(rc < 0)) 658 } else if (unlikely(rc < 0))
@@ -687,8 +660,13 @@ static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cac
687 } 660 }
688 if (ref->xd->xprefix == cmp->xd->xprefix 661 if (ref->xd->xprefix == cmp->xd->xprefix
689 && !strcmp(ref->xd->xname, cmp->xd->xname)) { 662 && !strcmp(ref->xd->xname, cmp->xd->xname)) {
690 *pref = cmp->next; 663 if (ref->xseqno > cmp->xseqno) {
691 delete_xattr_ref(c, cmp); 664 *pcmp = cmp->next;
665 delete_xattr_ref(c, cmp);
666 } else {
667 *pref = ref->next;
668 delete_xattr_ref(c, ref);
669 }
692 goto retry; 670 goto retry;
693 } 671 }
694 } 672 }
@@ -719,9 +697,13 @@ void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c)
719 for (i=0; i < XATTRINDEX_HASHSIZE; i++) 697 for (i=0; i < XATTRINDEX_HASHSIZE; i++)
720 INIT_LIST_HEAD(&c->xattrindex[i]); 698 INIT_LIST_HEAD(&c->xattrindex[i]);
721 INIT_LIST_HEAD(&c->xattr_unchecked); 699 INIT_LIST_HEAD(&c->xattr_unchecked);
700 INIT_LIST_HEAD(&c->xattr_dead_list);
701 c->xref_dead_list = NULL;
722 c->xref_temp = NULL; 702 c->xref_temp = NULL;
723 703
724 init_rwsem(&c->xattr_sem); 704 init_rwsem(&c->xattr_sem);
705 c->highest_xid = 0;
706 c->highest_xseqno = 0;
725 c->xdatum_mem_usage = 0; 707 c->xdatum_mem_usage = 0;
726 c->xdatum_mem_threshold = 32 * 1024; /* Default 32KB */ 708 c->xdatum_mem_threshold = 32 * 1024; /* Default 32KB */
727} 709}
@@ -751,7 +733,11 @@ void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c)
751 _ref = ref->next; 733 _ref = ref->next;
752 jffs2_free_xattr_ref(ref); 734 jffs2_free_xattr_ref(ref);
753 } 735 }
754 c->xref_temp = NULL; 736
737 for (ref=c->xref_dead_list; ref; ref = _ref) {
738 _ref = ref->next;
739 jffs2_free_xattr_ref(ref);
740 }
755 741
756 for (i=0; i < XATTRINDEX_HASHSIZE; i++) { 742 for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
757 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) { 743 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
@@ -761,100 +747,143 @@ void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c)
761 jffs2_free_xattr_datum(xd); 747 jffs2_free_xattr_datum(xd);
762 } 748 }
763 } 749 }
750
751 list_for_each_entry_safe(xd, _xd, &c->xattr_dead_list, xindex) {
752 list_del(&xd->xindex);
753 jffs2_free_xattr_datum(xd);
754 }
764} 755}
765 756
757#define XREF_TMPHASH_SIZE (128)
766void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c) 758void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
767{ 759{
768 struct jffs2_xattr_ref *ref, *_ref; 760 struct jffs2_xattr_ref *ref, *_ref;
761 struct jffs2_xattr_ref *xref_tmphash[XREF_TMPHASH_SIZE];
769 struct jffs2_xattr_datum *xd, *_xd; 762 struct jffs2_xattr_datum *xd, *_xd;
770 struct jffs2_inode_cache *ic; 763 struct jffs2_inode_cache *ic;
771 int i, xdatum_count =0, xdatum_unchecked_count = 0, xref_count = 0; 764 struct jffs2_raw_node_ref *raw;
765 int i, xdatum_count = 0, xdatum_unchecked_count = 0, xref_count = 0;
766 int xdatum_orphan_count = 0, xref_orphan_count = 0, xref_dead_count = 0;
772 767
773 BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING)); 768 BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING));
774 769
775 /* Phase.1 */ 770 /* Phase.1 : Merge same xref */
771 for (i=0; i < XREF_TMPHASH_SIZE; i++)
772 xref_tmphash[i] = NULL;
776 for (ref=c->xref_temp; ref; ref=_ref) { 773 for (ref=c->xref_temp; ref; ref=_ref) {
774 struct jffs2_xattr_ref *tmp;
775
777 _ref = ref->next; 776 _ref = ref->next;
778 /* checking REF_UNCHECKED nodes */
779 if (ref_flags(ref->node) != REF_PRISTINE) { 777 if (ref_flags(ref->node) != REF_PRISTINE) {
780 if (verify_xattr_ref(c, ref)) { 778 if (verify_xattr_ref(c, ref)) {
781 delete_xattr_ref_node(c, ref); 779 BUG_ON(ref->node->next_in_ino != (void *)ref);
780 ref->node->next_in_ino = NULL;
781 jffs2_mark_node_obsolete(c, ref->node);
782 jffs2_free_xattr_ref(ref); 782 jffs2_free_xattr_ref(ref);
783 continue; 783 continue;
784 } 784 }
785 } 785 }
786 /* At this point, ref->xid and ref->ino contain XID and inode number. 786
787 ref->xd and ref->ic are not valid yet. */ 787 i = (ref->ino ^ ref->xid) % XREF_TMPHASH_SIZE;
788 xd = jffs2_find_xattr_datum(c, ref->xid); 788 for (tmp=xref_tmphash[i]; tmp; tmp=tmp->next) {
789 ic = jffs2_get_ino_cache(c, ref->ino); 789 if (tmp->ino == ref->ino && tmp->xid == ref->xid)
790 if (!xd || !ic) { 790 break;
791 if (ref_flags(ref->node) != REF_UNCHECKED) 791 }
792 JFFS2_WARNING("xref(ino=%u, xid=%u) is orphan. \n", 792 if (tmp) {
793 ref->ino, ref->xid); 793 raw = ref->node;
794 delete_xattr_ref_node(c, ref); 794 if (ref->xseqno > tmp->xseqno) {
795 tmp->xseqno = ref->xseqno;
796 raw->next_in_ino = tmp->node;
797 tmp->node = raw;
798 } else {
799 raw->next_in_ino = tmp->node->next_in_ino;
800 tmp->node->next_in_ino = raw;
801 }
795 jffs2_free_xattr_ref(ref); 802 jffs2_free_xattr_ref(ref);
796 continue; 803 continue;
804 } else {
805 ref->next = xref_tmphash[i];
806 xref_tmphash[i] = ref;
797 } 807 }
798 ref->xd = xd;
799 ref->ic = ic;
800 xd->refcnt++;
801 ref->next = ic->xref;
802 ic->xref = ref;
803 xref_count++;
804 } 808 }
805 c->xref_temp = NULL; 809 c->xref_temp = NULL;
806 /* After this, ref->xid/ino are NEVER used. */
807 810
808 /* Phase.2 */ 811 /* Phase.2 : Bind xref with inode_cache and xattr_datum */
812 for (i=0; i < XREF_TMPHASH_SIZE; i++) {
813 for (ref=xref_tmphash[i]; ref; ref=_ref) {
814 xref_count++;
815 _ref = ref->next;
816 if (is_xattr_ref_dead(ref)) {
817 ref->next = c->xref_dead_list;
818 c->xref_dead_list = ref;
819 xref_dead_count++;
820 continue;
821 }
822 /* At this point, ref->xid and ref->ino contain XID and inode number.
823 ref->xd and ref->ic are not valid yet. */
824 xd = jffs2_find_xattr_datum(c, ref->xid);
825 ic = jffs2_get_ino_cache(c, ref->ino);
826 if (!xd || !ic) {
827 dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) is orphan.\n",
828 ref->ino, ref->xid, ref->xseqno);
829 ref->xseqno |= XREF_DELETE_MARKER;
830 ref->next = c->xref_dead_list;
831 c->xref_dead_list = ref;
832 xref_orphan_count++;
833 continue;
834 }
835 ref->xd = xd;
836 ref->ic = ic;
837 atomic_inc(&xd->refcnt);
838 ref->next = ic->xref;
839 ic->xref = ref;
840 }
841 }
842
843 /* Phase.3 : Link unchecked xdatum to xattr_unchecked list */
809 for (i=0; i < XATTRINDEX_HASHSIZE; i++) { 844 for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
810 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) { 845 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
846 xdatum_count++;
811 list_del_init(&xd->xindex); 847 list_del_init(&xd->xindex);
812 if (!xd->refcnt) { 848 if (!atomic_read(&xd->refcnt)) {
813 if (ref_flags(xd->node) != REF_UNCHECKED) 849 dbg_xattr("xdatum(xid=%u, version=%u) is orphan.\n",
814 JFFS2_WARNING("orphan xdatum(xid=%u, version=%u) at %#08x\n", 850 xd->xid, xd->version);
815 xd->xid, xd->version, ref_offset(xd->node)); 851 xd->flags |= JFFS2_XFLAGS_DEAD;
816 delete_xattr_datum(c, xd); 852 list_add(&xd->xindex, &c->xattr_unchecked);
853 xdatum_orphan_count++;
817 continue; 854 continue;
818 } 855 }
819 if (ref_flags(xd->node) != REF_PRISTINE) { 856 if (is_xattr_datum_unchecked(c, xd)) {
820 dbg_xattr("unchecked xdatum(xid=%u) at %#08x\n", 857 dbg_xattr("unchecked xdatum(xid=%u, version=%u)\n",
821 xd->xid, ref_offset(xd->node)); 858 xd->xid, xd->version);
822 list_add(&xd->xindex, &c->xattr_unchecked); 859 list_add(&xd->xindex, &c->xattr_unchecked);
823 xdatum_unchecked_count++; 860 xdatum_unchecked_count++;
824 } 861 }
825 xdatum_count++;
826 } 862 }
827 } 863 }
828 /* build complete */ 864 /* build complete */
829 JFFS2_NOTICE("complete building xattr subsystem, %u of xdatum (%u unchecked) and " 865 JFFS2_NOTICE("complete building xattr subsystem, %u of xdatum"
830 "%u of xref found.\n", xdatum_count, xdatum_unchecked_count, xref_count); 866 " (%u unchecked, %u orphan) and "
867 "%u of xref (%u dead, %u orphan) found.\n",
868 xdatum_count, xdatum_unchecked_count, xdatum_orphan_count,
869 xref_count, xref_dead_count, xref_orphan_count);
831} 870}
832 871
833struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c, 872struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
834 uint32_t xid, uint32_t version) 873 uint32_t xid, uint32_t version)
835{ 874{
836 struct jffs2_xattr_datum *xd, *_xd; 875 struct jffs2_xattr_datum *xd;
837 876
838 _xd = jffs2_find_xattr_datum(c, xid); 877 xd = jffs2_find_xattr_datum(c, xid);
839 if (_xd) { 878 if (!xd) {
840 dbg_xattr("duplicate xdatum (xid=%u, version=%u/%u) at %#08x\n", 879 xd = jffs2_alloc_xattr_datum();
841 xid, version, _xd->version, ref_offset(_xd->node)); 880 if (!xd)
842 if (version < _xd->version) 881 return ERR_PTR(-ENOMEM);
843 return ERR_PTR(-EEXIST); 882 xd->xid = xid;
844 } 883 xd->version = version;
845 xd = jffs2_alloc_xattr_datum(); 884 if (xd->xid > c->highest_xid)
846 if (!xd) 885 c->highest_xid = xd->xid;
847 return ERR_PTR(-ENOMEM); 886 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 } 887 }
859 return xd; 888 return xd;
860} 889}
@@ -1080,9 +1109,23 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1080 goto out; 1109 goto out;
1081 } 1110 }
1082 if (!buffer) { 1111 if (!buffer) {
1083 *pref = ref->next; 1112 ref->ino = ic->ino;
1084 delete_xattr_ref(c, ref); 1113 ref->xid = xd->xid;
1085 rc = 0; 1114 ref->xseqno |= XREF_DELETE_MARKER;
1115 rc = save_xattr_ref(c, ref);
1116 if (!rc) {
1117 *pref = ref->next;
1118 spin_lock(&c->erase_completion_lock);
1119 ref->next = c->xref_dead_list;
1120 c->xref_dead_list = ref;
1121 spin_unlock(&c->erase_completion_lock);
1122 if (atomic_dec_and_test(&xd->refcnt))
1123 delete_xattr_datum(c, xd);
1124 } else {
1125 ref->ic = ic;
1126 ref->xd = xd;
1127 ref->xseqno &= ~XREF_DELETE_MARKER;
1128 }
1086 goto out; 1129 goto out;
1087 } 1130 }
1088 goto found; 1131 goto found;
@@ -1094,7 +1137,7 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1094 goto out; 1137 goto out;
1095 } 1138 }
1096 if (!buffer) { 1139 if (!buffer) {
1097 rc = -EINVAL; 1140 rc = -ENODATA;
1098 goto out; 1141 goto out;
1099 } 1142 }
1100 found: 1143 found:
@@ -1110,16 +1153,14 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1110 request = PAD(sizeof(struct jffs2_raw_xref)); 1153 request = PAD(sizeof(struct jffs2_raw_xref));
1111 rc = jffs2_reserve_space(c, request, &length, 1154 rc = jffs2_reserve_space(c, request, &length,
1112 ALLOC_NORMAL, JFFS2_SUMMARY_XREF_SIZE); 1155 ALLOC_NORMAL, JFFS2_SUMMARY_XREF_SIZE);
1156 down_write(&c->xattr_sem);
1113 if (rc) { 1157 if (rc) {
1114 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request); 1158 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request);
1115 down_write(&c->xattr_sem); 1159 if (atomic_dec_and_test(&xd->refcnt))
1116 xd->refcnt--;
1117 if (!xd->refcnt)
1118 delete_xattr_datum(c, xd); 1160 delete_xattr_datum(c, xd);
1119 up_write(&c->xattr_sem); 1161 up_write(&c->xattr_sem);
1120 return rc; 1162 return rc;
1121 } 1163 }
1122 down_write(&c->xattr_sem);
1123 if (ref) 1164 if (ref)
1124 *pref = ref->next; 1165 *pref = ref->next;
1125 newref = create_xattr_ref(c, ic, xd); 1166 newref = create_xattr_ref(c, ic, xd);
@@ -1129,8 +1170,7 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1129 ic->xref = ref; 1170 ic->xref = ref;
1130 } 1171 }
1131 rc = PTR_ERR(newref); 1172 rc = PTR_ERR(newref);
1132 xd->refcnt--; 1173 if (atomic_dec_and_test(&xd->refcnt))
1133 if (!xd->refcnt)
1134 delete_xattr_datum(c, xd); 1174 delete_xattr_datum(c, xd);
1135 } else if (ref) { 1175 } else if (ref) {
1136 delete_xattr_ref(c, ref); 1176 delete_xattr_ref(c, ref);
@@ -1142,38 +1182,40 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1142} 1182}
1143 1183
1144/* -------- garbage collector functions ------------- 1184/* -------- garbage collector functions -------------
1145 * jffs2_garbage_collect_xattr_datum(c, xd) 1185 * jffs2_garbage_collect_xattr_datum(c, xd, raw)
1146 * is used to move xdatum into new node. 1186 * is used to move xdatum into new node.
1147 * jffs2_garbage_collect_xattr_ref(c, ref) 1187 * jffs2_garbage_collect_xattr_ref(c, ref, raw)
1148 * is used to move xref into new node. 1188 * is used to move xref into new node.
1149 * jffs2_verify_xattr(c) 1189 * jffs2_verify_xattr(c)
1150 * is used to call do_verify_xattr_datum() before garbage collecting. 1190 * is used to call do_verify_xattr_datum() before garbage collecting.
1191 * jffs2_release_xattr_datum(c, xd)
1192 * is used to release an in-memory object of xdatum.
1193 * jffs2_release_xattr_ref(c, ref)
1194 * is used to release an in-memory object of xref.
1151 * -------------------------------------------------- */ 1195 * -------------------------------------------------- */
1152int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) 1196int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd,
1197 struct jffs2_raw_node_ref *raw)
1153{ 1198{
1154 uint32_t totlen, length, old_ofs; 1199 uint32_t totlen, length, old_ofs;
1155 int rc = -EINVAL; 1200 int rc = 0;
1156 1201
1157 down_write(&c->xattr_sem); 1202 down_write(&c->xattr_sem);
1158 BUG_ON(!xd->node); 1203 if (xd->node != raw)
1159 1204 goto out;
1160 old_ofs = ref_offset(xd->node); 1205 if (xd->flags & (JFFS2_XFLAGS_DEAD|JFFS2_XFLAGS_INVALID))
1161 totlen = ref_totlen(c, c->gcblock, xd->node);
1162 if (totlen < sizeof(struct jffs2_raw_xattr))
1163 goto out; 1206 goto out;
1164 1207
1165 if (!xd->xname) { 1208 rc = load_xattr_datum(c, xd);
1166 rc = load_xattr_datum(c, xd); 1209 if (unlikely(rc)) {
1167 if (unlikely(rc > 0)) { 1210 rc = (rc > 0) ? 0 : rc;
1168 delete_xattr_datum_node(c, xd); 1211 goto out;
1169 rc = 0;
1170 goto out;
1171 } else if (unlikely(rc < 0))
1172 goto out;
1173 } 1212 }
1213 old_ofs = ref_offset(xd->node);
1214 totlen = PAD(sizeof(struct jffs2_raw_xattr)
1215 + xd->name_len + 1 + xd->value_len);
1174 rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE); 1216 rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE);
1175 if (rc || length < totlen) { 1217 if (rc) {
1176 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, totlen); 1218 JFFS2_WARNING("jffs2_reserve_space_gc()=%d, request=%u\n", rc, totlen);
1177 rc = rc ? rc : -EBADFD; 1219 rc = rc ? rc : -EBADFD;
1178 goto out; 1220 goto out;
1179 } 1221 }
@@ -1182,27 +1224,32 @@ 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", 1224 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)); 1225 xd->xid, xd->version, old_ofs, ref_offset(xd->node));
1184 out: 1226 out:
1227 if (!rc)
1228 jffs2_mark_node_obsolete(c, raw);
1185 up_write(&c->xattr_sem); 1229 up_write(&c->xattr_sem);
1186 return rc; 1230 return rc;
1187} 1231}
1188 1232
1189 1233int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref,
1190int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) 1234 struct jffs2_raw_node_ref *raw)
1191{ 1235{
1192 uint32_t totlen, length, old_ofs; 1236 uint32_t totlen, length, old_ofs;
1193 int rc = -EINVAL; 1237 int rc = 0;
1194 1238
1195 down_write(&c->xattr_sem); 1239 down_write(&c->xattr_sem);
1196 BUG_ON(!ref->node); 1240 BUG_ON(!ref->node);
1197 1241
1242 if (ref->node != raw)
1243 goto out;
1244 if (is_xattr_ref_dead(ref) && (raw->next_in_ino == (void *)ref))
1245 goto out;
1246
1198 old_ofs = ref_offset(ref->node); 1247 old_ofs = ref_offset(ref->node);
1199 totlen = ref_totlen(c, c->gcblock, ref->node); 1248 totlen = ref_totlen(c, c->gcblock, ref->node);
1200 if (totlen != sizeof(struct jffs2_raw_xref))
1201 goto out;
1202 1249
1203 rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XREF_SIZE); 1250 rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XREF_SIZE);
1204 if (rc || length < totlen) { 1251 if (rc) {
1205 JFFS2_WARNING("%s: jffs2_reserve_space() = %d, request = %u\n", 1252 JFFS2_WARNING("%s: jffs2_reserve_space_gc() = %d, request = %u\n",
1206 __FUNCTION__, rc, totlen); 1253 __FUNCTION__, rc, totlen);
1207 rc = rc ? rc : -EBADFD; 1254 rc = rc ? rc : -EBADFD;
1208 goto out; 1255 goto out;
@@ -1212,6 +1259,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", 1259 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)); 1260 ref->ic->ino, ref->xd->xid, old_ofs, ref_offset(ref->node));
1214 out: 1261 out:
1262 if (!rc)
1263 jffs2_mark_node_obsolete(c, raw);
1215 up_write(&c->xattr_sem); 1264 up_write(&c->xattr_sem);
1216 return rc; 1265 return rc;
1217} 1266}
@@ -1219,20 +1268,59 @@ int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_
1219int jffs2_verify_xattr(struct jffs2_sb_info *c) 1268int jffs2_verify_xattr(struct jffs2_sb_info *c)
1220{ 1269{
1221 struct jffs2_xattr_datum *xd, *_xd; 1270 struct jffs2_xattr_datum *xd, *_xd;
1271 struct jffs2_eraseblock *jeb;
1272 struct jffs2_raw_node_ref *raw;
1273 uint32_t totlen;
1222 int rc; 1274 int rc;
1223 1275
1224 down_write(&c->xattr_sem); 1276 down_write(&c->xattr_sem);
1225 list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) { 1277 list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) {
1226 rc = do_verify_xattr_datum(c, xd); 1278 rc = do_verify_xattr_datum(c, xd);
1227 if (rc == 0) { 1279 if (rc < 0)
1228 list_del_init(&xd->xindex); 1280 continue;
1229 break; 1281 list_del_init(&xd->xindex);
1230 } else if (rc > 0) { 1282 spin_lock(&c->erase_completion_lock);
1231 list_del_init(&xd->xindex); 1283 for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) {
1232 delete_xattr_datum_node(c, xd); 1284 if (ref_flags(raw) != REF_UNCHECKED)
1285 continue;
1286 jeb = &c->blocks[ref_offset(raw) / c->sector_size];
1287 totlen = PAD(ref_totlen(c, jeb, raw));
1288 c->unchecked_size -= totlen; c->used_size += totlen;
1289 jeb->unchecked_size -= totlen; jeb->used_size += totlen;
1290 raw->flash_offset = ref_offset(raw)
1291 | ((xd->node == (void *)raw) ? REF_PRISTINE : REF_NORMAL);
1233 } 1292 }
1293 if (xd->flags & JFFS2_XFLAGS_DEAD)
1294 list_add(&xd->xindex, &c->xattr_dead_list);
1295 spin_unlock(&c->erase_completion_lock);
1234 } 1296 }
1235 up_write(&c->xattr_sem); 1297 up_write(&c->xattr_sem);
1236
1237 return list_empty(&c->xattr_unchecked) ? 1 : 0; 1298 return list_empty(&c->xattr_unchecked) ? 1 : 0;
1238} 1299}
1300
1301void jffs2_release_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
1302{
1303 /* must be called under spin_lock(&c->erase_completion_lock) */
1304 if (atomic_read(&xd->refcnt) || xd->node != (void *)xd)
1305 return;
1306
1307 list_del(&xd->xindex);
1308 jffs2_free_xattr_datum(xd);
1309}
1310
1311void jffs2_release_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
1312{
1313 /* must be called under spin_lock(&c->erase_completion_lock) */
1314 struct jffs2_xattr_ref *tmp, **ptmp;
1315
1316 if (ref->node != (void *)ref)
1317 return;
1318
1319 for (tmp=c->xref_dead_list, ptmp=&c->xref_dead_list; tmp; ptmp=&tmp->next, tmp=tmp->next) {
1320 if (ref == tmp) {
1321 *ptmp = tmp->next;
1322 break;
1323 }
1324 }
1325 jffs2_free_xattr_ref(ref);
1326}
diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h
index 2c199856c582..06a5c69dcf8b 100644
--- a/fs/jffs2/xattr.h
+++ b/fs/jffs2/xattr.h
@@ -16,6 +16,8 @@
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_DEAD (0x40) /* This datum is already dead */
20#define JFFS2_XFLAGS_INVALID (0x80) /* This datum contains crc error */
19 21
20struct jffs2_xattr_datum 22struct jffs2_xattr_datum
21{ 23{
@@ -23,10 +25,10 @@ struct jffs2_xattr_datum
23 struct jffs2_raw_node_ref *node; 25 struct jffs2_raw_node_ref *node;
24 uint8_t class; 26 uint8_t class;
25 uint8_t flags; 27 uint8_t flags;
26 uint16_t xprefix; /* see JFFS2_XATTR_PREFIX_* */ 28 uint16_t xprefix; /* see JFFS2_XATTR_PREFIX_* */
27 29
28 struct list_head xindex; /* chained from c->xattrindex[n] */ 30 struct list_head xindex; /* chained from c->xattrindex[n] */
29 uint32_t refcnt; /* # of xattr_ref refers this */ 31 atomic_t refcnt; /* # of xattr_ref refers this */
30 uint32_t xid; 32 uint32_t xid;
31 uint32_t version; 33 uint32_t version;
32 34
@@ -47,6 +49,7 @@ struct jffs2_xattr_ref
47 uint8_t flags; /* Currently unused */ 49 uint8_t flags; /* Currently unused */
48 u16 unused; 50 u16 unused;
49 51
52 uint32_t xseqno;
50 union { 53 union {
51 struct jffs2_inode_cache *ic; /* reference to jffs2_inode_cache */ 54 struct jffs2_inode_cache *ic; /* reference to jffs2_inode_cache */
52 uint32_t ino; /* only used in scanning/building */ 55 uint32_t ino; /* only used in scanning/building */
@@ -58,6 +61,12 @@ struct jffs2_xattr_ref
58 struct jffs2_xattr_ref *next; /* chained from ic->xref_list */ 61 struct jffs2_xattr_ref *next; /* chained from ic->xref_list */
59}; 62};
60 63
64#define XREF_DELETE_MARKER (0x00000001)
65static inline int is_xattr_ref_dead(struct jffs2_xattr_ref *ref)
66{
67 return ((ref->xseqno & XREF_DELETE_MARKER) != 0);
68}
69
61#ifdef CONFIG_JFFS2_FS_XATTR 70#ifdef CONFIG_JFFS2_FS_XATTR
62 71
63extern void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c); 72extern void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c);
@@ -70,9 +79,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); 79extern 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); 80extern void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
72 81
73extern int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd); 82extern 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); 83 struct jffs2_raw_node_ref *raw);
84extern int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref,
85 struct jffs2_raw_node_ref *raw);
75extern int jffs2_verify_xattr(struct jffs2_sb_info *c); 86extern int jffs2_verify_xattr(struct jffs2_sb_info *c);
87extern void jffs2_release_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd);
88extern void jffs2_release_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref);
76 89
77extern int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname, 90extern int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname,
78 char *buffer, size_t size); 91 char *buffer, size_t size);