aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2/xattr.c
diff options
context:
space:
mode:
authorKaiGai Kohei <kaigai@ak.jp.nec.com>2006-05-13 02:09:47 -0400
committerKaiGai Kohei <kaigai@ak.jp.nec.com>2006-05-13 02:09:47 -0400
commitaa98d7cf59b5b0764d3502662053489585faf2fe (patch)
treee98e83f3e69ebe3a1112394a19d440419e899749 /fs/jffs2/xattr.c
parent4992a9e88886b0c5ebc3d27eb74d0344c873eeea (diff)
[JFFS2][XATTR] XATTR support on JFFS2 (version. 5)
This attached patches provide xattr support including POSIX-ACL and SELinux support on JFFS2 (version.5). There are some significant differences from previous version posted at last December. The biggest change is addition of EBS(Erase Block Summary) support. Currently, both kernel and usermode utility (sumtool) can recognize xattr nodes which have JFFS2_NODETYPE_XATTR/_XREF nodetype. In addition, some bugs are fixed. - A potential race condition was fixed. - Unexpected fail when updating a xattr by same name/value pair was fixed. - A bug when removing xattr name/value pair was fixed. The fundamental structures (such as using two new nodetypes and exclusion mechanism by rwsem) are unchanged. But most of implementation were reviewed and updated if necessary. Espacially, we had to change several internal implementations related to load_xattr_datum() to avoid a potential race condition. [1/2] xattr_on_jffs2.kernel.version-5.patch [2/2] xattr_on_jffs2.utils.version-5.patch Signed-off-by: KaiGai Kohei <kaigai@ak.jp.nec.com> Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'fs/jffs2/xattr.c')
-rw-r--r--fs/jffs2/xattr.c1271
1 files changed, 1271 insertions, 0 deletions
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
new file mode 100644
index 000000000000..c9a185c54ce7
--- /dev/null
+++ b/fs/jffs2/xattr.c
@@ -0,0 +1,1271 @@
1/* -------------------------------------------------------------------------
2 * File: fs/jffs2/xattr.c
3 * XATTR support on JFFS2 FileSystem
4 *
5 * Implemented by KaiGai Kohei <kaigai@ak.jp.nec.com>
6 * Copyright (C) 2006 NEC Corporation
7 *
8 * For licensing information, see the file 'LICENCE' in the jffs2 directory.
9 * ------------------------------------------------------------------------- */
10
11#include <linux/kernel.h>
12#include <linux/slab.h>
13#include <linux/fs.h>
14#include <linux/time.h>
15#include <linux/pagemap.h>
16#include <linux/highmem.h>
17#include <linux/crc32.h>
18#include <linux/jffs2.h>
19#include <linux/xattr.h>
20#include <linux/mtd/mtd.h>
21#include "nodelist.h"
22/* -------- xdatum related functions ----------------
23 * xattr_datum_hashkey(xprefix, xname, xvalue, xsize)
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).
26 * unload_xattr_datum(c, xd)
27 * is used to release xattr name/value pair and detach from c->xattrindex.
28 * reclaim_xattr_datum(c)
29 * 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
31 * 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)
39 * 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
41 * process when EBS is enabled.
42 * 0 will be returned, if success. An negative return value means recoverable error, and
43 * positive return value means unrecoverable error. Thus, caller must remove this xdatum
44 * and xref when it returned positive value.
45 * do_load_xattr_datum(c, xd)
46 * is used to load name/value pair from the medium.
47 * The meanings of return value is same as do_verify_xattr_datum().
48 * load_xattr_datum(c, xd)
49 * is used to be as a wrapper of do_verify_xattr_datum() and do_load_xattr_datum().
50 * If xd need to call do_verify_xattr_datum() at first, it's called before calling
51 * do_load_xattr_datum(). The meanings of return value is same as do_verify_xattr_datum().
52 * save_xattr_datum(c, xd, phys_ofs)
53 * is used to write xdatum to medium. xd->version will be incremented.
54 * create_xattr_datum(c, xprefix, xname, xvalue, xsize, phys_ofs)
55 * is used to create new xdatum and write to medium.
56 * -------------------------------------------------- */
57
58static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *xvalue, int xsize)
59{
60 int name_len = strlen(xname);
61
62 return crc32(xprefix, xname, name_len) ^ crc32(xprefix, xvalue, xsize);
63}
64
65static void unload_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
66{
67 /* must be called under down_write(xattr_sem) */
68 D1(dbg_xattr("%s: xid=%u, version=%u\n", __FUNCTION__, xd->xid, xd->version));
69 if (xd->xname) {
70 c->xdatum_mem_usage -= (xd->name_len + 1 + xd->value_len);
71 kfree(xd->xname);
72 }
73
74 list_del_init(&xd->xindex);
75 xd->hashkey = 0;
76 xd->xname = NULL;
77 xd->xvalue = NULL;
78}
79
80static void reclaim_xattr_datum(struct jffs2_sb_info *c)
81{
82 /* must be called under down_write(xattr_sem) */
83 struct jffs2_xattr_datum *xd, *_xd;
84 uint32_t target, before;
85 static int index = 0;
86 int count;
87
88 if (c->xdatum_mem_threshold > c->xdatum_mem_usage)
89 return;
90
91 before = c->xdatum_mem_usage;
92 target = c->xdatum_mem_usage * 4 / 5; /* 20% reduction */
93 for (count = 0; count < XATTRINDEX_HASHSIZE; count++) {
94 list_for_each_entry_safe(xd, _xd, &c->xattrindex[index], xindex) {
95 if (xd->flags & JFFS2_XFLAGS_HOT) {
96 xd->flags &= ~JFFS2_XFLAGS_HOT;
97 } else if (!(xd->flags & JFFS2_XFLAGS_BIND)) {
98 unload_xattr_datum(c, xd);
99 }
100 if (c->xdatum_mem_usage <= target)
101 goto out;
102 }
103 index = (index+1) % XATTRINDEX_HASHSIZE;
104 }
105 out:
106 JFFS2_NOTICE("xdatum_mem_usage from %u byte to %u byte (%u byte reclaimed)\n",
107 before, c->xdatum_mem_usage, before - c->xdatum_mem_usage);
108}
109
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 uint32_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=%u, read=%u 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=%u, wrote=%u 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)
159{
160 /* must be called under down_write(xattr_sem) */
161 struct jffs2_eraseblock *jeb;
162 struct jffs2_raw_xattr rx;
163 size_t readlen;
164 uint32_t crc, totlen;
165 int rc;
166
167 BUG_ON(!xd->node);
168 BUG_ON(ref_flags(xd->node) != REF_UNCHECKED);
169
170 rc = jffs2_flash_read(c, ref_offset(xd->node), sizeof(rx), &readlen, (char *)&rx);
171 if (rc || readlen != sizeof(rx)) {
172 JFFS2_WARNING("jffs2_flash_read()=%d, req=%u, read=%u at %#08x\n",
173 rc, sizeof(rx), readlen, ref_offset(xd->node));
174 return rc ? rc : -EIO;
175 }
176 crc = crc32(0, &rx, sizeof(rx) - 4);
177 if (crc != je32_to_cpu(rx.node_crc)) {
178 if (je32_to_cpu(rx.node_crc) != 0xffffffff)
179 JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
180 ref_offset(xd->node), je32_to_cpu(rx.hdr_crc), crc);
181 return EIO;
182 }
183 totlen = PAD(sizeof(rx) + rx.name_len + 1 + je16_to_cpu(rx.value_len));
184 if (je16_to_cpu(rx.magic) != JFFS2_MAGIC_BITMASK
185 || je16_to_cpu(rx.nodetype) != JFFS2_NODETYPE_XATTR
186 || je32_to_cpu(rx.totlen) != totlen
187 || je32_to_cpu(rx.xid) != xd->xid
188 || je32_to_cpu(rx.version) != xd->version) {
189 JFFS2_ERROR("inconsistent xdatum at %#08x, magic=%#04x/%#04x, "
190 "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,
192 je16_to_cpu(rx.nodetype), JFFS2_NODETYPE_XATTR,
193 je32_to_cpu(rx.totlen), totlen,
194 je32_to_cpu(rx.xid), xd->xid,
195 je32_to_cpu(rx.version), xd->version);
196 return EIO;
197 }
198 xd->xprefix = rx.xprefix;
199 xd->name_len = rx.name_len;
200 xd->value_len = je16_to_cpu(rx.value_len);
201 xd->data_crc = je32_to_cpu(rx.data_crc);
202
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);
208 c->unchecked_size -= totlen; c->used_size += totlen;
209 jeb->unchecked_size -= totlen; jeb->used_size += totlen;
210 xd->node->flash_offset = ref_offset(xd->node) | REF_PRISTINE;
211 spin_unlock(&c->erase_completion_lock);
212
213 /* unchecked xdatum is chained with c->xattr_unchecked */
214 list_del_init(&xd->xindex);
215
216 dbg_xattr("success on verfying xdatum (xid=%u, version=%u)\n",
217 xd->xid, xd->version);
218
219 return 0;
220}
221
222static int do_load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
223{
224 /* must be called under down_write(xattr_sem) */
225 char *data;
226 size_t readlen;
227 uint32_t crc, length;
228 int i, ret, retry = 0;
229
230 BUG_ON(!xd->node);
231 BUG_ON(ref_flags(xd->node) != REF_PRISTINE);
232 BUG_ON(!list_empty(&xd->xindex));
233 retry:
234 length = xd->name_len + 1 + xd->value_len;
235 data = kmalloc(length, GFP_KERNEL);
236 if (!data)
237 return -ENOMEM;
238
239 ret = jffs2_flash_read(c, ref_offset(xd->node)+sizeof(struct jffs2_raw_xattr),
240 length, &readlen, data);
241
242 if (ret || length!=readlen) {
243 JFFS2_WARNING("jffs2_flash_read() returned %d, request=%d, readlen=%d, at %#08x\n",
244 ret, length, readlen, ref_offset(xd->node));
245 kfree(data);
246 return ret ? ret : -EIO;
247 }
248
249 data[xd->name_len] = '\0';
250 crc = crc32(0, data, length);
251 if (crc != xd->data_crc) {
252 JFFS2_WARNING("node CRC failed (JFFS2_NODETYPE_XREF)"
253 " at %#08x, read: 0x%08x calculated: 0x%08x\n",
254 ref_offset(xd->node), xd->data_crc, crc);
255 kfree(data);
256 return EIO;
257 }
258
259 xd->flags |= JFFS2_XFLAGS_HOT;
260 xd->xname = data;
261 xd->xvalue = data + xd->name_len+1;
262
263 c->xdatum_mem_usage += length;
264
265 xd->hashkey = xattr_datum_hashkey(xd->xprefix, xd->xname, xd->xvalue, xd->value_len);
266 i = xd->hashkey % XATTRINDEX_HASHSIZE;
267 list_add(&xd->xindex, &c->xattrindex[i]);
268 if (!retry) {
269 retry = 1;
270 reclaim_xattr_datum(c);
271 if (!xd->xname)
272 goto retry;
273 }
274
275 dbg_xattr("success on loading xdatum (xid=%u, xprefix=%u, xname='%s')\n",
276 xd->xid, xd->xprefix, xd->xname);
277
278 return 0;
279}
280
281static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
282{
283 /* must be called under down_write(xattr_sem);
284 * rc < 0 : recoverable error, try again
285 * rc = 0 : success
286 * rc > 0 : Unrecoverable error, this node should be deleted.
287 */
288 int rc = 0;
289 BUG_ON(xd->xname);
290 if (!xd->node)
291 return EIO;
292 if (unlikely(ref_flags(xd->node) != REF_PRISTINE)) {
293 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)
300 rc = do_load_xattr_datum(c, xd);
301 return rc;
302}
303
304static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd, uint32_t phys_ofs)
305{
306 /* must be called under down_write(xattr_sem) */
307 struct jffs2_raw_xattr rx;
308 struct jffs2_raw_node_ref *raw;
309 struct kvec vecs[2];
310 uint32_t length;
311 int rc, totlen;
312
313 BUG_ON(!xd->xname);
314
315 vecs[0].iov_base = &rx;
316 vecs[0].iov_len = PAD(sizeof(rx));
317 vecs[1].iov_base = xd->xname;
318 vecs[1].iov_len = xd->name_len + 1 + xd->value_len;
319 totlen = vecs[0].iov_len + vecs[1].iov_len;
320
321 raw = jffs2_alloc_raw_node_ref();
322 if (!raw)
323 return -ENOMEM;
324 raw->flash_offset = phys_ofs;
325 raw->__totlen = PAD(totlen);
326 raw->next_phys = NULL;
327 raw->next_in_ino = (void *)xd;
328
329 /* Setup raw-xattr */
330 rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
331 rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR);
332 rx.totlen = cpu_to_je32(PAD(totlen));
333 rx.hdr_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_unknown_node) - 4));
334
335 rx.xid = cpu_to_je32(xd->xid);
336 rx.version = cpu_to_je32(++xd->version);
337 rx.xprefix = xd->xprefix;
338 rx.name_len = xd->name_len;
339 rx.value_len = cpu_to_je16(xd->value_len);
340 rx.data_crc = cpu_to_je32(crc32(0, vecs[1].iov_base, vecs[1].iov_len));
341 rx.node_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_raw_xattr) - 4));
342
343 rc = jffs2_flash_writev(c, vecs, 2, phys_ofs, &length, 0);
344 if (rc || totlen != length) {
345 JFFS2_WARNING("jffs2_flash_writev()=%d, req=%u, wrote=%u, at %#08x\n",
346 rc, totlen, length, phys_ofs);
347 rc = rc ? rc : -EIO;
348 if (length) {
349 raw->flash_offset |= REF_OBSOLETE;
350 raw->next_in_ino = NULL;
351 jffs2_add_physical_node_ref(c, raw);
352 jffs2_mark_node_obsolete(c, raw);
353 } else {
354 jffs2_free_raw_node_ref(raw);
355 }
356 return rc;
357 }
358 BUG_ON(raw->__totlen < sizeof(struct jffs2_raw_xattr));
359 /* success */
360 raw->flash_offset |= REF_PRISTINE;
361 jffs2_add_physical_node_ref(c, raw);
362 if (xd->node)
363 delete_xattr_datum_node(c, xd);
364 xd->node = raw;
365
366 dbg_xattr("success on saving xdatum (xid=%u, version=%u, xprefix=%u, xname='%s')\n",
367 xd->xid, xd->version, xd->xprefix, xd->xname);
368
369 return 0;
370}
371
372static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c,
373 int xprefix, const char *xname,
374 const char *xvalue, int xsize,
375 uint32_t phys_ofs)
376{
377 /* must be called under down_write(xattr_sem) */
378 struct jffs2_xattr_datum *xd;
379 uint32_t hashkey, name_len;
380 char *data;
381 int i, rc;
382
383 /* Search xattr_datum has same xname/xvalue by index */
384 hashkey = xattr_datum_hashkey(xprefix, xname, xvalue, xsize);
385 i = hashkey % XATTRINDEX_HASHSIZE;
386 list_for_each_entry(xd, &c->xattrindex[i], xindex) {
387 if (xd->hashkey==hashkey
388 && xd->xprefix==xprefix
389 && xd->value_len==xsize
390 && !strcmp(xd->xname, xname)
391 && !memcmp(xd->xvalue, xvalue, xsize)) {
392 xd->refcnt++;
393 return xd;
394 }
395 }
396
397 /* Not found, Create NEW XATTR-Cache */
398 name_len = strlen(xname);
399
400 xd = jffs2_alloc_xattr_datum();
401 if (!xd)
402 return ERR_PTR(-ENOMEM);
403
404 data = kmalloc(name_len + 1 + xsize, GFP_KERNEL);
405 if (!data) {
406 jffs2_free_xattr_datum(xd);
407 return ERR_PTR(-ENOMEM);
408 }
409 strcpy(data, xname);
410 memcpy(data + name_len + 1, xvalue, xsize);
411
412 xd->refcnt = 1;
413 xd->xid = ++c->highest_xid;
414 xd->flags |= JFFS2_XFLAGS_HOT;
415 xd->xprefix = xprefix;
416
417 xd->hashkey = hashkey;
418 xd->xname = data;
419 xd->xvalue = data + name_len + 1;
420 xd->name_len = name_len;
421 xd->value_len = xsize;
422 xd->data_crc = crc32(0, data, xd->name_len + 1 + xd->value_len);
423
424 rc = save_xattr_datum(c, xd, phys_ofs);
425 if (rc) {
426 kfree(xd->xname);
427 jffs2_free_xattr_datum(xd);
428 return ERR_PTR(rc);
429 }
430
431 /* Insert Hash Index */
432 i = hashkey % XATTRINDEX_HASHSIZE;
433 list_add(&xd->xindex, &c->xattrindex[i]);
434
435 c->xdatum_mem_usage += (xd->name_len + 1 + xd->value_len);
436 reclaim_xattr_datum(c);
437
438 return xd;
439}
440
441/* -------- xdatum related functions ----------------
442 * verify_xattr_ref(c, ref)
443 * is used to load xref information from medium. Because summary data does not
444 * contain xid/ino, it's necessary to verify once while mounting process.
445 * delete_xattr_ref_node(c, ref)
446 * is used to delete a jffs2 node is dominated by xref. When EBS is enabled,
447 * it overwrites the obsolete node by myself.
448 * delete_xattr_ref(c, ref)
449 * is used to delete jffs2_xattr_ref object. If the reference counter of xdatum
450 * is refered by this xref become 0, delete_xattr_datum() is called later.
451 * save_xattr_ref(c, ref, phys_ofs)
452 * is used to write xref to medium.
453 * create_xattr_ref(c, ic, xd, phys_ofs)
454 * is used to create a new xref and write to medium.
455 * jffs2_xattr_delete_inode(c, ic)
456 * is called to remove xrefs related to obsolete inode when inode is unlinked.
457 * jffs2_xattr_free_inode(c, ic)
458 * is called to release xattr related objects when unmounting.
459 * check_xattr_ref_ilist(c, ic)
460 * is used to confirm inode does not have duplicate xattr name/value pair.
461 * -------------------------------------------------- */
462static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
463{
464 struct jffs2_eraseblock *jeb;
465 struct jffs2_raw_xref rr;
466 size_t readlen;
467 uint32_t crc, totlen;
468 int rc;
469
470 BUG_ON(ref_flags(ref->node) != REF_UNCHECKED);
471
472 rc = jffs2_flash_read(c, ref_offset(ref->node), sizeof(rr), &readlen, (char *)&rr);
473 if (rc || sizeof(rr) != readlen) {
474 JFFS2_WARNING("jffs2_flash_read()=%d, req=%u, read=%u, at %#08x\n",
475 rc, sizeof(rr), readlen, ref_offset(ref->node));
476 return rc ? rc : -EIO;
477 }
478 /* obsolete node */
479 crc = crc32(0, &rr, sizeof(rr) - 4);
480 if (crc != je32_to_cpu(rr.node_crc)) {
481 if (je32_to_cpu(rr.node_crc) != 0xffffffff)
482 JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
483 ref_offset(ref->node), je32_to_cpu(rr.node_crc), crc);
484 return EIO;
485 }
486 if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK
487 || je16_to_cpu(rr.nodetype) != JFFS2_NODETYPE_XREF
488 || je32_to_cpu(rr.totlen) != PAD(sizeof(rr))) {
489 JFFS2_ERROR("inconsistent xref at %#08x, magic=%#04x/%#04x, "
490 "nodetype=%#04x/%#04x, totlen=%u/%u\n",
491 ref_offset(ref->node), je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK,
492 je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF,
493 je32_to_cpu(rr.totlen), PAD(sizeof(rr)));
494 return EIO;
495 }
496 ref->ino = je32_to_cpu(rr.ino);
497 ref->xid = je32_to_cpu(rr.xid);
498
499 /* fixup superblock/eraseblock info */
500 jeb = &c->blocks[ref_offset(ref->node) / c->sector_size];
501 totlen = PAD(sizeof(rr));
502
503 spin_lock(&c->erase_completion_lock);
504 c->unchecked_size -= totlen; c->used_size += totlen;
505 jeb->unchecked_size -= totlen; jeb->used_size += totlen;
506 ref->node->flash_offset = ref_offset(ref->node) | REF_PRISTINE;
507 spin_unlock(&c->erase_completion_lock);
508
509 dbg_xattr("success on verifying xref (ino=%u, xid=%u) at %#08x\n",
510 ref->ino, ref->xid, ref_offset(ref->node));
511 return 0;
512}
513
514static void delete_xattr_ref_node(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
515{
516 struct jffs2_raw_xref rr;
517 uint32_t length;
518 int rc;
519
520 if (jffs2_sum_active()) {
521 memset(&rr, 0xff, sizeof(rr));
522 rc = jffs2_flash_read(c, ref_offset(ref->node),
523 sizeof(struct jffs2_unknown_node),
524 &length, (char *)&rr);
525 if (rc || length != sizeof(struct jffs2_unknown_node)) {
526 JFFS2_ERROR("jffs2_flash_read()=%d, req=%u, read=%u at %#08x\n",
527 rc, sizeof(struct jffs2_unknown_node),
528 length, ref_offset(ref->node));
529 }
530 rc = jffs2_flash_write(c, ref_offset(ref->node), sizeof(rr),
531 &length, (char *)&rr);
532 if (rc || length != sizeof(struct jffs2_raw_xref)) {
533 JFFS2_ERROR("jffs2_flash_write()=%d, req=%u, wrote=%u at %#08x\n",
534 rc, sizeof(rr), length, ref_offset(ref->node));
535 }
536 }
537 spin_lock(&c->erase_completion_lock);
538 ref->node->next_in_ino = NULL;
539 spin_unlock(&c->erase_completion_lock);
540 jffs2_mark_node_obsolete(c, ref->node);
541 ref->node = NULL;
542}
543
544static void delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
545{
546 /* must be called under down_write(xattr_sem) */
547 struct jffs2_xattr_datum *xd;
548
549 BUG_ON(!ref->node);
550 delete_xattr_ref_node(c, ref);
551
552 list_del(&ref->ilist);
553 xd = ref->xd;
554 xd->refcnt--;
555 if (!xd->refcnt)
556 delete_xattr_datum(c, xd);
557 jffs2_free_xattr_ref(ref);
558}
559
560static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref, uint32_t phys_ofs)
561{
562 /* must be called under down_write(xattr_sem) */
563 struct jffs2_raw_node_ref *raw;
564 struct jffs2_raw_xref rr;
565 uint32_t length;
566 int ret;
567
568 raw = jffs2_alloc_raw_node_ref();
569 if (!raw)
570 return -ENOMEM;
571 raw->flash_offset = phys_ofs;
572 raw->__totlen = PAD(sizeof(rr));
573 raw->next_phys = NULL;
574 raw->next_in_ino = (void *)ref;
575
576 rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
577 rr.nodetype = cpu_to_je16(JFFS2_NODETYPE_XREF);
578 rr.totlen = cpu_to_je32(PAD(sizeof(rr)));
579 rr.hdr_crc = cpu_to_je32(crc32(0, &rr, sizeof(struct jffs2_unknown_node) - 4));
580
581 rr.ino = cpu_to_je32(ref->ic->ino);
582 rr.xid = cpu_to_je32(ref->xd->xid);
583 rr.node_crc = cpu_to_je32(crc32(0, &rr, sizeof(rr) - 4));
584
585 ret = jffs2_flash_write(c, phys_ofs, sizeof(rr), &length, (char *)&rr);
586 if (ret || sizeof(rr) != length) {
587 JFFS2_WARNING("jffs2_flash_write() returned %d, request=%u, retlen=%u, at %#08x\n",
588 ret, sizeof(rr), length, phys_ofs);
589 ret = ret ? ret : -EIO;
590 if (length) {
591 raw->flash_offset |= REF_OBSOLETE;
592 raw->next_in_ino = NULL;
593 jffs2_add_physical_node_ref(c, raw);
594 jffs2_mark_node_obsolete(c, raw);
595 } else {
596 jffs2_free_raw_node_ref(raw);
597 }
598 return ret;
599 }
600 raw->flash_offset |= REF_PRISTINE;
601
602 jffs2_add_physical_node_ref(c, raw);
603 if (ref->node)
604 delete_xattr_ref_node(c, ref);
605 ref->node = raw;
606
607 dbg_xattr("success on saving xref (ino=%u, xid=%u)\n", ref->ic->ino, ref->xd->xid);
608
609 return 0;
610}
611
612static struct jffs2_xattr_ref *create_xattr_ref(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic,
613 struct jffs2_xattr_datum *xd, uint32_t phys_ofs)
614{
615 /* must be called under down_write(xattr_sem) */
616 struct jffs2_xattr_ref *ref;
617 int ret;
618
619 ref = jffs2_alloc_xattr_ref();
620 if (!ref)
621 return ERR_PTR(-ENOMEM);
622 ref->ic = ic;
623 ref->xd = xd;
624
625 ret = save_xattr_ref(c, ref, phys_ofs);
626 if (ret) {
627 jffs2_free_xattr_ref(ref);
628 return ERR_PTR(ret);
629 }
630
631 /* Chain to inode */
632 list_add(&ref->ilist, &ic->ilist);
633
634 return ref; /* success */
635}
636
637void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
638{
639 /* It's called from jffs2_clear_inode() on inode removing.
640 When an inode with XATTR is removed, those XATTRs must be removed. */
641 struct jffs2_xattr_ref *ref, *_ref;
642
643 if (!ic || ic->nlink > 0)
644 return;
645
646 down_write(&c->xattr_sem);
647 list_for_each_entry_safe(ref, _ref, &ic->ilist, ilist)
648 delete_xattr_ref(c, ref);
649 up_write(&c->xattr_sem);
650}
651
652void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
653{
654 /* It's called from jffs2_free_ino_caches() until unmounting FS. */
655 struct jffs2_xattr_datum *xd;
656 struct jffs2_xattr_ref *ref, *_ref;
657
658 down_write(&c->xattr_sem);
659 list_for_each_entry_safe(ref, _ref, &ic->ilist, ilist) {
660 list_del(&ref->ilist);
661 xd = ref->xd;
662 xd->refcnt--;
663 if (!xd->refcnt) {
664 unload_xattr_datum(c, xd);
665 jffs2_free_xattr_datum(xd);
666 }
667 jffs2_free_xattr_ref(ref);
668 }
669 up_write(&c->xattr_sem);
670}
671
672static int check_xattr_ref_ilist(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
673{
674 /* success of check_xattr_ref_ilist() means taht inode (ic) dose not have
675 * duplicate name/value pairs. If duplicate name/value pair would be found,
676 * one will be removed.
677 */
678 struct jffs2_xattr_ref *ref, *cmp;
679 int rc = 0;
680
681 if (likely(ic->flags & INO_FLAGS_XATTR_CHECKED))
682 return 0;
683 down_write(&c->xattr_sem);
684 retry:
685 rc = 0;
686 list_for_each_entry(ref, &ic->ilist, ilist) {
687 if (!ref->xd->xname) {
688 rc = load_xattr_datum(c, ref->xd);
689 if (unlikely(rc > 0)) {
690 delete_xattr_ref(c, ref);
691 goto retry;
692 } else if (unlikely(rc < 0))
693 goto out;
694 }
695 cmp = ref;
696 list_for_each_entry_continue(cmp, &ic->ilist, ilist) {
697 if (!cmp->xd->xname) {
698 ref->xd->flags |= JFFS2_XFLAGS_BIND;
699 rc = load_xattr_datum(c, cmp->xd);
700 ref->xd->flags &= ~JFFS2_XFLAGS_BIND;
701 if (unlikely(rc > 0)) {
702 delete_xattr_ref(c, cmp);
703 goto retry;
704 } else if (unlikely(rc < 0))
705 goto out;
706 }
707 if (ref->xd->xprefix == cmp->xd->xprefix
708 && !strcmp(ref->xd->xname, cmp->xd->xname)) {
709 delete_xattr_ref(c, cmp);
710 goto retry;
711 }
712 }
713 }
714 ic->flags |= INO_FLAGS_XATTR_CHECKED;
715 out:
716 up_write(&c->xattr_sem);
717
718 return rc;
719}
720
721/* -------- xattr subsystem functions ---------------
722 * jffs2_init_xattr_subsystem(c)
723 * is used to initialize semaphore and list_head, and some variables.
724 * jffs2_find_xattr_datum(c, xid)
725 * is used to lookup xdatum while scanning process.
726 * jffs2_clear_xattr_subsystem(c)
727 * is used to release any xattr related objects.
728 * jffs2_build_xattr_subsystem(c)
729 * is used to associate xdatum and xref while super block building process.
730 * jffs2_setup_xattr_datum(c, xid, version)
731 * is used to insert xdatum while scanning process.
732 * -------------------------------------------------- */
733void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c)
734{
735 int i;
736
737 for (i=0; i < XATTRINDEX_HASHSIZE; i++)
738 INIT_LIST_HEAD(&c->xattrindex[i]);
739 INIT_LIST_HEAD(&c->xattr_temp);
740 INIT_LIST_HEAD(&c->xattr_unchecked);
741
742 init_rwsem(&c->xattr_sem);
743 c->xdatum_mem_usage = 0;
744 c->xdatum_mem_threshold = 32 * 1024; /* Default 32KB */
745}
746
747static struct jffs2_xattr_datum *jffs2_find_xattr_datum(struct jffs2_sb_info *c, uint32_t xid)
748{
749 struct jffs2_xattr_datum *xd;
750 int i = xid % XATTRINDEX_HASHSIZE;
751
752 /* It's only used in scanning/building process. */
753 BUG_ON(!(c->flags & (JFFS2_SB_FLAG_SCANNING|JFFS2_SB_FLAG_BUILDING)));
754
755 list_for_each_entry(xd, &c->xattrindex[i], xindex) {
756 if (xd->xid==xid)
757 return xd;
758 }
759 return NULL;
760}
761
762void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c)
763{
764 struct jffs2_xattr_datum *xd, *_xd;
765 struct jffs2_xattr_ref *ref, *_ref;
766 int i;
767
768 list_for_each_entry_safe(ref, _ref, &c->xattr_temp, ilist)
769 jffs2_free_xattr_ref(ref);
770
771 for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
772 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
773 list_del(&xd->xindex);
774 if (xd->xname)
775 kfree(xd->xname);
776 jffs2_free_xattr_datum(xd);
777 }
778 }
779}
780
781void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
782{
783 struct jffs2_xattr_ref *ref, *_ref;
784 struct jffs2_xattr_datum *xd, *_xd;
785 struct jffs2_inode_cache *ic;
786 int i, xdatum_count =0, xdatum_unchecked_count = 0, xref_count = 0;
787
788 BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING));
789
790 /* Phase.1 */
791 list_for_each_entry_safe(ref, _ref, &c->xattr_temp, ilist) {
792 list_del_init(&ref->ilist);
793 /* checking REF_UNCHECKED nodes */
794 if (ref_flags(ref->node) != REF_PRISTINE) {
795 if (verify_xattr_ref(c, ref)) {
796 delete_xattr_ref_node(c, ref);
797 jffs2_free_xattr_ref(ref);
798 continue;
799 }
800 }
801 /* At this point, ref->xid and ref->ino contain XID and inode number.
802 ref->xd and ref->ic are not valid yet. */
803 xd = jffs2_find_xattr_datum(c, ref->xid);
804 ic = jffs2_get_ino_cache(c, ref->ino);
805 if (!xd || !ic) {
806 if (ref_flags(ref->node) != REF_UNCHECKED)
807 JFFS2_WARNING("xref(ino=%u, xid=%u) is orphan. \n",
808 ref->ino, ref->xid);
809 delete_xattr_ref_node(c, ref);
810 jffs2_free_xattr_ref(ref);
811 continue;
812 }
813 ref->xd = xd;
814 ref->ic = ic;
815 xd->refcnt++;
816 list_add_tail(&ref->ilist, &ic->ilist);
817 xref_count++;
818 }
819 /* After this, ref->xid/ino are NEVER used. */
820
821 /* Phase.2 */
822 for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
823 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
824 list_del_init(&xd->xindex);
825 if (!xd->refcnt) {
826 if (ref_flags(xd->node) != REF_UNCHECKED)
827 JFFS2_WARNING("orphan xdatum(xid=%u, version=%u) at %#08x\n",
828 xd->xid, xd->version, ref_offset(xd->node));
829 delete_xattr_datum(c, xd);
830 continue;
831 }
832 if (ref_flags(xd->node) != REF_PRISTINE) {
833 dbg_xattr("unchecked xdatum(xid=%u) at %#08x\n",
834 xd->xid, ref_offset(xd->node));
835 list_add(&xd->xindex, &c->xattr_unchecked);
836 xdatum_unchecked_count++;
837 }
838 xdatum_count++;
839 }
840 }
841 /* build complete */
842 JFFS2_NOTICE("complete building xattr subsystem, %u of xdatum (%u unchecked) and "
843 "%u of xref found.\n", xdatum_count, xdatum_unchecked_count, xref_count);
844}
845
846struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
847 uint32_t xid, uint32_t version)
848{
849 struct jffs2_xattr_datum *xd, *_xd;
850
851 _xd = jffs2_find_xattr_datum(c, xid);
852 if (_xd) {
853 dbg_xattr("duplicate xdatum (xid=%u, version=%u/%u) at %#08x\n",
854 xid, version, _xd->version, ref_offset(_xd->node));
855 if (version < _xd->version)
856 return ERR_PTR(-EEXIST);
857 }
858 xd = jffs2_alloc_xattr_datum();
859 if (!xd)
860 return ERR_PTR(-ENOMEM);
861 xd->xid = xid;
862 xd->version = version;
863 if (xd->xid > c->highest_xid)
864 c->highest_xid = xd->xid;
865 list_add_tail(&xd->xindex, &c->xattrindex[xid % XATTRINDEX_HASHSIZE]);
866
867 if (_xd) {
868 list_del_init(&_xd->xindex);
869 delete_xattr_datum_node(c, _xd);
870 jffs2_free_xattr_datum(_xd);
871 }
872 return xd;
873}
874
875/* -------- xattr subsystem functions ---------------
876 * xprefix_to_handler(xprefix)
877 * is used to translate xprefix into xattr_handler.
878 * jffs2_listxattr(dentry, buffer, size)
879 * is an implementation of listxattr handler on jffs2.
880 * do_jffs2_getxattr(inode, xprefix, xname, buffer, size)
881 * is an implementation of getxattr handler on jffs2.
882 * do_jffs2_setxattr(inode, xprefix, xname, buffer, size, flags)
883 * is an implementation of setxattr handler on jffs2.
884 * -------------------------------------------------- */
885struct xattr_handler *jffs2_xattr_handlers[] = {
886 &jffs2_user_xattr_handler,
887#ifdef CONFIG_JFFS2_FS_SECURITY
888 &jffs2_security_xattr_handler,
889#endif
890#ifdef CONFIG_JFFS2_FS_POSIX_ACL
891 &jffs2_acl_access_xattr_handler,
892 &jffs2_acl_default_xattr_handler,
893#endif
894 &jffs2_trusted_xattr_handler,
895 NULL
896};
897
898static struct xattr_handler *xprefix_to_handler(int xprefix) {
899 struct xattr_handler *ret;
900
901 switch (xprefix) {
902 case JFFS2_XPREFIX_USER:
903 ret = &jffs2_user_xattr_handler;
904 break;
905#ifdef CONFIG_JFFS2_FS_SECURITY
906 case JFFS2_XPREFIX_SECURITY:
907 ret = &jffs2_security_xattr_handler;
908 break;
909#endif
910#ifdef CONFIG_JFFS2_FS_POSIX_ACL
911 case JFFS2_XPREFIX_ACL_ACCESS:
912 ret = &jffs2_acl_access_xattr_handler;
913 break;
914 case JFFS2_XPREFIX_ACL_DEFAULT:
915 ret = &jffs2_acl_default_xattr_handler;
916 break;
917#endif
918 case JFFS2_XPREFIX_TRUSTED:
919 ret = &jffs2_trusted_xattr_handler;
920 break;
921 default:
922 ret = NULL;
923 break;
924 }
925 return ret;
926}
927
928ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
929{
930 struct inode *inode = dentry->d_inode;
931 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
932 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
933 struct jffs2_inode_cache *ic = f->inocache;
934 struct jffs2_xattr_ref *ref;
935 struct jffs2_xattr_datum *xd;
936 struct xattr_handler *xhandle;
937 ssize_t len, rc;
938 int retry = 0;
939
940 rc = check_xattr_ref_ilist(c, ic);
941 if (unlikely(rc))
942 return rc;
943
944 down_read(&c->xattr_sem);
945 retry:
946 len = 0;
947 list_for_each_entry(ref, &ic->ilist, ilist) {
948 BUG_ON(ref->ic != ic);
949 xd = ref->xd;
950 if (!xd->xname) {
951 /* xdatum is unchached */
952 if (!retry) {
953 retry = 1;
954 up_read(&c->xattr_sem);
955 down_write(&c->xattr_sem);
956 goto retry;
957 } else {
958 rc = load_xattr_datum(c, xd);
959 if (unlikely(rc > 0)) {
960 delete_xattr_ref(c, ref);
961 goto retry;
962 } else if (unlikely(rc < 0))
963 goto out;
964 }
965 }
966 xhandle = xprefix_to_handler(xd->xprefix);
967 if (!xhandle)
968 continue;
969 if (buffer) {
970 rc = xhandle->list(inode, buffer+len, size-len, xd->xname, xd->name_len);
971 } else {
972 rc = xhandle->list(inode, NULL, 0, xd->xname, xd->name_len);
973 }
974 if (rc < 0)
975 goto out;
976 len += rc;
977 }
978 rc = len;
979 out:
980 if (!retry) {
981 up_read(&c->xattr_sem);
982 } else {
983 up_write(&c->xattr_sem);
984 }
985 return rc;
986}
987
988int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname,
989 char *buffer, size_t size)
990{
991 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
992 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
993 struct jffs2_inode_cache *ic = f->inocache;
994 struct jffs2_xattr_datum *xd;
995 struct jffs2_xattr_ref *ref;
996 int rc, retry = 0;
997
998 rc = check_xattr_ref_ilist(c, ic);
999 if (unlikely(rc))
1000 return rc;
1001
1002 down_read(&c->xattr_sem);
1003 retry:
1004 list_for_each_entry(ref, &ic->ilist, ilist) {
1005 BUG_ON(ref->ic!=ic);
1006
1007 xd = ref->xd;
1008 if (xd->xprefix != xprefix)
1009 continue;
1010 if (!xd->xname) {
1011 /* xdatum is unchached */
1012 if (!retry) {
1013 retry = 1;
1014 up_read(&c->xattr_sem);
1015 down_write(&c->xattr_sem);
1016 goto retry;
1017 } else {
1018 rc = load_xattr_datum(c, xd);
1019 if (unlikely(rc > 0)) {
1020 delete_xattr_ref(c, ref);
1021 goto retry;
1022 } else if (unlikely(rc < 0)) {
1023 goto out;
1024 }
1025 }
1026 }
1027 if (!strcmp(xname, xd->xname)) {
1028 rc = xd->value_len;
1029 if (buffer) {
1030 if (size < rc) {
1031 rc = -ERANGE;
1032 } else {
1033 memcpy(buffer, xd->xvalue, rc);
1034 }
1035 }
1036 goto out;
1037 }
1038 }
1039 rc = -ENODATA;
1040 out:
1041 if (!retry) {
1042 up_read(&c->xattr_sem);
1043 } else {
1044 up_write(&c->xattr_sem);
1045 }
1046 return rc;
1047}
1048
1049int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1050 const char *buffer, size_t size, int flags)
1051{
1052 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
1053 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
1054 struct jffs2_inode_cache *ic = f->inocache;
1055 struct jffs2_xattr_datum *xd;
1056 struct jffs2_xattr_ref *ref, *newref;
1057 uint32_t phys_ofs, length, request;
1058 int rc;
1059
1060 rc = check_xattr_ref_ilist(c, ic);
1061 if (unlikely(rc))
1062 return rc;
1063
1064 request = PAD(sizeof(struct jffs2_raw_xattr) + strlen(xname) + 1 + size);
1065 rc = jffs2_reserve_space(c, request, &phys_ofs, &length,
1066 ALLOC_NORMAL, JFFS2_SUMMARY_XATTR_SIZE);
1067 if (rc) {
1068 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request);
1069 return rc;
1070 }
1071
1072 /* Find existing xattr */
1073 down_write(&c->xattr_sem);
1074 retry:
1075 list_for_each_entry(ref, &ic->ilist, ilist) {
1076 xd = ref->xd;
1077 if (xd->xprefix != xprefix)
1078 continue;
1079 if (!xd->xname) {
1080 rc = load_xattr_datum(c, xd);
1081 if (unlikely(rc > 0)) {
1082 delete_xattr_ref(c, ref);
1083 goto retry;
1084 } else if (unlikely(rc < 0))
1085 goto out;
1086 }
1087 if (!strcmp(xd->xname, xname)) {
1088 if (flags & XATTR_CREATE) {
1089 rc = -EEXIST;
1090 goto out;
1091 }
1092 if (!buffer) {
1093 delete_xattr_ref(c, ref);
1094 rc = 0;
1095 goto out;
1096 }
1097 goto found;
1098 }
1099 }
1100 /* not found */
1101 ref = NULL;
1102 if (flags & XATTR_REPLACE) {
1103 rc = -ENODATA;
1104 goto out;
1105 }
1106 if (!buffer) {
1107 rc = -EINVAL;
1108 goto out;
1109 }
1110 found:
1111 xd = create_xattr_datum(c, xprefix, xname, buffer, size, phys_ofs);
1112 if (IS_ERR(xd)) {
1113 rc = PTR_ERR(xd);
1114 goto out;
1115 }
1116 up_write(&c->xattr_sem);
1117 jffs2_complete_reservation(c);
1118
1119 /* create xattr_ref */
1120 request = PAD(sizeof(struct jffs2_raw_xref));
1121 rc = jffs2_reserve_space(c, request, &phys_ofs, &length,
1122 ALLOC_NORMAL, JFFS2_SUMMARY_XREF_SIZE);
1123 if (rc) {
1124 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request);
1125 down_write(&c->xattr_sem);
1126 xd->refcnt--;
1127 if (!xd->refcnt)
1128 delete_xattr_datum(c, xd);
1129 up_write(&c->xattr_sem);
1130 return rc;
1131 }
1132 down_write(&c->xattr_sem);
1133 newref = create_xattr_ref(c, ic, xd, phys_ofs);
1134 if (IS_ERR(newref)) {
1135 rc = PTR_ERR(newref);
1136 xd->refcnt--;
1137 if (!xd->refcnt)
1138 delete_xattr_datum(c, xd);
1139 } else if (ref) {
1140 /* If replaced xattr_ref exists */
1141 delete_xattr_ref(c, ref);
1142 }
1143 out:
1144 up_write(&c->xattr_sem);
1145 jffs2_complete_reservation(c);
1146 return rc;
1147}
1148
1149/* -------- garbage collector functions -------------
1150 * jffs2_garbage_collect_xattr_datum(c, xd)
1151 * is used to move xdatum into new node.
1152 * jffs2_garbage_collect_xattr_ref(c, ref)
1153 * is used to move xref into new node.
1154 * jffs2_garbage_collect_xattr(c, ic)
1155 * is used to call appropriate garbage collector function, if argument
1156 * pointer (ic) is the reference of xdatum/xref.
1157 * jffs2_verify_xattr(c)
1158 * is used to call do_verify_xattr_datum() before garbage collecting.
1159 * -------------------------------------------------- */
1160static int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c,
1161 struct jffs2_xattr_datum *xd)
1162{
1163 /* must be called under down_write(xattr_sem), and called from GC thread */
1164 uint32_t phys_ofs, totlen, length, old_ofs;
1165 int rc;
1166
1167 BUG_ON(!xd->node);
1168
1169 old_ofs = ref_offset(xd->node);
1170 totlen = ref_totlen(c, c->gcblock, xd->node);
1171 if (totlen < sizeof(struct jffs2_raw_xattr))
1172 return -EINVAL;
1173
1174 if (!xd->xname) {
1175 rc = load_xattr_datum(c, xd);
1176 if (unlikely(rc > 0)) {
1177 delete_xattr_datum_node(c, xd);
1178 return 0;
1179 } else if (unlikely(rc < 0))
1180 return -EINVAL;
1181 }
1182 rc = jffs2_reserve_space_gc(c, totlen, &phys_ofs, &length, JFFS2_SUMMARY_XATTR_SIZE);
1183 if (rc || length < totlen) {
1184 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, totlen);
1185 return rc ? rc : -EBADFD;
1186 }
1187 rc = save_xattr_datum(c, xd, phys_ofs);
1188 if (!rc)
1189 dbg_xattr("xdatum (xid=%u, version=%u) GC'ed from %#08x to %08x\n",
1190 xd->xid, xd->version, old_ofs, ref_offset(xd->node));
1191 return rc;
1192}
1193
1194
1195static int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c,
1196 struct jffs2_xattr_ref *ref)
1197{
1198 /* must be called under down(alloc_sem) */
1199 uint32_t phys_ofs, totlen, length, old_ofs;
1200 int rc;
1201
1202 BUG_ON(!ref->node);
1203
1204 old_ofs = ref_offset(ref->node);
1205 totlen = ref_totlen(c, c->gcblock, ref->node);
1206 if (totlen != sizeof(struct jffs2_raw_xref))
1207 return -EINVAL;
1208 rc = jffs2_reserve_space_gc(c, totlen, &phys_ofs, &length, JFFS2_SUMMARY_XREF_SIZE);
1209 if (rc || length < totlen) {
1210 JFFS2_WARNING("%s: jffs2_reserve_space() = %d, request = %u\n",
1211 __FUNCTION__, rc, totlen);
1212 return rc ? rc : -EBADFD;
1213 }
1214 rc = save_xattr_ref(c, ref, phys_ofs);
1215 if (!rc)
1216 dbg_xattr("xref (ino=%u, xid=%u) GC'ed from %#08x to %08x\n",
1217 ref->ic->ino, ref->xd->xid, old_ofs, ref_offset(ref->node));
1218 return rc;
1219}
1220
1221int jffs2_garbage_collect_xattr(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
1222{
1223 struct jffs2_xattr_datum *xd;
1224 struct jffs2_xattr_ref *ref;
1225 int ret;
1226
1227 switch (ic->class) {
1228 case RAWNODE_CLASS_XATTR_DATUM:
1229 spin_unlock(&c->erase_completion_lock);
1230
1231 down_write(&c->xattr_sem);
1232 xd = (struct jffs2_xattr_datum *)ic;
1233 ret = xd ? jffs2_garbage_collect_xattr_datum(c, xd) : 0;
1234 up_write(&c->xattr_sem);
1235 break;
1236 case RAWNODE_CLASS_XATTR_REF:
1237 spin_unlock(&c->erase_completion_lock);
1238
1239 down_write(&c->xattr_sem);
1240 ref = (struct jffs2_xattr_ref *)ic;
1241 ret = ref ? jffs2_garbage_collect_xattr_ref(c, ref) : 0;
1242 up_write(&c->xattr_sem);
1243 break;
1244 default:
1245 /* This node is not xattr_datum/xattr_ref */
1246 ret = 1;
1247 break;
1248 }
1249 return ret;
1250}
1251
1252int jffs2_verify_xattr(struct jffs2_sb_info *c)
1253{
1254 struct jffs2_xattr_datum *xd, *_xd;
1255 int rc;
1256
1257 down_write(&c->xattr_sem);
1258 list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) {
1259 rc = do_verify_xattr_datum(c, xd);
1260 if (rc == 0) {
1261 list_del_init(&xd->xindex);
1262 break;
1263 } else if (rc > 0) {
1264 list_del_init(&xd->xindex);
1265 delete_xattr_datum_node(c, xd);
1266 }
1267 }
1268 up_write(&c->xattr_sem);
1269
1270 return list_empty(&c->xattr_unchecked) ? 1 : 0;
1271}