1
2
3
4
5
6
7
8
9
10
11
12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13
14#define JFFS2_XATTR_IS_CORRUPTED 1
15
16#include <linux/kernel.h>
17#include <linux/slab.h>
18#include <linux/fs.h>
19#include <linux/time.h>
20#include <linux/pagemap.h>
21#include <linux/highmem.h>
22#include <linux/crc32.h>
23#include <linux/jffs2.h>
24#include <linux/xattr.h>
25#include <linux/mtd/mtd.h>
26#include "nodelist.h"
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *xvalue, int xsize)
64{
65 int name_len = strlen(xname);
66
67 return crc32(xprefix, xname, name_len) ^ crc32(xprefix, xvalue, xsize);
68}
69
70static int is_xattr_datum_unchecked(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
71{
72 struct jffs2_raw_node_ref *raw;
73 int rc = 0;
74
75 spin_lock(&c->erase_completion_lock);
76 for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) {
77 if (ref_flags(raw) == REF_UNCHECKED) {
78 rc = 1;
79 break;
80 }
81 }
82 spin_unlock(&c->erase_completion_lock);
83 return rc;
84}
85
86static void unload_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
87{
88
89 D1(dbg_xattr("%s: xid=%u, version=%u\n", __func__, xd->xid, xd->version));
90 if (xd->xname) {
91 c->xdatum_mem_usage -= (xd->name_len + 1 + xd->value_len);
92 kfree(xd->xname);
93 }
94
95 list_del_init(&xd->xindex);
96 xd->hashkey = 0;
97 xd->xname = NULL;
98 xd->xvalue = NULL;
99}
100
101static void reclaim_xattr_datum(struct jffs2_sb_info *c)
102{
103
104 struct jffs2_xattr_datum *xd, *_xd;
105 uint32_t target, before;
106 static int index = 0;
107 int count;
108
109 if (c->xdatum_mem_threshold > c->xdatum_mem_usage)
110 return;
111
112 before = c->xdatum_mem_usage;
113 target = c->xdatum_mem_usage * 4 / 5;
114 for (count = 0; count < XATTRINDEX_HASHSIZE; count++) {
115 list_for_each_entry_safe(xd, _xd, &c->xattrindex[index], xindex) {
116 if (xd->flags & JFFS2_XFLAGS_HOT) {
117 xd->flags &= ~JFFS2_XFLAGS_HOT;
118 } else if (!(xd->flags & JFFS2_XFLAGS_BIND)) {
119 unload_xattr_datum(c, xd);
120 }
121 if (c->xdatum_mem_usage <= target)
122 goto out;
123 }
124 index = (index+1) % XATTRINDEX_HASHSIZE;
125 }
126 out:
127 JFFS2_NOTICE("xdatum_mem_usage from %u byte to %u byte (%u byte reclaimed)\n",
128 before, c->xdatum_mem_usage, before - c->xdatum_mem_usage);
129}
130
131static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
132{
133
134 struct jffs2_eraseblock *jeb;
135 struct jffs2_raw_node_ref *raw;
136 struct jffs2_raw_xattr rx;
137 size_t readlen;
138 uint32_t crc, offset, totlen;
139 int rc;
140
141 spin_lock(&c->erase_completion_lock);
142 offset = ref_offset(xd->node);
143 if (ref_flags(xd->node) == REF_PRISTINE)
144 goto complete;
145 spin_unlock(&c->erase_completion_lock);
146
147 rc = jffs2_flash_read(c, offset, sizeof(rx), &readlen, (char *)&rx);
148 if (rc || readlen != sizeof(rx)) {
149 JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n",
150 rc, sizeof(rx), readlen, offset);
151 return rc ? rc : -EIO;
152 }
153 crc = crc32(0, &rx, sizeof(rx) - 4);
154 if (crc != je32_to_cpu(rx.node_crc)) {
155 JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
156 offset, je32_to_cpu(rx.hdr_crc), crc);
157 xd->flags |= JFFS2_XFLAGS_INVALID;
158 return JFFS2_XATTR_IS_CORRUPTED;
159 }
160 totlen = PAD(sizeof(rx) + rx.name_len + 1 + je16_to_cpu(rx.value_len));
161 if (je16_to_cpu(rx.magic) != JFFS2_MAGIC_BITMASK
162 || je16_to_cpu(rx.nodetype) != JFFS2_NODETYPE_XATTR
163 || je32_to_cpu(rx.totlen) != totlen
164 || je32_to_cpu(rx.xid) != xd->xid
165 || je32_to_cpu(rx.version) != xd->version) {
166 JFFS2_ERROR("inconsistent xdatum at %#08x, magic=%#04x/%#04x, "
167 "nodetype=%#04x/%#04x, totlen=%u/%u, xid=%u/%u, version=%u/%u\n",
168 offset, je16_to_cpu(rx.magic), JFFS2_MAGIC_BITMASK,
169 je16_to_cpu(rx.nodetype), JFFS2_NODETYPE_XATTR,
170 je32_to_cpu(rx.totlen), totlen,
171 je32_to_cpu(rx.xid), xd->xid,
172 je32_to_cpu(rx.version), xd->version);
173 xd->flags |= JFFS2_XFLAGS_INVALID;
174 return JFFS2_XATTR_IS_CORRUPTED;
175 }
176 xd->xprefix = rx.xprefix;
177 xd->name_len = rx.name_len;
178 xd->value_len = je16_to_cpu(rx.value_len);
179 xd->data_crc = je32_to_cpu(rx.data_crc);
180
181 spin_lock(&c->erase_completion_lock);
182 complete:
183 for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) {
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 }
192 spin_unlock(&c->erase_completion_lock);
193
194
195 list_del_init(&xd->xindex);
196
197 dbg_xattr("success on verfying xdatum (xid=%u, version=%u)\n",
198 xd->xid, xd->version);
199
200 return 0;
201}
202
203static int do_load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
204{
205
206 char *data;
207 size_t readlen;
208 uint32_t crc, length;
209 int i, ret, retry = 0;
210
211 BUG_ON(ref_flags(xd->node) != REF_PRISTINE);
212 BUG_ON(!list_empty(&xd->xindex));
213 retry:
214 length = xd->name_len + 1 + xd->value_len;
215 data = kmalloc(length, GFP_KERNEL);
216 if (!data)
217 return -ENOMEM;
218
219 ret = jffs2_flash_read(c, ref_offset(xd->node)+sizeof(struct jffs2_raw_xattr),
220 length, &readlen, data);
221
222 if (ret || length!=readlen) {
223 JFFS2_WARNING("jffs2_flash_read() returned %d, request=%d, readlen=%zu, at %#08x\n",
224 ret, length, readlen, ref_offset(xd->node));
225 kfree(data);
226 return ret ? ret : -EIO;
227 }
228
229 data[xd->name_len] = '\0';
230 crc = crc32(0, data, length);
231 if (crc != xd->data_crc) {
232 JFFS2_WARNING("node CRC failed (JFFS2_NODETYPE_XATTR)"
233 " at %#08x, read: 0x%08x calculated: 0x%08x\n",
234 ref_offset(xd->node), xd->data_crc, crc);
235 kfree(data);
236 xd->flags |= JFFS2_XFLAGS_INVALID;
237 return JFFS2_XATTR_IS_CORRUPTED;
238 }
239
240 xd->flags |= JFFS2_XFLAGS_HOT;
241 xd->xname = data;
242 xd->xvalue = data + xd->name_len+1;
243
244 c->xdatum_mem_usage += length;
245
246 xd->hashkey = xattr_datum_hashkey(xd->xprefix, xd->xname, xd->xvalue, xd->value_len);
247 i = xd->hashkey % XATTRINDEX_HASHSIZE;
248 list_add(&xd->xindex, &c->xattrindex[i]);
249 if (!retry) {
250 retry = 1;
251 reclaim_xattr_datum(c);
252 if (!xd->xname)
253 goto retry;
254 }
255
256 dbg_xattr("success on loading xdatum (xid=%u, xprefix=%u, xname='%s')\n",
257 xd->xid, xd->xprefix, xd->xname);
258
259 return 0;
260}
261
262static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
263{
264
265
266
267
268
269 int rc = 0;
270
271 BUG_ON(xd->flags & JFFS2_XFLAGS_DEAD);
272 if (xd->xname)
273 return 0;
274 if (xd->flags & JFFS2_XFLAGS_INVALID)
275 return JFFS2_XATTR_IS_CORRUPTED;
276 if (unlikely(is_xattr_datum_unchecked(c, xd)))
277 rc = do_verify_xattr_datum(c, xd);
278 if (!rc)
279 rc = do_load_xattr_datum(c, xd);
280 return rc;
281}
282
283static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
284{
285
286 struct jffs2_raw_xattr rx;
287 struct kvec vecs[2];
288 size_t length;
289 int rc, totlen;
290 uint32_t phys_ofs = write_ofs(c);
291
292 BUG_ON(!xd->xname);
293 BUG_ON(xd->flags & (JFFS2_XFLAGS_DEAD|JFFS2_XFLAGS_INVALID));
294
295 vecs[0].iov_base = ℞
296 vecs[0].iov_len = sizeof(rx);
297 vecs[1].iov_base = xd->xname;
298 vecs[1].iov_len = xd->name_len + 1 + xd->value_len;
299 totlen = vecs[0].iov_len + vecs[1].iov_len;
300
301
302 memset(&rx, 0, sizeof(rx));
303 rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
304 rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR);
305 rx.totlen = cpu_to_je32(PAD(totlen));
306 rx.hdr_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_unknown_node) - 4));
307
308 rx.xid = cpu_to_je32(xd->xid);
309 rx.version = cpu_to_je32(++xd->version);
310 rx.xprefix = xd->xprefix;
311 rx.name_len = xd->name_len;
312 rx.value_len = cpu_to_je16(xd->value_len);
313 rx.data_crc = cpu_to_je32(crc32(0, vecs[1].iov_base, vecs[1].iov_len));
314 rx.node_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_raw_xattr) - 4));
315
316 rc = jffs2_flash_writev(c, vecs, 2, phys_ofs, &length, 0);
317 if (rc || totlen != length) {
318 JFFS2_WARNING("jffs2_flash_writev()=%d, req=%u, wrote=%zu, at %#08x\n",
319 rc, totlen, length, phys_ofs);
320 rc = rc ? rc : -EIO;
321 if (length)
322 jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, PAD(totlen), NULL);
323
324 return rc;
325 }
326
327 jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(totlen), (void *)xd);
328
329 dbg_xattr("success on saving xdatum (xid=%u, version=%u, xprefix=%u, xname='%s')\n",
330 xd->xid, xd->version, xd->xprefix, xd->xname);
331
332 return 0;
333}
334
335static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c,
336 int xprefix, const char *xname,
337 const char *xvalue, int xsize)
338{
339
340 struct jffs2_xattr_datum *xd;
341 uint32_t hashkey, name_len;
342 char *data;
343 int i, rc;
344
345
346 hashkey = xattr_datum_hashkey(xprefix, xname, xvalue, xsize);
347 i = hashkey % XATTRINDEX_HASHSIZE;
348 list_for_each_entry(xd, &c->xattrindex[i], xindex) {
349 if (xd->hashkey==hashkey
350 && xd->xprefix==xprefix
351 && xd->value_len==xsize
352 && !strcmp(xd->xname, xname)
353 && !memcmp(xd->xvalue, xvalue, xsize)) {
354 atomic_inc(&xd->refcnt);
355 return xd;
356 }
357 }
358
359
360 name_len = strlen(xname);
361
362 xd = jffs2_alloc_xattr_datum();
363 if (!xd)
364 return ERR_PTR(-ENOMEM);
365
366 data = kmalloc(name_len + 1 + xsize, GFP_KERNEL);
367 if (!data) {
368 jffs2_free_xattr_datum(xd);
369 return ERR_PTR(-ENOMEM);
370 }
371 strcpy(data, xname);
372 memcpy(data + name_len + 1, xvalue, xsize);
373
374 atomic_set(&xd->refcnt, 1);
375 xd->xid = ++c->highest_xid;
376 xd->flags |= JFFS2_XFLAGS_HOT;
377 xd->xprefix = xprefix;
378
379 xd->hashkey = hashkey;
380 xd->xname = data;
381 xd->xvalue = data + name_len + 1;
382 xd->name_len = name_len;
383 xd->value_len = xsize;
384 xd->data_crc = crc32(0, data, xd->name_len + 1 + xd->value_len);
385
386 rc = save_xattr_datum(c, xd);
387 if (rc) {
388 kfree(xd->xname);
389 jffs2_free_xattr_datum(xd);
390 return ERR_PTR(rc);
391 }
392
393
394 i = hashkey % XATTRINDEX_HASHSIZE;
395 list_add(&xd->xindex, &c->xattrindex[i]);
396
397 c->xdatum_mem_usage += (xd->name_len + 1 + xd->value_len);
398 reclaim_xattr_datum(c);
399
400 return xd;
401}
402
403static void unrefer_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
404{
405
406 if (atomic_dec_and_lock(&xd->refcnt, &c->erase_completion_lock)) {
407 unload_xattr_datum(c, xd);
408 xd->flags |= JFFS2_XFLAGS_DEAD;
409 if (xd->node == (void *)xd) {
410 BUG_ON(!(xd->flags & JFFS2_XFLAGS_INVALID));
411 jffs2_free_xattr_datum(xd);
412 } else {
413 list_add(&xd->xindex, &c->xattr_dead_list);
414 }
415 spin_unlock(&c->erase_completion_lock);
416
417 dbg_xattr("xdatum(xid=%u, version=%u) was removed.\n",
418 xd->xid, xd->version);
419 }
420}
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
444{
445 struct jffs2_eraseblock *jeb;
446 struct jffs2_raw_node_ref *raw;
447 struct jffs2_raw_xref rr;
448 size_t readlen;
449 uint32_t crc, offset, totlen;
450 int rc;
451
452 spin_lock(&c->erase_completion_lock);
453 if (ref_flags(ref->node) != REF_UNCHECKED)
454 goto complete;
455 offset = ref_offset(ref->node);
456 spin_unlock(&c->erase_completion_lock);
457
458 rc = jffs2_flash_read(c, offset, sizeof(rr), &readlen, (char *)&rr);
459 if (rc || sizeof(rr) != readlen) {
460 JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu, at %#08x\n",
461 rc, sizeof(rr), readlen, offset);
462 return rc ? rc : -EIO;
463 }
464
465 crc = crc32(0, &rr, sizeof(rr) - 4);
466 if (crc != je32_to_cpu(rr.node_crc)) {
467 JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
468 offset, je32_to_cpu(rr.node_crc), crc);
469 return JFFS2_XATTR_IS_CORRUPTED;
470 }
471 if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK
472 || je16_to_cpu(rr.nodetype) != JFFS2_NODETYPE_XREF
473 || je32_to_cpu(rr.totlen) != PAD(sizeof(rr))) {
474 JFFS2_ERROR("inconsistent xref at %#08x, magic=%#04x/%#04x, "
475 "nodetype=%#04x/%#04x, totlen=%u/%zu\n",
476 offset, je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK,
477 je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF,
478 je32_to_cpu(rr.totlen), PAD(sizeof(rr)));
479 return JFFS2_XATTR_IS_CORRUPTED;
480 }
481 ref->ino = je32_to_cpu(rr.ino);
482 ref->xid = je32_to_cpu(rr.xid);
483 ref->xseqno = je32_to_cpu(rr.xseqno);
484 if (ref->xseqno > c->highest_xseqno)
485 c->highest_xseqno = (ref->xseqno & ~XREF_DELETE_MARKER);
486
487 spin_lock(&c->erase_completion_lock);
488 complete:
489 for (raw=ref->node; raw != (void *)ref; raw=raw->next_in_ino) {
490 jeb = &c->blocks[ref_offset(raw) / c->sector_size];
491 totlen = PAD(ref_totlen(c, jeb, raw));
492 if (ref_flags(raw) == REF_UNCHECKED) {
493 c->unchecked_size -= totlen; c->used_size += totlen;
494 jeb->unchecked_size -= totlen; jeb->used_size += totlen;
495 }
496 raw->flash_offset = ref_offset(raw) | ((ref->node==raw) ? REF_PRISTINE : REF_NORMAL);
497 }
498 spin_unlock(&c->erase_completion_lock);
499
500 dbg_xattr("success on verifying xref (ino=%u, xid=%u) at %#08x\n",
501 ref->ino, ref->xid, ref_offset(ref->node));
502 return 0;
503}
504
505static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
506{
507
508 struct jffs2_raw_xref rr;
509 size_t length;
510 uint32_t xseqno, phys_ofs = write_ofs(c);
511 int ret;
512
513 rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
514 rr.nodetype = cpu_to_je16(JFFS2_NODETYPE_XREF);
515 rr.totlen = cpu_to_je32(PAD(sizeof(rr)));
516 rr.hdr_crc = cpu_to_je32(crc32(0, &rr, sizeof(struct jffs2_unknown_node) - 4));
517
518 xseqno = (c->highest_xseqno += 2);
519 if (is_xattr_ref_dead(ref)) {
520 xseqno |= XREF_DELETE_MARKER;
521 rr.ino = cpu_to_je32(ref->ino);
522 rr.xid = cpu_to_je32(ref->xid);
523 } else {
524 rr.ino = cpu_to_je32(ref->ic->ino);
525 rr.xid = cpu_to_je32(ref->xd->xid);
526 }
527 rr.xseqno = cpu_to_je32(xseqno);
528 rr.node_crc = cpu_to_je32(crc32(0, &rr, sizeof(rr) - 4));
529
530 ret = jffs2_flash_write(c, phys_ofs, sizeof(rr), &length, (char *)&rr);
531 if (ret || sizeof(rr) != length) {
532 JFFS2_WARNING("jffs2_flash_write() returned %d, request=%zu, retlen=%zu, at %#08x\n",
533 ret, sizeof(rr), length, phys_ofs);
534 ret = ret ? ret : -EIO;
535 if (length)
536 jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, PAD(sizeof(rr)), NULL);
537
538 return ret;
539 }
540
541 ref->xseqno = xseqno;
542 jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(sizeof(rr)), (void *)ref);
543
544 dbg_xattr("success on saving xref (ino=%u, xid=%u)\n", ref->ic->ino, ref->xd->xid);
545
546 return 0;
547}
548
549static struct jffs2_xattr_ref *create_xattr_ref(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic,
550 struct jffs2_xattr_datum *xd)
551{
552
553 struct jffs2_xattr_ref *ref;
554 int ret;
555
556 ref = jffs2_alloc_xattr_ref();
557 if (!ref)
558 return ERR_PTR(-ENOMEM);
559 ref->ic = ic;
560 ref->xd = xd;
561
562 ret = save_xattr_ref(c, ref);
563 if (ret) {
564 jffs2_free_xattr_ref(ref);
565 return ERR_PTR(ret);
566 }
567
568
569 ref->next = ic->xref;
570 ic->xref = ref;
571
572 return ref;
573}
574
575static void delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
576{
577
578 struct jffs2_xattr_datum *xd;
579
580 xd = ref->xd;
581 ref->xseqno |= XREF_DELETE_MARKER;
582 ref->ino = ref->ic->ino;
583 ref->xid = ref->xd->xid;
584 spin_lock(&c->erase_completion_lock);
585 ref->next = c->xref_dead_list;
586 c->xref_dead_list = ref;
587 spin_unlock(&c->erase_completion_lock);
588
589 dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) was removed.\n",
590 ref->ino, ref->xid, ref->xseqno);
591
592 unrefer_xattr_datum(c, xd);
593}
594
595void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
596{
597
598
599 struct jffs2_xattr_ref *ref, *_ref;
600
601 if (!ic || ic->pino_nlink > 0)
602 return;
603
604 down_write(&c->xattr_sem);
605 for (ref = ic->xref; ref; ref = _ref) {
606 _ref = ref->next;
607 delete_xattr_ref(c, ref);
608 }
609 ic->xref = NULL;
610 up_write(&c->xattr_sem);
611}
612
613void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
614{
615
616 struct jffs2_xattr_datum *xd;
617 struct jffs2_xattr_ref *ref, *_ref;
618
619 down_write(&c->xattr_sem);
620 for (ref = ic->xref; ref; ref = _ref) {
621 _ref = ref->next;
622 xd = ref->xd;
623 if (atomic_dec_and_test(&xd->refcnt)) {
624 unload_xattr_datum(c, xd);
625 jffs2_free_xattr_datum(xd);
626 }
627 jffs2_free_xattr_ref(ref);
628 }
629 ic->xref = NULL;
630 up_write(&c->xattr_sem);
631}
632
633static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
634{
635
636
637
638
639 struct jffs2_xattr_ref *ref, *cmp, **pref, **pcmp;
640 int rc = 0;
641
642 if (likely(ic->flags & INO_FLAGS_XATTR_CHECKED))
643 return 0;
644 down_write(&c->xattr_sem);
645 retry:
646 rc = 0;
647 for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
648 if (!ref->xd->xname) {
649 rc = load_xattr_datum(c, ref->xd);
650 if (unlikely(rc > 0)) {
651 *pref = ref->next;
652 delete_xattr_ref(c, ref);
653 goto retry;
654 } else if (unlikely(rc < 0))
655 goto out;
656 }
657 for (cmp=ref->next, pcmp=&ref->next; cmp; pcmp=&cmp->next, cmp=cmp->next) {
658 if (!cmp->xd->xname) {
659 ref->xd->flags |= JFFS2_XFLAGS_BIND;
660 rc = load_xattr_datum(c, cmp->xd);
661 ref->xd->flags &= ~JFFS2_XFLAGS_BIND;
662 if (unlikely(rc > 0)) {
663 *pcmp = cmp->next;
664 delete_xattr_ref(c, cmp);
665 goto retry;
666 } else if (unlikely(rc < 0))
667 goto out;
668 }
669 if (ref->xd->xprefix == cmp->xd->xprefix
670 && !strcmp(ref->xd->xname, cmp->xd->xname)) {
671 if (ref->xseqno > cmp->xseqno) {
672 *pcmp = cmp->next;
673 delete_xattr_ref(c, cmp);
674 } else {
675 *pref = ref->next;
676 delete_xattr_ref(c, ref);
677 }
678 goto retry;
679 }
680 }
681 }
682 ic->flags |= INO_FLAGS_XATTR_CHECKED;
683 out:
684 up_write(&c->xattr_sem);
685
686 return rc;
687}
688
689void jffs2_xattr_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
690{
691 check_xattr_ref_inode(c, ic);
692}
693
694
695
696
697
698
699
700
701
702
703
704
705
706void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c)
707{
708 int i;
709
710 for (i=0; i < XATTRINDEX_HASHSIZE; i++)
711 INIT_LIST_HEAD(&c->xattrindex[i]);
712 INIT_LIST_HEAD(&c->xattr_unchecked);
713 INIT_LIST_HEAD(&c->xattr_dead_list);
714 c->xref_dead_list = NULL;
715 c->xref_temp = NULL;
716
717 init_rwsem(&c->xattr_sem);
718 c->highest_xid = 0;
719 c->highest_xseqno = 0;
720 c->xdatum_mem_usage = 0;
721 c->xdatum_mem_threshold = 32 * 1024;
722}
723
724static struct jffs2_xattr_datum *jffs2_find_xattr_datum(struct jffs2_sb_info *c, uint32_t xid)
725{
726 struct jffs2_xattr_datum *xd;
727 int i = xid % XATTRINDEX_HASHSIZE;
728
729
730 BUG_ON(!(c->flags & (JFFS2_SB_FLAG_SCANNING|JFFS2_SB_FLAG_BUILDING)));
731
732 list_for_each_entry(xd, &c->xattrindex[i], xindex) {
733 if (xd->xid==xid)
734 return xd;
735 }
736 return NULL;
737}
738
739void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c)
740{
741 struct jffs2_xattr_datum *xd, *_xd;
742 struct jffs2_xattr_ref *ref, *_ref;
743 int i;
744
745 for (ref=c->xref_temp; ref; ref = _ref) {
746 _ref = ref->next;
747 jffs2_free_xattr_ref(ref);
748 }
749
750 for (ref=c->xref_dead_list; ref; ref = _ref) {
751 _ref = ref->next;
752 jffs2_free_xattr_ref(ref);
753 }
754
755 for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
756 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
757 list_del(&xd->xindex);
758 if (xd->xname)
759 kfree(xd->xname);
760 jffs2_free_xattr_datum(xd);
761 }
762 }
763
764 list_for_each_entry_safe(xd, _xd, &c->xattr_dead_list, xindex) {
765 list_del(&xd->xindex);
766 jffs2_free_xattr_datum(xd);
767 }
768 list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) {
769 list_del(&xd->xindex);
770 jffs2_free_xattr_datum(xd);
771 }
772}
773
774#define XREF_TMPHASH_SIZE (128)
775void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
776{
777 struct jffs2_xattr_ref *ref, *_ref;
778 struct jffs2_xattr_ref *xref_tmphash[XREF_TMPHASH_SIZE];
779 struct jffs2_xattr_datum *xd, *_xd;
780 struct jffs2_inode_cache *ic;
781 struct jffs2_raw_node_ref *raw;
782 int i, xdatum_count = 0, xdatum_unchecked_count = 0, xref_count = 0;
783 int xdatum_orphan_count = 0, xref_orphan_count = 0, xref_dead_count = 0;
784
785 BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING));
786
787
788 for (i=0; i < XREF_TMPHASH_SIZE; i++)
789 xref_tmphash[i] = NULL;
790 for (ref=c->xref_temp; ref; ref=_ref) {
791 struct jffs2_xattr_ref *tmp;
792
793 _ref = ref->next;
794 if (ref_flags(ref->node) != REF_PRISTINE) {
795 if (verify_xattr_ref(c, ref)) {
796 BUG_ON(ref->node->next_in_ino != (void *)ref);
797 ref->node->next_in_ino = NULL;
798 jffs2_mark_node_obsolete(c, ref->node);
799 jffs2_free_xattr_ref(ref);
800 continue;
801 }
802 }
803
804 i = (ref->ino ^ ref->xid) % XREF_TMPHASH_SIZE;
805 for (tmp=xref_tmphash[i]; tmp; tmp=tmp->next) {
806 if (tmp->ino == ref->ino && tmp->xid == ref->xid)
807 break;
808 }
809 if (tmp) {
810 raw = ref->node;
811 if (ref->xseqno > tmp->xseqno) {
812 tmp->xseqno = ref->xseqno;
813 raw->next_in_ino = tmp->node;
814 tmp->node = raw;
815 } else {
816 raw->next_in_ino = tmp->node->next_in_ino;
817 tmp->node->next_in_ino = raw;
818 }
819 jffs2_free_xattr_ref(ref);
820 continue;
821 } else {
822 ref->next = xref_tmphash[i];
823 xref_tmphash[i] = ref;
824 }
825 }
826 c->xref_temp = NULL;
827
828
829 for (i=0; i < XREF_TMPHASH_SIZE; i++) {
830 for (ref=xref_tmphash[i]; ref; ref=_ref) {
831 xref_count++;
832 _ref = ref->next;
833 if (is_xattr_ref_dead(ref)) {
834 ref->next = c->xref_dead_list;
835 c->xref_dead_list = ref;
836 xref_dead_count++;
837 continue;
838 }
839
840
841 xd = jffs2_find_xattr_datum(c, ref->xid);
842 ic = jffs2_get_ino_cache(c, ref->ino);
843 if (!xd || !ic || !ic->pino_nlink) {
844 dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) is orphan.\n",
845 ref->ino, ref->xid, ref->xseqno);
846 ref->xseqno |= XREF_DELETE_MARKER;
847 ref->next = c->xref_dead_list;
848 c->xref_dead_list = ref;
849 xref_orphan_count++;
850 continue;
851 }
852 ref->xd = xd;
853 ref->ic = ic;
854 atomic_inc(&xd->refcnt);
855 ref->next = ic->xref;
856 ic->xref = ref;
857 }
858 }
859
860
861 for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
862 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
863 xdatum_count++;
864 list_del_init(&xd->xindex);
865 if (!atomic_read(&xd->refcnt)) {
866 dbg_xattr("xdatum(xid=%u, version=%u) is orphan.\n",
867 xd->xid, xd->version);
868 xd->flags |= JFFS2_XFLAGS_DEAD;
869 list_add(&xd->xindex, &c->xattr_unchecked);
870 xdatum_orphan_count++;
871 continue;
872 }
873 if (is_xattr_datum_unchecked(c, xd)) {
874 dbg_xattr("unchecked xdatum(xid=%u, version=%u)\n",
875 xd->xid, xd->version);
876 list_add(&xd->xindex, &c->xattr_unchecked);
877 xdatum_unchecked_count++;
878 }
879 }
880 }
881
882 JFFS2_NOTICE("complete building xattr subsystem, %u of xdatum"
883 " (%u unchecked, %u orphan) and "
884 "%u of xref (%u dead, %u orphan) found.\n",
885 xdatum_count, xdatum_unchecked_count, xdatum_orphan_count,
886 xref_count, xref_dead_count, xref_orphan_count);
887}
888
889struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
890 uint32_t xid, uint32_t version)
891{
892 struct jffs2_xattr_datum *xd;
893
894 xd = jffs2_find_xattr_datum(c, xid);
895 if (!xd) {
896 xd = jffs2_alloc_xattr_datum();
897 if (!xd)
898 return ERR_PTR(-ENOMEM);
899 xd->xid = xid;
900 xd->version = version;
901 if (xd->xid > c->highest_xid)
902 c->highest_xid = xd->xid;
903 list_add_tail(&xd->xindex, &c->xattrindex[xid % XATTRINDEX_HASHSIZE]);
904 }
905 return xd;
906}
907
908
909
910
911
912
913
914
915
916
917
918const struct xattr_handler *jffs2_xattr_handlers[] = {
919 &jffs2_user_xattr_handler,
920#ifdef CONFIG_JFFS2_FS_SECURITY
921 &jffs2_security_xattr_handler,
922#endif
923#ifdef CONFIG_JFFS2_FS_POSIX_ACL
924 &jffs2_acl_access_xattr_handler,
925 &jffs2_acl_default_xattr_handler,
926#endif
927 &jffs2_trusted_xattr_handler,
928 NULL
929};
930
931static const struct xattr_handler *xprefix_to_handler(int xprefix) {
932 const struct xattr_handler *ret;
933
934 switch (xprefix) {
935 case JFFS2_XPREFIX_USER:
936 ret = &jffs2_user_xattr_handler;
937 break;
938#ifdef CONFIG_JFFS2_FS_SECURITY
939 case JFFS2_XPREFIX_SECURITY:
940 ret = &jffs2_security_xattr_handler;
941 break;
942#endif
943#ifdef CONFIG_JFFS2_FS_POSIX_ACL
944 case JFFS2_XPREFIX_ACL_ACCESS:
945 ret = &jffs2_acl_access_xattr_handler;
946 break;
947 case JFFS2_XPREFIX_ACL_DEFAULT:
948 ret = &jffs2_acl_default_xattr_handler;
949 break;
950#endif
951 case JFFS2_XPREFIX_TRUSTED:
952 ret = &jffs2_trusted_xattr_handler;
953 break;
954 default:
955 ret = NULL;
956 break;
957 }
958 return ret;
959}
960
961ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
962{
963 struct inode *inode = dentry->d_inode;
964 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
965 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
966 struct jffs2_inode_cache *ic = f->inocache;
967 struct jffs2_xattr_ref *ref, **pref;
968 struct jffs2_xattr_datum *xd;
969 const struct xattr_handler *xhandle;
970 ssize_t len, rc;
971 int retry = 0;
972
973 rc = check_xattr_ref_inode(c, ic);
974 if (unlikely(rc))
975 return rc;
976
977 down_read(&c->xattr_sem);
978 retry:
979 len = 0;
980 for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
981 BUG_ON(ref->ic != ic);
982 xd = ref->xd;
983 if (!xd->xname) {
984
985 if (!retry) {
986 retry = 1;
987 up_read(&c->xattr_sem);
988 down_write(&c->xattr_sem);
989 goto retry;
990 } else {
991 rc = load_xattr_datum(c, xd);
992 if (unlikely(rc > 0)) {
993 *pref = ref->next;
994 delete_xattr_ref(c, ref);
995 goto retry;
996 } else if (unlikely(rc < 0))
997 goto out;
998 }
999 }
1000 xhandle = xprefix_to_handler(xd->xprefix);
1001 if (!xhandle)
1002 continue;
1003 if (buffer) {
1004 rc = xhandle->list(dentry, buffer+len, size-len,
1005 xd->xname, xd->name_len, xd->flags);
1006 } else {
1007 rc = xhandle->list(dentry, NULL, 0, xd->xname,
1008 xd->name_len, xd->flags);
1009 }
1010 if (rc < 0)
1011 goto out;
1012 len += rc;
1013 }
1014 rc = len;
1015 out:
1016 if (!retry) {
1017 up_read(&c->xattr_sem);
1018 } else {
1019 up_write(&c->xattr_sem);
1020 }
1021 return rc;
1022}
1023
1024int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname,
1025 char *buffer, size_t size)
1026{
1027 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
1028 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
1029 struct jffs2_inode_cache *ic = f->inocache;
1030 struct jffs2_xattr_datum *xd;
1031 struct jffs2_xattr_ref *ref, **pref;
1032 int rc, retry = 0;
1033
1034 rc = check_xattr_ref_inode(c, ic);
1035 if (unlikely(rc))
1036 return rc;
1037
1038 down_read(&c->xattr_sem);
1039 retry:
1040 for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
1041 BUG_ON(ref->ic!=ic);
1042
1043 xd = ref->xd;
1044 if (xd->xprefix != xprefix)
1045 continue;
1046 if (!xd->xname) {
1047
1048 if (!retry) {
1049 retry = 1;
1050 up_read(&c->xattr_sem);
1051 down_write(&c->xattr_sem);
1052 goto retry;
1053 } else {
1054 rc = load_xattr_datum(c, xd);
1055 if (unlikely(rc > 0)) {
1056 *pref = ref->next;
1057 delete_xattr_ref(c, ref);
1058 goto retry;
1059 } else if (unlikely(rc < 0)) {
1060 goto out;
1061 }
1062 }
1063 }
1064 if (!strcmp(xname, xd->xname)) {
1065 rc = xd->value_len;
1066 if (buffer) {
1067 if (size < rc) {
1068 rc = -ERANGE;
1069 } else {
1070 memcpy(buffer, xd->xvalue, rc);
1071 }
1072 }
1073 goto out;
1074 }
1075 }
1076 rc = -ENODATA;
1077 out:
1078 if (!retry) {
1079 up_read(&c->xattr_sem);
1080 } else {
1081 up_write(&c->xattr_sem);
1082 }
1083 return rc;
1084}
1085
1086int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1087 const char *buffer, size_t size, int flags)
1088{
1089 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
1090 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
1091 struct jffs2_inode_cache *ic = f->inocache;
1092 struct jffs2_xattr_datum *xd;
1093 struct jffs2_xattr_ref *ref, *newref, **pref;
1094 uint32_t length, request;
1095 int rc;
1096
1097 rc = check_xattr_ref_inode(c, ic);
1098 if (unlikely(rc))
1099 return rc;
1100
1101 request = PAD(sizeof(struct jffs2_raw_xattr) + strlen(xname) + 1 + size);
1102 rc = jffs2_reserve_space(c, request, &length,
1103 ALLOC_NORMAL, JFFS2_SUMMARY_XATTR_SIZE);
1104 if (rc) {
1105 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request);
1106 return rc;
1107 }
1108
1109
1110 down_write(&c->xattr_sem);
1111 retry:
1112 for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
1113 xd = ref->xd;
1114 if (xd->xprefix != xprefix)
1115 continue;
1116 if (!xd->xname) {
1117 rc = load_xattr_datum(c, xd);
1118 if (unlikely(rc > 0)) {
1119 *pref = ref->next;
1120 delete_xattr_ref(c, ref);
1121 goto retry;
1122 } else if (unlikely(rc < 0))
1123 goto out;
1124 }
1125 if (!strcmp(xd->xname, xname)) {
1126 if (flags & XATTR_CREATE) {
1127 rc = -EEXIST;
1128 goto out;
1129 }
1130 if (!buffer) {
1131 ref->ino = ic->ino;
1132 ref->xid = xd->xid;
1133 ref->xseqno |= XREF_DELETE_MARKER;
1134 rc = save_xattr_ref(c, ref);
1135 if (!rc) {
1136 *pref = ref->next;
1137 spin_lock(&c->erase_completion_lock);
1138 ref->next = c->xref_dead_list;
1139 c->xref_dead_list = ref;
1140 spin_unlock(&c->erase_completion_lock);
1141 unrefer_xattr_datum(c, xd);
1142 } else {
1143 ref->ic = ic;
1144 ref->xd = xd;
1145 ref->xseqno &= ~XREF_DELETE_MARKER;
1146 }
1147 goto out;
1148 }
1149 goto found;
1150 }
1151 }
1152
1153 if (flags & XATTR_REPLACE) {
1154 rc = -ENODATA;
1155 goto out;
1156 }
1157 if (!buffer) {
1158 rc = -ENODATA;
1159 goto out;
1160 }
1161 found:
1162 xd = create_xattr_datum(c, xprefix, xname, buffer, size);
1163 if (IS_ERR(xd)) {
1164 rc = PTR_ERR(xd);
1165 goto out;
1166 }
1167 up_write(&c->xattr_sem);
1168 jffs2_complete_reservation(c);
1169
1170
1171 request = PAD(sizeof(struct jffs2_raw_xref));
1172 rc = jffs2_reserve_space(c, request, &length,
1173 ALLOC_NORMAL, JFFS2_SUMMARY_XREF_SIZE);
1174 down_write(&c->xattr_sem);
1175 if (rc) {
1176 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request);
1177 unrefer_xattr_datum(c, xd);
1178 up_write(&c->xattr_sem);
1179 return rc;
1180 }
1181 if (ref)
1182 *pref = ref->next;
1183 newref = create_xattr_ref(c, ic, xd);
1184 if (IS_ERR(newref)) {
1185 if (ref) {
1186 ref->next = ic->xref;
1187 ic->xref = ref;
1188 }
1189 rc = PTR_ERR(newref);
1190 unrefer_xattr_datum(c, xd);
1191 } else if (ref) {
1192 delete_xattr_ref(c, ref);
1193 }
1194 out:
1195 up_write(&c->xattr_sem);
1196 jffs2_complete_reservation(c);
1197 return rc;
1198}
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd,
1213 struct jffs2_raw_node_ref *raw)
1214{
1215 uint32_t totlen, length, old_ofs;
1216 int rc = 0;
1217
1218 down_write(&c->xattr_sem);
1219 if (xd->node != raw)
1220 goto out;
1221 if (xd->flags & (JFFS2_XFLAGS_DEAD|JFFS2_XFLAGS_INVALID))
1222 goto out;
1223
1224 rc = load_xattr_datum(c, xd);
1225 if (unlikely(rc)) {
1226 rc = (rc > 0) ? 0 : rc;
1227 goto out;
1228 }
1229 old_ofs = ref_offset(xd->node);
1230 totlen = PAD(sizeof(struct jffs2_raw_xattr)
1231 + xd->name_len + 1 + xd->value_len);
1232 rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE);
1233 if (rc) {
1234 JFFS2_WARNING("jffs2_reserve_space_gc()=%d, request=%u\n", rc, totlen);
1235 goto out;
1236 }
1237 rc = save_xattr_datum(c, xd);
1238 if (!rc)
1239 dbg_xattr("xdatum (xid=%u, version=%u) GC'ed from %#08x to %08x\n",
1240 xd->xid, xd->version, old_ofs, ref_offset(xd->node));
1241 out:
1242 if (!rc)
1243 jffs2_mark_node_obsolete(c, raw);
1244 up_write(&c->xattr_sem);
1245 return rc;
1246}
1247
1248int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref,
1249 struct jffs2_raw_node_ref *raw)
1250{
1251 uint32_t totlen, length, old_ofs;
1252 int rc = 0;
1253
1254 down_write(&c->xattr_sem);
1255 BUG_ON(!ref->node);
1256
1257 if (ref->node != raw)
1258 goto out;
1259 if (is_xattr_ref_dead(ref) && (raw->next_in_ino == (void *)ref))
1260 goto out;
1261
1262 old_ofs = ref_offset(ref->node);
1263 totlen = ref_totlen(c, c->gcblock, ref->node);
1264
1265 rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XREF_SIZE);
1266 if (rc) {
1267 JFFS2_WARNING("%s: jffs2_reserve_space_gc() = %d, request = %u\n",
1268 __func__, rc, totlen);
1269 rc = rc ? rc : -EBADFD;
1270 goto out;
1271 }
1272 rc = save_xattr_ref(c, ref);
1273 if (!rc)
1274 dbg_xattr("xref (ino=%u, xid=%u) GC'ed from %#08x to %08x\n",
1275 ref->ic->ino, ref->xd->xid, old_ofs, ref_offset(ref->node));
1276 out:
1277 if (!rc)
1278 jffs2_mark_node_obsolete(c, raw);
1279 up_write(&c->xattr_sem);
1280 return rc;
1281}
1282
1283int jffs2_verify_xattr(struct jffs2_sb_info *c)
1284{
1285 struct jffs2_xattr_datum *xd, *_xd;
1286 struct jffs2_eraseblock *jeb;
1287 struct jffs2_raw_node_ref *raw;
1288 uint32_t totlen;
1289 int rc;
1290
1291 down_write(&c->xattr_sem);
1292 list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) {
1293 rc = do_verify_xattr_datum(c, xd);
1294 if (rc < 0)
1295 continue;
1296 list_del_init(&xd->xindex);
1297 spin_lock(&c->erase_completion_lock);
1298 for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) {
1299 if (ref_flags(raw) != REF_UNCHECKED)
1300 continue;
1301 jeb = &c->blocks[ref_offset(raw) / c->sector_size];
1302 totlen = PAD(ref_totlen(c, jeb, raw));
1303 c->unchecked_size -= totlen; c->used_size += totlen;
1304 jeb->unchecked_size -= totlen; jeb->used_size += totlen;
1305 raw->flash_offset = ref_offset(raw)
1306 | ((xd->node == (void *)raw) ? REF_PRISTINE : REF_NORMAL);
1307 }
1308 if (xd->flags & JFFS2_XFLAGS_DEAD)
1309 list_add(&xd->xindex, &c->xattr_dead_list);
1310 spin_unlock(&c->erase_completion_lock);
1311 }
1312 up_write(&c->xattr_sem);
1313 return list_empty(&c->xattr_unchecked) ? 1 : 0;
1314}
1315
1316void jffs2_release_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
1317{
1318
1319 if (atomic_read(&xd->refcnt) || xd->node != (void *)xd)
1320 return;
1321
1322 list_del(&xd->xindex);
1323 jffs2_free_xattr_datum(xd);
1324}
1325
1326void jffs2_release_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
1327{
1328
1329 struct jffs2_xattr_ref *tmp, **ptmp;
1330
1331 if (ref->node != (void *)ref)
1332 return;
1333
1334 for (tmp=c->xref_dead_list, ptmp=&c->xref_dead_list; tmp; ptmp=&tmp->next, tmp=tmp->next) {
1335 if (ref == tmp) {
1336 *ptmp = tmp->next;
1337 break;
1338 }
1339 }
1340 jffs2_free_xattr_ref(ref);
1341}
1342