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/posix_acl_xattr.h>
26#include <linux/mtd/mtd.h>
27#include "nodelist.h"
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
63
64static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *xvalue, int xsize)
65{
66 int name_len = strlen(xname);
67
68 return crc32(xprefix, xname, name_len) ^ crc32(xprefix, xvalue, xsize);
69}
70
71static int is_xattr_datum_unchecked(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
72{
73 struct jffs2_raw_node_ref *raw;
74 int rc = 0;
75
76 spin_lock(&c->erase_completion_lock);
77 for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) {
78 if (ref_flags(raw) == REF_UNCHECKED) {
79 rc = 1;
80 break;
81 }
82 }
83 spin_unlock(&c->erase_completion_lock);
84 return rc;
85}
86
87static void unload_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
88{
89
90 D1(dbg_xattr("%s: xid=%u, version=%u\n", __func__, xd->xid, xd->version));
91 if (xd->xname) {
92 c->xdatum_mem_usage -= (xd->name_len + 1 + xd->value_len);
93 kfree(xd->xname);
94 }
95
96 list_del_init(&xd->xindex);
97 xd->hashkey = 0;
98 xd->xname = NULL;
99 xd->xvalue = NULL;
100}
101
102static void reclaim_xattr_datum(struct jffs2_sb_info *c)
103{
104
105 struct jffs2_xattr_datum *xd, *_xd;
106 uint32_t target, before;
107 static int index = 0;
108 int count;
109
110 if (c->xdatum_mem_threshold > c->xdatum_mem_usage)
111 return;
112
113 before = c->xdatum_mem_usage;
114 target = c->xdatum_mem_usage * 4 / 5;
115 for (count = 0; count < XATTRINDEX_HASHSIZE; count++) {
116 list_for_each_entry_safe(xd, _xd, &c->xattrindex[index], xindex) {
117 if (xd->flags & JFFS2_XFLAGS_HOT) {
118 xd->flags &= ~JFFS2_XFLAGS_HOT;
119 } else if (!(xd->flags & JFFS2_XFLAGS_BIND)) {
120 unload_xattr_datum(c, xd);
121 }
122 if (c->xdatum_mem_usage <= target)
123 goto out;
124 }
125 index = (index+1) % XATTRINDEX_HASHSIZE;
126 }
127 out:
128 JFFS2_NOTICE("xdatum_mem_usage from %u byte to %u byte (%u byte reclaimed)\n",
129 before, c->xdatum_mem_usage, before - c->xdatum_mem_usage);
130}
131
132static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
133{
134
135 struct jffs2_eraseblock *jeb;
136 struct jffs2_raw_node_ref *raw;
137 struct jffs2_raw_xattr rx;
138 size_t readlen;
139 uint32_t crc, offset, totlen;
140 int rc;
141
142 spin_lock(&c->erase_completion_lock);
143 offset = ref_offset(xd->node);
144 if (ref_flags(xd->node) == REF_PRISTINE)
145 goto complete;
146 spin_unlock(&c->erase_completion_lock);
147
148 rc = jffs2_flash_read(c, offset, sizeof(rx), &readlen, (char *)&rx);
149 if (rc || readlen != sizeof(rx)) {
150 JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n",
151 rc, sizeof(rx), readlen, offset);
152 return rc ? rc : -EIO;
153 }
154 crc = crc32(0, &rx, sizeof(rx) - 4);
155 if (crc != je32_to_cpu(rx.node_crc)) {
156 JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
157 offset, je32_to_cpu(rx.hdr_crc), crc);
158 xd->flags |= JFFS2_XFLAGS_INVALID;
159 return JFFS2_XATTR_IS_CORRUPTED;
160 }
161 totlen = PAD(sizeof(rx) + rx.name_len + 1 + je16_to_cpu(rx.value_len));
162 if (je16_to_cpu(rx.magic) != JFFS2_MAGIC_BITMASK
163 || je16_to_cpu(rx.nodetype) != JFFS2_NODETYPE_XATTR
164 || je32_to_cpu(rx.totlen) != totlen
165 || je32_to_cpu(rx.xid) != xd->xid
166 || je32_to_cpu(rx.version) != xd->version) {
167 JFFS2_ERROR("inconsistent xdatum at %#08x, magic=%#04x/%#04x, "
168 "nodetype=%#04x/%#04x, totlen=%u/%u, xid=%u/%u, version=%u/%u\n",
169 offset, je16_to_cpu(rx.magic), JFFS2_MAGIC_BITMASK,
170 je16_to_cpu(rx.nodetype), JFFS2_NODETYPE_XATTR,
171 je32_to_cpu(rx.totlen), totlen,
172 je32_to_cpu(rx.xid), xd->xid,
173 je32_to_cpu(rx.version), xd->version);
174 xd->flags |= JFFS2_XFLAGS_INVALID;
175 return JFFS2_XATTR_IS_CORRUPTED;
176 }
177 xd->xprefix = rx.xprefix;
178 xd->name_len = rx.name_len;
179 xd->value_len = je16_to_cpu(rx.value_len);
180 xd->data_crc = je32_to_cpu(rx.data_crc);
181
182 spin_lock(&c->erase_completion_lock);
183 complete:
184 for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) {
185 jeb = &c->blocks[ref_offset(raw) / c->sector_size];
186 totlen = PAD(ref_totlen(c, jeb, raw));
187 if (ref_flags(raw) == REF_UNCHECKED) {
188 c->unchecked_size -= totlen; c->used_size += totlen;
189 jeb->unchecked_size -= totlen; jeb->used_size += totlen;
190 }
191 raw->flash_offset = ref_offset(raw) | ((xd->node==raw) ? REF_PRISTINE : REF_NORMAL);
192 }
193 spin_unlock(&c->erase_completion_lock);
194
195
196 list_del_init(&xd->xindex);
197
198 dbg_xattr("success on verfying xdatum (xid=%u, version=%u)\n",
199 xd->xid, xd->version);
200
201 return 0;
202}
203
204static int do_load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
205{
206
207 char *data;
208 size_t readlen;
209 uint32_t crc, length;
210 int i, ret, retry = 0;
211
212 BUG_ON(ref_flags(xd->node) != REF_PRISTINE);
213 BUG_ON(!list_empty(&xd->xindex));
214 retry:
215 length = xd->name_len + 1 + xd->value_len;
216 data = kmalloc(length, GFP_KERNEL);
217 if (!data)
218 return -ENOMEM;
219
220 ret = jffs2_flash_read(c, ref_offset(xd->node)+sizeof(struct jffs2_raw_xattr),
221 length, &readlen, data);
222
223 if (ret || length!=readlen) {
224 JFFS2_WARNING("jffs2_flash_read() returned %d, request=%d, readlen=%zu, at %#08x\n",
225 ret, length, readlen, ref_offset(xd->node));
226 kfree(data);
227 return ret ? ret : -EIO;
228 }
229
230 data[xd->name_len] = '\0';
231 crc = crc32(0, data, length);
232 if (crc != xd->data_crc) {
233 JFFS2_WARNING("node CRC failed (JFFS2_NODETYPE_XATTR)"
234 " at %#08x, read: 0x%08x calculated: 0x%08x\n",
235 ref_offset(xd->node), xd->data_crc, crc);
236 kfree(data);
237 xd->flags |= JFFS2_XFLAGS_INVALID;
238 return JFFS2_XATTR_IS_CORRUPTED;
239 }
240
241 xd->flags |= JFFS2_XFLAGS_HOT;
242 xd->xname = data;
243 xd->xvalue = data + xd->name_len+1;
244
245 c->xdatum_mem_usage += length;
246
247 xd->hashkey = xattr_datum_hashkey(xd->xprefix, xd->xname, xd->xvalue, xd->value_len);
248 i = xd->hashkey % XATTRINDEX_HASHSIZE;
249 list_add(&xd->xindex, &c->xattrindex[i]);
250 if (!retry) {
251 retry = 1;
252 reclaim_xattr_datum(c);
253 if (!xd->xname)
254 goto retry;
255 }
256
257 dbg_xattr("success on loading xdatum (xid=%u, xprefix=%u, xname='%s')\n",
258 xd->xid, xd->xprefix, xd->xname);
259
260 return 0;
261}
262
263static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
264{
265
266
267
268
269
270 int rc = 0;
271
272 BUG_ON(xd->flags & JFFS2_XFLAGS_DEAD);
273 if (xd->xname)
274 return 0;
275 if (xd->flags & JFFS2_XFLAGS_INVALID)
276 return JFFS2_XATTR_IS_CORRUPTED;
277 if (unlikely(is_xattr_datum_unchecked(c, xd)))
278 rc = do_verify_xattr_datum(c, xd);
279 if (!rc)
280 rc = do_load_xattr_datum(c, xd);
281 return rc;
282}
283
284static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
285{
286
287 struct jffs2_raw_xattr rx;
288 struct kvec vecs[2];
289 size_t length;
290 int rc, totlen;
291 uint32_t phys_ofs = write_ofs(c);
292
293 BUG_ON(!xd->xname);
294 BUG_ON(xd->flags & (JFFS2_XFLAGS_DEAD|JFFS2_XFLAGS_INVALID));
295
296 vecs[0].iov_base = ℞
297 vecs[0].iov_len = sizeof(rx);
298 vecs[1].iov_base = xd->xname;
299 vecs[1].iov_len = xd->name_len + 1 + xd->value_len;
300 totlen = vecs[0].iov_len + vecs[1].iov_len;
301
302
303 memset(&rx, 0, sizeof(rx));
304 rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
305 rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR);
306 rx.totlen = cpu_to_je32(PAD(totlen));
307 rx.hdr_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_unknown_node) - 4));
308
309 rx.xid = cpu_to_je32(xd->xid);
310 rx.version = cpu_to_je32(++xd->version);
311 rx.xprefix = xd->xprefix;
312 rx.name_len = xd->name_len;
313 rx.value_len = cpu_to_je16(xd->value_len);
314 rx.data_crc = cpu_to_je32(crc32(0, vecs[1].iov_base, vecs[1].iov_len));
315 rx.node_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_raw_xattr) - 4));
316
317 rc = jffs2_flash_writev(c, vecs, 2, phys_ofs, &length, 0);
318 if (rc || totlen != length) {
319 JFFS2_WARNING("jffs2_flash_writev()=%d, req=%u, wrote=%zu, at %#08x\n",
320 rc, totlen, length, phys_ofs);
321 rc = rc ? rc : -EIO;
322 if (length)
323 jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, PAD(totlen), NULL);
324
325 return rc;
326 }
327
328 jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(totlen), (void *)xd);
329
330 dbg_xattr("success on saving xdatum (xid=%u, version=%u, xprefix=%u, xname='%s')\n",
331 xd->xid, xd->version, xd->xprefix, xd->xname);
332
333 return 0;
334}
335
336static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c,
337 int xprefix, const char *xname,
338 const char *xvalue, int xsize)
339{
340
341 struct jffs2_xattr_datum *xd;
342 uint32_t hashkey, name_len;
343 char *data;
344 int i, rc;
345
346
347 hashkey = xattr_datum_hashkey(xprefix, xname, xvalue, xsize);
348 i = hashkey % XATTRINDEX_HASHSIZE;
349 list_for_each_entry(xd, &c->xattrindex[i], xindex) {
350 if (xd->hashkey==hashkey
351 && xd->xprefix==xprefix
352 && xd->value_len==xsize
353 && !strcmp(xd->xname, xname)
354 && !memcmp(xd->xvalue, xvalue, xsize)) {
355 atomic_inc(&xd->refcnt);
356 return xd;
357 }
358 }
359
360
361 name_len = strlen(xname);
362
363 xd = jffs2_alloc_xattr_datum();
364 if (!xd)
365 return ERR_PTR(-ENOMEM);
366
367 data = kmalloc(name_len + 1 + xsize, GFP_KERNEL);
368 if (!data) {
369 jffs2_free_xattr_datum(xd);
370 return ERR_PTR(-ENOMEM);
371 }
372 strcpy(data, xname);
373 memcpy(data + name_len + 1, xvalue, xsize);
374
375 atomic_set(&xd->refcnt, 1);
376 xd->xid = ++c->highest_xid;
377 xd->flags |= JFFS2_XFLAGS_HOT;
378 xd->xprefix = xprefix;
379
380 xd->hashkey = hashkey;
381 xd->xname = data;
382 xd->xvalue = data + name_len + 1;
383 xd->name_len = name_len;
384 xd->value_len = xsize;
385 xd->data_crc = crc32(0, data, xd->name_len + 1 + xd->value_len);
386
387 rc = save_xattr_datum(c, xd);
388 if (rc) {
389 kfree(xd->xname);
390 jffs2_free_xattr_datum(xd);
391 return ERR_PTR(rc);
392 }
393
394
395 i = hashkey % XATTRINDEX_HASHSIZE;
396 list_add(&xd->xindex, &c->xattrindex[i]);
397
398 c->xdatum_mem_usage += (xd->name_len + 1 + xd->value_len);
399 reclaim_xattr_datum(c);
400
401 return xd;
402}
403
404static void unrefer_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
405{
406
407 if (atomic_dec_and_lock(&xd->refcnt, &c->erase_completion_lock)) {
408 unload_xattr_datum(c, xd);
409 xd->flags |= JFFS2_XFLAGS_DEAD;
410 if (xd->node == (void *)xd) {
411 BUG_ON(!(xd->flags & JFFS2_XFLAGS_INVALID));
412 jffs2_free_xattr_datum(xd);
413 } else {
414 list_add(&xd->xindex, &c->xattr_dead_list);
415 }
416 spin_unlock(&c->erase_completion_lock);
417
418 dbg_xattr("xdatum(xid=%u, version=%u) was removed.\n",
419 xd->xid, xd->version);
420 }
421}
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
445{
446 struct jffs2_eraseblock *jeb;
447 struct jffs2_raw_node_ref *raw;
448 struct jffs2_raw_xref rr;
449 size_t readlen;
450 uint32_t crc, offset, totlen;
451 int rc;
452
453 spin_lock(&c->erase_completion_lock);
454 if (ref_flags(ref->node) != REF_UNCHECKED)
455 goto complete;
456 offset = ref_offset(ref->node);
457 spin_unlock(&c->erase_completion_lock);
458
459 rc = jffs2_flash_read(c, offset, sizeof(rr), &readlen, (char *)&rr);
460 if (rc || sizeof(rr) != readlen) {
461 JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu, at %#08x\n",
462 rc, sizeof(rr), readlen, offset);
463 return rc ? rc : -EIO;
464 }
465
466 crc = crc32(0, &rr, sizeof(rr) - 4);
467 if (crc != je32_to_cpu(rr.node_crc)) {
468 JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
469 offset, je32_to_cpu(rr.node_crc), crc);
470 return JFFS2_XATTR_IS_CORRUPTED;
471 }
472 if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK
473 || je16_to_cpu(rr.nodetype) != JFFS2_NODETYPE_XREF
474 || je32_to_cpu(rr.totlen) != PAD(sizeof(rr))) {
475 JFFS2_ERROR("inconsistent xref at %#08x, magic=%#04x/%#04x, "
476 "nodetype=%#04x/%#04x, totlen=%u/%zu\n",
477 offset, je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK,
478 je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF,
479 je32_to_cpu(rr.totlen), PAD(sizeof(rr)));
480 return JFFS2_XATTR_IS_CORRUPTED;
481 }
482 ref->ino = je32_to_cpu(rr.ino);
483 ref->xid = je32_to_cpu(rr.xid);
484 ref->xseqno = je32_to_cpu(rr.xseqno);
485 if (ref->xseqno > c->highest_xseqno)
486 c->highest_xseqno = (ref->xseqno & ~XREF_DELETE_MARKER);
487
488 spin_lock(&c->erase_completion_lock);
489 complete:
490 for (raw=ref->node; raw != (void *)ref; raw=raw->next_in_ino) {
491 jeb = &c->blocks[ref_offset(raw) / c->sector_size];
492 totlen = PAD(ref_totlen(c, jeb, raw));
493 if (ref_flags(raw) == REF_UNCHECKED) {
494 c->unchecked_size -= totlen; c->used_size += totlen;
495 jeb->unchecked_size -= totlen; jeb->used_size += totlen;
496 }
497 raw->flash_offset = ref_offset(raw) | ((ref->node==raw) ? REF_PRISTINE : REF_NORMAL);
498 }
499 spin_unlock(&c->erase_completion_lock);
500
501 dbg_xattr("success on verifying xref (ino=%u, xid=%u) at %#08x\n",
502 ref->ino, ref->xid, ref_offset(ref->node));
503 return 0;
504}
505
506static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
507{
508
509 struct jffs2_raw_xref rr;
510 size_t length;
511 uint32_t xseqno, phys_ofs = write_ofs(c);
512 int ret;
513
514 rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
515 rr.nodetype = cpu_to_je16(JFFS2_NODETYPE_XREF);
516 rr.totlen = cpu_to_je32(PAD(sizeof(rr)));
517 rr.hdr_crc = cpu_to_je32(crc32(0, &rr, sizeof(struct jffs2_unknown_node) - 4));
518
519 xseqno = (c->highest_xseqno += 2);
520 if (is_xattr_ref_dead(ref)) {
521 xseqno |= XREF_DELETE_MARKER;
522 rr.ino = cpu_to_je32(ref->ino);
523 rr.xid = cpu_to_je32(ref->xid);
524 } else {
525 rr.ino = cpu_to_je32(ref->ic->ino);
526 rr.xid = cpu_to_je32(ref->xd->xid);
527 }
528 rr.xseqno = cpu_to_je32(xseqno);
529 rr.node_crc = cpu_to_je32(crc32(0, &rr, sizeof(rr) - 4));
530
531 ret = jffs2_flash_write(c, phys_ofs, sizeof(rr), &length, (char *)&rr);
532 if (ret || sizeof(rr) != length) {
533 JFFS2_WARNING("jffs2_flash_write() returned %d, request=%zu, retlen=%zu, at %#08x\n",
534 ret, sizeof(rr), length, phys_ofs);
535 ret = ret ? ret : -EIO;
536 if (length)
537 jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, PAD(sizeof(rr)), NULL);
538
539 return ret;
540 }
541
542 ref->xseqno = xseqno;
543 jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(sizeof(rr)), (void *)ref);
544
545 dbg_xattr("success on saving xref (ino=%u, xid=%u)\n", ref->ic->ino, ref->xd->xid);
546
547 return 0;
548}
549
550static struct jffs2_xattr_ref *create_xattr_ref(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic,
551 struct jffs2_xattr_datum *xd)
552{
553
554 struct jffs2_xattr_ref *ref;
555 int ret;
556
557 ref = jffs2_alloc_xattr_ref();
558 if (!ref)
559 return ERR_PTR(-ENOMEM);
560 ref->ic = ic;
561 ref->xd = xd;
562
563 ret = save_xattr_ref(c, ref);
564 if (ret) {
565 jffs2_free_xattr_ref(ref);
566 return ERR_PTR(ret);
567 }
568
569
570 ref->next = ic->xref;
571 ic->xref = ref;
572
573 return ref;
574}
575
576static void delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
577{
578
579 struct jffs2_xattr_datum *xd;
580
581 xd = ref->xd;
582 ref->xseqno |= XREF_DELETE_MARKER;
583 ref->ino = ref->ic->ino;
584 ref->xid = ref->xd->xid;
585 spin_lock(&c->erase_completion_lock);
586 ref->next = c->xref_dead_list;
587 c->xref_dead_list = ref;
588 spin_unlock(&c->erase_completion_lock);
589
590 dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) was removed.\n",
591 ref->ino, ref->xid, ref->xseqno);
592
593 unrefer_xattr_datum(c, xd);
594}
595
596void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
597{
598
599
600 struct jffs2_xattr_ref *ref, *_ref;
601
602 if (!ic || ic->pino_nlink > 0)
603 return;
604
605 down_write(&c->xattr_sem);
606 for (ref = ic->xref; ref; ref = _ref) {
607 _ref = ref->next;
608 delete_xattr_ref(c, ref);
609 }
610 ic->xref = NULL;
611 up_write(&c->xattr_sem);
612}
613
614void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
615{
616
617 struct jffs2_xattr_datum *xd;
618 struct jffs2_xattr_ref *ref, *_ref;
619
620 down_write(&c->xattr_sem);
621 for (ref = ic->xref; ref; ref = _ref) {
622 _ref = ref->next;
623 xd = ref->xd;
624 if (atomic_dec_and_test(&xd->refcnt)) {
625 unload_xattr_datum(c, xd);
626 jffs2_free_xattr_datum(xd);
627 }
628 jffs2_free_xattr_ref(ref);
629 }
630 ic->xref = NULL;
631 up_write(&c->xattr_sem);
632}
633
634static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
635{
636
637
638
639
640 struct jffs2_xattr_ref *ref, *cmp, **pref, **pcmp;
641 int rc = 0;
642
643 if (likely(ic->flags & INO_FLAGS_XATTR_CHECKED))
644 return 0;
645 down_write(&c->xattr_sem);
646 retry:
647 rc = 0;
648 for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
649 if (!ref->xd->xname) {
650 rc = load_xattr_datum(c, ref->xd);
651 if (unlikely(rc > 0)) {
652 *pref = ref->next;
653 delete_xattr_ref(c, ref);
654 goto retry;
655 } else if (unlikely(rc < 0))
656 goto out;
657 }
658 for (cmp=ref->next, pcmp=&ref->next; cmp; pcmp=&cmp->next, cmp=cmp->next) {
659 if (!cmp->xd->xname) {
660 ref->xd->flags |= JFFS2_XFLAGS_BIND;
661 rc = load_xattr_datum(c, cmp->xd);
662 ref->xd->flags &= ~JFFS2_XFLAGS_BIND;
663 if (unlikely(rc > 0)) {
664 *pcmp = cmp->next;
665 delete_xattr_ref(c, cmp);
666 goto retry;
667 } else if (unlikely(rc < 0))
668 goto out;
669 }
670 if (ref->xd->xprefix == cmp->xd->xprefix
671 && !strcmp(ref->xd->xname, cmp->xd->xname)) {
672 if (ref->xseqno > cmp->xseqno) {
673 *pcmp = cmp->next;
674 delete_xattr_ref(c, cmp);
675 } else {
676 *pref = ref->next;
677 delete_xattr_ref(c, ref);
678 }
679 goto retry;
680 }
681 }
682 }
683 ic->flags |= INO_FLAGS_XATTR_CHECKED;
684 out:
685 up_write(&c->xattr_sem);
686
687 return rc;
688}
689
690void jffs2_xattr_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
691{
692 check_xattr_ref_inode(c, ic);
693}
694
695
696
697
698
699
700
701
702
703
704
705
706
707void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c)
708{
709 int i;
710
711 for (i=0; i < XATTRINDEX_HASHSIZE; i++)
712 INIT_LIST_HEAD(&c->xattrindex[i]);
713 INIT_LIST_HEAD(&c->xattr_unchecked);
714 INIT_LIST_HEAD(&c->xattr_dead_list);
715 c->xref_dead_list = NULL;
716 c->xref_temp = NULL;
717
718 init_rwsem(&c->xattr_sem);
719 c->highest_xid = 0;
720 c->highest_xseqno = 0;
721 c->xdatum_mem_usage = 0;
722 c->xdatum_mem_threshold = 32 * 1024;
723}
724
725static struct jffs2_xattr_datum *jffs2_find_xattr_datum(struct jffs2_sb_info *c, uint32_t xid)
726{
727 struct jffs2_xattr_datum *xd;
728 int i = xid % XATTRINDEX_HASHSIZE;
729
730
731 BUG_ON(!(c->flags & (JFFS2_SB_FLAG_SCANNING|JFFS2_SB_FLAG_BUILDING)));
732
733 list_for_each_entry(xd, &c->xattrindex[i], xindex) {
734 if (xd->xid==xid)
735 return xd;
736 }
737 return NULL;
738}
739
740void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c)
741{
742 struct jffs2_xattr_datum *xd, *_xd;
743 struct jffs2_xattr_ref *ref, *_ref;
744 int i;
745
746 for (ref=c->xref_temp; ref; ref = _ref) {
747 _ref = ref->next;
748 jffs2_free_xattr_ref(ref);
749 }
750
751 for (ref=c->xref_dead_list; ref; ref = _ref) {
752 _ref = ref->next;
753 jffs2_free_xattr_ref(ref);
754 }
755
756 for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
757 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
758 list_del(&xd->xindex);
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 &posix_acl_access_xattr_handler,
925 &posix_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 = &posix_acl_access_xattr_handler;
946 break;
947 case JFFS2_XPREFIX_ACL_DEFAULT:
948 ret = &posix_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