aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2006-05-21 14:05:55 -0400
committerDavid Woodhouse <dwmw2@infradead.org>2006-05-21 14:05:55 -0400
commit0d25971d7c969debf76f9fab6d6b37cb62408f55 (patch)
tree89e6b432d4e8c84d59b4738e5bc1c47a2402adf2
parent615191bb1dfc6980e7c7a85225444d860d74b343 (diff)
parentca89a517fa577e6f26621463d3aa4f3c3d530b1e (diff)
Merge git://git.infradead.org/jffs2-devel-2.6
-rw-r--r--fs/Kconfig38
-rw-r--r--fs/jffs2/Makefile3
-rw-r--r--fs/jffs2/README.Locking21
-rw-r--r--fs/jffs2/acl.c485
-rw-r--r--fs/jffs2/acl.h45
-rw-r--r--fs/jffs2/build.c2
-rw-r--r--fs/jffs2/debug.h6
-rw-r--r--fs/jffs2/dir.c62
-rw-r--r--fs/jffs2/erase.c21
-rw-r--r--fs/jffs2/file.c7
-rw-r--r--fs/jffs2/fs.c11
-rw-r--r--fs/jffs2/gc.c78
-rw-r--r--fs/jffs2/jffs2_fs_i.h5
-rw-r--r--fs/jffs2/jffs2_fs_sb.h10
-rw-r--r--fs/jffs2/malloc.c67
-rw-r--r--fs/jffs2/nodelist.c147
-rw-r--r--fs/jffs2/nodelist.h90
-rw-r--r--fs/jffs2/nodemgmt.c67
-rw-r--r--fs/jffs2/os-linux.h4
-rw-r--r--fs/jffs2/scan.c392
-rw-r--r--fs/jffs2/security.c82
-rw-r--r--fs/jffs2/summary.c385
-rw-r--r--fs/jffs2/summary.h62
-rw-r--r--fs/jffs2/super.c6
-rw-r--r--fs/jffs2/symlink.c7
-rw-r--r--fs/jffs2/wbuf.c33
-rw-r--r--fs/jffs2/write.c13
-rw-r--r--fs/jffs2/xattr.c1258
-rw-r--r--fs/jffs2/xattr.h116
-rw-r--r--fs/jffs2/xattr_trusted.c52
-rw-r--r--fs/jffs2/xattr_user.c52
-rw-r--r--include/linux/jffs2.h40
32 files changed, 3306 insertions, 361 deletions
diff --git a/fs/Kconfig b/fs/Kconfig
index f9b5842c8d2d..2496ccbe2604 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1075,6 +1075,44 @@ config JFFS2_FS_DEBUG
1075 If reporting bugs, please try to have available a full dump of the 1075 If reporting bugs, please try to have available a full dump of the
1076 messages at debug level 1 while the misbehaviour was occurring. 1076 messages at debug level 1 while the misbehaviour was occurring.
1077 1077
1078config JFFS2_FS_XATTR
1079 bool "JFFS2 XATTR support"
1080 depends on JFFS2_FS
1081 default n
1082 help
1083 Extended attributes are name:value pairs associated with inodes by
1084 the kernel or by users (see the attr(5) manual page, or visit
1085 <http://acl.bestbits.at/> for details).
1086
1087 If unsure, say N.
1088
1089config JFFS2_FS_POSIX_ACL
1090 bool "JFFS2 POSIX Access Control Lists"
1091 depends on JFFS2_FS_XATTR
1092 default y
1093 select FS_POSIX_ACL
1094 help
1095 Posix Access Control Lists (ACLs) support permissions for users and
1096 groups beyond the owner/group/world scheme.
1097
1098 To learn more about Access Control Lists, visit the Posix ACLs for
1099 Linux website <http://acl.bestbits.at/>.
1100
1101 If you don't know what Access Control Lists are, say N
1102
1103config JFFS2_FS_SECURITY
1104 bool "JFFS2 Security Labels"
1105 depends on JFFS2_FS_XATTR
1106 default y
1107 help
1108 Security labels support alternative access control models
1109 implemented by security modules like SELinux. This option
1110 enables an extended attribute handler for file security
1111 labels in the jffs2 filesystem.
1112
1113 If you are not using a security module that requires using
1114 extended attributes for file security labels, say N.
1115
1078config JFFS2_FS_WRITEBUFFER 1116config JFFS2_FS_WRITEBUFFER
1079 bool "JFFS2 write-buffering support" 1117 bool "JFFS2 write-buffering support"
1080 depends on JFFS2_FS 1118 depends on JFFS2_FS
diff --git a/fs/jffs2/Makefile b/fs/jffs2/Makefile
index 77dc5561a04e..7f28ee0bd132 100644
--- a/fs/jffs2/Makefile
+++ b/fs/jffs2/Makefile
@@ -12,6 +12,9 @@ jffs2-y += symlink.o build.o erase.o background.o fs.o writev.o
12jffs2-y += super.o debug.o 12jffs2-y += super.o debug.o
13 13
14jffs2-$(CONFIG_JFFS2_FS_WRITEBUFFER) += wbuf.o 14jffs2-$(CONFIG_JFFS2_FS_WRITEBUFFER) += wbuf.o
15jffs2-$(CONFIG_JFFS2_FS_XATTR) += xattr.o xattr_trusted.o xattr_user.o
16jffs2-$(CONFIG_JFFS2_FS_SECURITY) += security.o
17jffs2-$(CONFIG_JFFS2_FS_POSIX_ACL) += acl.o
15jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rubin.o 18jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rubin.o
16jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o 19jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o
17jffs2-$(CONFIG_JFFS2_ZLIB) += compr_zlib.o 20jffs2-$(CONFIG_JFFS2_ZLIB) += compr_zlib.o
diff --git a/fs/jffs2/README.Locking b/fs/jffs2/README.Locking
index b7943439b6ec..c8f0bd64e53e 100644
--- a/fs/jffs2/README.Locking
+++ b/fs/jffs2/README.Locking
@@ -150,3 +150,24 @@ the buffer.
150 150
151Ordering constraints: 151Ordering constraints:
152 Lock wbuf_sem last, after the alloc_sem or and f->sem. 152 Lock wbuf_sem last, after the alloc_sem or and f->sem.
153
154
155 c->xattr_sem
156 ------------
157
158This read/write semaphore protects against concurrent access to the
159xattr related objects which include stuff in superblock and ic->xref.
160In read-only path, write-semaphore is too much exclusion. It's enough
161by read-semaphore. But you must hold write-semaphore when updating,
162creating or deleting any xattr related object.
163
164Once xattr_sem released, there would be no assurance for the existence
165of those objects. Thus, a series of processes is often required to retry,
166when updating such a object is necessary under holding read semaphore.
167For example, do_jffs2_getxattr() holds read-semaphore to scan xref and
168xdatum at first. But it retries this process with holding write-semaphore
169after release read-semaphore, if it's necessary to load name/value pair
170from medium.
171
172Ordering constraints:
173 Lock xattr_sem last, after the alloc_sem.
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
new file mode 100644
index 000000000000..320dd48b834e
--- /dev/null
+++ b/fs/jffs2/acl.c
@@ -0,0 +1,485 @@
1/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright (C) 2006 NEC Corporation
5 *
6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
7 *
8 * For licensing information, see the file 'LICENCE' in this 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/crc32.h>
16#include <linux/jffs2.h>
17#include <linux/xattr.h>
18#include <linux/posix_acl_xattr.h>
19#include <linux/mtd/mtd.h>
20#include "nodelist.h"
21
22static size_t jffs2_acl_size(int count)
23{
24 if (count <= 4) {
25 return sizeof(struct jffs2_acl_header)
26 + count * sizeof(struct jffs2_acl_entry_short);
27 } else {
28 return sizeof(struct jffs2_acl_header)
29 + 4 * sizeof(struct jffs2_acl_entry_short)
30 + (count - 4) * sizeof(struct jffs2_acl_entry);
31 }
32}
33
34static int jffs2_acl_count(size_t size)
35{
36 size_t s;
37
38 size -= sizeof(struct jffs2_acl_header);
39 s = size - 4 * sizeof(struct jffs2_acl_entry_short);
40 if (s < 0) {
41 if (size % sizeof(struct jffs2_acl_entry_short))
42 return -1;
43 return size / sizeof(struct jffs2_acl_entry_short);
44 } else {
45 if (s % sizeof(struct jffs2_acl_entry))
46 return -1;
47 return s / sizeof(struct jffs2_acl_entry) + 4;
48 }
49}
50
51static struct posix_acl *jffs2_acl_from_medium(void *value, size_t size)
52{
53 void *end = value + size;
54 struct jffs2_acl_header *header = value;
55 struct jffs2_acl_entry *entry;
56 struct posix_acl *acl;
57 uint32_t ver;
58 int i, count;
59
60 if (!value)
61 return NULL;
62 if (size < sizeof(struct jffs2_acl_header))
63 return ERR_PTR(-EINVAL);
64 ver = je32_to_cpu(header->a_version);
65 if (ver != JFFS2_ACL_VERSION) {
66 JFFS2_WARNING("Invalid ACL version. (=%u)\n", ver);
67 return ERR_PTR(-EINVAL);
68 }
69
70 value += sizeof(struct jffs2_acl_header);
71 count = jffs2_acl_count(size);
72 if (count < 0)
73 return ERR_PTR(-EINVAL);
74 if (count == 0)
75 return NULL;
76
77 acl = posix_acl_alloc(count, GFP_KERNEL);
78 if (!acl)
79 return ERR_PTR(-ENOMEM);
80
81 for (i=0; i < count; i++) {
82 entry = value;
83 if (value + sizeof(struct jffs2_acl_entry_short) > end)
84 goto fail;
85 acl->a_entries[i].e_tag = je16_to_cpu(entry->e_tag);
86 acl->a_entries[i].e_perm = je16_to_cpu(entry->e_perm);
87 switch (acl->a_entries[i].e_tag) {
88 case ACL_USER_OBJ:
89 case ACL_GROUP_OBJ:
90 case ACL_MASK:
91 case ACL_OTHER:
92 value += sizeof(struct jffs2_acl_entry_short);
93 acl->a_entries[i].e_id = ACL_UNDEFINED_ID;
94 break;
95
96 case ACL_USER:
97 case ACL_GROUP:
98 value += sizeof(struct jffs2_acl_entry);
99 if (value > end)
100 goto fail;
101 acl->a_entries[i].e_id = je32_to_cpu(entry->e_id);
102 break;
103
104 default:
105 goto fail;
106 }
107 }
108 if (value != end)
109 goto fail;
110 return acl;
111 fail:
112 posix_acl_release(acl);
113 return ERR_PTR(-EINVAL);
114}
115
116static void *jffs2_acl_to_medium(const struct posix_acl *acl, size_t *size)
117{
118 struct jffs2_acl_header *header;
119 struct jffs2_acl_entry *entry;
120 void *e;
121 size_t i;
122
123 *size = jffs2_acl_size(acl->a_count);
124 header = kmalloc(sizeof(*header) + acl->a_count * sizeof(*entry), GFP_KERNEL);
125 if (!header)
126 return ERR_PTR(-ENOMEM);
127 header->a_version = cpu_to_je32(JFFS2_ACL_VERSION);
128 e = header + 1;
129 for (i=0; i < acl->a_count; i++) {
130 entry = e;
131 entry->e_tag = cpu_to_je16(acl->a_entries[i].e_tag);
132 entry->e_perm = cpu_to_je16(acl->a_entries[i].e_perm);
133 switch(acl->a_entries[i].e_tag) {
134 case ACL_USER:
135 case ACL_GROUP:
136 entry->e_id = cpu_to_je32(acl->a_entries[i].e_id);
137 e += sizeof(struct jffs2_acl_entry);
138 break;
139
140 case ACL_USER_OBJ:
141 case ACL_GROUP_OBJ:
142 case ACL_MASK:
143 case ACL_OTHER:
144 e += sizeof(struct jffs2_acl_entry_short);
145 break;
146
147 default:
148 goto fail;
149 }
150 }
151 return header;
152 fail:
153 kfree(header);
154 return ERR_PTR(-EINVAL);
155}
156
157static struct posix_acl *jffs2_iget_acl(struct inode *inode, struct posix_acl **i_acl)
158{
159 struct posix_acl *acl = JFFS2_ACL_NOT_CACHED;
160
161 spin_lock(&inode->i_lock);
162 if (*i_acl != JFFS2_ACL_NOT_CACHED)
163 acl = posix_acl_dup(*i_acl);
164 spin_unlock(&inode->i_lock);
165 return acl;
166}
167
168static void jffs2_iset_acl(struct inode *inode, struct posix_acl **i_acl, struct posix_acl *acl)
169{
170 spin_lock(&inode->i_lock);
171 if (*i_acl != JFFS2_ACL_NOT_CACHED)
172 posix_acl_release(*i_acl);
173 *i_acl = posix_acl_dup(acl);
174 spin_unlock(&inode->i_lock);
175}
176
177static struct posix_acl *jffs2_get_acl(struct inode *inode, int type)
178{
179 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
180 struct posix_acl *acl;
181 char *value = NULL;
182 int rc, xprefix;
183
184 switch (type) {
185 case ACL_TYPE_ACCESS:
186 acl = jffs2_iget_acl(inode, &f->i_acl_access);
187 if (acl != JFFS2_ACL_NOT_CACHED)
188 return acl;
189 xprefix = JFFS2_XPREFIX_ACL_ACCESS;
190 break;
191 case ACL_TYPE_DEFAULT:
192 acl = jffs2_iget_acl(inode, &f->i_acl_default);
193 if (acl != JFFS2_ACL_NOT_CACHED)
194 return acl;
195 xprefix = JFFS2_XPREFIX_ACL_DEFAULT;
196 break;
197 default:
198 return ERR_PTR(-EINVAL);
199 }
200 rc = do_jffs2_getxattr(inode, xprefix, "", NULL, 0);
201 if (rc > 0) {
202 value = kmalloc(rc, GFP_KERNEL);
203 if (!value)
204 return ERR_PTR(-ENOMEM);
205 rc = do_jffs2_getxattr(inode, xprefix, "", value, rc);
206 }
207 if (rc > 0) {
208 acl = jffs2_acl_from_medium(value, rc);
209 } else if (rc == -ENODATA || rc == -ENOSYS) {
210 acl = NULL;
211 } else {
212 acl = ERR_PTR(rc);
213 }
214 if (value)
215 kfree(value);
216 if (!IS_ERR(acl)) {
217 switch (type) {
218 case ACL_TYPE_ACCESS:
219 jffs2_iset_acl(inode, &f->i_acl_access, acl);
220 break;
221 case ACL_TYPE_DEFAULT:
222 jffs2_iset_acl(inode, &f->i_acl_default, acl);
223 break;
224 }
225 }
226 return acl;
227}
228
229static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
230{
231 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
232 size_t size = 0;
233 char *value = NULL;
234 int rc, xprefix;
235
236 if (S_ISLNK(inode->i_mode))
237 return -EOPNOTSUPP;
238
239 switch (type) {
240 case ACL_TYPE_ACCESS:
241 xprefix = JFFS2_XPREFIX_ACL_ACCESS;
242 if (acl) {
243 mode_t mode = inode->i_mode;
244 rc = posix_acl_equiv_mode(acl, &mode);
245 if (rc < 0)
246 return rc;
247 if (inode->i_mode != mode) {
248 inode->i_mode = mode;
249 jffs2_dirty_inode(inode);
250 }
251 if (rc == 0)
252 acl = NULL;
253 }
254 break;
255 case ACL_TYPE_DEFAULT:
256 xprefix = JFFS2_XPREFIX_ACL_DEFAULT;
257 if (!S_ISDIR(inode->i_mode))
258 return acl ? -EACCES : 0;
259 break;
260 default:
261 return -EINVAL;
262 }
263 if (acl) {
264 value = jffs2_acl_to_medium(acl, &size);
265 if (IS_ERR(value))
266 return PTR_ERR(value);
267 }
268
269 rc = do_jffs2_setxattr(inode, xprefix, "", value, size, 0);
270 if (value)
271 kfree(value);
272 if (!rc) {
273 switch(type) {
274 case ACL_TYPE_ACCESS:
275 jffs2_iset_acl(inode, &f->i_acl_access, acl);
276 break;
277 case ACL_TYPE_DEFAULT:
278 jffs2_iset_acl(inode, &f->i_acl_default, acl);
279 break;
280 }
281 }
282 return rc;
283}
284
285static int jffs2_check_acl(struct inode *inode, int mask)
286{
287 struct posix_acl *acl;
288 int rc;
289
290 acl = jffs2_get_acl(inode, ACL_TYPE_ACCESS);
291 if (IS_ERR(acl))
292 return PTR_ERR(acl);
293 if (acl) {
294 rc = posix_acl_permission(inode, acl, mask);
295 posix_acl_release(acl);
296 return rc;
297 }
298 return -EAGAIN;
299}
300
301int jffs2_permission(struct inode *inode, int mask, struct nameidata *nd)
302{
303 return generic_permission(inode, mask, jffs2_check_acl);
304}
305
306int jffs2_init_acl(struct inode *inode, struct inode *dir)
307{
308 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
309 struct posix_acl *acl = NULL, *clone;
310 mode_t mode;
311 int rc = 0;
312
313 f->i_acl_access = JFFS2_ACL_NOT_CACHED;
314 f->i_acl_default = JFFS2_ACL_NOT_CACHED;
315 if (!S_ISLNK(inode->i_mode)) {
316 acl = jffs2_get_acl(dir, ACL_TYPE_DEFAULT);
317 if (IS_ERR(acl))
318 return PTR_ERR(acl);
319 if (!acl)
320 inode->i_mode &= ~current->fs->umask;
321 }
322 if (acl) {
323 if (S_ISDIR(inode->i_mode)) {
324 rc = jffs2_set_acl(inode, ACL_TYPE_DEFAULT, acl);
325 if (rc)
326 goto cleanup;
327 }
328 clone = posix_acl_clone(acl, GFP_KERNEL);
329 rc = -ENOMEM;
330 if (!clone)
331 goto cleanup;
332 mode = inode->i_mode;
333 rc = posix_acl_create_masq(clone, &mode);
334 if (rc >= 0) {
335 inode->i_mode = mode;
336 if (rc > 0)
337 rc = jffs2_set_acl(inode, ACL_TYPE_ACCESS, clone);
338 }
339 posix_acl_release(clone);
340 }
341 cleanup:
342 posix_acl_release(acl);
343 return rc;
344}
345
346void jffs2_clear_acl(struct inode *inode)
347{
348 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
349
350 if (f->i_acl_access && f->i_acl_access != JFFS2_ACL_NOT_CACHED) {
351 posix_acl_release(f->i_acl_access);
352 f->i_acl_access = JFFS2_ACL_NOT_CACHED;
353 }
354 if (f->i_acl_default && f->i_acl_default != JFFS2_ACL_NOT_CACHED) {
355 posix_acl_release(f->i_acl_default);
356 f->i_acl_default = JFFS2_ACL_NOT_CACHED;
357 }
358}
359
360int jffs2_acl_chmod(struct inode *inode)
361{
362 struct posix_acl *acl, *clone;
363 int rc;
364
365 if (S_ISLNK(inode->i_mode))
366 return -EOPNOTSUPP;
367 acl = jffs2_get_acl(inode, ACL_TYPE_ACCESS);
368 if (IS_ERR(acl) || !acl)
369 return PTR_ERR(acl);
370 clone = posix_acl_clone(acl, GFP_KERNEL);
371 posix_acl_release(acl);
372 if (!clone)
373 return -ENOMEM;
374 rc = posix_acl_chmod_masq(clone, inode->i_mode);
375 if (!rc)
376 rc = jffs2_set_acl(inode, ACL_TYPE_ACCESS, clone);
377 posix_acl_release(clone);
378 return rc;
379}
380
381static size_t jffs2_acl_access_listxattr(struct inode *inode, char *list, size_t list_size,
382 const char *name, size_t name_len)
383{
384 const int retlen = sizeof(POSIX_ACL_XATTR_ACCESS);
385
386 if (list && retlen <= list_size)
387 strcpy(list, POSIX_ACL_XATTR_ACCESS);
388 return retlen;
389}
390
391static size_t jffs2_acl_default_listxattr(struct inode *inode, char *list, size_t list_size,
392 const char *name, size_t name_len)
393{
394 const int retlen = sizeof(POSIX_ACL_XATTR_DEFAULT);
395
396 if (list && retlen <= list_size)
397 strcpy(list, POSIX_ACL_XATTR_DEFAULT);
398 return retlen;
399}
400
401static int jffs2_acl_getxattr(struct inode *inode, int type, void *buffer, size_t size)
402{
403 struct posix_acl *acl;
404 int rc;
405
406 acl = jffs2_get_acl(inode, type);
407 if (IS_ERR(acl))
408 return PTR_ERR(acl);
409 if (!acl)
410 return -ENODATA;
411 rc = posix_acl_to_xattr(acl, buffer, size);
412 posix_acl_release(acl);
413
414 return rc;
415}
416
417static int jffs2_acl_access_getxattr(struct inode *inode, const char *name, void *buffer, size_t size)
418{
419 if (name[0] != '\0')
420 return -EINVAL;
421 return jffs2_acl_getxattr(inode, ACL_TYPE_ACCESS, buffer, size);
422}
423
424static int jffs2_acl_default_getxattr(struct inode *inode, const char *name, void *buffer, size_t size)
425{
426 if (name[0] != '\0')
427 return -EINVAL;
428 return jffs2_acl_getxattr(inode, ACL_TYPE_DEFAULT, buffer, size);
429}
430
431static int jffs2_acl_setxattr(struct inode *inode, int type, const void *value, size_t size)
432{
433 struct posix_acl *acl;
434 int rc;
435
436 if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
437 return -EPERM;
438
439 if (value) {
440 acl = posix_acl_from_xattr(value, size);
441 if (IS_ERR(acl))
442 return PTR_ERR(acl);
443 if (acl) {
444 rc = posix_acl_valid(acl);
445 if (rc)
446 goto out;
447 }
448 } else {
449 acl = NULL;
450 }
451 rc = jffs2_set_acl(inode, type, acl);
452 out:
453 posix_acl_release(acl);
454 return rc;
455}
456
457static int jffs2_acl_access_setxattr(struct inode *inode, const char *name,
458 const void *buffer, size_t size, int flags)
459{
460 if (name[0] != '\0')
461 return -EINVAL;
462 return jffs2_acl_setxattr(inode, ACL_TYPE_ACCESS, buffer, size);
463}
464
465static int jffs2_acl_default_setxattr(struct inode *inode, const char *name,
466 const void *buffer, size_t size, int flags)
467{
468 if (name[0] != '\0')
469 return -EINVAL;
470 return jffs2_acl_setxattr(inode, ACL_TYPE_DEFAULT, buffer, size);
471}
472
473struct xattr_handler jffs2_acl_access_xattr_handler = {
474 .prefix = POSIX_ACL_XATTR_ACCESS,
475 .list = jffs2_acl_access_listxattr,
476 .get = jffs2_acl_access_getxattr,
477 .set = jffs2_acl_access_setxattr,
478};
479
480struct xattr_handler jffs2_acl_default_xattr_handler = {
481 .prefix = POSIX_ACL_XATTR_DEFAULT,
482 .list = jffs2_acl_default_listxattr,
483 .get = jffs2_acl_default_getxattr,
484 .set = jffs2_acl_default_setxattr,
485};
diff --git a/fs/jffs2/acl.h b/fs/jffs2/acl.h
new file mode 100644
index 000000000000..8893bd1a6ba7
--- /dev/null
+++ b/fs/jffs2/acl.h
@@ -0,0 +1,45 @@
1/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright (C) 2006 NEC Corporation
5 *
6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
7 *
8 * For licensing information, see the file 'LICENCE' in this directory.
9 *
10 */
11struct jffs2_acl_entry {
12 jint16_t e_tag;
13 jint16_t e_perm;
14 jint32_t e_id;
15};
16
17struct jffs2_acl_entry_short {
18 jint16_t e_tag;
19 jint16_t e_perm;
20};
21
22struct jffs2_acl_header {
23 jint32_t a_version;
24};
25
26#ifdef CONFIG_JFFS2_FS_POSIX_ACL
27
28#define JFFS2_ACL_NOT_CACHED ((void *)-1)
29
30extern int jffs2_permission(struct inode *, int, struct nameidata *);
31extern int jffs2_acl_chmod(struct inode *);
32extern int jffs2_init_acl(struct inode *, struct inode *);
33extern void jffs2_clear_acl(struct inode *);
34
35extern struct xattr_handler jffs2_acl_access_xattr_handler;
36extern struct xattr_handler jffs2_acl_default_xattr_handler;
37
38#else
39
40#define jffs2_permission NULL
41#define jffs2_acl_chmod(inode) (0)
42#define jffs2_init_acl(inode,dir) (0)
43#define jffs2_clear_acl(inode)
44
45#endif /* CONFIG_JFFS2_FS_POSIX_ACL */
diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c
index 70f7a896c04a..02826967ab58 100644
--- a/fs/jffs2/build.c
+++ b/fs/jffs2/build.c
@@ -160,6 +160,7 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c)
160 ic->scan_dents = NULL; 160 ic->scan_dents = NULL;
161 cond_resched(); 161 cond_resched();
162 } 162 }
163 jffs2_build_xattr_subsystem(c);
163 c->flags &= ~JFFS2_SB_FLAG_BUILDING; 164 c->flags &= ~JFFS2_SB_FLAG_BUILDING;
164 165
165 dbg_fsbuild("FS build complete\n"); 166 dbg_fsbuild("FS build complete\n");
@@ -178,6 +179,7 @@ exit:
178 jffs2_free_full_dirent(fd); 179 jffs2_free_full_dirent(fd);
179 } 180 }
180 } 181 }
182 jffs2_clear_xattr_subsystem(c);
181 } 183 }
182 184
183 return ret; 185 return ret;
diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h
index 162af6dfe292..5fa494a792b2 100644
--- a/fs/jffs2/debug.h
+++ b/fs/jffs2/debug.h
@@ -171,6 +171,12 @@
171#define dbg_memalloc(fmt, ...) 171#define dbg_memalloc(fmt, ...)
172#endif 172#endif
173 173
174/* Watch the XATTR subsystem */
175#ifdef JFFS2_DBG_XATTR_MESSAGES
176#define dbg_xattr(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__)
177#else
178#define dbg_xattr(fmt, ...)
179#endif
174 180
175/* "Sanity" checks */ 181/* "Sanity" checks */
176void 182void
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index a6c11cef1b73..ff1b7950dd44 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -57,7 +57,12 @@ struct inode_operations jffs2_dir_inode_operations =
57 .rmdir = jffs2_rmdir, 57 .rmdir = jffs2_rmdir,
58 .mknod = jffs2_mknod, 58 .mknod = jffs2_mknod,
59 .rename = jffs2_rename, 59 .rename = jffs2_rename,
60 .permission = jffs2_permission,
60 .setattr = jffs2_setattr, 61 .setattr = jffs2_setattr,
62 .setxattr = jffs2_setxattr,
63 .getxattr = jffs2_getxattr,
64 .listxattr = jffs2_listxattr,
65 .removexattr = jffs2_removexattr
61}; 66};
62 67
63/***********************************************************************/ 68/***********************************************************************/
@@ -209,12 +214,15 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
209 ret = jffs2_do_create(c, dir_f, f, ri, 214 ret = jffs2_do_create(c, dir_f, f, ri,
210 dentry->d_name.name, dentry->d_name.len); 215 dentry->d_name.name, dentry->d_name.len);
211 216
212 if (ret) { 217 if (ret)
213 make_bad_inode(inode); 218 goto fail;
214 iput(inode); 219
215 jffs2_free_raw_inode(ri); 220 ret = jffs2_init_security(inode, dir_i);
216 return ret; 221 if (ret)
217 } 222 goto fail;
223 ret = jffs2_init_acl(inode, dir_i);
224 if (ret)
225 goto fail;
218 226
219 dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(ri->ctime)); 227 dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(ri->ctime));
220 228
@@ -224,6 +232,12 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
224 D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d). nrpages %ld\n", 232 D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d). nrpages %ld\n",
225 inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink, inode->i_mapping->nrpages)); 233 inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink, inode->i_mapping->nrpages));
226 return 0; 234 return 0;
235
236 fail:
237 make_bad_inode(inode);
238 iput(inode);
239 jffs2_free_raw_inode(ri);
240 return ret;
227} 241}
228 242
229/***********************************************************************/ 243/***********************************************************************/
@@ -374,6 +388,18 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
374 up(&f->sem); 388 up(&f->sem);
375 389
376 jffs2_complete_reservation(c); 390 jffs2_complete_reservation(c);
391
392 ret = jffs2_init_security(inode, dir_i);
393 if (ret) {
394 jffs2_clear_inode(inode);
395 return ret;
396 }
397 ret = jffs2_init_acl(inode, dir_i);
398 if (ret) {
399 jffs2_clear_inode(inode);
400 return ret;
401 }
402
377 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, 403 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen,
378 ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); 404 ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
379 if (ret) { 405 if (ret) {
@@ -504,6 +530,18 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
504 up(&f->sem); 530 up(&f->sem);
505 531
506 jffs2_complete_reservation(c); 532 jffs2_complete_reservation(c);
533
534 ret = jffs2_init_security(inode, dir_i);
535 if (ret) {
536 jffs2_clear_inode(inode);
537 return ret;
538 }
539 ret = jffs2_init_acl(inode, dir_i);
540 if (ret) {
541 jffs2_clear_inode(inode);
542 return ret;
543 }
544
507 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, 545 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen,
508 ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); 546 ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
509 if (ret) { 547 if (ret) {
@@ -658,6 +696,18 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
658 up(&f->sem); 696 up(&f->sem);
659 697
660 jffs2_complete_reservation(c); 698 jffs2_complete_reservation(c);
699
700 ret = jffs2_init_security(inode, dir_i);
701 if (ret) {
702 jffs2_clear_inode(inode);
703 return ret;
704 }
705 ret = jffs2_init_acl(inode, dir_i);
706 if (ret) {
707 jffs2_clear_inode(inode);
708 return ret;
709 }
710
661 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, 711 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen,
662 ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); 712 ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
663 if (ret) { 713 if (ret) {
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index dad68fdffe9e..f677d6950fd4 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -30,7 +30,6 @@ static void jffs2_erase_callback(struct erase_info *);
30#endif 30#endif
31static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t bad_offset); 31static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t bad_offset);
32static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); 32static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
33static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
34static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); 33static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
35 34
36static void jffs2_erase_block(struct jffs2_sb_info *c, 35static void jffs2_erase_block(struct jffs2_sb_info *c,
@@ -283,7 +282,7 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
283 jffs2_del_ino_cache(c, ic); 282 jffs2_del_ino_cache(c, ic);
284} 283}
285 284
286static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) 285void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
287{ 286{
288 struct jffs2_raw_node_ref *ref; 287 struct jffs2_raw_node_ref *ref;
289 D1(printk(KERN_DEBUG "Freeing all node refs for eraseblock offset 0x%08x\n", jeb->offset)); 288 D1(printk(KERN_DEBUG "Freeing all node refs for eraseblock offset 0x%08x\n", jeb->offset));
@@ -373,12 +372,8 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
373 goto filebad; 372 goto filebad;
374 } 373 }
375 374
376 jeb->first_node = jeb->last_node = NULL; 375 /* Everything else got zeroed before the erase */
377 jeb->free_size = c->sector_size; 376 jeb->free_size = c->sector_size;
378 jeb->used_size = 0;
379 jeb->dirty_size = 0;
380 jeb->wasted_size = 0;
381
382 } else { 377 } else {
383 378
384 struct kvec vecs[1]; 379 struct kvec vecs[1];
@@ -412,17 +407,13 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
412 goto filebad; 407 goto filebad;
413 } 408 }
414 409
410 /* Everything else got zeroed before the erase */
411 jeb->free_size = c->sector_size;
412
415 marker_ref->next_in_ino = NULL; 413 marker_ref->next_in_ino = NULL;
416 marker_ref->next_phys = NULL;
417 marker_ref->flash_offset = jeb->offset | REF_NORMAL; 414 marker_ref->flash_offset = jeb->offset | REF_NORMAL;
418 marker_ref->__totlen = c->cleanmarker_size;
419
420 jeb->first_node = jeb->last_node = marker_ref;
421 415
422 jeb->free_size = c->sector_size - c->cleanmarker_size; 416 jffs2_link_node_ref(c, jeb, marker_ref, c->cleanmarker_size);
423 jeb->used_size = c->cleanmarker_size;
424 jeb->dirty_size = 0;
425 jeb->wasted_size = 0;
426 } 417 }
427 418
428 spin_lock(&c->erase_completion_lock); 419 spin_lock(&c->erase_completion_lock);
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 3349db0a7863..e18c9437d58f 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -54,7 +54,12 @@ const struct file_operations jffs2_file_operations =
54 54
55struct inode_operations jffs2_file_inode_operations = 55struct inode_operations jffs2_file_inode_operations =
56{ 56{
57 .setattr = jffs2_setattr 57 .permission = jffs2_permission,
58 .setattr = jffs2_setattr,
59 .setxattr = jffs2_setxattr,
60 .getxattr = jffs2_getxattr,
61 .listxattr = jffs2_listxattr,
62 .removexattr = jffs2_removexattr
58}; 63};
59 64
60struct address_space_operations jffs2_file_address_operations = 65struct address_space_operations jffs2_file_address_operations =
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 24cb4c688efc..a0f84673ce54 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -184,7 +184,12 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
184 184
185int jffs2_setattr(struct dentry *dentry, struct iattr *iattr) 185int jffs2_setattr(struct dentry *dentry, struct iattr *iattr)
186{ 186{
187 return jffs2_do_setattr(dentry->d_inode, iattr); 187 int rc;
188
189 rc = jffs2_do_setattr(dentry->d_inode, iattr);
190 if (!rc && (iattr->ia_valid & ATTR_MODE))
191 rc = jffs2_acl_chmod(dentry->d_inode);
192 return rc;
188} 193}
189 194
190int jffs2_statfs(struct super_block *sb, struct kstatfs *buf) 195int jffs2_statfs(struct super_block *sb, struct kstatfs *buf)
@@ -223,6 +228,7 @@ void jffs2_clear_inode (struct inode *inode)
223 228
224 D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode)); 229 D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode));
225 230
231 jffs2_xattr_delete_inode(c, f->inocache);
226 jffs2_do_clear_inode(c, f); 232 jffs2_do_clear_inode(c, f);
227} 233}
228 234
@@ -508,6 +514,8 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
508 } 514 }
509 memset(c->inocache_list, 0, INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *)); 515 memset(c->inocache_list, 0, INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *));
510 516
517 jffs2_init_xattr_subsystem(c);
518
511 if ((ret = jffs2_do_mount_fs(c))) 519 if ((ret = jffs2_do_mount_fs(c)))
512 goto out_inohash; 520 goto out_inohash;
513 521
@@ -542,6 +550,7 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
542 else 550 else
543 kfree(c->blocks); 551 kfree(c->blocks);
544 out_inohash: 552 out_inohash:
553 jffs2_clear_xattr_subsystem(c);
545 kfree(c->inocache_list); 554 kfree(c->inocache_list);
546 out_wbuf: 555 out_wbuf:
547 jffs2_flash_cleanup(c); 556 jffs2_flash_cleanup(c);
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index 77d30707de56..4773ba24304f 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -125,6 +125,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
125 struct jffs2_eraseblock *jeb; 125 struct jffs2_eraseblock *jeb;
126 struct jffs2_raw_node_ref *raw; 126 struct jffs2_raw_node_ref *raw;
127 int ret = 0, inum, nlink; 127 int ret = 0, inum, nlink;
128 int xattr = 0;
128 129
129 if (down_interruptible(&c->alloc_sem)) 130 if (down_interruptible(&c->alloc_sem))
130 return -EINTR; 131 return -EINTR;
@@ -138,7 +139,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
138 the node CRCs etc. Do it now. */ 139 the node CRCs etc. Do it now. */
139 140
140 /* checked_ino is protected by the alloc_sem */ 141 /* checked_ino is protected by the alloc_sem */
141 if (c->checked_ino > c->highest_ino) { 142 if (c->checked_ino > c->highest_ino && xattr) {
142 printk(KERN_CRIT "Checked all inodes but still 0x%x bytes of unchecked space?\n", 143 printk(KERN_CRIT "Checked all inodes but still 0x%x bytes of unchecked space?\n",
143 c->unchecked_size); 144 c->unchecked_size);
144 jffs2_dbg_dump_block_lists_nolock(c); 145 jffs2_dbg_dump_block_lists_nolock(c);
@@ -148,6 +149,9 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
148 149
149 spin_unlock(&c->erase_completion_lock); 150 spin_unlock(&c->erase_completion_lock);
150 151
152 if (!xattr)
153 xattr = jffs2_verify_xattr(c);
154
151 spin_lock(&c->inocache_lock); 155 spin_lock(&c->inocache_lock);
152 156
153 ic = jffs2_get_ino_cache(c, c->checked_ino++); 157 ic = jffs2_get_ino_cache(c, c->checked_ino++);
@@ -252,16 +256,37 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
252 256
253 if (!raw->next_in_ino) { 257 if (!raw->next_in_ino) {
254 /* Inode-less node. Clean marker, snapshot or something like that */ 258 /* Inode-less node. Clean marker, snapshot or something like that */
255 /* FIXME: If it's something that needs to be copied, including something
256 we don't grok that has JFFS2_NODETYPE_RWCOMPAT_COPY, we should do so */
257 spin_unlock(&c->erase_completion_lock); 259 spin_unlock(&c->erase_completion_lock);
258 jffs2_mark_node_obsolete(c, raw); 260 if (ref_flags(raw) == REF_PRISTINE) {
261 /* It's an unknown node with JFFS2_FEATURE_RWCOMPAT_COPY */
262 jffs2_garbage_collect_pristine(c, NULL, raw);
263 } else {
264 /* Just mark it obsolete */
265 jffs2_mark_node_obsolete(c, raw);
266 }
259 up(&c->alloc_sem); 267 up(&c->alloc_sem);
260 goto eraseit_lock; 268 goto eraseit_lock;
261 } 269 }
262 270
263 ic = jffs2_raw_ref_to_ic(raw); 271 ic = jffs2_raw_ref_to_ic(raw);
264 272
273#ifdef CONFIG_JFFS2_FS_XATTR
274 /* When 'ic' refers xattr_datum/xattr_ref, this node is GCed as xattr.
275 * We can decide whether this node is inode or xattr by ic->class. */
276 if (ic->class == RAWNODE_CLASS_XATTR_DATUM
277 || ic->class == RAWNODE_CLASS_XATTR_REF) {
278 BUG_ON(raw->next_in_ino != (void *)ic);
279 spin_unlock(&c->erase_completion_lock);
280
281 if (ic->class == RAWNODE_CLASS_XATTR_DATUM) {
282 ret = jffs2_garbage_collect_xattr_datum(c, (struct jffs2_xattr_datum *)ic);
283 } else {
284 ret = jffs2_garbage_collect_xattr_ref(c, (struct jffs2_xattr_ref *)ic);
285 }
286 goto release_sem;
287 }
288#endif
289
265 /* We need to hold the inocache. Either the erase_completion_lock or 290 /* We need to hold the inocache. Either the erase_completion_lock or
266 the inocache_lock are sufficient; we trade down since the inocache_lock 291 the inocache_lock are sufficient; we trade down since the inocache_lock
267 causes less contention. */ 292 causes less contention. */
@@ -512,15 +537,16 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
512 537
513 D1(printk(KERN_DEBUG "Going to GC REF_PRISTINE node at 0x%08x\n", ref_offset(raw))); 538 D1(printk(KERN_DEBUG "Going to GC REF_PRISTINE node at 0x%08x\n", ref_offset(raw)));
514 539
515 rawlen = ref_totlen(c, c->gcblock, raw); 540 alloclen = rawlen = ref_totlen(c, c->gcblock, raw);
516 541
517 /* Ask for a small amount of space (or the totlen if smaller) because we 542 /* Ask for a small amount of space (or the totlen if smaller) because we
518 don't want to force wastage of the end of a block if splitting would 543 don't want to force wastage of the end of a block if splitting would
519 work. */ 544 work. */
520 ret = jffs2_reserve_space_gc(c, min_t(uint32_t, sizeof(struct jffs2_raw_inode) + 545 if (ic && alloclen > sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN)
521 JFFS2_MIN_DATA_LEN, rawlen), &phys_ofs, &alloclen, rawlen); 546 alloclen = sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN;
522 /* this is not the exact summary size of it, 547
523 it is only an upper estimation */ 548 ret = jffs2_reserve_space_gc(c, alloclen, &phys_ofs, &alloclen, rawlen);
549 /* 'rawlen' is not the exact summary size; it is only an upper estimation */
524 550
525 if (ret) 551 if (ret)
526 return ret; 552 return ret;
@@ -584,9 +610,12 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
584 } 610 }
585 break; 611 break;
586 default: 612 default:
587 printk(KERN_WARNING "Unknown node type for REF_PRISTINE node at 0x%08x: 0x%04x\n", 613 /* If it's inode-less, we don't _know_ what it is. Just copy it intact */
588 ref_offset(raw), je16_to_cpu(node->u.nodetype)); 614 if (ic) {
589 goto bail; 615 printk(KERN_WARNING "Unknown node type for REF_PRISTINE node at 0x%08x: 0x%04x\n",
616 ref_offset(raw), je16_to_cpu(node->u.nodetype));
617 goto bail;
618 }
590 } 619 }
591 620
592 nraw = jffs2_alloc_raw_node_ref(); 621 nraw = jffs2_alloc_raw_node_ref();
@@ -598,8 +627,6 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
598 /* OK, all the CRCs are good; this node can just be copied as-is. */ 627 /* OK, all the CRCs are good; this node can just be copied as-is. */
599 retry: 628 retry:
600 nraw->flash_offset = phys_ofs; 629 nraw->flash_offset = phys_ofs;
601 nraw->__totlen = rawlen;
602 nraw->next_phys = NULL;
603 630
604 ret = jffs2_flash_write(c, phys_ofs, rawlen, &retlen, (char *)node); 631 ret = jffs2_flash_write(c, phys_ofs, rawlen, &retlen, (char *)node);
605 632
@@ -611,7 +638,7 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
611 nraw->next_in_ino = NULL; 638 nraw->next_in_ino = NULL;
612 639
613 nraw->flash_offset |= REF_OBSOLETE; 640 nraw->flash_offset |= REF_OBSOLETE;
614 jffs2_add_physical_node_ref(c, nraw); 641 jffs2_add_physical_node_ref(c, nraw, rawlen);
615 jffs2_mark_node_obsolete(c, nraw); 642 jffs2_mark_node_obsolete(c, nraw);
616 } else { 643 } else {
617 printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", nraw->flash_offset); 644 printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", nraw->flash_offset);
@@ -651,17 +678,18 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
651 goto out_node; 678 goto out_node;
652 } 679 }
653 nraw->flash_offset |= REF_PRISTINE; 680 nraw->flash_offset |= REF_PRISTINE;
654 jffs2_add_physical_node_ref(c, nraw); 681 jffs2_add_physical_node_ref(c, nraw, rawlen);
655
656 /* Link into per-inode list. This is safe because of the ic
657 state being INO_STATE_GC. Note that if we're doing this
658 for an inode which is in-core, the 'nraw' pointer is then
659 going to be fetched from ic->nodes by our caller. */
660 spin_lock(&c->erase_completion_lock);
661 nraw->next_in_ino = ic->nodes;
662 ic->nodes = nraw;
663 spin_unlock(&c->erase_completion_lock);
664 682
683 if (ic) {
684 /* Link into per-inode list. This is safe because of the ic
685 state being INO_STATE_GC. Note that if we're doing this
686 for an inode which is in-core, the 'nraw' pointer is then
687 going to be fetched from ic->nodes by our caller. */
688 spin_lock(&c->erase_completion_lock);
689 nraw->next_in_ino = ic->nodes;
690 ic->nodes = nraw;
691 spin_unlock(&c->erase_completion_lock);
692 }
665 jffs2_mark_node_obsolete(c, raw); 693 jffs2_mark_node_obsolete(c, raw);
666 D1(printk(KERN_DEBUG "WHEEE! GC REF_PRISTINE node at 0x%08x succeeded\n", ref_offset(raw))); 694 D1(printk(KERN_DEBUG "WHEEE! GC REF_PRISTINE node at 0x%08x succeeded\n", ref_offset(raw)));
667 695
diff --git a/fs/jffs2/jffs2_fs_i.h b/fs/jffs2/jffs2_fs_i.h
index ad565bf9dcc1..2e0cc8e00b85 100644
--- a/fs/jffs2/jffs2_fs_i.h
+++ b/fs/jffs2/jffs2_fs_i.h
@@ -5,6 +5,7 @@
5 5
6#include <linux/version.h> 6#include <linux/version.h>
7#include <linux/rbtree.h> 7#include <linux/rbtree.h>
8#include <linux/posix_acl.h>
8#include <asm/semaphore.h> 9#include <asm/semaphore.h>
9 10
10struct jffs2_inode_info { 11struct jffs2_inode_info {
@@ -45,6 +46,10 @@ struct jffs2_inode_info {
45 struct inode vfs_inode; 46 struct inode vfs_inode;
46#endif 47#endif
47#endif 48#endif
49#ifdef CONFIG_JFFS2_FS_POSIX_ACL
50 struct posix_acl *i_acl_access;
51 struct posix_acl *i_acl_default;
52#endif
48}; 53};
49 54
50#endif /* _JFFS2_FS_I */ 55#endif /* _JFFS2_FS_I */
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
index 4bcfb5570221..272fbea55192 100644
--- a/fs/jffs2/jffs2_fs_sb.h
+++ b/fs/jffs2/jffs2_fs_sb.h
@@ -115,6 +115,16 @@ struct jffs2_sb_info {
115 115
116 struct jffs2_summary *summary; /* Summary information */ 116 struct jffs2_summary *summary; /* Summary information */
117 117
118#ifdef CONFIG_JFFS2_FS_XATTR
119#define XATTRINDEX_HASHSIZE (57)
120 uint32_t highest_xid;
121 struct list_head xattrindex[XATTRINDEX_HASHSIZE];
122 struct list_head xattr_unchecked;
123 struct jffs2_xattr_ref *xref_temp;
124 struct rw_semaphore xattr_sem;
125 uint32_t xdatum_mem_usage;
126 uint32_t xdatum_mem_threshold;
127#endif
118 /* OS-private pointer for getting back to master superblock info */ 128 /* OS-private pointer for getting back to master superblock info */
119 void *os_priv; 129 void *os_priv;
120}; 130};
diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c
index 036cbd11c004..f2473fa2fd16 100644
--- a/fs/jffs2/malloc.c
+++ b/fs/jffs2/malloc.c
@@ -26,6 +26,10 @@ static kmem_cache_t *tmp_dnode_info_slab;
26static kmem_cache_t *raw_node_ref_slab; 26static kmem_cache_t *raw_node_ref_slab;
27static kmem_cache_t *node_frag_slab; 27static kmem_cache_t *node_frag_slab;
28static kmem_cache_t *inode_cache_slab; 28static kmem_cache_t *inode_cache_slab;
29#ifdef CONFIG_JFFS2_FS_XATTR
30static kmem_cache_t *xattr_datum_cache;
31static kmem_cache_t *xattr_ref_cache;
32#endif
29 33
30int __init jffs2_create_slab_caches(void) 34int __init jffs2_create_slab_caches(void)
31{ 35{
@@ -68,8 +72,24 @@ int __init jffs2_create_slab_caches(void)
68 inode_cache_slab = kmem_cache_create("jffs2_inode_cache", 72 inode_cache_slab = kmem_cache_create("jffs2_inode_cache",
69 sizeof(struct jffs2_inode_cache), 73 sizeof(struct jffs2_inode_cache),
70 0, 0, NULL, NULL); 74 0, 0, NULL, NULL);
71 if (inode_cache_slab) 75 if (!inode_cache_slab)
72 return 0; 76 goto err;
77
78#ifdef CONFIG_JFFS2_FS_XATTR
79 xattr_datum_cache = kmem_cache_create("jffs2_xattr_datum",
80 sizeof(struct jffs2_xattr_datum),
81 0, 0, NULL, NULL);
82 if (!xattr_datum_cache)
83 goto err;
84
85 xattr_ref_cache = kmem_cache_create("jffs2_xattr_ref",
86 sizeof(struct jffs2_xattr_ref),
87 0, 0, NULL, NULL);
88 if (!xattr_ref_cache)
89 goto err;
90#endif
91
92 return 0;
73 err: 93 err:
74 jffs2_destroy_slab_caches(); 94 jffs2_destroy_slab_caches();
75 return -ENOMEM; 95 return -ENOMEM;
@@ -91,6 +111,12 @@ void jffs2_destroy_slab_caches(void)
91 kmem_cache_destroy(node_frag_slab); 111 kmem_cache_destroy(node_frag_slab);
92 if(inode_cache_slab) 112 if(inode_cache_slab)
93 kmem_cache_destroy(inode_cache_slab); 113 kmem_cache_destroy(inode_cache_slab);
114#ifdef CONFIG_JFFS2_FS_XATTR
115 if (xattr_datum_cache)
116 kmem_cache_destroy(xattr_datum_cache);
117 if (xattr_ref_cache)
118 kmem_cache_destroy(xattr_ref_cache);
119#endif
94} 120}
95 121
96struct jffs2_full_dirent *jffs2_alloc_full_dirent(int namesize) 122struct jffs2_full_dirent *jffs2_alloc_full_dirent(int namesize)
@@ -205,3 +231,40 @@ void jffs2_free_inode_cache(struct jffs2_inode_cache *x)
205 dbg_memalloc("%p\n", x); 231 dbg_memalloc("%p\n", x);
206 kmem_cache_free(inode_cache_slab, x); 232 kmem_cache_free(inode_cache_slab, x);
207} 233}
234
235#ifdef CONFIG_JFFS2_FS_XATTR
236struct jffs2_xattr_datum *jffs2_alloc_xattr_datum(void)
237{
238 struct jffs2_xattr_datum *xd;
239 xd = kmem_cache_alloc(xattr_datum_cache, GFP_KERNEL);
240 dbg_memalloc("%p\n", xd);
241
242 memset(xd, 0, sizeof(struct jffs2_xattr_datum));
243 xd->class = RAWNODE_CLASS_XATTR_DATUM;
244 INIT_LIST_HEAD(&xd->xindex);
245 return xd;
246}
247
248void jffs2_free_xattr_datum(struct jffs2_xattr_datum *xd)
249{
250 dbg_memalloc("%p\n", xd);
251 kmem_cache_free(xattr_datum_cache, xd);
252}
253
254struct jffs2_xattr_ref *jffs2_alloc_xattr_ref(void)
255{
256 struct jffs2_xattr_ref *ref;
257 ref = kmem_cache_alloc(xattr_ref_cache, GFP_KERNEL);
258 dbg_memalloc("%p\n", ref);
259
260 memset(ref, 0, sizeof(struct jffs2_xattr_ref));
261 ref->class = RAWNODE_CLASS_XATTR_REF;
262 return ref;
263}
264
265void jffs2_free_xattr_ref(struct jffs2_xattr_ref *ref)
266{
267 dbg_memalloc("%p\n", ref);
268 kmem_cache_free(xattr_ref_cache, ref);
269}
270#endif
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c
index 7d71593d7fd3..9a6ced05f894 100644
--- a/fs/jffs2/nodelist.c
+++ b/fs/jffs2/nodelist.c
@@ -938,6 +938,7 @@ void jffs2_free_ino_caches(struct jffs2_sb_info *c)
938 this = c->inocache_list[i]; 938 this = c->inocache_list[i];
939 while (this) { 939 while (this) {
940 next = this->next; 940 next = this->next;
941 jffs2_xattr_free_inode(c, this);
941 jffs2_free_inode_cache(this); 942 jffs2_free_inode_cache(this);
942 this = next; 943 this = next;
943 } 944 }
@@ -1045,3 +1046,149 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c)
1045 cond_resched(); 1046 cond_resched();
1046 } 1047 }
1047} 1048}
1049
1050void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
1051 struct jffs2_raw_node_ref *ref, uint32_t len)
1052{
1053 if (!jeb->first_node)
1054 jeb->first_node = ref;
1055 if (jeb->last_node) {
1056 jeb->last_node->next_phys = ref;
1057#ifdef TEST_TOTLEN
1058 if (ref_offset(jeb->last_node) + jeb->last_node->__totlen != ref_offset(ref)) {
1059 printk(KERN_CRIT "Adding new ref %p at (0x%08x-0x%08x) not immediately after previous (0x%08x-0x%08x)\n",
1060 ref, ref_offset(ref), ref_offset(ref)+ref->__totlen,
1061 ref_offset(jeb->last_node), ref_offset(jeb->last_node)+jeb->last_node->__totlen);
1062 WARN_ON(1);
1063 }
1064#endif
1065 }
1066 jeb->last_node = ref;
1067
1068 switch(ref_flags(ref)) {
1069 case REF_UNCHECKED:
1070 c->unchecked_size += len;
1071 jeb->unchecked_size += len;
1072 break;
1073
1074 case REF_NORMAL:
1075 case REF_PRISTINE:
1076 c->used_size += len;
1077 jeb->used_size += len;
1078 break;
1079
1080 case REF_OBSOLETE:
1081 c->dirty_size += len;
1082 jeb->used_size += len;
1083 break;
1084 }
1085 c->free_size -= len;
1086 jeb->free_size -= len;
1087
1088 ref->next_phys = NULL;
1089#ifdef TEST_TOTLEN
1090 /* Set (and test) __totlen field... for now */
1091 ref->__totlen = len;
1092 ref_totlen(c, jeb, ref);
1093#endif
1094}
1095
1096/* No locking. Do not use on a live file system */
1097int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
1098 uint32_t size)
1099{
1100 if (!size)
1101 return 0;
1102 if (size > c->sector_size - jeb->used_size) {
1103 printk(KERN_CRIT "Dirty space 0x%x larger then used_size 0x%x (wasted 0x%x)\n",
1104 size, jeb->used_size, jeb->wasted_size);
1105 BUG();
1106 }
1107 if (jeb->last_node && ref_obsolete(jeb->last_node)) {
1108#ifdef TEST_TOTLEN
1109 jeb->last_node->__totlen += size;
1110#endif
1111 c->dirty_size += size;
1112 c->free_size -= size;
1113 jeb->dirty_size += size;
1114 jeb->free_size -= size;
1115 } else {
1116 struct jffs2_raw_node_ref *ref;
1117 ref = jffs2_alloc_raw_node_ref();
1118 if (!ref)
1119 return -ENOMEM;
1120
1121 ref->flash_offset = jeb->offset + c->sector_size - jeb->free_size;
1122 ref->flash_offset |= REF_OBSOLETE;
1123 ref->next_in_ino = 0;
1124#ifdef TEST_TOTLEN
1125 ref->__totlen = size;
1126#endif
1127
1128 jffs2_link_node_ref(c, jeb, ref, size);
1129 }
1130
1131 return 0;
1132}
1133
1134/* Calculate totlen from surrounding nodes or eraseblock */
1135static inline uint32_t __ref_totlen(struct jffs2_sb_info *c,
1136 struct jffs2_eraseblock *jeb,
1137 struct jffs2_raw_node_ref *ref)
1138{
1139 uint32_t ref_end;
1140
1141 if (ref->next_phys)
1142 ref_end = ref_offset(ref->next_phys);
1143 else {
1144 if (!jeb)
1145 jeb = &c->blocks[ref->flash_offset / c->sector_size];
1146
1147 /* Last node in block. Use free_space */
1148 if (ref != jeb->last_node) {
1149 printk(KERN_CRIT "ref %p @0x%08x is not jeb->last_node (%p @0x%08x)\n",
1150 ref, ref_offset(ref), jeb->last_node, jeb->last_node?ref_offset(jeb->last_node):0);
1151 BUG();
1152 }
1153 ref_end = jeb->offset + c->sector_size - jeb->free_size;
1154 }
1155 return ref_end - ref_offset(ref);
1156}
1157
1158uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
1159 struct jffs2_raw_node_ref *ref)
1160{
1161 uint32_t ret;
1162
1163#if CONFIG_JFFS2_FS_DEBUG > 0
1164 if (jeb && jeb != &c->blocks[ref->flash_offset / c->sector_size]) {
1165 printk(KERN_CRIT "ref_totlen called with wrong block -- at 0x%08x instead of 0x%08x; ref 0x%08x\n",
1166 jeb->offset, c->blocks[ref->flash_offset / c->sector_size].offset, ref_offset(ref));
1167 BUG();
1168 }
1169#endif
1170
1171 ret = __ref_totlen(c, jeb, ref);
1172#ifdef TEST_TOTLEN
1173 if (ret != ref->__totlen) {
1174 printk(KERN_CRIT "Totlen for ref at %p (0x%08x-0x%08x) miscalculated as 0x%x instead of %x\n",
1175 ref, ref_offset(ref), ref_offset(ref)+ref->__totlen,
1176 ret, ref->__totlen);
1177 if (ref->next_phys) {
1178 printk(KERN_CRIT "next_phys %p (0x%08x-0x%08x)\n", ref->next_phys, ref_offset(ref->next_phys),
1179 ref_offset(ref->next_phys)+ref->__totlen);
1180 } else
1181 printk(KERN_CRIT "No next_phys. jeb->last_node is %p\n", jeb->last_node);
1182
1183 printk(KERN_CRIT "jeb->wasted_size %x, dirty_size %x, used_size %x, free_size %x\n", jeb->wasted_size, jeb->dirty_size, jeb->used_size, jeb->free_size);
1184 ret = ref->__totlen;
1185 if (!jeb)
1186 jeb = &c->blocks[ref->flash_offset / c->sector_size];
1187#if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
1188 __jffs2_dbg_dump_node_refs_nolock(c, jeb);
1189#endif
1190 WARN_ON(1);
1191 }
1192#endif /* TEST_TOTLEN */
1193 return ret;
1194}
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index 24e0f28a8bac..80d1fda2212b 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -20,6 +20,8 @@
20#include <linux/jffs2.h> 20#include <linux/jffs2.h>
21#include "jffs2_fs_sb.h" 21#include "jffs2_fs_sb.h"
22#include "jffs2_fs_i.h" 22#include "jffs2_fs_i.h"
23#include "xattr.h"
24#include "acl.h"
23#include "summary.h" 25#include "summary.h"
24 26
25#ifdef __ECOS 27#ifdef __ECOS
@@ -80,7 +82,10 @@ struct jffs2_raw_node_ref
80 word so you know when you've got there :) */ 82 word so you know when you've got there :) */
81 struct jffs2_raw_node_ref *next_phys; 83 struct jffs2_raw_node_ref *next_phys;
82 uint32_t flash_offset; 84 uint32_t flash_offset;
85#define TEST_TOTLEN
86#ifdef TEST_TOTLEN
83 uint32_t __totlen; /* This may die; use ref_totlen(c, jeb, ) below */ 87 uint32_t __totlen; /* This may die; use ref_totlen(c, jeb, ) below */
88#endif
84}; 89};
85 90
86 /* flash_offset & 3 always has to be zero, because nodes are 91 /* flash_offset & 3 always has to be zero, because nodes are
@@ -95,6 +100,11 @@ struct jffs2_raw_node_ref
95#define ref_obsolete(ref) (((ref)->flash_offset & 3) == REF_OBSOLETE) 100#define ref_obsolete(ref) (((ref)->flash_offset & 3) == REF_OBSOLETE)
96#define mark_ref_normal(ref) do { (ref)->flash_offset = ref_offset(ref) | REF_NORMAL; } while(0) 101#define mark_ref_normal(ref) do { (ref)->flash_offset = ref_offset(ref) | REF_NORMAL; } while(0)
97 102
103/* NB: REF_PRISTINE for an inode-less node (ref->next_in_ino == NULL) indicates
104 it is an unknown node of type JFFS2_NODETYPE_RWCOMPAT_COPY, so it'll get
105 copied. If you need to do anything different to GC inode-less nodes, then
106 you need to modify gc.c accordingly. */
107
98/* For each inode in the filesystem, we need to keep a record of 108/* For each inode in the filesystem, we need to keep a record of
99 nlink, because it would be a PITA to scan the whole directory tree 109 nlink, because it would be a PITA to scan the whole directory tree
100 at read_inode() time to calculate it, and to keep sufficient information 110 at read_inode() time to calculate it, and to keep sufficient information
@@ -107,11 +117,16 @@ struct jffs2_inode_cache {
107 temporary lists of dirents, and later must be set to 117 temporary lists of dirents, and later must be set to
108 NULL to mark the end of the raw_node_ref->next_in_ino 118 NULL to mark the end of the raw_node_ref->next_in_ino
109 chain. */ 119 chain. */
120 u8 class; /* It's used for identification */
121 u8 flags;
122 uint16_t state;
110 struct jffs2_inode_cache *next; 123 struct jffs2_inode_cache *next;
111 struct jffs2_raw_node_ref *nodes; 124 struct jffs2_raw_node_ref *nodes;
112 uint32_t ino; 125 uint32_t ino;
113 int nlink; 126 int nlink;
114 int state; 127#ifdef CONFIG_JFFS2_FS_XATTR
128 struct jffs2_xattr_ref *xref;
129#endif
115}; 130};
116 131
117/* Inode states for 'state' above. We need the 'GC' state to prevent 132/* Inode states for 'state' above. We need the 'GC' state to prevent
@@ -125,6 +140,12 @@ struct jffs2_inode_cache {
125#define INO_STATE_READING 5 /* In read_inode() */ 140#define INO_STATE_READING 5 /* In read_inode() */
126#define INO_STATE_CLEARING 6 /* In clear_inode() */ 141#define INO_STATE_CLEARING 6 /* In clear_inode() */
127 142
143#define INO_FLAGS_XATTR_CHECKED 0x01 /* has no duplicate xattr_ref */
144
145#define RAWNODE_CLASS_INODE_CACHE 0
146#define RAWNODE_CLASS_XATTR_DATUM 1
147#define RAWNODE_CLASS_XATTR_REF 2
148
128#define INOCACHE_HASHSIZE 128 149#define INOCACHE_HASHSIZE 128
129 150
130/* 151/*
@@ -203,57 +224,7 @@ static inline int jffs2_blocks_use_vmalloc(struct jffs2_sb_info *c)
203 return ((c->flash_size / c->sector_size) * sizeof (struct jffs2_eraseblock)) > (128 * 1024); 224 return ((c->flash_size / c->sector_size) * sizeof (struct jffs2_eraseblock)) > (128 * 1024);
204} 225}
205 226
206/* Calculate totlen from surrounding nodes or eraseblock */ 227#define ref_totlen(a, b, c) __jffs2_ref_totlen((a), (b), (c))
207static inline uint32_t __ref_totlen(struct jffs2_sb_info *c,
208 struct jffs2_eraseblock *jeb,
209 struct jffs2_raw_node_ref *ref)
210{
211 uint32_t ref_end;
212
213 if (ref->next_phys)
214 ref_end = ref_offset(ref->next_phys);
215 else {
216 if (!jeb)
217 jeb = &c->blocks[ref->flash_offset / c->sector_size];
218
219 /* Last node in block. Use free_space */
220 BUG_ON(ref != jeb->last_node);
221 ref_end = jeb->offset + c->sector_size - jeb->free_size;
222 }
223 return ref_end - ref_offset(ref);
224}
225
226static inline uint32_t ref_totlen(struct jffs2_sb_info *c,
227 struct jffs2_eraseblock *jeb,
228 struct jffs2_raw_node_ref *ref)
229{
230 uint32_t ret;
231
232#if CONFIG_JFFS2_FS_DEBUG > 0
233 if (jeb && jeb != &c->blocks[ref->flash_offset / c->sector_size]) {
234 printk(KERN_CRIT "ref_totlen called with wrong block -- at 0x%08x instead of 0x%08x; ref 0x%08x\n",
235 jeb->offset, c->blocks[ref->flash_offset / c->sector_size].offset, ref_offset(ref));
236 BUG();
237 }
238#endif
239
240#if 1
241 ret = ref->__totlen;
242#else
243 /* This doesn't actually work yet */
244 ret = __ref_totlen(c, jeb, ref);
245 if (ret != ref->__totlen) {
246 printk(KERN_CRIT "Totlen for ref at %p (0x%08x-0x%08x) miscalculated as 0x%x instead of %x\n",
247 ref, ref_offset(ref), ref_offset(ref)+ref->__totlen,
248 ret, ref->__totlen);
249 if (!jeb)
250 jeb = &c->blocks[ref->flash_offset / c->sector_size];
251 jffs2_dbg_dump_node_refs_nolock(c, jeb);
252 BUG();
253 }
254#endif
255 return ret;
256}
257 228
258#define ALLOC_NORMAL 0 /* Normal allocation */ 229#define ALLOC_NORMAL 0 /* Normal allocation */
259#define ALLOC_DELETION 1 /* Deletion node. Best to allow it */ 230#define ALLOC_DELETION 1 /* Deletion node. Best to allow it */
@@ -335,6 +306,11 @@ void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *t
335int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); 306int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn);
336void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); 307void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size);
337int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn); 308int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn);
309void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
310 struct jffs2_raw_node_ref *ref, uint32_t len);
311extern uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c,
312 struct jffs2_eraseblock *jeb,
313 struct jffs2_raw_node_ref *ref);
338 314
339/* nodemgmt.c */ 315/* nodemgmt.c */
340int jffs2_thread_should_wake(struct jffs2_sb_info *c); 316int jffs2_thread_should_wake(struct jffs2_sb_info *c);
@@ -342,7 +318,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs
342 uint32_t *len, int prio, uint32_t sumsize); 318 uint32_t *len, int prio, uint32_t sumsize);
343int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, 319int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs,
344 uint32_t *len, uint32_t sumsize); 320 uint32_t *len, uint32_t sumsize);
345int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new); 321int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new, uint32_t len);
346void jffs2_complete_reservation(struct jffs2_sb_info *c); 322void jffs2_complete_reservation(struct jffs2_sb_info *c);
347void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw); 323void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw);
348 324
@@ -385,6 +361,12 @@ struct jffs2_node_frag *jffs2_alloc_node_frag(void);
385void jffs2_free_node_frag(struct jffs2_node_frag *); 361void jffs2_free_node_frag(struct jffs2_node_frag *);
386struct jffs2_inode_cache *jffs2_alloc_inode_cache(void); 362struct jffs2_inode_cache *jffs2_alloc_inode_cache(void);
387void jffs2_free_inode_cache(struct jffs2_inode_cache *); 363void jffs2_free_inode_cache(struct jffs2_inode_cache *);
364#ifdef CONFIG_JFFS2_FS_XATTR
365struct jffs2_xattr_datum *jffs2_alloc_xattr_datum(void);
366void jffs2_free_xattr_datum(struct jffs2_xattr_datum *);
367struct jffs2_xattr_ref *jffs2_alloc_xattr_ref(void);
368void jffs2_free_xattr_ref(struct jffs2_xattr_ref *);
369#endif
388 370
389/* gc.c */ 371/* gc.c */
390int jffs2_garbage_collect_pass(struct jffs2_sb_info *c); 372int jffs2_garbage_collect_pass(struct jffs2_sb_info *c);
@@ -404,12 +386,14 @@ int jffs2_fill_scan_buf(struct jffs2_sb_info *c, void *buf,
404 uint32_t ofs, uint32_t len); 386 uint32_t ofs, uint32_t len);
405struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino); 387struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino);
406int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); 388int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
389int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t size);
407 390
408/* build.c */ 391/* build.c */
409int jffs2_do_mount_fs(struct jffs2_sb_info *c); 392int jffs2_do_mount_fs(struct jffs2_sb_info *c);
410 393
411/* erase.c */ 394/* erase.c */
412void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count); 395void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count);
396void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
413 397
414#ifdef CONFIG_JFFS2_FS_WRITEBUFFER 398#ifdef CONFIG_JFFS2_FS_WRITEBUFFER
415/* wbuf.c */ 399/* wbuf.c */
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
index 49127a1f0458..9a0f312cfcda 100644
--- a/fs/jffs2/nodemgmt.c
+++ b/fs/jffs2/nodemgmt.c
@@ -374,7 +374,6 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin
374 * @c: superblock info 374 * @c: superblock info
375 * @new: new node reference to add 375 * @new: new node reference to add
376 * @len: length of this physical node 376 * @len: length of this physical node
377 * @dirty: dirty flag for new node
378 * 377 *
379 * Should only be used to report nodes for which space has been allocated 378 * Should only be used to report nodes for which space has been allocated
380 * by jffs2_reserve_space. 379 * by jffs2_reserve_space.
@@ -382,13 +381,14 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin
382 * Must be called with the alloc_sem held. 381 * Must be called with the alloc_sem held.
383 */ 382 */
384 383
385int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new) 384int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new, uint32_t len)
386{ 385{
387 struct jffs2_eraseblock *jeb; 386 struct jffs2_eraseblock *jeb;
388 uint32_t len;
389 387
390 jeb = &c->blocks[new->flash_offset / c->sector_size]; 388 jeb = &c->blocks[new->flash_offset / c->sector_size];
391 len = ref_totlen(c, jeb, new); 389#ifdef TEST_TOTLEN
390 new->__totlen = len;
391#endif
392 392
393 D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n", ref_offset(new), ref_flags(new), len)); 393 D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n", ref_offset(new), ref_flags(new), len));
394#if 1 394#if 1
@@ -403,21 +403,7 @@ int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_r
403#endif 403#endif
404 spin_lock(&c->erase_completion_lock); 404 spin_lock(&c->erase_completion_lock);
405 405
406 if (!jeb->first_node) 406 jffs2_link_node_ref(c, jeb, new, len);
407 jeb->first_node = new;
408 if (jeb->last_node)
409 jeb->last_node->next_phys = new;
410 jeb->last_node = new;
411
412 jeb->free_size -= len;
413 c->free_size -= len;
414 if (ref_obsolete(new)) {
415 jeb->dirty_size += len;
416 c->dirty_size += len;
417 } else {
418 jeb->used_size += len;
419 c->used_size += len;
420 }
421 407
422 if (!jeb->free_size && !jeb->dirty_size && !ISDIRTY(jeb->wasted_size)) { 408 if (!jeb->free_size && !jeb->dirty_size && !ISDIRTY(jeb->wasted_size)) {
423 /* If it lives on the dirty_list, jffs2_reserve_space will put it there */ 409 /* If it lives on the dirty_list, jffs2_reserve_space will put it there */
@@ -470,6 +456,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
470 struct jffs2_unknown_node n; 456 struct jffs2_unknown_node n;
471 int ret, addedsize; 457 int ret, addedsize;
472 size_t retlen; 458 size_t retlen;
459 uint32_t freed_len;
473 460
474 if(!ref) { 461 if(!ref) {
475 printk(KERN_NOTICE "EEEEEK. jffs2_mark_node_obsolete called with NULL node\n"); 462 printk(KERN_NOTICE "EEEEEK. jffs2_mark_node_obsolete called with NULL node\n");
@@ -499,32 +486,34 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
499 486
500 spin_lock(&c->erase_completion_lock); 487 spin_lock(&c->erase_completion_lock);
501 488
489 freed_len = ref_totlen(c, jeb, ref);
490
502 if (ref_flags(ref) == REF_UNCHECKED) { 491 if (ref_flags(ref) == REF_UNCHECKED) {
503 D1(if (unlikely(jeb->unchecked_size < ref_totlen(c, jeb, ref))) { 492 D1(if (unlikely(jeb->unchecked_size < freed_len)) {
504 printk(KERN_NOTICE "raw unchecked node of size 0x%08x freed from erase block %d at 0x%08x, but unchecked_size was already 0x%08x\n", 493 printk(KERN_NOTICE "raw unchecked node of size 0x%08x freed from erase block %d at 0x%08x, but unchecked_size was already 0x%08x\n",
505 ref_totlen(c, jeb, ref), blocknr, ref->flash_offset, jeb->used_size); 494 freed_len, blocknr, ref->flash_offset, jeb->used_size);
506 BUG(); 495 BUG();
507 }) 496 })
508 D1(printk(KERN_DEBUG "Obsoleting previously unchecked node at 0x%08x of len %x: ", ref_offset(ref), ref_totlen(c, jeb, ref))); 497 D1(printk(KERN_DEBUG "Obsoleting previously unchecked node at 0x%08x of len %x: ", ref_offset(ref), freed_len));
509 jeb->unchecked_size -= ref_totlen(c, jeb, ref); 498 jeb->unchecked_size -= freed_len;
510 c->unchecked_size -= ref_totlen(c, jeb, ref); 499 c->unchecked_size -= freed_len;
511 } else { 500 } else {
512 D1(if (unlikely(jeb->used_size < ref_totlen(c, jeb, ref))) { 501 D1(if (unlikely(jeb->used_size < freed_len)) {
513 printk(KERN_NOTICE "raw node of size 0x%08x freed from erase block %d at 0x%08x, but used_size was already 0x%08x\n", 502 printk(KERN_NOTICE "raw node of size 0x%08x freed from erase block %d at 0x%08x, but used_size was already 0x%08x\n",
514 ref_totlen(c, jeb, ref), blocknr, ref->flash_offset, jeb->used_size); 503 freed_len, blocknr, ref->flash_offset, jeb->used_size);
515 BUG(); 504 BUG();
516 }) 505 })
517 D1(printk(KERN_DEBUG "Obsoleting node at 0x%08x of len %#x: ", ref_offset(ref), ref_totlen(c, jeb, ref))); 506 D1(printk(KERN_DEBUG "Obsoleting node at 0x%08x of len %#x: ", ref_offset(ref), freed_len));
518 jeb->used_size -= ref_totlen(c, jeb, ref); 507 jeb->used_size -= freed_len;
519 c->used_size -= ref_totlen(c, jeb, ref); 508 c->used_size -= freed_len;
520 } 509 }
521 510
522 // Take care, that wasted size is taken into concern 511 // Take care, that wasted size is taken into concern
523 if ((jeb->dirty_size || ISDIRTY(jeb->wasted_size + ref_totlen(c, jeb, ref))) && jeb != c->nextblock) { 512 if ((jeb->dirty_size || ISDIRTY(jeb->wasted_size + freed_len)) && jeb != c->nextblock) {
524 D1(printk(KERN_DEBUG "Dirtying\n")); 513 D1(printk(KERN_DEBUG "Dirtying\n"));
525 addedsize = ref_totlen(c, jeb, ref); 514 addedsize = freed_len;
526 jeb->dirty_size += ref_totlen(c, jeb, ref); 515 jeb->dirty_size += freed_len;
527 c->dirty_size += ref_totlen(c, jeb, ref); 516 c->dirty_size += freed_len;
528 517
529 /* Convert wasted space to dirty, if not a bad block */ 518 /* Convert wasted space to dirty, if not a bad block */
530 if (jeb->wasted_size) { 519 if (jeb->wasted_size) {
@@ -545,8 +534,8 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
545 } else { 534 } else {
546 D1(printk(KERN_DEBUG "Wasting\n")); 535 D1(printk(KERN_DEBUG "Wasting\n"));
547 addedsize = 0; 536 addedsize = 0;
548 jeb->wasted_size += ref_totlen(c, jeb, ref); 537 jeb->wasted_size += freed_len;
549 c->wasted_size += ref_totlen(c, jeb, ref); 538 c->wasted_size += freed_len;
550 } 539 }
551 ref->flash_offset = ref_offset(ref) | REF_OBSOLETE; 540 ref->flash_offset = ref_offset(ref) | REF_OBSOLETE;
552 541
@@ -634,8 +623,8 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
634 printk(KERN_WARNING "Short read from obsoleted node at 0x%08x: %zd\n", ref_offset(ref), retlen); 623 printk(KERN_WARNING "Short read from obsoleted node at 0x%08x: %zd\n", ref_offset(ref), retlen);
635 goto out_erase_sem; 624 goto out_erase_sem;
636 } 625 }
637 if (PAD(je32_to_cpu(n.totlen)) != PAD(ref_totlen(c, jeb, ref))) { 626 if (PAD(je32_to_cpu(n.totlen)) != PAD(freed_len)) {
638 printk(KERN_WARNING "Node totlen on flash (0x%08x) != totlen from node ref (0x%08x)\n", je32_to_cpu(n.totlen), ref_totlen(c, jeb, ref)); 627 printk(KERN_WARNING "Node totlen on flash (0x%08x) != totlen from node ref (0x%08x)\n", je32_to_cpu(n.totlen), freed_len);
639 goto out_erase_sem; 628 goto out_erase_sem;
640 } 629 }
641 if (!(je16_to_cpu(n.nodetype) & JFFS2_NODE_ACCURATE)) { 630 if (!(je16_to_cpu(n.nodetype) & JFFS2_NODE_ACCURATE)) {
@@ -692,7 +681,9 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
692 681
693 spin_lock(&c->erase_completion_lock); 682 spin_lock(&c->erase_completion_lock);
694 683
684#ifdef TEST_TOTLEN
695 ref->__totlen += n->__totlen; 685 ref->__totlen += n->__totlen;
686#endif
696 ref->next_phys = n->next_phys; 687 ref->next_phys = n->next_phys;
697 if (jeb->last_node == n) jeb->last_node = ref; 688 if (jeb->last_node == n) jeb->last_node = ref;
698 if (jeb->gc_node == n) { 689 if (jeb->gc_node == n) {
@@ -715,7 +706,9 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
715 p = p->next_phys; 706 p = p->next_phys;
716 707
717 if (ref_obsolete(p) && !ref->next_in_ino) { 708 if (ref_obsolete(p) && !ref->next_in_ino) {
709#ifdef TEST_TOTLEN
718 p->__totlen += ref->__totlen; 710 p->__totlen += ref->__totlen;
711#endif
719 if (jeb->last_node == ref) { 712 if (jeb->last_node == ref) {
720 jeb->last_node = p; 713 jeb->last_node = p;
721 } 714 }
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index a10eb03ac95b..d2ad2a2081d8 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -58,6 +58,10 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
58 f->target = NULL; 58 f->target = NULL;
59 f->flags = 0; 59 f->flags = 0;
60 f->usercompr = 0; 60 f->usercompr = 0;
61#ifdef CONFIG_JFFS2_FS_POSIX_ACL
62 f->i_acl_access = JFFS2_ACL_NOT_CACHED;
63 f->i_acl_default = JFFS2_ACL_NOT_CACHED;
64#endif
61} 65}
62 66
63 67
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 352ada892f3e..cffafec01e48 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -65,6 +65,25 @@ static inline uint32_t EMPTY_SCAN_SIZE(uint32_t sector_size) {
65 return DEFAULT_EMPTY_SCAN_SIZE; 65 return DEFAULT_EMPTY_SCAN_SIZE;
66} 66}
67 67
68static int file_dirty(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
69{
70 int ret = jffs2_scan_dirty_space(c, jeb, jeb->free_size);
71 if (ret)
72 return ret;
73 /* Turned wasted size into dirty, since we apparently
74 think it's recoverable now. */
75 jeb->dirty_size += jeb->wasted_size;
76 c->dirty_size += jeb->wasted_size;
77 c->wasted_size -= jeb->wasted_size;
78 jeb->wasted_size = 0;
79 if (VERYDIRTY(c, jeb->dirty_size)) {
80 list_add(&jeb->list, &c->very_dirty_list);
81 } else {
82 list_add(&jeb->list, &c->dirty_list);
83 }
84 return 0;
85}
86
68int jffs2_scan_medium(struct jffs2_sb_info *c) 87int jffs2_scan_medium(struct jffs2_sb_info *c)
69{ 88{
70 int i, ret; 89 int i, ret;
@@ -170,34 +189,20 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
170 (!c->nextblock || c->nextblock->free_size < jeb->free_size)) { 189 (!c->nextblock || c->nextblock->free_size < jeb->free_size)) {
171 /* Better candidate for the next writes to go to */ 190 /* Better candidate for the next writes to go to */
172 if (c->nextblock) { 191 if (c->nextblock) {
173 c->nextblock->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size; 192 ret = file_dirty(c, c->nextblock);
174 c->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size; 193 if (ret)
175 c->free_size -= c->nextblock->free_size; 194 return ret;
176 c->wasted_size -= c->nextblock->wasted_size;
177 c->nextblock->free_size = c->nextblock->wasted_size = 0;
178 if (VERYDIRTY(c, c->nextblock->dirty_size)) {
179 list_add(&c->nextblock->list, &c->very_dirty_list);
180 } else {
181 list_add(&c->nextblock->list, &c->dirty_list);
182 }
183 /* deleting summary information of the old nextblock */ 195 /* deleting summary information of the old nextblock */
184 jffs2_sum_reset_collected(c->summary); 196 jffs2_sum_reset_collected(c->summary);
185 } 197 }
186 /* update collected summary infromation for the current nextblock */ 198 /* update collected summary information for the current nextblock */
187 jffs2_sum_move_collected(c, s); 199 jffs2_sum_move_collected(c, s);
188 D1(printk(KERN_DEBUG "jffs2_scan_medium(): new nextblock = 0x%08x\n", jeb->offset)); 200 D1(printk(KERN_DEBUG "jffs2_scan_medium(): new nextblock = 0x%08x\n", jeb->offset));
189 c->nextblock = jeb; 201 c->nextblock = jeb;
190 } else { 202 } else {
191 jeb->dirty_size += jeb->free_size + jeb->wasted_size; 203 ret = file_dirty(c, jeb);
192 c->dirty_size += jeb->free_size + jeb->wasted_size; 204 if (ret)
193 c->free_size -= jeb->free_size; 205 return ret;
194 c->wasted_size -= jeb->wasted_size;
195 jeb->free_size = jeb->wasted_size = 0;
196 if (VERYDIRTY(c, jeb->dirty_size)) {
197 list_add(&jeb->list, &c->very_dirty_list);
198 } else {
199 list_add(&jeb->list, &c->dirty_list);
200 }
201 } 206 }
202 break; 207 break;
203 208
@@ -306,11 +311,138 @@ int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *je
306 return BLK_STATE_ALLDIRTY; 311 return BLK_STATE_ALLDIRTY;
307} 312}
308 313
314#ifdef CONFIG_JFFS2_FS_XATTR
315static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
316 struct jffs2_raw_xattr *rx, uint32_t ofs,
317 struct jffs2_summary *s)
318{
319 struct jffs2_xattr_datum *xd;
320 struct jffs2_raw_node_ref *raw;
321 uint32_t totlen, crc;
322 int err;
323
324 crc = crc32(0, rx, sizeof(struct jffs2_raw_xattr) - 4);
325 if (crc != je32_to_cpu(rx->node_crc)) {
326 if (je32_to_cpu(rx->node_crc) != 0xffffffff)
327 JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
328 ofs, je32_to_cpu(rx->node_crc), crc);
329 if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rx->totlen))))
330 return err;
331 return 0;
332 }
333
334 totlen = PAD(sizeof(*rx) + rx->name_len + 1 + je16_to_cpu(rx->value_len));
335 if (totlen != je32_to_cpu(rx->totlen)) {
336 JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%u\n",
337 ofs, je32_to_cpu(rx->totlen), totlen);
338 if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rx->totlen))))
339 return err;
340 return 0;
341 }
342
343 raw = jffs2_alloc_raw_node_ref();
344 if (!raw)
345 return -ENOMEM;
346
347 xd = jffs2_setup_xattr_datum(c, je32_to_cpu(rx->xid), je32_to_cpu(rx->version));
348 if (IS_ERR(xd)) {
349 jffs2_free_raw_node_ref(raw);
350 if (PTR_ERR(xd) == -EEXIST) {
351 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rx->totlen)))))
352 return err;
353 return 0;
354 }
355 return PTR_ERR(xd);
356 }
357 xd->xprefix = rx->xprefix;
358 xd->name_len = rx->name_len;
359 xd->value_len = je16_to_cpu(rx->value_len);
360 xd->data_crc = je32_to_cpu(rx->data_crc);
361 xd->node = raw;
362
363 raw->flash_offset = ofs | REF_PRISTINE;
364 raw->next_in_ino = (void *)xd;
365
366 jffs2_link_node_ref(c, jeb, raw, totlen);
367
368 if (jffs2_sum_active())
369 jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset);
370 dbg_xattr("scaning xdatum at %#08x (xid=%u, version=%u)\n",
371 ofs, xd->xid, xd->version);
372 return 0;
373}
374
375static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
376 struct jffs2_raw_xref *rr, uint32_t ofs,
377 struct jffs2_summary *s)
378{
379 struct jffs2_xattr_ref *ref;
380 struct jffs2_raw_node_ref *raw;
381 uint32_t crc;
382 int err;
383
384 crc = crc32(0, rr, sizeof(*rr) - 4);
385 if (crc != je32_to_cpu(rr->node_crc)) {
386 if (je32_to_cpu(rr->node_crc) != 0xffffffff)
387 JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
388 ofs, je32_to_cpu(rr->node_crc), crc);
389 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rr->totlen)))))
390 return err;
391 return 0;
392 }
393
394 if (PAD(sizeof(struct jffs2_raw_xref)) != je32_to_cpu(rr->totlen)) {
395 JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%u\n",
396 ofs, je32_to_cpu(rr->totlen),
397 PAD(sizeof(struct jffs2_raw_xref)));
398 if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rr->totlen))))
399 return err;
400 return 0;
401 }
402
403 ref = jffs2_alloc_xattr_ref();
404 if (!ref)
405 return -ENOMEM;
406
407 raw = jffs2_alloc_raw_node_ref();
408 if (!raw) {
409 jffs2_free_xattr_ref(ref);
410 return -ENOMEM;
411 }
412
413 /* BEFORE jffs2_build_xattr_subsystem() called,
414 * ref->xid is used to store 32bit xid, xd is not used
415 * ref->ino is used to store 32bit inode-number, ic is not used
416 * Thoes variables are declared as union, thus using those
417 * are exclusive. In a similar way, ref->next is temporarily
418 * used to chain all xattr_ref object. It's re-chained to
419 * jffs2_inode_cache in jffs2_build_xattr_subsystem() correctly.
420 */
421 ref->node = raw;
422 ref->ino = je32_to_cpu(rr->ino);
423 ref->xid = je32_to_cpu(rr->xid);
424 ref->next = c->xref_temp;
425 c->xref_temp = ref;
426
427 raw->flash_offset = ofs | REF_PRISTINE;
428 raw->next_in_ino = (void *)ref;
429
430 jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(rr->totlen)));
431
432 if (jffs2_sum_active())
433 jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset);
434 dbg_xattr("scan xref at %#08x (xid=%u, ino=%u)\n",
435 ofs, ref->xid, ref->ino);
436 return 0;
437}
438#endif
439
440/* Called with 'buf_size == 0' if buf is in fact a pointer _directly_ into
441 the flash, XIP-style */
309static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 442static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
310 unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) { 443 unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) {
311 struct jffs2_unknown_node *node; 444 struct jffs2_unknown_node *node;
312 struct jffs2_unknown_node crcnode; 445 struct jffs2_unknown_node crcnode;
313 struct jffs2_sum_marker *sm;
314 uint32_t ofs, prevofs; 446 uint32_t ofs, prevofs;
315 uint32_t hdr_crc, buf_ofs, buf_len; 447 uint32_t hdr_crc, buf_ofs, buf_len;
316 int err; 448 int err;
@@ -344,32 +476,74 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
344#endif 476#endif
345 477
346 if (jffs2_sum_active()) { 478 if (jffs2_sum_active()) {
347 sm = kmalloc(sizeof(struct jffs2_sum_marker), GFP_KERNEL); 479 struct jffs2_sum_marker *sm;
348 if (!sm) { 480 void *sumptr = NULL;
349 return -ENOMEM; 481 uint32_t sumlen;
350 } 482
483 if (!buf_size) {
484 /* XIP case. Just look, point at the summary if it's there */
485 sm = (void *)buf + jeb->offset - sizeof(*sm);
486 if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC) {
487 sumptr = buf + je32_to_cpu(sm->offset);
488 sumlen = c->sector_size - je32_to_cpu(sm->offset);
489 }
490 } else {
491 /* If NAND flash, read a whole page of it. Else just the end */
492 if (c->wbuf_pagesize)
493 buf_len = c->wbuf_pagesize;
494 else
495 buf_len = sizeof(*sm);
496
497 /* Read as much as we want into the _end_ of the preallocated buffer */
498 err = jffs2_fill_scan_buf(c, buf + buf_size - buf_len,
499 jeb->offset + c->sector_size - buf_len,
500 buf_len);
501 if (err)
502 return err;
503
504 sm = (void *)buf + buf_size - sizeof(*sm);
505 if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC) {
506 sumlen = c->sector_size - je32_to_cpu(sm->offset);
507 sumptr = buf + buf_size - sumlen;
508
509 /* Now, make sure the summary itself is available */
510 if (sumlen > buf_size) {
511 /* Need to kmalloc for this. */
512 sumptr = kmalloc(sumlen, GFP_KERNEL);
513 if (!sumptr)
514 return -ENOMEM;
515 memcpy(sumptr + sumlen - buf_len, buf + buf_size - buf_len, buf_len);
516 }
517 if (buf_len < sumlen) {
518 /* Need to read more so that the entire summary node is present */
519 err = jffs2_fill_scan_buf(c, sumptr,
520 jeb->offset + c->sector_size - sumlen,
521 sumlen - buf_len);
522 if (err)
523 return err;
524 }
525 }
351 526
352 err = jffs2_fill_scan_buf(c, (unsigned char *) sm, jeb->offset + c->sector_size -
353 sizeof(struct jffs2_sum_marker), sizeof(struct jffs2_sum_marker));
354 if (err) {
355 kfree(sm);
356 return err;
357 } 527 }
358 528
359 if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC ) { 529 if (sumptr) {
360 err = jffs2_sum_scan_sumnode(c, jeb, je32_to_cpu(sm->offset), &pseudo_random); 530 err = jffs2_sum_scan_sumnode(c, jeb, sumptr, sumlen, &pseudo_random);
361 if (err) { 531
362 kfree(sm); 532 if (buf_size && sumlen > buf_size)
533 kfree(sumptr);
534 /* If it returns with a real error, bail.
535 If it returns positive, that's a block classification
536 (i.e. BLK_STATE_xxx) so return that too.
537 If it returns zero, fall through to full scan. */
538 if (err)
363 return err; 539 return err;
364 }
365 } 540 }
366
367 kfree(sm);
368 } 541 }
369 542
370 buf_ofs = jeb->offset; 543 buf_ofs = jeb->offset;
371 544
372 if (!buf_size) { 545 if (!buf_size) {
546 /* This is the XIP case -- we're reading _directly_ from the flash chip */
373 buf_len = c->sector_size; 547 buf_len = c->sector_size;
374 } else { 548 } else {
375 buf_len = EMPTY_SCAN_SIZE(c->sector_size); 549 buf_len = EMPTY_SCAN_SIZE(c->sector_size);
@@ -407,7 +581,8 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
407 if (ofs) { 581 if (ofs) {
408 D1(printk(KERN_DEBUG "Free space at %08x ends at %08x\n", jeb->offset, 582 D1(printk(KERN_DEBUG "Free space at %08x ends at %08x\n", jeb->offset,
409 jeb->offset + ofs)); 583 jeb->offset + ofs));
410 DIRTY_SPACE(ofs); 584 if ((err = jffs2_scan_dirty_space(c, jeb, ofs)))
585 return err;
411 } 586 }
412 587
413 /* Now ofs is a complete physical flash offset as it always was... */ 588 /* Now ofs is a complete physical flash offset as it always was... */
@@ -431,7 +606,8 @@ scan_more:
431 } 606 }
432 if (ofs == prevofs) { 607 if (ofs == prevofs) {
433 printk(KERN_WARNING "ofs 0x%08x has already been seen. Skipping\n", ofs); 608 printk(KERN_WARNING "ofs 0x%08x has already been seen. Skipping\n", ofs);
434 DIRTY_SPACE(4); 609 if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
610 return err;
435 ofs += 4; 611 ofs += 4;
436 continue; 612 continue;
437 } 613 }
@@ -440,7 +616,8 @@ scan_more:
440 if (jeb->offset + c->sector_size < ofs + sizeof(*node)) { 616 if (jeb->offset + c->sector_size < ofs + sizeof(*node)) {
441 D1(printk(KERN_DEBUG "Fewer than %zd bytes left to end of block. (%x+%x<%x+%zx) Not reading\n", sizeof(struct jffs2_unknown_node), 617 D1(printk(KERN_DEBUG "Fewer than %zd bytes left to end of block. (%x+%x<%x+%zx) Not reading\n", sizeof(struct jffs2_unknown_node),
442 jeb->offset, c->sector_size, ofs, sizeof(*node))); 618 jeb->offset, c->sector_size, ofs, sizeof(*node)));
443 DIRTY_SPACE((jeb->offset + c->sector_size)-ofs); 619 if ((err = jffs2_scan_dirty_space(c, jeb, (jeb->offset + c->sector_size)-ofs)))
620 return err;
444 break; 621 break;
445 } 622 }
446 623
@@ -470,7 +647,8 @@ scan_more:
470 if (*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff) { 647 if (*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff) {
471 printk(KERN_WARNING "Empty flash at 0x%08x ends at 0x%08x\n", 648 printk(KERN_WARNING "Empty flash at 0x%08x ends at 0x%08x\n",
472 empty_start, ofs); 649 empty_start, ofs);
473 DIRTY_SPACE(ofs-empty_start); 650 if ((err = jffs2_scan_dirty_space(c, jeb, ofs-empty_start)))
651 return err;
474 goto scan_more; 652 goto scan_more;
475 } 653 }
476 654
@@ -507,20 +685,23 @@ scan_more:
507 685
508 if (ofs == jeb->offset && je16_to_cpu(node->magic) == KSAMTIB_CIGAM_2SFFJ) { 686 if (ofs == jeb->offset && je16_to_cpu(node->magic) == KSAMTIB_CIGAM_2SFFJ) {
509 printk(KERN_WARNING "Magic bitmask is backwards at offset 0x%08x. Wrong endian filesystem?\n", ofs); 687 printk(KERN_WARNING "Magic bitmask is backwards at offset 0x%08x. Wrong endian filesystem?\n", ofs);
510 DIRTY_SPACE(4); 688 if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
689 return err;
511 ofs += 4; 690 ofs += 4;
512 continue; 691 continue;
513 } 692 }
514 if (je16_to_cpu(node->magic) == JFFS2_DIRTY_BITMASK) { 693 if (je16_to_cpu(node->magic) == JFFS2_DIRTY_BITMASK) {
515 D1(printk(KERN_DEBUG "Dirty bitmask at 0x%08x\n", ofs)); 694 D1(printk(KERN_DEBUG "Dirty bitmask at 0x%08x\n", ofs));
516 DIRTY_SPACE(4); 695 if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
696 return err;
517 ofs += 4; 697 ofs += 4;
518 continue; 698 continue;
519 } 699 }
520 if (je16_to_cpu(node->magic) == JFFS2_OLD_MAGIC_BITMASK) { 700 if (je16_to_cpu(node->magic) == JFFS2_OLD_MAGIC_BITMASK) {
521 printk(KERN_WARNING "Old JFFS2 bitmask found at 0x%08x\n", ofs); 701 printk(KERN_WARNING "Old JFFS2 bitmask found at 0x%08x\n", ofs);
522 printk(KERN_WARNING "You cannot use older JFFS2 filesystems with newer kernels\n"); 702 printk(KERN_WARNING "You cannot use older JFFS2 filesystems with newer kernels\n");
523 DIRTY_SPACE(4); 703 if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
704 return err;
524 ofs += 4; 705 ofs += 4;
525 continue; 706 continue;
526 } 707 }
@@ -529,7 +710,8 @@ scan_more:
529 noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead\n", 710 noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead\n",
530 JFFS2_MAGIC_BITMASK, ofs, 711 JFFS2_MAGIC_BITMASK, ofs,
531 je16_to_cpu(node->magic)); 712 je16_to_cpu(node->magic));
532 DIRTY_SPACE(4); 713 if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
714 return err;
533 ofs += 4; 715 ofs += 4;
534 continue; 716 continue;
535 } 717 }
@@ -546,7 +728,8 @@ scan_more:
546 je32_to_cpu(node->totlen), 728 je32_to_cpu(node->totlen),
547 je32_to_cpu(node->hdr_crc), 729 je32_to_cpu(node->hdr_crc),
548 hdr_crc); 730 hdr_crc);
549 DIRTY_SPACE(4); 731 if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
732 return err;
550 ofs += 4; 733 ofs += 4;
551 continue; 734 continue;
552 } 735 }
@@ -557,7 +740,8 @@ scan_more:
557 printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n", 740 printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n",
558 ofs, je32_to_cpu(node->totlen)); 741 ofs, je32_to_cpu(node->totlen));
559 printk(KERN_WARNING "Perhaps the file system was created with the wrong erase size?\n"); 742 printk(KERN_WARNING "Perhaps the file system was created with the wrong erase size?\n");
560 DIRTY_SPACE(4); 743 if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
744 return err;
561 ofs += 4; 745 ofs += 4;
562 continue; 746 continue;
563 } 747 }
@@ -565,7 +749,8 @@ scan_more:
565 if (!(je16_to_cpu(node->nodetype) & JFFS2_NODE_ACCURATE)) { 749 if (!(je16_to_cpu(node->nodetype) & JFFS2_NODE_ACCURATE)) {
566 /* Wheee. This is an obsoleted node */ 750 /* Wheee. This is an obsoleted node */
567 D2(printk(KERN_DEBUG "Node at 0x%08x is obsolete. Skipping\n", ofs)); 751 D2(printk(KERN_DEBUG "Node at 0x%08x is obsolete. Skipping\n", ofs));
568 DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); 752 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
753 return err;
569 ofs += PAD(je32_to_cpu(node->totlen)); 754 ofs += PAD(je32_to_cpu(node->totlen));
570 continue; 755 continue;
571 } 756 }
@@ -603,16 +788,55 @@ scan_more:
603 ofs += PAD(je32_to_cpu(node->totlen)); 788 ofs += PAD(je32_to_cpu(node->totlen));
604 break; 789 break;
605 790
791#ifdef CONFIG_JFFS2_FS_XATTR
792 case JFFS2_NODETYPE_XATTR:
793 if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) {
794 buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
795 D1(printk(KERN_DEBUG "Fewer than %d bytes (xattr node)"
796 " left to end of buf. Reading 0x%x at 0x%08x\n",
797 je32_to_cpu(node->totlen), buf_len, ofs));
798 err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
799 if (err)
800 return err;
801 buf_ofs = ofs;
802 node = (void *)buf;
803 }
804 err = jffs2_scan_xattr_node(c, jeb, (void *)node, ofs, s);
805 if (err)
806 return err;
807 ofs += PAD(je32_to_cpu(node->totlen));
808 break;
809 case JFFS2_NODETYPE_XREF:
810 if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) {
811 buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
812 D1(printk(KERN_DEBUG "Fewer than %d bytes (xref node)"
813 " left to end of buf. Reading 0x%x at 0x%08x\n",
814 je32_to_cpu(node->totlen), buf_len, ofs));
815 err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
816 if (err)
817 return err;
818 buf_ofs = ofs;
819 node = (void *)buf;
820 }
821 err = jffs2_scan_xref_node(c, jeb, (void *)node, ofs, s);
822 if (err)
823 return err;
824 ofs += PAD(je32_to_cpu(node->totlen));
825 break;
826#endif /* CONFIG_JFFS2_FS_XATTR */
827
606 case JFFS2_NODETYPE_CLEANMARKER: 828 case JFFS2_NODETYPE_CLEANMARKER:
607 D1(printk(KERN_DEBUG "CLEANMARKER node found at 0x%08x\n", ofs)); 829 D1(printk(KERN_DEBUG "CLEANMARKER node found at 0x%08x\n", ofs));
608 if (je32_to_cpu(node->totlen) != c->cleanmarker_size) { 830 if (je32_to_cpu(node->totlen) != c->cleanmarker_size) {
609 printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x\n", 831 printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x\n",
610 ofs, je32_to_cpu(node->totlen), c->cleanmarker_size); 832 ofs, je32_to_cpu(node->totlen), c->cleanmarker_size);
611 DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node))); 833 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(sizeof(struct jffs2_unknown_node)))))
834 return err;
612 ofs += PAD(sizeof(struct jffs2_unknown_node)); 835 ofs += PAD(sizeof(struct jffs2_unknown_node));
613 } else if (jeb->first_node) { 836 } else if (jeb->first_node) {
614 printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x, not first node in block (0x%08x)\n", ofs, jeb->offset); 837 printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x, not first node in block (0x%08x)\n", ofs, jeb->offset);
615 DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node))); 838 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(sizeof(struct jffs2_unknown_node)))))
839 return err;
616 ofs += PAD(sizeof(struct jffs2_unknown_node)); 840 ofs += PAD(sizeof(struct jffs2_unknown_node));
617 } else { 841 } else {
618 struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref(); 842 struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref();
@@ -621,12 +845,10 @@ scan_more:
621 return -ENOMEM; 845 return -ENOMEM;
622 } 846 }
623 marker_ref->next_in_ino = NULL; 847 marker_ref->next_in_ino = NULL;
624 marker_ref->next_phys = NULL;
625 marker_ref->flash_offset = ofs | REF_NORMAL; 848 marker_ref->flash_offset = ofs | REF_NORMAL;
626 marker_ref->__totlen = c->cleanmarker_size;
627 jeb->first_node = jeb->last_node = marker_ref;
628 849
629 USED_SPACE(PAD(c->cleanmarker_size)); 850 jffs2_link_node_ref(c, jeb, marker_ref, c->cleanmarker_size);
851
630 ofs += PAD(c->cleanmarker_size); 852 ofs += PAD(c->cleanmarker_size);
631 } 853 }
632 break; 854 break;
@@ -634,7 +856,8 @@ scan_more:
634 case JFFS2_NODETYPE_PADDING: 856 case JFFS2_NODETYPE_PADDING:
635 if (jffs2_sum_active()) 857 if (jffs2_sum_active())
636 jffs2_sum_add_padding_mem(s, je32_to_cpu(node->totlen)); 858 jffs2_sum_add_padding_mem(s, je32_to_cpu(node->totlen));
637 DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); 859 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
860 return err;
638 ofs += PAD(je32_to_cpu(node->totlen)); 861 ofs += PAD(je32_to_cpu(node->totlen));
639 break; 862 break;
640 863
@@ -645,7 +868,8 @@ scan_more:
645 c->flags |= JFFS2_SB_FLAG_RO; 868 c->flags |= JFFS2_SB_FLAG_RO;
646 if (!(jffs2_is_readonly(c))) 869 if (!(jffs2_is_readonly(c)))
647 return -EROFS; 870 return -EROFS;
648 DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); 871 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
872 return err;
649 ofs += PAD(je32_to_cpu(node->totlen)); 873 ofs += PAD(je32_to_cpu(node->totlen));
650 break; 874 break;
651 875
@@ -655,15 +879,27 @@ scan_more:
655 879
656 case JFFS2_FEATURE_RWCOMPAT_DELETE: 880 case JFFS2_FEATURE_RWCOMPAT_DELETE:
657 D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs)); 881 D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs));
658 DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); 882 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
883 return err;
659 ofs += PAD(je32_to_cpu(node->totlen)); 884 ofs += PAD(je32_to_cpu(node->totlen));
660 break; 885 break;
661 886
662 case JFFS2_FEATURE_RWCOMPAT_COPY: 887 case JFFS2_FEATURE_RWCOMPAT_COPY: {
888 struct jffs2_raw_node_ref *ref;
663 D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs)); 889 D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs));
664 USED_SPACE(PAD(je32_to_cpu(node->totlen))); 890
891 ref = jffs2_alloc_raw_node_ref();
892 if (!ref)
893 return -ENOMEM;
894 ref->flash_offset = ofs | REF_PRISTINE;
895 ref->next_in_ino = 0;
896 jffs2_link_node_ref(c, jeb, ref, PAD(je32_to_cpu(node->totlen)));
897
898 /* We can't summarise nodes we don't grok */
899 jffs2_sum_disable_collecting(s);
665 ofs += PAD(je32_to_cpu(node->totlen)); 900 ofs += PAD(je32_to_cpu(node->totlen));
666 break; 901 break;
902 }
667 } 903 }
668 } 904 }
669 } 905 }
@@ -722,6 +958,7 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
722 struct jffs2_raw_node_ref *raw; 958 struct jffs2_raw_node_ref *raw;
723 struct jffs2_inode_cache *ic; 959 struct jffs2_inode_cache *ic;
724 uint32_t ino = je32_to_cpu(ri->ino); 960 uint32_t ino = je32_to_cpu(ri->ino);
961 int err;
725 962
726 D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", ofs)); 963 D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", ofs));
727 964
@@ -751,7 +988,8 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
751 printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", 988 printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
752 ofs, je32_to_cpu(ri->node_crc), crc); 989 ofs, je32_to_cpu(ri->node_crc), crc);
753 /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */ 990 /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */
754 DIRTY_SPACE(PAD(je32_to_cpu(ri->totlen))); 991 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(ri->totlen)))))
992 return err;
755 jffs2_free_raw_node_ref(raw); 993 jffs2_free_raw_node_ref(raw);
756 return 0; 994 return 0;
757 } 995 }
@@ -765,16 +1003,11 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
765 /* Wheee. It worked */ 1003 /* Wheee. It worked */
766 1004
767 raw->flash_offset = ofs | REF_UNCHECKED; 1005 raw->flash_offset = ofs | REF_UNCHECKED;
768 raw->__totlen = PAD(je32_to_cpu(ri->totlen));
769 raw->next_phys = NULL;
770 raw->next_in_ino = ic->nodes;
771 1006
1007 raw->next_in_ino = ic->nodes;
772 ic->nodes = raw; 1008 ic->nodes = raw;
773 if (!jeb->first_node) 1009
774 jeb->first_node = raw; 1010 jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(ri->totlen)));
775 if (jeb->last_node)
776 jeb->last_node->next_phys = raw;
777 jeb->last_node = raw;
778 1011
779 D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n", 1012 D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n",
780 je32_to_cpu(ri->ino), je32_to_cpu(ri->version), 1013 je32_to_cpu(ri->ino), je32_to_cpu(ri->version),
@@ -783,8 +1016,6 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
783 1016
784 pseudo_random += je32_to_cpu(ri->version); 1017 pseudo_random += je32_to_cpu(ri->version);
785 1018
786 UNCHECKED_SPACE(PAD(je32_to_cpu(ri->totlen)));
787
788 if (jffs2_sum_active()) { 1019 if (jffs2_sum_active()) {
789 jffs2_sum_add_inode_mem(s, ri, ofs - jeb->offset); 1020 jffs2_sum_add_inode_mem(s, ri, ofs - jeb->offset);
790 } 1021 }
@@ -799,6 +1030,7 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo
799 struct jffs2_full_dirent *fd; 1030 struct jffs2_full_dirent *fd;
800 struct jffs2_inode_cache *ic; 1031 struct jffs2_inode_cache *ic;
801 uint32_t crc; 1032 uint32_t crc;
1033 int err;
802 1034
803 D1(printk(KERN_DEBUG "jffs2_scan_dirent_node(): Node at 0x%08x\n", ofs)); 1035 D1(printk(KERN_DEBUG "jffs2_scan_dirent_node(): Node at 0x%08x\n", ofs));
804 1036
@@ -810,7 +1042,8 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo
810 printk(KERN_NOTICE "jffs2_scan_dirent_node(): Node CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", 1042 printk(KERN_NOTICE "jffs2_scan_dirent_node(): Node CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
811 ofs, je32_to_cpu(rd->node_crc), crc); 1043 ofs, je32_to_cpu(rd->node_crc), crc);
812 /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */ 1044 /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */
813 DIRTY_SPACE(PAD(je32_to_cpu(rd->totlen))); 1045 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rd->totlen)))))
1046 return err;
814 return 0; 1047 return 0;
815 } 1048 }
816 1049
@@ -831,7 +1064,8 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo
831 jffs2_free_full_dirent(fd); 1064 jffs2_free_full_dirent(fd);
832 /* FIXME: Why do we believe totlen? */ 1065 /* FIXME: Why do we believe totlen? */
833 /* We believe totlen because the CRC on the node _header_ was OK, just the name failed. */ 1066 /* We believe totlen because the CRC on the node _header_ was OK, just the name failed. */
834 DIRTY_SPACE(PAD(je32_to_cpu(rd->totlen))); 1067 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rd->totlen)))))
1068 return err;
835 return 0; 1069 return 0;
836 } 1070 }
837 raw = jffs2_alloc_raw_node_ref(); 1071 raw = jffs2_alloc_raw_node_ref();
@@ -847,16 +1081,11 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo
847 return -ENOMEM; 1081 return -ENOMEM;
848 } 1082 }
849 1083
850 raw->__totlen = PAD(je32_to_cpu(rd->totlen));
851 raw->flash_offset = ofs | REF_PRISTINE; 1084 raw->flash_offset = ofs | REF_PRISTINE;
852 raw->next_phys = NULL;
853 raw->next_in_ino = ic->nodes; 1085 raw->next_in_ino = ic->nodes;
854 ic->nodes = raw; 1086 ic->nodes = raw;
855 if (!jeb->first_node) 1087
856 jeb->first_node = raw; 1088 jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(rd->totlen)));
857 if (jeb->last_node)
858 jeb->last_node->next_phys = raw;
859 jeb->last_node = raw;
860 1089
861 fd->raw = raw; 1090 fd->raw = raw;
862 fd->next = NULL; 1091 fd->next = NULL;
@@ -864,7 +1093,6 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo
864 fd->ino = je32_to_cpu(rd->ino); 1093 fd->ino = je32_to_cpu(rd->ino);
865 fd->nhash = full_name_hash(fd->name, rd->nsize); 1094 fd->nhash = full_name_hash(fd->name, rd->nsize);
866 fd->type = rd->type; 1095 fd->type = rd->type;
867 USED_SPACE(PAD(je32_to_cpu(rd->totlen)));
868 jffs2_add_fd_to_list(c, fd, &ic->scan_dents); 1096 jffs2_add_fd_to_list(c, fd, &ic->scan_dents);
869 1097
870 if (jffs2_sum_active()) { 1098 if (jffs2_sum_active()) {
diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c
new file mode 100644
index 000000000000..52a9894a6364
--- /dev/null
+++ b/fs/jffs2/security.c
@@ -0,0 +1,82 @@
1/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright (C) 2006 NEC Corporation
5 *
6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
7 *
8 * For licensing information, see the file 'LICENCE' in this 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 <linux/security.h>
22#include "nodelist.h"
23
24/* ---- Initial Security Label Attachment -------------- */
25int jffs2_init_security(struct inode *inode, struct inode *dir)
26{
27 int rc;
28 size_t len;
29 void *value;
30 char *name;
31
32 rc = security_inode_init_security(inode, dir, &name, &value, &len);
33 if (rc) {
34 if (rc == -EOPNOTSUPP)
35 return 0;
36 return rc;
37 }
38 rc = do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, value, len, 0);
39
40 kfree(name);
41 kfree(value);
42 return rc;
43}
44
45/* ---- XATTR Handler for "security.*" ----------------- */
46static int jffs2_security_getxattr(struct inode *inode, const char *name,
47 void *buffer, size_t size)
48{
49 if (!strcmp(name, ""))
50 return -EINVAL;
51
52 return do_jffs2_getxattr(inode, JFFS2_XPREFIX_SECURITY, name, buffer, size);
53}
54
55static int jffs2_security_setxattr(struct inode *inode, const char *name, const void *buffer,
56 size_t size, int flags)
57{
58 if (!strcmp(name, ""))
59 return -EINVAL;
60
61 return do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, buffer, size, flags);
62}
63
64static size_t jffs2_security_listxattr(struct inode *inode, char *list, size_t list_size,
65 const char *name, size_t name_len)
66{
67 size_t retlen = XATTR_SECURITY_PREFIX_LEN + name_len + 1;
68
69 if (list && retlen <= list_size) {
70 strcpy(list, XATTR_SECURITY_PREFIX);
71 strcpy(list + XATTR_SECURITY_PREFIX_LEN, name);
72 }
73
74 return retlen;
75}
76
77struct xattr_handler jffs2_security_xattr_handler = {
78 .prefix = XATTR_SECURITY_PREFIX,
79 .list = jffs2_security_listxattr,
80 .set = jffs2_security_setxattr,
81 .get = jffs2_security_getxattr
82};
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
index 48293c197f13..1451732e1fa7 100644
--- a/fs/jffs2/summary.c
+++ b/fs/jffs2/summary.c
@@ -5,6 +5,7 @@
5 * Zoltan Sogor <weth@inf.u-szeged.hu>, 5 * Zoltan Sogor <weth@inf.u-szeged.hu>,
6 * Patrik Kluba <pajko@halom.u-szeged.hu>, 6 * Patrik Kluba <pajko@halom.u-szeged.hu>,
7 * University of Szeged, Hungary 7 * University of Szeged, Hungary
8 * 2005 KaiGai Kohei <kaigai@ak.jp.nec.com>
8 * 9 *
9 * For licensing information, see the file 'LICENCE' in this directory. 10 * For licensing information, see the file 'LICENCE' in this directory.
10 * 11 *
@@ -81,6 +82,19 @@ static int jffs2_sum_add_mem(struct jffs2_summary *s, union jffs2_sum_mem *item)
81 dbg_summary("dirent (%u) added to summary\n", 82 dbg_summary("dirent (%u) added to summary\n",
82 je32_to_cpu(item->d.ino)); 83 je32_to_cpu(item->d.ino));
83 break; 84 break;
85#ifdef CONFIG_JFFS2_FS_XATTR
86 case JFFS2_NODETYPE_XATTR:
87 s->sum_size += JFFS2_SUMMARY_XATTR_SIZE;
88 s->sum_num++;
89 dbg_summary("xattr (xid=%u, version=%u) added to summary\n",
90 je32_to_cpu(item->x.xid), je32_to_cpu(item->x.version));
91 break;
92 case JFFS2_NODETYPE_XREF:
93 s->sum_size += JFFS2_SUMMARY_XREF_SIZE;
94 s->sum_num++;
95 dbg_summary("xref added to summary\n");
96 break;
97#endif
84 default: 98 default:
85 JFFS2_WARNING("UNKNOWN node type %u\n", 99 JFFS2_WARNING("UNKNOWN node type %u\n",
86 je16_to_cpu(item->u.nodetype)); 100 je16_to_cpu(item->u.nodetype));
@@ -141,6 +155,40 @@ int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *r
141 return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp); 155 return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
142} 156}
143 157
158#ifdef CONFIG_JFFS2_FS_XATTR
159int jffs2_sum_add_xattr_mem(struct jffs2_summary *s, struct jffs2_raw_xattr *rx, uint32_t ofs)
160{
161 struct jffs2_sum_xattr_mem *temp;
162
163 temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL);
164 if (!temp)
165 return -ENOMEM;
166
167 temp->nodetype = rx->nodetype;
168 temp->xid = rx->xid;
169 temp->version = rx->version;
170 temp->offset = cpu_to_je32(ofs);
171 temp->totlen = rx->totlen;
172 temp->next = NULL;
173
174 return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
175}
176
177int jffs2_sum_add_xref_mem(struct jffs2_summary *s, struct jffs2_raw_xref *rr, uint32_t ofs)
178{
179 struct jffs2_sum_xref_mem *temp;
180
181 temp = kmalloc(sizeof(struct jffs2_sum_xref_mem), GFP_KERNEL);
182 if (!temp)
183 return -ENOMEM;
184
185 temp->nodetype = rr->nodetype;
186 temp->offset = cpu_to_je32(ofs);
187 temp->next = NULL;
188
189 return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
190}
191#endif
144/* Cleanup every collected summary information */ 192/* Cleanup every collected summary information */
145 193
146static void jffs2_sum_clean_collected(struct jffs2_summary *s) 194static void jffs2_sum_clean_collected(struct jffs2_summary *s)
@@ -259,7 +307,40 @@ int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs,
259 307
260 return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp); 308 return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
261 } 309 }
310#ifdef CONFIG_JFFS2_FS_XATTR
311 case JFFS2_NODETYPE_XATTR: {
312 struct jffs2_sum_xattr_mem *temp;
313 if (je32_to_cpu(node->x.version) == 0xffffffff)
314 return 0;
315 temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL);
316 if (!temp)
317 goto no_mem;
318
319 temp->nodetype = node->x.nodetype;
320 temp->xid = node->x.xid;
321 temp->version = node->x.version;
322 temp->totlen = node->x.totlen;
323 temp->offset = cpu_to_je32(ofs);
324 temp->next = NULL;
262 325
326 return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
327 }
328 case JFFS2_NODETYPE_XREF: {
329 struct jffs2_sum_xref_mem *temp;
330
331 if (je32_to_cpu(node->r.ino) == 0xffffffff
332 && je32_to_cpu(node->r.xid) == 0xffffffff)
333 return 0;
334 temp = kmalloc(sizeof(struct jffs2_sum_xref_mem), GFP_KERNEL);
335 if (!temp)
336 goto no_mem;
337 temp->nodetype = node->r.nodetype;
338 temp->offset = cpu_to_je32(ofs);
339 temp->next = NULL;
340
341 return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
342 }
343#endif
263 case JFFS2_NODETYPE_PADDING: 344 case JFFS2_NODETYPE_PADDING:
264 dbg_summary("node PADDING\n"); 345 dbg_summary("node PADDING\n");
265 c->summary->sum_padded += je32_to_cpu(node->u.totlen); 346 c->summary->sum_padded += je32_to_cpu(node->u.totlen);
@@ -288,6 +369,23 @@ no_mem:
288 return -ENOMEM; 369 return -ENOMEM;
289} 370}
290 371
372static struct jffs2_raw_node_ref *alloc_ref_at(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
373 uint32_t offset)
374{
375 struct jffs2_raw_node_ref *ref;
376 /* If there was a gap, mark it dirty */
377 if (offset > c->sector_size - jeb->free_size) {
378 int ret = jffs2_scan_dirty_space(c, jeb, offset - (c->sector_size - jeb->free_size));
379 if (ret)
380 return NULL;
381 }
382 ref = jffs2_alloc_raw_node_ref();
383 if (!ref)
384 return NULL;
385
386 ref->flash_offset = jeb->offset + offset;
387 return ref;
388}
291 389
292/* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */ 390/* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */
293 391
@@ -299,6 +397,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
299 struct jffs2_full_dirent *fd; 397 struct jffs2_full_dirent *fd;
300 void *sp; 398 void *sp;
301 int i, ino; 399 int i, ino;
400 int err;
302 401
303 sp = summary->sum; 402 sp = summary->sum;
304 403
@@ -312,13 +411,13 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
312 411
313 ino = je32_to_cpu(spi->inode); 412 ino = je32_to_cpu(spi->inode);
314 413
315 dbg_summary("Inode at 0x%08x\n", 414 dbg_summary("Inode at 0x%08x-0x%08x\n",
316 jeb->offset + je32_to_cpu(spi->offset)); 415 jeb->offset + je32_to_cpu(spi->offset),
416 jeb->offset + je32_to_cpu(spi->offset) + je32_to_cpu(spu->totlen));
317 417
318 raw = jffs2_alloc_raw_node_ref(); 418 raw = alloc_ref_at(c, jeb, je32_to_cpu(spi->offset));
319 if (!raw) { 419 if (!raw) {
320 JFFS2_NOTICE("allocation of node reference failed\n"); 420 JFFS2_NOTICE("allocation of node reference failed\n");
321 kfree(summary);
322 return -ENOMEM; 421 return -ENOMEM;
323 } 422 }
324 423
@@ -326,24 +425,17 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
326 if (!ic) { 425 if (!ic) {
327 JFFS2_NOTICE("scan_make_ino_cache failed\n"); 426 JFFS2_NOTICE("scan_make_ino_cache failed\n");
328 jffs2_free_raw_node_ref(raw); 427 jffs2_free_raw_node_ref(raw);
329 kfree(summary);
330 return -ENOMEM; 428 return -ENOMEM;
331 } 429 }
332 430
333 raw->flash_offset = (jeb->offset + je32_to_cpu(spi->offset)) | REF_UNCHECKED; 431 raw->flash_offset |= REF_UNCHECKED;
334 raw->__totlen = PAD(je32_to_cpu(spi->totlen));
335 raw->next_phys = NULL;
336 raw->next_in_ino = ic->nodes;
337 432
433 raw->next_in_ino = ic->nodes;
338 ic->nodes = raw; 434 ic->nodes = raw;
339 if (!jeb->first_node)
340 jeb->first_node = raw;
341 if (jeb->last_node)
342 jeb->last_node->next_phys = raw;
343 jeb->last_node = raw;
344 *pseudo_random += je32_to_cpu(spi->version);
345 435
346 UNCHECKED_SPACE(PAD(je32_to_cpu(spi->totlen))); 436 jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spi->totlen)));
437
438 *pseudo_random += je32_to_cpu(spi->version);
347 439
348 sp += JFFS2_SUMMARY_INODE_SIZE; 440 sp += JFFS2_SUMMARY_INODE_SIZE;
349 441
@@ -355,22 +447,21 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
355 spd = sp; 447 spd = sp;
356 448
357 dbg_summary("Dirent at 0x%08x\n", 449 dbg_summary("Dirent at 0x%08x\n",
358 jeb->offset + je32_to_cpu(spd->offset)); 450 jeb->offset + je32_to_cpu(spd->offset),
451 jeb->offset + je32_to_cpu(spd->offset) + je32_to_cpu(spd->totlen));
452
359 453
360 fd = jffs2_alloc_full_dirent(spd->nsize+1); 454 fd = jffs2_alloc_full_dirent(spd->nsize+1);
361 if (!fd) { 455 if (!fd)
362 kfree(summary);
363 return -ENOMEM; 456 return -ENOMEM;
364 }
365 457
366 memcpy(&fd->name, spd->name, spd->nsize); 458 memcpy(&fd->name, spd->name, spd->nsize);
367 fd->name[spd->nsize] = 0; 459 fd->name[spd->nsize] = 0;
368 460
369 raw = jffs2_alloc_raw_node_ref(); 461 raw = alloc_ref_at(c, jeb, je32_to_cpu(spd->offset));
370 if (!raw) { 462 if (!raw) {
371 jffs2_free_full_dirent(fd); 463 jffs2_free_full_dirent(fd);
372 JFFS2_NOTICE("allocation of node reference failed\n"); 464 JFFS2_NOTICE("allocation of node reference failed\n");
373 kfree(summary);
374 return -ENOMEM; 465 return -ENOMEM;
375 } 466 }
376 467
@@ -378,20 +469,14 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
378 if (!ic) { 469 if (!ic) {
379 jffs2_free_full_dirent(fd); 470 jffs2_free_full_dirent(fd);
380 jffs2_free_raw_node_ref(raw); 471 jffs2_free_raw_node_ref(raw);
381 kfree(summary);
382 return -ENOMEM; 472 return -ENOMEM;
383 } 473 }
384 474
385 raw->__totlen = PAD(je32_to_cpu(spd->totlen)); 475 raw->flash_offset |= REF_PRISTINE;
386 raw->flash_offset = (jeb->offset + je32_to_cpu(spd->offset)) | REF_PRISTINE;
387 raw->next_phys = NULL;
388 raw->next_in_ino = ic->nodes; 476 raw->next_in_ino = ic->nodes;
389 ic->nodes = raw; 477 ic->nodes = raw;
390 if (!jeb->first_node) 478
391 jeb->first_node = raw; 479 jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spd->totlen)));
392 if (jeb->last_node)
393 jeb->last_node->next_phys = raw;
394 jeb->last_node = raw;
395 480
396 fd->raw = raw; 481 fd->raw = raw;
397 fd->next = NULL; 482 fd->next = NULL;
@@ -399,7 +484,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
399 fd->ino = je32_to_cpu(spd->ino); 484 fd->ino = je32_to_cpu(spd->ino);
400 fd->nhash = full_name_hash(fd->name, spd->nsize); 485 fd->nhash = full_name_hash(fd->name, spd->nsize);
401 fd->type = spd->type; 486 fd->type = spd->type;
402 USED_SPACE(PAD(je32_to_cpu(spd->totlen))); 487
403 jffs2_add_fd_to_list(c, fd, &ic->scan_dents); 488 jffs2_add_fd_to_list(c, fd, &ic->scan_dents);
404 489
405 *pseudo_random += je32_to_cpu(spd->version); 490 *pseudo_random += je32_to_cpu(spd->version);
@@ -408,48 +493,122 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
408 493
409 break; 494 break;
410 } 495 }
496#ifdef CONFIG_JFFS2_FS_XATTR
497 case JFFS2_NODETYPE_XATTR: {
498 struct jffs2_xattr_datum *xd;
499 struct jffs2_sum_xattr_flash *spx;
500
501 spx = (struct jffs2_sum_xattr_flash *)sp;
502 dbg_summary("xattr at %#08x-%#08x (xid=%u, version=%u)\n",
503 jeb->offset + je32_to_cpu(spx->offset),
504 jeb->offset + je32_to_cpu(spx->offset) + je32_to_cpu(spx->totlen),
505 je32_to_cpu(spx->xid), je32_to_cpu(spx->version));
506 raw = alloc_ref_at(c, jeb, je32_to_cpu(spx->offset));
507 if (!raw) {
508 JFFS2_NOTICE("allocation of node reference failed\n");
509 return -ENOMEM;
510 }
511 xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid),
512 je32_to_cpu(spx->version));
513 if (IS_ERR(xd)) {
514 jffs2_free_raw_node_ref(raw);
515 if (PTR_ERR(xd) == -EEXIST) {
516 /* a newer version of xd exists */
517 if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(spx->totlen))))
518 return err;
519 sp += JFFS2_SUMMARY_XATTR_SIZE;
520 break;
521 }
522 JFFS2_NOTICE("allocation of xattr_datum failed\n");
523 return PTR_ERR(xd);
524 }
525 xd->node = raw;
526
527 raw->flash_offset |= REF_UNCHECKED;
528 raw->next_in_ino = (void *)xd;
529
530 jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spx->totlen)));
531
532 *pseudo_random += je32_to_cpu(spx->xid);
533 sp += JFFS2_SUMMARY_XATTR_SIZE;
534
535 break;
536 }
537 case JFFS2_NODETYPE_XREF: {
538 struct jffs2_xattr_ref *ref;
539 struct jffs2_sum_xref_flash *spr;
540
541 spr = (struct jffs2_sum_xref_flash *)sp;
542 dbg_summary("xref at %#08x-%#08x\n",
543 jeb->offset + je32_to_cpu(spr->offset),
544 jeb->offset + je32_to_cpu(spr->offset) + PAD(sizeof(struct jffs2_raw_xref)));
545
546 raw = alloc_ref_at(c, jeb, je32_to_cpu(spr->offset));
547 if (!raw) {
548 JFFS2_NOTICE("allocation of node reference failed\n");
549 return -ENOMEM;
550 }
551 ref = jffs2_alloc_xattr_ref();
552 if (!ref) {
553 JFFS2_NOTICE("allocation of xattr_datum failed\n");
554 jffs2_free_raw_node_ref(raw);
555 return -ENOMEM;
556 }
557 ref->ino = 0xfffffffe;
558 ref->xid = 0xfffffffd;
559 ref->node = raw;
560 ref->next = c->xref_temp;
561 c->xref_temp = ref;
562
563 raw->flash_offset |= REF_UNCHECKED;
564 raw->next_in_ino = (void *)ref;
411 565
566 jffs2_link_node_ref(c, jeb, raw, PAD(sizeof(struct jffs2_raw_xref)));
567
568 *pseudo_random += raw->flash_offset;
569 sp += JFFS2_SUMMARY_XREF_SIZE;
570
571 break;
572 }
573#endif
412 default : { 574 default : {
413 JFFS2_WARNING("Unsupported node type found in summary! Exiting..."); 575 uint16_t nodetype = je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype);
414 kfree(summary); 576 JFFS2_WARNING("Unsupported node type %x found in summary! Exiting...\n", nodetype);
415 return -EIO; 577 if ((nodetype & JFFS2_COMPAT_MASK) == JFFS2_FEATURE_INCOMPAT)
578 return -EIO;
579
580 /* For compatible node types, just fall back to the full scan */
581 c->wasted_size -= jeb->wasted_size;
582 c->free_size += c->sector_size - jeb->free_size;
583 c->used_size -= jeb->used_size;
584 c->dirty_size -= jeb->dirty_size;
585 jeb->wasted_size = jeb->used_size = jeb->dirty_size = 0;
586 jeb->free_size = c->sector_size;
587
588 jffs2_free_all_node_refs(c, jeb);
589 return -ENOTRECOVERABLE;
416 } 590 }
417 } 591 }
418 } 592 }
419 593
420 kfree(summary);
421 return 0; 594 return 0;
422} 595}
423 596
424/* Process the summary node - called from jffs2_scan_eraseblock() */ 597/* Process the summary node - called from jffs2_scan_eraseblock() */
425
426int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 598int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
427 uint32_t ofs, uint32_t *pseudo_random) 599 struct jffs2_raw_summary *summary, uint32_t sumsize,
600 uint32_t *pseudo_random)
428{ 601{
429 struct jffs2_unknown_node crcnode; 602 struct jffs2_unknown_node crcnode;
430 struct jffs2_raw_node_ref *cache_ref; 603 struct jffs2_raw_node_ref *cache_ref;
431 struct jffs2_raw_summary *summary; 604 int ret, ofs;
432 int ret, sumsize;
433 uint32_t crc; 605 uint32_t crc;
606 int err;
434 607
435 sumsize = c->sector_size - ofs; 608 ofs = c->sector_size - sumsize;
436 ofs += jeb->offset;
437 609
438 dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n", 610 dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n",
439 jeb->offset, ofs, sumsize); 611 jeb->offset, jeb->offset + ofs, sumsize);
440
441 summary = kmalloc(sumsize, GFP_KERNEL);
442
443 if (!summary) {
444 return -ENOMEM;
445 }
446
447 ret = jffs2_fill_scan_buf(c, (unsigned char *)summary, ofs, sumsize);
448
449 if (ret) {
450 kfree(summary);
451 return ret;
452 }
453 612
454 /* OK, now check for node validity and CRC */ 613 /* OK, now check for node validity and CRC */
455 crcnode.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 614 crcnode.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -489,40 +648,38 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
489 if (je32_to_cpu(summary->cln_mkr) != c->cleanmarker_size) { 648 if (je32_to_cpu(summary->cln_mkr) != c->cleanmarker_size) {
490 dbg_summary("CLEANMARKER node has totlen 0x%x != normal 0x%x\n", 649 dbg_summary("CLEANMARKER node has totlen 0x%x != normal 0x%x\n",
491 je32_to_cpu(summary->cln_mkr), c->cleanmarker_size); 650 je32_to_cpu(summary->cln_mkr), c->cleanmarker_size);
492 UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr))); 651 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr)))))
652 return err;
493 } else if (jeb->first_node) { 653 } else if (jeb->first_node) {
494 dbg_summary("CLEANMARKER node not first node in block " 654 dbg_summary("CLEANMARKER node not first node in block "
495 "(0x%08x)\n", jeb->offset); 655 "(0x%08x)\n", jeb->offset);
496 UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr))); 656 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr)))))
657 return err;
497 } else { 658 } else {
498 struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref(); 659 struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref();
499 660
500 if (!marker_ref) { 661 if (!marker_ref) {
501 JFFS2_NOTICE("Failed to allocate node ref for clean marker\n"); 662 JFFS2_NOTICE("Failed to allocate node ref for clean marker\n");
502 kfree(summary);
503 return -ENOMEM; 663 return -ENOMEM;
504 } 664 }
505 665
506 marker_ref->next_in_ino = NULL;
507 marker_ref->next_phys = NULL;
508 marker_ref->flash_offset = jeb->offset | REF_NORMAL; 666 marker_ref->flash_offset = jeb->offset | REF_NORMAL;
509 marker_ref->__totlen = je32_to_cpu(summary->cln_mkr); 667 marker_ref->next_in_ino = NULL;
510 jeb->first_node = jeb->last_node = marker_ref;
511 668
512 USED_SPACE( PAD(je32_to_cpu(summary->cln_mkr)) ); 669 jffs2_link_node_ref(c, jeb, marker_ref, je32_to_cpu(summary->cln_mkr));
513 } 670 }
514 } 671 }
515 672
516 if (je32_to_cpu(summary->padded)) {
517 DIRTY_SPACE(je32_to_cpu(summary->padded));
518 }
519
520 ret = jffs2_sum_process_sum_data(c, jeb, summary, pseudo_random); 673 ret = jffs2_sum_process_sum_data(c, jeb, summary, pseudo_random);
674 /* -ENOTRECOVERABLE isn't a fatal error -- it means we should do a full
675 scan of this eraseblock. So return zero */
676 if (ret == -ENOTRECOVERABLE)
677 return 0;
521 if (ret) 678 if (ret)
522 return ret; 679 return ret; /* real error */
523 680
524 /* for PARANOIA_CHECK */ 681 /* for PARANOIA_CHECK */
525 cache_ref = jffs2_alloc_raw_node_ref(); 682 cache_ref = alloc_ref_at(c, jeb, ofs);
526 683
527 if (!cache_ref) { 684 if (!cache_ref) {
528 JFFS2_NOTICE("Failed to allocate node ref for cache\n"); 685 JFFS2_NOTICE("Failed to allocate node ref for cache\n");
@@ -530,22 +687,18 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
530 } 687 }
531 688
532 cache_ref->next_in_ino = NULL; 689 cache_ref->next_in_ino = NULL;
533 cache_ref->next_phys = NULL; 690 cache_ref->flash_offset |= REF_NORMAL;
534 cache_ref->flash_offset = ofs | REF_NORMAL;
535 cache_ref->__totlen = sumsize;
536 691
537 if (!jeb->first_node) 692 jffs2_link_node_ref(c, jeb, cache_ref, sumsize);
538 jeb->first_node = cache_ref;
539 if (jeb->last_node)
540 jeb->last_node->next_phys = cache_ref;
541 jeb->last_node = cache_ref;
542 693
543 USED_SPACE(sumsize); 694 if (unlikely(jeb->free_size)) {
544 695 JFFS2_WARNING("Free size 0x%x bytes in eraseblock @0x%08x with summary?\n",
545 jeb->wasted_size += jeb->free_size; 696 jeb->free_size, jeb->offset);
546 c->wasted_size += jeb->free_size; 697 jeb->wasted_size += jeb->free_size;
547 c->free_size -= jeb->free_size; 698 c->wasted_size += jeb->free_size;
548 jeb->free_size = 0; 699 c->free_size -= jeb->free_size;
700 jeb->free_size = 0;
701 }
549 702
550 return jffs2_scan_classify_jeb(c, jeb); 703 return jffs2_scan_classify_jeb(c, jeb);
551 704
@@ -617,9 +770,40 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
617 770
618 break; 771 break;
619 } 772 }
773#ifdef CONFIG_JFFS2_FS_XATTR
774 case JFFS2_NODETYPE_XATTR: {
775 struct jffs2_sum_xattr_flash *sxattr_ptr = wpage;
776
777 temp = c->summary->sum_list_head;
778 sxattr_ptr->nodetype = temp->x.nodetype;
779 sxattr_ptr->xid = temp->x.xid;
780 sxattr_ptr->version = temp->x.version;
781 sxattr_ptr->offset = temp->x.offset;
782 sxattr_ptr->totlen = temp->x.totlen;
783
784 wpage += JFFS2_SUMMARY_XATTR_SIZE;
785 break;
786 }
787 case JFFS2_NODETYPE_XREF: {
788 struct jffs2_sum_xref_flash *sxref_ptr = wpage;
620 789
790 temp = c->summary->sum_list_head;
791 sxref_ptr->nodetype = temp->r.nodetype;
792 sxref_ptr->offset = temp->r.offset;
793
794 wpage += JFFS2_SUMMARY_XREF_SIZE;
795 break;
796 }
797#endif
621 default : { 798 default : {
622 BUG(); /* unknown node in summary information */ 799 if ((je16_to_cpu(temp->u.nodetype) & JFFS2_COMPAT_MASK)
800 == JFFS2_FEATURE_RWCOMPAT_COPY) {
801 dbg_summary("Writing unknown RWCOMPAT_COPY node type %x\n",
802 je16_to_cpu(temp->u.nodetype));
803 jffs2_sum_disable_collecting(c->summary);
804 } else {
805 BUG(); /* unknown node in summary information */
806 }
623 } 807 }
624 } 808 }
625 809
@@ -651,19 +835,32 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
651 spin_unlock(&c->erase_completion_lock); 835 spin_unlock(&c->erase_completion_lock);
652 ret = jffs2_flash_writev(c, vecs, 2, jeb->offset + c->sector_size - 836 ret = jffs2_flash_writev(c, vecs, 2, jeb->offset + c->sector_size -
653 jeb->free_size, &retlen, 0); 837 jeb->free_size, &retlen, 0);
654 spin_lock(&c->erase_completion_lock);
655
656 838
657 if (ret || (retlen != infosize)) { 839 if (ret || (retlen != infosize)) {
840 struct jffs2_raw_node_ref *ref;
841
658 JFFS2_WARNING("Write of %u bytes at 0x%08x failed. returned %d, retlen %zd\n", 842 JFFS2_WARNING("Write of %u bytes at 0x%08x failed. returned %d, retlen %zd\n",
659 infosize, jeb->offset + c->sector_size - jeb->free_size, ret, retlen); 843 infosize, jeb->offset + c->sector_size - jeb->free_size, ret, retlen);
660 844
845 /* Waste remaining space */
846 ref = jffs2_alloc_raw_node_ref();
847 if (ref) {
848 spin_lock(&c->erase_completion_lock);
849
850 ref->flash_offset = jeb->offset + c->sector_size - jeb->free_size;
851 ref->flash_offset |= REF_OBSOLETE;
852 ref->next_in_ino = 0;
853
854 jffs2_link_node_ref(c, jeb, ref, c->sector_size - jeb->free_size);
855 }
856
661 c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; 857 c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE;
662 WASTED_SPACE(infosize);
663 858
664 return 1; 859 return 1;
665 } 860 }
666 861
862 spin_lock(&c->erase_completion_lock);
863
667 return 0; 864 return 0;
668} 865}
669 866
@@ -706,7 +903,6 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c)
706 /* for ACCT_PARANOIA_CHECK */ 903 /* for ACCT_PARANOIA_CHECK */
707 spin_unlock(&c->erase_completion_lock); 904 spin_unlock(&c->erase_completion_lock);
708 summary_ref = jffs2_alloc_raw_node_ref(); 905 summary_ref = jffs2_alloc_raw_node_ref();
709 spin_lock(&c->erase_completion_lock);
710 906
711 if (!summary_ref) { 907 if (!summary_ref) {
712 JFFS2_NOTICE("Failed to allocate node ref for summary\n"); 908 JFFS2_NOTICE("Failed to allocate node ref for summary\n");
@@ -714,17 +910,10 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c)
714 } 910 }
715 911
716 summary_ref->next_in_ino = NULL; 912 summary_ref->next_in_ino = NULL;
717 summary_ref->next_phys = NULL;
718 summary_ref->flash_offset = (jeb->offset + c->sector_size - jeb->free_size) | REF_NORMAL; 913 summary_ref->flash_offset = (jeb->offset + c->sector_size - jeb->free_size) | REF_NORMAL;
719 summary_ref->__totlen = infosize;
720
721 if (!jeb->first_node)
722 jeb->first_node = summary_ref;
723 if (jeb->last_node)
724 jeb->last_node->next_phys = summary_ref;
725 jeb->last_node = summary_ref;
726 914
727 USED_SPACE(infosize); 915 spin_lock(&c->erase_completion_lock);
916 jffs2_link_node_ref(c, jeb, summary_ref, infosize);
728 917
729 return 0; 918 return 0;
730} 919}
diff --git a/fs/jffs2/summary.h b/fs/jffs2/summary.h
index b7a678be1709..e7eb0c5814f6 100644
--- a/fs/jffs2/summary.h
+++ b/fs/jffs2/summary.h
@@ -18,23 +18,6 @@
18#include <linux/uio.h> 18#include <linux/uio.h>
19#include <linux/jffs2.h> 19#include <linux/jffs2.h>
20 20
21#define DIRTY_SPACE(x) do { typeof(x) _x = (x); \
22 c->free_size -= _x; c->dirty_size += _x; \
23 jeb->free_size -= _x ; jeb->dirty_size += _x; \
24 }while(0)
25#define USED_SPACE(x) do { typeof(x) _x = (x); \
26 c->free_size -= _x; c->used_size += _x; \
27 jeb->free_size -= _x ; jeb->used_size += _x; \
28 }while(0)
29#define WASTED_SPACE(x) do { typeof(x) _x = (x); \
30 c->free_size -= _x; c->wasted_size += _x; \
31 jeb->free_size -= _x ; jeb->wasted_size += _x; \
32 }while(0)
33#define UNCHECKED_SPACE(x) do { typeof(x) _x = (x); \
34 c->free_size -= _x; c->unchecked_size += _x; \
35 jeb->free_size -= _x ; jeb->unchecked_size += _x; \
36 }while(0)
37
38#define BLK_STATE_ALLFF 0 21#define BLK_STATE_ALLFF 0
39#define BLK_STATE_CLEAN 1 22#define BLK_STATE_CLEAN 1
40#define BLK_STATE_PARTDIRTY 2 23#define BLK_STATE_PARTDIRTY 2
@@ -45,6 +28,8 @@
45#define JFFS2_SUMMARY_NOSUM_SIZE 0xffffffff 28#define JFFS2_SUMMARY_NOSUM_SIZE 0xffffffff
46#define JFFS2_SUMMARY_INODE_SIZE (sizeof(struct jffs2_sum_inode_flash)) 29#define JFFS2_SUMMARY_INODE_SIZE (sizeof(struct jffs2_sum_inode_flash))
47#define JFFS2_SUMMARY_DIRENT_SIZE(x) (sizeof(struct jffs2_sum_dirent_flash) + (x)) 30#define JFFS2_SUMMARY_DIRENT_SIZE(x) (sizeof(struct jffs2_sum_dirent_flash) + (x))
31#define JFFS2_SUMMARY_XATTR_SIZE (sizeof(struct jffs2_sum_xattr_flash))
32#define JFFS2_SUMMARY_XREF_SIZE (sizeof(struct jffs2_sum_xref_flash))
48 33
49/* Summary structures used on flash */ 34/* Summary structures used on flash */
50 35
@@ -75,11 +60,28 @@ struct jffs2_sum_dirent_flash
75 uint8_t name[0]; /* dirent name */ 60 uint8_t name[0]; /* dirent name */
76} __attribute__((packed)); 61} __attribute__((packed));
77 62
63struct jffs2_sum_xattr_flash
64{
65 jint16_t nodetype; /* == JFFS2_NODETYPE_XATR */
66 jint32_t xid; /* xattr identifier */
67 jint32_t version; /* version number */
68 jint32_t offset; /* offset on jeb */
69 jint32_t totlen; /* node length */
70} __attribute__((packed));
71
72struct jffs2_sum_xref_flash
73{
74 jint16_t nodetype; /* == JFFS2_NODETYPE_XREF */
75 jint32_t offset; /* offset on jeb */
76} __attribute__((packed));
77
78union jffs2_sum_flash 78union jffs2_sum_flash
79{ 79{
80 struct jffs2_sum_unknown_flash u; 80 struct jffs2_sum_unknown_flash u;
81 struct jffs2_sum_inode_flash i; 81 struct jffs2_sum_inode_flash i;
82 struct jffs2_sum_dirent_flash d; 82 struct jffs2_sum_dirent_flash d;
83 struct jffs2_sum_xattr_flash x;
84 struct jffs2_sum_xref_flash r;
83}; 85};
84 86
85/* Summary structures used in the memory */ 87/* Summary structures used in the memory */
@@ -114,11 +116,30 @@ struct jffs2_sum_dirent_mem
114 uint8_t name[0]; /* dirent name */ 116 uint8_t name[0]; /* dirent name */
115} __attribute__((packed)); 117} __attribute__((packed));
116 118
119struct jffs2_sum_xattr_mem
120{
121 union jffs2_sum_mem *next;
122 jint16_t nodetype;
123 jint32_t xid;
124 jint32_t version;
125 jint32_t offset;
126 jint32_t totlen;
127} __attribute__((packed));
128
129struct jffs2_sum_xref_mem
130{
131 union jffs2_sum_mem *next;
132 jint16_t nodetype;
133 jint32_t offset;
134} __attribute__((packed));
135
117union jffs2_sum_mem 136union jffs2_sum_mem
118{ 137{
119 struct jffs2_sum_unknown_mem u; 138 struct jffs2_sum_unknown_mem u;
120 struct jffs2_sum_inode_mem i; 139 struct jffs2_sum_inode_mem i;
121 struct jffs2_sum_dirent_mem d; 140 struct jffs2_sum_dirent_mem d;
141 struct jffs2_sum_xattr_mem x;
142 struct jffs2_sum_xref_mem r;
122}; 143};
123 144
124/* Summary related information stored in superblock */ 145/* Summary related information stored in superblock */
@@ -159,8 +180,11 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c);
159int jffs2_sum_add_padding_mem(struct jffs2_summary *s, uint32_t size); 180int jffs2_sum_add_padding_mem(struct jffs2_summary *s, uint32_t size);
160int jffs2_sum_add_inode_mem(struct jffs2_summary *s, struct jffs2_raw_inode *ri, uint32_t ofs); 181int jffs2_sum_add_inode_mem(struct jffs2_summary *s, struct jffs2_raw_inode *ri, uint32_t ofs);
161int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *rd, uint32_t ofs); 182int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *rd, uint32_t ofs);
183int jffs2_sum_add_xattr_mem(struct jffs2_summary *s, struct jffs2_raw_xattr *rx, uint32_t ofs);
184int jffs2_sum_add_xref_mem(struct jffs2_summary *s, struct jffs2_raw_xref *rr, uint32_t ofs);
162int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 185int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
163 uint32_t ofs, uint32_t *pseudo_random); 186 struct jffs2_raw_summary *summary, uint32_t sumlen,
187 uint32_t *pseudo_random);
164 188
165#else /* SUMMARY DISABLED */ 189#else /* SUMMARY DISABLED */
166 190
@@ -176,6 +200,8 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
176#define jffs2_sum_add_padding_mem(a,b) 200#define jffs2_sum_add_padding_mem(a,b)
177#define jffs2_sum_add_inode_mem(a,b,c) 201#define jffs2_sum_add_inode_mem(a,b,c)
178#define jffs2_sum_add_dirent_mem(a,b,c) 202#define jffs2_sum_add_dirent_mem(a,b,c)
203#define jffs2_sum_add_xattr_mem(a,b,c)
204#define jffs2_sum_add_xref_mem(a,b,c)
179#define jffs2_sum_scan_sumnode(a,b,c,d) (0) 205#define jffs2_sum_scan_sumnode(a,b,c,d) (0)
180 206
181#endif /* CONFIG_JFFS2_SUMMARY */ 207#endif /* CONFIG_JFFS2_SUMMARY */
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index 5f73de586928..9d0521451f59 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -151,7 +151,10 @@ static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type,
151 151
152 sb->s_op = &jffs2_super_operations; 152 sb->s_op = &jffs2_super_operations;
153 sb->s_flags = flags | MS_NOATIME; 153 sb->s_flags = flags | MS_NOATIME;
154 154 sb->s_xattr = jffs2_xattr_handlers;
155#ifdef CONFIG_JFFS2_FS_POSIX_ACL
156 sb->s_flags |= MS_POSIXACL;
157#endif
155 ret = jffs2_do_fill_super(sb, data, flags & MS_SILENT ? 1 : 0); 158 ret = jffs2_do_fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
156 159
157 if (ret) { 160 if (ret) {
@@ -293,6 +296,7 @@ static void jffs2_put_super (struct super_block *sb)
293 kfree(c->blocks); 296 kfree(c->blocks);
294 jffs2_flash_cleanup(c); 297 jffs2_flash_cleanup(c);
295 kfree(c->inocache_list); 298 kfree(c->inocache_list);
299 jffs2_clear_xattr_subsystem(c);
296 if (c->mtd->sync) 300 if (c->mtd->sync)
297 c->mtd->sync(c->mtd); 301 c->mtd->sync(c->mtd);
298 302
diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c
index d55754fe8925..fc211b6e9b03 100644
--- a/fs/jffs2/symlink.c
+++ b/fs/jffs2/symlink.c
@@ -24,7 +24,12 @@ struct inode_operations jffs2_symlink_inode_operations =
24{ 24{
25 .readlink = generic_readlink, 25 .readlink = generic_readlink,
26 .follow_link = jffs2_follow_link, 26 .follow_link = jffs2_follow_link,
27 .setattr = jffs2_setattr 27 .permission = jffs2_permission,
28 .setattr = jffs2_setattr,
29 .setxattr = jffs2_setxattr,
30 .getxattr = jffs2_getxattr,
31 .listxattr = jffs2_listxattr,
32 .removexattr = jffs2_removexattr
28}; 33};
29 34
30static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd) 35static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd)
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index 4cebf0e57c46..404b547c6cf4 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -312,11 +312,9 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
312 return; 312 return;
313 313
314 raw2->flash_offset = ofs | REF_OBSOLETE; 314 raw2->flash_offset = ofs | REF_OBSOLETE;
315 raw2->__totlen = ref_totlen(c, jeb, *first_raw);
316 raw2->next_phys = NULL;
317 raw2->next_in_ino = NULL; 315 raw2->next_in_ino = NULL;
318 316
319 jffs2_add_physical_node_ref(c, raw2); 317 jffs2_add_physical_node_ref(c, raw2, ref_totlen(c, jeb, *first_raw));
320 } 318 }
321 return; 319 return;
322 } 320 }
@@ -483,11 +481,11 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
483 return ret; 481 return ret;
484 } 482 }
485 483
486 spin_lock(&c->erase_completion_lock);
487
488 /* Adjust free size of the block if we padded. */ 484 /* Adjust free size of the block if we padded. */
489 if (pad) { 485 if (pad) {
490 struct jffs2_eraseblock *jeb; 486 struct jffs2_eraseblock *jeb;
487 struct jffs2_raw_node_ref *ref;
488 uint32_t waste = c->wbuf_pagesize - c->wbuf_len;
491 489
492 jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; 490 jeb = &c->blocks[c->wbuf_ofs / c->sector_size];
493 491
@@ -497,18 +495,29 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
497 /* wbuf_pagesize - wbuf_len is the amount of space that's to be 495 /* wbuf_pagesize - wbuf_len is the amount of space that's to be
498 padded. If there is less free space in the block than that, 496 padded. If there is less free space in the block than that,
499 something screwed up */ 497 something screwed up */
500 if (jeb->free_size < (c->wbuf_pagesize - c->wbuf_len)) { 498 if (jeb->free_size < waste) {
501 printk(KERN_CRIT "jffs2_flush_wbuf(): Accounting error. wbuf at 0x%08x has 0x%03x bytes, 0x%03x left.\n", 499 printk(KERN_CRIT "jffs2_flush_wbuf(): Accounting error. wbuf at 0x%08x has 0x%03x bytes, 0x%03x left.\n",
502 c->wbuf_ofs, c->wbuf_len, c->wbuf_pagesize-c->wbuf_len); 500 c->wbuf_ofs, c->wbuf_len, waste);
503 printk(KERN_CRIT "jffs2_flush_wbuf(): But free_size for block at 0x%08x is only 0x%08x\n", 501 printk(KERN_CRIT "jffs2_flush_wbuf(): But free_size for block at 0x%08x is only 0x%08x\n",
504 jeb->offset, jeb->free_size); 502 jeb->offset, jeb->free_size);
505 BUG(); 503 BUG();
506 } 504 }
507 jeb->free_size -= (c->wbuf_pagesize - c->wbuf_len); 505 ref = jffs2_alloc_raw_node_ref();
508 c->free_size -= (c->wbuf_pagesize - c->wbuf_len); 506 if (!ref)
509 jeb->wasted_size += (c->wbuf_pagesize - c->wbuf_len); 507 return -ENOMEM;
510 c->wasted_size += (c->wbuf_pagesize - c->wbuf_len); 508 ref->flash_offset = c->wbuf_ofs + c->wbuf_len;
511 } 509 ref->flash_offset |= REF_OBSOLETE;
510
511 spin_lock(&c->erase_completion_lock);
512
513 jffs2_link_node_ref(c, jeb, ref, waste);
514 /* FIXME: that made it count as dirty. Convert to wasted */
515 jeb->dirty_size -= waste;
516 c->dirty_size -= waste;
517 jeb->wasted_size += waste;
518 c->wasted_size += waste;
519 } else
520 spin_lock(&c->erase_completion_lock);
512 521
513 /* Stick any now-obsoleted blocks on the erase_pending_list */ 522 /* Stick any now-obsoleted blocks on the erase_pending_list */
514 jffs2_refile_wbuf_blocks(c); 523 jffs2_refile_wbuf_blocks(c);
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c
index 1342f0158e9b..4462541d11f8 100644
--- a/fs/jffs2/write.c
+++ b/fs/jffs2/write.c
@@ -37,7 +37,6 @@ int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint
37 f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; 37 f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
38 f->inocache->state = INO_STATE_PRESENT; 38 f->inocache->state = INO_STATE_PRESENT;
39 39
40
41 jffs2_add_ino_cache(c, f->inocache); 40 jffs2_add_ino_cache(c, f->inocache);
42 D1(printk(KERN_DEBUG "jffs2_do_new_inode(): Assigned ino# %d\n", f->inocache->ino)); 41 D1(printk(KERN_DEBUG "jffs2_do_new_inode(): Assigned ino# %d\n", f->inocache->ino));
43 ri->ino = cpu_to_je32(f->inocache->ino); 42 ri->ino = cpu_to_je32(f->inocache->ino);
@@ -104,8 +103,6 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
104 fn->raw = raw; 103 fn->raw = raw;
105 104
106 raw->flash_offset = flash_ofs; 105 raw->flash_offset = flash_ofs;
107 raw->__totlen = PAD(sizeof(*ri)+datalen);
108 raw->next_phys = NULL;
109 106
110 if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(ri->version) < f->highest_version)) { 107 if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(ri->version) < f->highest_version)) {
111 BUG_ON(!retried); 108 BUG_ON(!retried);
@@ -134,7 +131,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
134 any node we write before the original intended end of 131 any node we write before the original intended end of
135 this node */ 132 this node */
136 raw->flash_offset |= REF_OBSOLETE; 133 raw->flash_offset |= REF_OBSOLETE;
137 jffs2_add_physical_node_ref(c, raw); 134 jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*ri)+datalen));
138 jffs2_mark_node_obsolete(c, raw); 135 jffs2_mark_node_obsolete(c, raw);
139 } else { 136 } else {
140 printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); 137 printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset);
@@ -192,7 +189,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
192 } else { 189 } else {
193 raw->flash_offset |= REF_NORMAL; 190 raw->flash_offset |= REF_NORMAL;
194 } 191 }
195 jffs2_add_physical_node_ref(c, raw); 192 jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*ri)+datalen));
196 193
197 /* Link into per-inode list */ 194 /* Link into per-inode list */
198 spin_lock(&c->erase_completion_lock); 195 spin_lock(&c->erase_completion_lock);
@@ -260,8 +257,6 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
260 fd->raw = raw; 257 fd->raw = raw;
261 258
262 raw->flash_offset = flash_ofs; 259 raw->flash_offset = flash_ofs;
263 raw->__totlen = PAD(sizeof(*rd)+namelen);
264 raw->next_phys = NULL;
265 260
266 if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(rd->version) < f->highest_version)) { 261 if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(rd->version) < f->highest_version)) {
267 BUG_ON(!retried); 262 BUG_ON(!retried);
@@ -282,7 +277,7 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
282 if (retlen) { 277 if (retlen) {
283 raw->next_in_ino = NULL; 278 raw->next_in_ino = NULL;
284 raw->flash_offset |= REF_OBSOLETE; 279 raw->flash_offset |= REF_OBSOLETE;
285 jffs2_add_physical_node_ref(c, raw); 280 jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*rd)+namelen));
286 jffs2_mark_node_obsolete(c, raw); 281 jffs2_mark_node_obsolete(c, raw);
287 } else { 282 } else {
288 printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); 283 printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset);
@@ -328,7 +323,7 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
328 } 323 }
329 /* Mark the space used */ 324 /* Mark the space used */
330 raw->flash_offset |= REF_PRISTINE; 325 raw->flash_offset |= REF_PRISTINE;
331 jffs2_add_physical_node_ref(c, raw); 326 jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*rd)+namelen));
332 327
333 spin_lock(&c->erase_completion_lock); 328 spin_lock(&c->erase_completion_lock);
334 raw->next_in_ino = f->inocache->nodes; 329 raw->next_in_ino = f->inocache->nodes;
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
new file mode 100644
index 000000000000..e16f8460ff04
--- /dev/null
+++ b/fs/jffs2/xattr.c
@@ -0,0 +1,1258 @@
1/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright (C) 2006 NEC Corporation
5 *
6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
7 *
8 * For licensing information, see the file 'LICENCE' in this 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->next_in_ino = (void *)xd;
326
327 /* Setup raw-xattr */
328 rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
329 rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR);
330 rx.totlen = cpu_to_je32(PAD(totlen));
331 rx.hdr_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_unknown_node) - 4));
332
333 rx.xid = cpu_to_je32(xd->xid);
334 rx.version = cpu_to_je32(++xd->version);
335 rx.xprefix = xd->xprefix;
336 rx.name_len = xd->name_len;
337 rx.value_len = cpu_to_je16(xd->value_len);
338 rx.data_crc = cpu_to_je32(crc32(0, vecs[1].iov_base, vecs[1].iov_len));
339 rx.node_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_raw_xattr) - 4));
340
341 rc = jffs2_flash_writev(c, vecs, 2, phys_ofs, &length, 0);
342 if (rc || totlen != length) {
343 JFFS2_WARNING("jffs2_flash_writev()=%d, req=%u, wrote=%u, at %#08x\n",
344 rc, totlen, length, phys_ofs);
345 rc = rc ? rc : -EIO;
346 if (length) {
347 raw->flash_offset |= REF_OBSOLETE;
348 raw->next_in_ino = NULL;
349 jffs2_add_physical_node_ref(c, raw, PAD(totlen));
350 jffs2_mark_node_obsolete(c, raw);
351 } else {
352 jffs2_free_raw_node_ref(raw);
353 }
354 return rc;
355 }
356
357 /* success */
358 raw->flash_offset |= REF_PRISTINE;
359 jffs2_add_physical_node_ref(c, raw, PAD(totlen));
360 if (xd->node)
361 delete_xattr_datum_node(c, xd);
362 xd->node = raw;
363
364 dbg_xattr("success on saving xdatum (xid=%u, version=%u, xprefix=%u, xname='%s')\n",
365 xd->xid, xd->version, xd->xprefix, xd->xname);
366
367 return 0;
368}
369
370static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c,
371 int xprefix, const char *xname,
372 const char *xvalue, int xsize,
373 uint32_t phys_ofs)
374{
375 /* must be called under down_write(xattr_sem) */
376 struct jffs2_xattr_datum *xd;
377 uint32_t hashkey, name_len;
378 char *data;
379 int i, rc;
380
381 /* Search xattr_datum has same xname/xvalue by index */
382 hashkey = xattr_datum_hashkey(xprefix, xname, xvalue, xsize);
383 i = hashkey % XATTRINDEX_HASHSIZE;
384 list_for_each_entry(xd, &c->xattrindex[i], xindex) {
385 if (xd->hashkey==hashkey
386 && xd->xprefix==xprefix
387 && xd->value_len==xsize
388 && !strcmp(xd->xname, xname)
389 && !memcmp(xd->xvalue, xvalue, xsize)) {
390 xd->refcnt++;
391 return xd;
392 }
393 }
394
395 /* Not found, Create NEW XATTR-Cache */
396 name_len = strlen(xname);
397
398 xd = jffs2_alloc_xattr_datum();
399 if (!xd)
400 return ERR_PTR(-ENOMEM);
401
402 data = kmalloc(name_len + 1 + xsize, GFP_KERNEL);
403 if (!data) {
404 jffs2_free_xattr_datum(xd);
405 return ERR_PTR(-ENOMEM);
406 }
407 strcpy(data, xname);
408 memcpy(data + name_len + 1, xvalue, xsize);
409
410 xd->refcnt = 1;
411 xd->xid = ++c->highest_xid;
412 xd->flags |= JFFS2_XFLAGS_HOT;
413 xd->xprefix = xprefix;
414
415 xd->hashkey = hashkey;
416 xd->xname = data;
417 xd->xvalue = data + name_len + 1;
418 xd->name_len = name_len;
419 xd->value_len = xsize;
420 xd->data_crc = crc32(0, data, xd->name_len + 1 + xd->value_len);
421
422 rc = save_xattr_datum(c, xd, phys_ofs);
423 if (rc) {
424 kfree(xd->xname);
425 jffs2_free_xattr_datum(xd);
426 return ERR_PTR(rc);
427 }
428
429 /* Insert Hash Index */
430 i = hashkey % XATTRINDEX_HASHSIZE;
431 list_add(&xd->xindex, &c->xattrindex[i]);
432
433 c->xdatum_mem_usage += (xd->name_len + 1 + xd->value_len);
434 reclaim_xattr_datum(c);
435
436 return xd;
437}
438
439/* -------- xref related functions ------------------
440 * verify_xattr_ref(c, ref)
441 * is used to load xref information from medium. Because summary data does not
442 * contain xid/ino, it's necessary to verify once while mounting process.
443 * delete_xattr_ref_node(c, ref)
444 * is used to delete a jffs2 node is dominated by xref. When EBS is enabled,
445 * it overwrites the obsolete node by myself.
446 * delete_xattr_ref(c, ref)
447 * is used to delete jffs2_xattr_ref object. If the reference counter of xdatum
448 * is refered by this xref become 0, delete_xattr_datum() is called later.
449 * save_xattr_ref(c, ref, phys_ofs)
450 * is used to write xref to medium.
451 * create_xattr_ref(c, ic, xd, phys_ofs)
452 * is used to create a new xref and write to medium.
453 * jffs2_xattr_delete_inode(c, ic)
454 * is called to remove xrefs related to obsolete inode when inode is unlinked.
455 * jffs2_xattr_free_inode(c, ic)
456 * is called to release xattr related objects when unmounting.
457 * check_xattr_ref_inode(c, ic)
458 * is used to confirm inode does not have duplicate xattr name/value pair.
459 * -------------------------------------------------- */
460static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
461{
462 struct jffs2_eraseblock *jeb;
463 struct jffs2_raw_xref rr;
464 size_t readlen;
465 uint32_t crc, totlen;
466 int rc;
467
468 BUG_ON(ref_flags(ref->node) != REF_UNCHECKED);
469
470 rc = jffs2_flash_read(c, ref_offset(ref->node), sizeof(rr), &readlen, (char *)&rr);
471 if (rc || sizeof(rr) != readlen) {
472 JFFS2_WARNING("jffs2_flash_read()=%d, req=%u, read=%u, at %#08x\n",
473 rc, sizeof(rr), readlen, ref_offset(ref->node));
474 return rc ? rc : -EIO;
475 }
476 /* obsolete node */
477 crc = crc32(0, &rr, sizeof(rr) - 4);
478 if (crc != je32_to_cpu(rr.node_crc)) {
479 if (je32_to_cpu(rr.node_crc) != 0xffffffff)
480 JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
481 ref_offset(ref->node), je32_to_cpu(rr.node_crc), crc);
482 return EIO;
483 }
484 if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK
485 || je16_to_cpu(rr.nodetype) != JFFS2_NODETYPE_XREF
486 || je32_to_cpu(rr.totlen) != PAD(sizeof(rr))) {
487 JFFS2_ERROR("inconsistent xref at %#08x, magic=%#04x/%#04x, "
488 "nodetype=%#04x/%#04x, totlen=%u/%u\n",
489 ref_offset(ref->node), je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK,
490 je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF,
491 je32_to_cpu(rr.totlen), PAD(sizeof(rr)));
492 return EIO;
493 }
494 ref->ino = je32_to_cpu(rr.ino);
495 ref->xid = je32_to_cpu(rr.xid);
496
497 /* fixup superblock/eraseblock info */
498 jeb = &c->blocks[ref_offset(ref->node) / c->sector_size];
499 totlen = PAD(sizeof(rr));
500
501 spin_lock(&c->erase_completion_lock);
502 c->unchecked_size -= totlen; c->used_size += totlen;
503 jeb->unchecked_size -= totlen; jeb->used_size += totlen;
504 ref->node->flash_offset = ref_offset(ref->node) | REF_PRISTINE;
505 spin_unlock(&c->erase_completion_lock);
506
507 dbg_xattr("success on verifying xref (ino=%u, xid=%u) at %#08x\n",
508 ref->ino, ref->xid, ref_offset(ref->node));
509 return 0;
510}
511
512static void delete_xattr_ref_node(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
513{
514 struct jffs2_raw_xref rr;
515 uint32_t length;
516 int rc;
517
518 if (jffs2_sum_active()) {
519 memset(&rr, 0xff, sizeof(rr));
520 rc = jffs2_flash_read(c, ref_offset(ref->node),
521 sizeof(struct jffs2_unknown_node),
522 &length, (char *)&rr);
523 if (rc || length != sizeof(struct jffs2_unknown_node)) {
524 JFFS2_ERROR("jffs2_flash_read()=%d, req=%u, read=%u at %#08x\n",
525 rc, sizeof(struct jffs2_unknown_node),
526 length, ref_offset(ref->node));
527 }
528 rc = jffs2_flash_write(c, ref_offset(ref->node), sizeof(rr),
529 &length, (char *)&rr);
530 if (rc || length != sizeof(struct jffs2_raw_xref)) {
531 JFFS2_ERROR("jffs2_flash_write()=%d, req=%u, wrote=%u at %#08x\n",
532 rc, sizeof(rr), length, ref_offset(ref->node));
533 }
534 }
535 spin_lock(&c->erase_completion_lock);
536 ref->node->next_in_ino = NULL;
537 spin_unlock(&c->erase_completion_lock);
538 jffs2_mark_node_obsolete(c, ref->node);
539 ref->node = NULL;
540}
541
542static void delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
543{
544 /* must be called under down_write(xattr_sem) */
545 struct jffs2_xattr_datum *xd;
546
547 BUG_ON(!ref->node);
548 delete_xattr_ref_node(c, ref);
549
550 xd = ref->xd;
551 xd->refcnt--;
552 if (!xd->refcnt)
553 delete_xattr_datum(c, xd);
554 jffs2_free_xattr_ref(ref);
555}
556
557static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref, uint32_t phys_ofs)
558{
559 /* must be called under down_write(xattr_sem) */
560 struct jffs2_raw_node_ref *raw;
561 struct jffs2_raw_xref rr;
562 uint32_t length;
563 int ret;
564
565 raw = jffs2_alloc_raw_node_ref();
566 if (!raw)
567 return -ENOMEM;
568 raw->flash_offset = phys_ofs;
569 raw->next_in_ino = (void *)ref;
570
571 rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
572 rr.nodetype = cpu_to_je16(JFFS2_NODETYPE_XREF);
573 rr.totlen = cpu_to_je32(PAD(sizeof(rr)));
574 rr.hdr_crc = cpu_to_je32(crc32(0, &rr, sizeof(struct jffs2_unknown_node) - 4));
575
576 rr.ino = cpu_to_je32(ref->ic->ino);
577 rr.xid = cpu_to_je32(ref->xd->xid);
578 rr.node_crc = cpu_to_je32(crc32(0, &rr, sizeof(rr) - 4));
579
580 ret = jffs2_flash_write(c, phys_ofs, sizeof(rr), &length, (char *)&rr);
581 if (ret || sizeof(rr) != length) {
582 JFFS2_WARNING("jffs2_flash_write() returned %d, request=%u, retlen=%u, at %#08x\n",
583 ret, sizeof(rr), length, phys_ofs);
584 ret = ret ? ret : -EIO;
585 if (length) {
586 raw->flash_offset |= REF_OBSOLETE;
587 raw->next_in_ino = NULL;
588 jffs2_add_physical_node_ref(c, raw, PAD(sizeof(rr)));
589 jffs2_mark_node_obsolete(c, raw);
590 } else {
591 jffs2_free_raw_node_ref(raw);
592 }
593 return ret;
594 }
595 raw->flash_offset |= REF_PRISTINE;
596
597 jffs2_add_physical_node_ref(c, raw, PAD(sizeof(rr)));
598 if (ref->node)
599 delete_xattr_ref_node(c, ref);
600 ref->node = raw;
601
602 dbg_xattr("success on saving xref (ino=%u, xid=%u)\n", ref->ic->ino, ref->xd->xid);
603
604 return 0;
605}
606
607static struct jffs2_xattr_ref *create_xattr_ref(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic,
608 struct jffs2_xattr_datum *xd, uint32_t phys_ofs)
609{
610 /* must be called under down_write(xattr_sem) */
611 struct jffs2_xattr_ref *ref;
612 int ret;
613
614 ref = jffs2_alloc_xattr_ref();
615 if (!ref)
616 return ERR_PTR(-ENOMEM);
617 ref->ic = ic;
618 ref->xd = xd;
619
620 ret = save_xattr_ref(c, ref, phys_ofs);
621 if (ret) {
622 jffs2_free_xattr_ref(ref);
623 return ERR_PTR(ret);
624 }
625
626 /* Chain to inode */
627 ref->next = ic->xref;
628 ic->xref = ref;
629
630 return ref; /* success */
631}
632
633void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
634{
635 /* It's called from jffs2_clear_inode() on inode removing.
636 When an inode with XATTR is removed, those XATTRs must be removed. */
637 struct jffs2_xattr_ref *ref, *_ref;
638
639 if (!ic || ic->nlink > 0)
640 return;
641
642 down_write(&c->xattr_sem);
643 for (ref = ic->xref; ref; ref = _ref) {
644 _ref = ref->next;
645 delete_xattr_ref(c, ref);
646 }
647 ic->xref = NULL;
648 up_write(&c->xattr_sem);
649}
650
651void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
652{
653 /* It's called from jffs2_free_ino_caches() until unmounting FS. */
654 struct jffs2_xattr_datum *xd;
655 struct jffs2_xattr_ref *ref, *_ref;
656
657 down_write(&c->xattr_sem);
658 for (ref = ic->xref; ref; ref = _ref) {
659 _ref = ref->next;
660 xd = ref->xd;
661 xd->refcnt--;
662 if (!xd->refcnt) {
663 unload_xattr_datum(c, xd);
664 jffs2_free_xattr_datum(xd);
665 }
666 jffs2_free_xattr_ref(ref);
667 }
668 ic->xref = NULL;
669 up_write(&c->xattr_sem);
670}
671
672static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
673{
674 /* success of check_xattr_ref_inode() 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, **pref;
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 for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
687 if (!ref->xd->xname) {
688 rc = load_xattr_datum(c, ref->xd);
689 if (unlikely(rc > 0)) {
690 *pref = ref->next;
691 delete_xattr_ref(c, ref);
692 goto retry;
693 } else if (unlikely(rc < 0))
694 goto out;
695 }
696 for (cmp=ref->next, pref=&ref->next; cmp; pref=&cmp->next, cmp=cmp->next) {
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 *pref = cmp->next;
703 delete_xattr_ref(c, cmp);
704 goto retry;
705 } else if (unlikely(rc < 0))
706 goto out;
707 }
708 if (ref->xd->xprefix == cmp->xd->xprefix
709 && !strcmp(ref->xd->xname, cmp->xd->xname)) {
710 *pref = cmp->next;
711 delete_xattr_ref(c, cmp);
712 goto retry;
713 }
714 }
715 }
716 ic->flags |= INO_FLAGS_XATTR_CHECKED;
717 out:
718 up_write(&c->xattr_sem);
719
720 return rc;
721}
722
723/* -------- xattr subsystem functions ---------------
724 * jffs2_init_xattr_subsystem(c)
725 * is used to initialize semaphore and list_head, and some variables.
726 * jffs2_find_xattr_datum(c, xid)
727 * is used to lookup xdatum while scanning process.
728 * jffs2_clear_xattr_subsystem(c)
729 * is used to release any xattr related objects.
730 * jffs2_build_xattr_subsystem(c)
731 * is used to associate xdatum and xref while super block building process.
732 * jffs2_setup_xattr_datum(c, xid, version)
733 * is used to insert xdatum while scanning process.
734 * -------------------------------------------------- */
735void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c)
736{
737 int i;
738
739 for (i=0; i < XATTRINDEX_HASHSIZE; i++)
740 INIT_LIST_HEAD(&c->xattrindex[i]);
741 INIT_LIST_HEAD(&c->xattr_unchecked);
742 c->xref_temp = NULL;
743
744 init_rwsem(&c->xattr_sem);
745 c->xdatum_mem_usage = 0;
746 c->xdatum_mem_threshold = 32 * 1024; /* Default 32KB */
747}
748
749static struct jffs2_xattr_datum *jffs2_find_xattr_datum(struct jffs2_sb_info *c, uint32_t xid)
750{
751 struct jffs2_xattr_datum *xd;
752 int i = xid % XATTRINDEX_HASHSIZE;
753
754 /* It's only used in scanning/building process. */
755 BUG_ON(!(c->flags & (JFFS2_SB_FLAG_SCANNING|JFFS2_SB_FLAG_BUILDING)));
756
757 list_for_each_entry(xd, &c->xattrindex[i], xindex) {
758 if (xd->xid==xid)
759 return xd;
760 }
761 return NULL;
762}
763
764void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c)
765{
766 struct jffs2_xattr_datum *xd, *_xd;
767 struct jffs2_xattr_ref *ref, *_ref;
768 int i;
769
770 for (ref=c->xref_temp; ref; ref = _ref) {
771 _ref = ref->next;
772 jffs2_free_xattr_ref(ref);
773 }
774 c->xref_temp = NULL;
775
776 for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
777 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
778 list_del(&xd->xindex);
779 if (xd->xname)
780 kfree(xd->xname);
781 jffs2_free_xattr_datum(xd);
782 }
783 }
784}
785
786void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
787{
788 struct jffs2_xattr_ref *ref, *_ref;
789 struct jffs2_xattr_datum *xd, *_xd;
790 struct jffs2_inode_cache *ic;
791 int i, xdatum_count =0, xdatum_unchecked_count = 0, xref_count = 0;
792
793 BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING));
794
795 /* Phase.1 */
796 for (ref=c->xref_temp; ref; ref=_ref) {
797 _ref = ref->next;
798 /* checking REF_UNCHECKED nodes */
799 if (ref_flags(ref->node) != REF_PRISTINE) {
800 if (verify_xattr_ref(c, ref)) {
801 delete_xattr_ref_node(c, ref);
802 jffs2_free_xattr_ref(ref);
803 continue;
804 }
805 }
806 /* At this point, ref->xid and ref->ino contain XID and inode number.
807 ref->xd and ref->ic are not valid yet. */
808 xd = jffs2_find_xattr_datum(c, ref->xid);
809 ic = jffs2_get_ino_cache(c, ref->ino);
810 if (!xd || !ic) {
811 if (ref_flags(ref->node) != REF_UNCHECKED)
812 JFFS2_WARNING("xref(ino=%u, xid=%u) is orphan. \n",
813 ref->ino, ref->xid);
814 delete_xattr_ref_node(c, ref);
815 jffs2_free_xattr_ref(ref);
816 continue;
817 }
818 ref->xd = xd;
819 ref->ic = ic;
820 xd->refcnt++;
821 ref->next = ic->xref;
822 ic->xref = ref;
823 xref_count++;
824 }
825 c->xref_temp = NULL;
826 /* After this, ref->xid/ino are NEVER used. */
827
828 /* Phase.2 */
829 for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
830 list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
831 list_del_init(&xd->xindex);
832 if (!xd->refcnt) {
833 if (ref_flags(xd->node) != REF_UNCHECKED)
834 JFFS2_WARNING("orphan xdatum(xid=%u, version=%u) at %#08x\n",
835 xd->xid, xd->version, ref_offset(xd->node));
836 delete_xattr_datum(c, xd);
837 continue;
838 }
839 if (ref_flags(xd->node) != REF_PRISTINE) {
840 dbg_xattr("unchecked xdatum(xid=%u) at %#08x\n",
841 xd->xid, ref_offset(xd->node));
842 list_add(&xd->xindex, &c->xattr_unchecked);
843 xdatum_unchecked_count++;
844 }
845 xdatum_count++;
846 }
847 }
848 /* build complete */
849 JFFS2_NOTICE("complete building xattr subsystem, %u of xdatum (%u unchecked) and "
850 "%u of xref found.\n", xdatum_count, xdatum_unchecked_count, xref_count);
851}
852
853struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
854 uint32_t xid, uint32_t version)
855{
856 struct jffs2_xattr_datum *xd, *_xd;
857
858 _xd = jffs2_find_xattr_datum(c, xid);
859 if (_xd) {
860 dbg_xattr("duplicate xdatum (xid=%u, version=%u/%u) at %#08x\n",
861 xid, version, _xd->version, ref_offset(_xd->node));
862 if (version < _xd->version)
863 return ERR_PTR(-EEXIST);
864 }
865 xd = jffs2_alloc_xattr_datum();
866 if (!xd)
867 return ERR_PTR(-ENOMEM);
868 xd->xid = xid;
869 xd->version = version;
870 if (xd->xid > c->highest_xid)
871 c->highest_xid = xd->xid;
872 list_add_tail(&xd->xindex, &c->xattrindex[xid % XATTRINDEX_HASHSIZE]);
873
874 if (_xd) {
875 list_del_init(&_xd->xindex);
876 delete_xattr_datum_node(c, _xd);
877 jffs2_free_xattr_datum(_xd);
878 }
879 return xd;
880}
881
882/* -------- xattr subsystem functions ---------------
883 * xprefix_to_handler(xprefix)
884 * is used to translate xprefix into xattr_handler.
885 * jffs2_listxattr(dentry, buffer, size)
886 * is an implementation of listxattr handler on jffs2.
887 * do_jffs2_getxattr(inode, xprefix, xname, buffer, size)
888 * is an implementation of getxattr handler on jffs2.
889 * do_jffs2_setxattr(inode, xprefix, xname, buffer, size, flags)
890 * is an implementation of setxattr handler on jffs2.
891 * -------------------------------------------------- */
892struct xattr_handler *jffs2_xattr_handlers[] = {
893 &jffs2_user_xattr_handler,
894#ifdef CONFIG_JFFS2_FS_SECURITY
895 &jffs2_security_xattr_handler,
896#endif
897#ifdef CONFIG_JFFS2_FS_POSIX_ACL
898 &jffs2_acl_access_xattr_handler,
899 &jffs2_acl_default_xattr_handler,
900#endif
901 &jffs2_trusted_xattr_handler,
902 NULL
903};
904
905static struct xattr_handler *xprefix_to_handler(int xprefix) {
906 struct xattr_handler *ret;
907
908 switch (xprefix) {
909 case JFFS2_XPREFIX_USER:
910 ret = &jffs2_user_xattr_handler;
911 break;
912#ifdef CONFIG_JFFS2_FS_SECURITY
913 case JFFS2_XPREFIX_SECURITY:
914 ret = &jffs2_security_xattr_handler;
915 break;
916#endif
917#ifdef CONFIG_JFFS2_FS_POSIX_ACL
918 case JFFS2_XPREFIX_ACL_ACCESS:
919 ret = &jffs2_acl_access_xattr_handler;
920 break;
921 case JFFS2_XPREFIX_ACL_DEFAULT:
922 ret = &jffs2_acl_default_xattr_handler;
923 break;
924#endif
925 case JFFS2_XPREFIX_TRUSTED:
926 ret = &jffs2_trusted_xattr_handler;
927 break;
928 default:
929 ret = NULL;
930 break;
931 }
932 return ret;
933}
934
935ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
936{
937 struct inode *inode = dentry->d_inode;
938 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
939 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
940 struct jffs2_inode_cache *ic = f->inocache;
941 struct jffs2_xattr_ref *ref, **pref;
942 struct jffs2_xattr_datum *xd;
943 struct xattr_handler *xhandle;
944 ssize_t len, rc;
945 int retry = 0;
946
947 rc = check_xattr_ref_inode(c, ic);
948 if (unlikely(rc))
949 return rc;
950
951 down_read(&c->xattr_sem);
952 retry:
953 len = 0;
954 for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
955 BUG_ON(ref->ic != ic);
956 xd = ref->xd;
957 if (!xd->xname) {
958 /* xdatum is unchached */
959 if (!retry) {
960 retry = 1;
961 up_read(&c->xattr_sem);
962 down_write(&c->xattr_sem);
963 goto retry;
964 } else {
965 rc = load_xattr_datum(c, xd);
966 if (unlikely(rc > 0)) {
967 *pref = ref->next;
968 delete_xattr_ref(c, ref);
969 goto retry;
970 } else if (unlikely(rc < 0))
971 goto out;
972 }
973 }
974 xhandle = xprefix_to_handler(xd->xprefix);
975 if (!xhandle)
976 continue;
977 if (buffer) {
978 rc = xhandle->list(inode, buffer+len, size-len, xd->xname, xd->name_len);
979 } else {
980 rc = xhandle->list(inode, NULL, 0, xd->xname, xd->name_len);
981 }
982 if (rc < 0)
983 goto out;
984 len += rc;
985 }
986 rc = len;
987 out:
988 if (!retry) {
989 up_read(&c->xattr_sem);
990 } else {
991 up_write(&c->xattr_sem);
992 }
993 return rc;
994}
995
996int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname,
997 char *buffer, size_t size)
998{
999 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
1000 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
1001 struct jffs2_inode_cache *ic = f->inocache;
1002 struct jffs2_xattr_datum *xd;
1003 struct jffs2_xattr_ref *ref, **pref;
1004 int rc, retry = 0;
1005
1006 rc = check_xattr_ref_inode(c, ic);
1007 if (unlikely(rc))
1008 return rc;
1009
1010 down_read(&c->xattr_sem);
1011 retry:
1012 for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
1013 BUG_ON(ref->ic!=ic);
1014
1015 xd = ref->xd;
1016 if (xd->xprefix != xprefix)
1017 continue;
1018 if (!xd->xname) {
1019 /* xdatum is unchached */
1020 if (!retry) {
1021 retry = 1;
1022 up_read(&c->xattr_sem);
1023 down_write(&c->xattr_sem);
1024 goto retry;
1025 } else {
1026 rc = load_xattr_datum(c, xd);
1027 if (unlikely(rc > 0)) {
1028 *pref = ref->next;
1029 delete_xattr_ref(c, ref);
1030 goto retry;
1031 } else if (unlikely(rc < 0)) {
1032 goto out;
1033 }
1034 }
1035 }
1036 if (!strcmp(xname, xd->xname)) {
1037 rc = xd->value_len;
1038 if (buffer) {
1039 if (size < rc) {
1040 rc = -ERANGE;
1041 } else {
1042 memcpy(buffer, xd->xvalue, rc);
1043 }
1044 }
1045 goto out;
1046 }
1047 }
1048 rc = -ENODATA;
1049 out:
1050 if (!retry) {
1051 up_read(&c->xattr_sem);
1052 } else {
1053 up_write(&c->xattr_sem);
1054 }
1055 return rc;
1056}
1057
1058int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
1059 const char *buffer, size_t size, int flags)
1060{
1061 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
1062 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
1063 struct jffs2_inode_cache *ic = f->inocache;
1064 struct jffs2_xattr_datum *xd;
1065 struct jffs2_xattr_ref *ref, *newref, **pref;
1066 uint32_t phys_ofs, length, request;
1067 int rc;
1068
1069 rc = check_xattr_ref_inode(c, ic);
1070 if (unlikely(rc))
1071 return rc;
1072
1073 request = PAD(sizeof(struct jffs2_raw_xattr) + strlen(xname) + 1 + size);
1074 rc = jffs2_reserve_space(c, request, &phys_ofs, &length,
1075 ALLOC_NORMAL, JFFS2_SUMMARY_XATTR_SIZE);
1076 if (rc) {
1077 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request);
1078 return rc;
1079 }
1080
1081 /* Find existing xattr */
1082 down_write(&c->xattr_sem);
1083 retry:
1084 for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
1085 xd = ref->xd;
1086 if (xd->xprefix != xprefix)
1087 continue;
1088 if (!xd->xname) {
1089 rc = load_xattr_datum(c, xd);
1090 if (unlikely(rc > 0)) {
1091 *pref = ref->next;
1092 delete_xattr_ref(c, ref);
1093 goto retry;
1094 } else if (unlikely(rc < 0))
1095 goto out;
1096 }
1097 if (!strcmp(xd->xname, xname)) {
1098 if (flags & XATTR_CREATE) {
1099 rc = -EEXIST;
1100 goto out;
1101 }
1102 if (!buffer) {
1103 *pref = ref->next;
1104 delete_xattr_ref(c, ref);
1105 rc = 0;
1106 goto out;
1107 }
1108 goto found;
1109 }
1110 }
1111 /* not found */
1112 if (flags & XATTR_REPLACE) {
1113 rc = -ENODATA;
1114 goto out;
1115 }
1116 if (!buffer) {
1117 rc = -EINVAL;
1118 goto out;
1119 }
1120 found:
1121 xd = create_xattr_datum(c, xprefix, xname, buffer, size, phys_ofs);
1122 if (IS_ERR(xd)) {
1123 rc = PTR_ERR(xd);
1124 goto out;
1125 }
1126 up_write(&c->xattr_sem);
1127 jffs2_complete_reservation(c);
1128
1129 /* create xattr_ref */
1130 request = PAD(sizeof(struct jffs2_raw_xref));
1131 rc = jffs2_reserve_space(c, request, &phys_ofs, &length,
1132 ALLOC_NORMAL, JFFS2_SUMMARY_XREF_SIZE);
1133 if (rc) {
1134 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request);
1135 down_write(&c->xattr_sem);
1136 xd->refcnt--;
1137 if (!xd->refcnt)
1138 delete_xattr_datum(c, xd);
1139 up_write(&c->xattr_sem);
1140 return rc;
1141 }
1142 down_write(&c->xattr_sem);
1143 if (ref)
1144 *pref = ref->next;
1145 newref = create_xattr_ref(c, ic, xd, phys_ofs);
1146 if (IS_ERR(newref)) {
1147 if (ref) {
1148 ref->next = ic->xref;
1149 ic->xref = ref;
1150 }
1151 rc = PTR_ERR(newref);
1152 xd->refcnt--;
1153 if (!xd->refcnt)
1154 delete_xattr_datum(c, xd);
1155 } else if (ref) {
1156 delete_xattr_ref(c, ref);
1157 }
1158 out:
1159 up_write(&c->xattr_sem);
1160 jffs2_complete_reservation(c);
1161 return rc;
1162}
1163
1164/* -------- garbage collector functions -------------
1165 * jffs2_garbage_collect_xattr_datum(c, xd)
1166 * is used to move xdatum into new node.
1167 * jffs2_garbage_collect_xattr_ref(c, ref)
1168 * is used to move xref into new node.
1169 * jffs2_verify_xattr(c)
1170 * is used to call do_verify_xattr_datum() before garbage collecting.
1171 * -------------------------------------------------- */
1172int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
1173{
1174 uint32_t phys_ofs, totlen, length, old_ofs;
1175 int rc = -EINVAL;
1176
1177 down_write(&c->xattr_sem);
1178 BUG_ON(!xd->node);
1179
1180 old_ofs = ref_offset(xd->node);
1181 totlen = ref_totlen(c, c->gcblock, xd->node);
1182 if (totlen < sizeof(struct jffs2_raw_xattr))
1183 goto out;
1184
1185 if (!xd->xname) {
1186 rc = load_xattr_datum(c, xd);
1187 if (unlikely(rc > 0)) {
1188 delete_xattr_datum_node(c, xd);
1189 rc = 0;
1190 goto out;
1191 } else if (unlikely(rc < 0))
1192 goto out;
1193 }
1194 rc = jffs2_reserve_space_gc(c, totlen, &phys_ofs, &length, JFFS2_SUMMARY_XATTR_SIZE);
1195 if (rc || length < totlen) {
1196 JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, totlen);
1197 rc = rc ? rc : -EBADFD;
1198 goto out;
1199 }
1200 rc = save_xattr_datum(c, xd, phys_ofs);
1201 if (!rc)
1202 dbg_xattr("xdatum (xid=%u, version=%u) GC'ed from %#08x to %08x\n",
1203 xd->xid, xd->version, old_ofs, ref_offset(xd->node));
1204 out:
1205 up_write(&c->xattr_sem);
1206 return rc;
1207}
1208
1209
1210int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
1211{
1212 uint32_t phys_ofs, totlen, length, old_ofs;
1213 int rc = -EINVAL;
1214
1215 down_write(&c->xattr_sem);
1216 BUG_ON(!ref->node);
1217
1218 old_ofs = ref_offset(ref->node);
1219 totlen = ref_totlen(c, c->gcblock, ref->node);
1220 if (totlen != sizeof(struct jffs2_raw_xref))
1221 goto out;
1222
1223 rc = jffs2_reserve_space_gc(c, totlen, &phys_ofs, &length, JFFS2_SUMMARY_XREF_SIZE);
1224 if (rc || length < totlen) {
1225 JFFS2_WARNING("%s: jffs2_reserve_space() = %d, request = %u\n",
1226 __FUNCTION__, rc, totlen);
1227 rc = rc ? rc : -EBADFD;
1228 goto out;
1229 }
1230 rc = save_xattr_ref(c, ref, phys_ofs);
1231 if (!rc)
1232 dbg_xattr("xref (ino=%u, xid=%u) GC'ed from %#08x to %08x\n",
1233 ref->ic->ino, ref->xd->xid, old_ofs, ref_offset(ref->node));
1234 out:
1235 up_write(&c->xattr_sem);
1236 return rc;
1237}
1238
1239int jffs2_verify_xattr(struct jffs2_sb_info *c)
1240{
1241 struct jffs2_xattr_datum *xd, *_xd;
1242 int rc;
1243
1244 down_write(&c->xattr_sem);
1245 list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) {
1246 rc = do_verify_xattr_datum(c, xd);
1247 if (rc == 0) {
1248 list_del_init(&xd->xindex);
1249 break;
1250 } else if (rc > 0) {
1251 list_del_init(&xd->xindex);
1252 delete_xattr_datum_node(c, xd);
1253 }
1254 }
1255 up_write(&c->xattr_sem);
1256
1257 return list_empty(&c->xattr_unchecked) ? 1 : 0;
1258}
diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h
new file mode 100644
index 000000000000..e2aa2394ab64
--- /dev/null
+++ b/fs/jffs2/xattr.h
@@ -0,0 +1,116 @@
1/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright (C) 2006 NEC Corporation
5 *
6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
7 *
8 * For licensing information, see the file 'LICENCE' in this directory.
9 *
10 */
11#ifndef _JFFS2_FS_XATTR_H_
12#define _JFFS2_FS_XATTR_H_
13
14#include <linux/xattr.h>
15#include <linux/list.h>
16
17#define JFFS2_XFLAGS_HOT (0x01) /* This datum is HOT */
18#define JFFS2_XFLAGS_BIND (0x02) /* This datum is not reclaimed */
19
20struct jffs2_xattr_datum
21{
22 void *always_null;
23 u8 class;
24 u8 flags;
25 u16 xprefix; /* see JFFS2_XATTR_PREFIX_* */
26
27 struct jffs2_raw_node_ref *node;
28 struct list_head xindex; /* chained from c->xattrindex[n] */
29 uint32_t refcnt; /* # of xattr_ref refers this */
30 uint32_t xid;
31 uint32_t version;
32
33 uint32_t data_crc;
34 uint32_t hashkey;
35 char *xname; /* XATTR name without prefix */
36 uint32_t name_len; /* length of xname */
37 char *xvalue; /* XATTR value */
38 uint32_t value_len; /* length of xvalue */
39};
40
41struct jffs2_inode_cache;
42struct jffs2_xattr_ref
43{
44 void *always_null;
45 u8 class;
46 u8 flags; /* Currently unused */
47 u16 unused;
48
49 struct jffs2_raw_node_ref *node;
50 union {
51 struct jffs2_inode_cache *ic; /* reference to jffs2_inode_cache */
52 uint32_t ino; /* only used in scanning/building */
53 };
54 union {
55 struct jffs2_xattr_datum *xd; /* reference to jffs2_xattr_datum */
56 uint32_t xid; /* only used in sccanning/building */
57 };
58 struct jffs2_xattr_ref *next; /* chained from ic->xref_list */
59};
60
61#ifdef CONFIG_JFFS2_FS_XATTR
62
63extern void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c);
64extern void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c);
65extern void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c);
66
67extern struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
68 uint32_t xid, uint32_t version);
69
70extern void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
71extern void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
72
73extern int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd);
74extern int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref);
75extern int jffs2_verify_xattr(struct jffs2_sb_info *c);
76
77extern int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname,
78 char *buffer, size_t size);
79extern int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
80 const char *buffer, size_t size, int flags);
81
82extern struct xattr_handler *jffs2_xattr_handlers[];
83extern struct xattr_handler jffs2_user_xattr_handler;
84extern struct xattr_handler jffs2_trusted_xattr_handler;
85
86extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t);
87#define jffs2_getxattr generic_getxattr
88#define jffs2_setxattr generic_setxattr
89#define jffs2_removexattr generic_removexattr
90
91#else
92
93#define jffs2_init_xattr_subsystem(c)
94#define jffs2_build_xattr_subsystem(c)
95#define jffs2_clear_xattr_subsystem(c)
96
97#define jffs2_xattr_delete_inode(c, ic)
98#define jffs2_xattr_free_inode(c, ic)
99#define jffs2_verify_xattr(c) (1)
100
101#define jffs2_xattr_handlers NULL
102#define jffs2_listxattr NULL
103#define jffs2_getxattr NULL
104#define jffs2_setxattr NULL
105#define jffs2_removexattr NULL
106
107#endif /* CONFIG_JFFS2_FS_XATTR */
108
109#ifdef CONFIG_JFFS2_FS_SECURITY
110extern int jffs2_init_security(struct inode *inode, struct inode *dir);
111extern struct xattr_handler jffs2_security_xattr_handler;
112#else
113#define jffs2_init_security(inode,dir) (0)
114#endif /* CONFIG_JFFS2_FS_SECURITY */
115
116#endif /* _JFFS2_FS_XATTR_H_ */
diff --git a/fs/jffs2/xattr_trusted.c b/fs/jffs2/xattr_trusted.c
new file mode 100644
index 000000000000..ed046e19dbfa
--- /dev/null
+++ b/fs/jffs2/xattr_trusted.c
@@ -0,0 +1,52 @@
1/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright (C) 2006 NEC Corporation
5 *
6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
7 *
8 * For licensing information, see the file 'LICENCE' in this directory.
9 *
10 */
11#include <linux/kernel.h>
12#include <linux/fs.h>
13#include <linux/jffs2.h>
14#include <linux/xattr.h>
15#include <linux/mtd/mtd.h>
16#include "nodelist.h"
17
18static int jffs2_trusted_getxattr(struct inode *inode, const char *name,
19 void *buffer, size_t size)
20{
21 if (!strcmp(name, ""))
22 return -EINVAL;
23 return do_jffs2_getxattr(inode, JFFS2_XPREFIX_TRUSTED, name, buffer, size);
24}
25
26static int jffs2_trusted_setxattr(struct inode *inode, const char *name, const void *buffer,
27 size_t size, int flags)
28{
29 if (!strcmp(name, ""))
30 return -EINVAL;
31 return do_jffs2_setxattr(inode, JFFS2_XPREFIX_TRUSTED, name, buffer, size, flags);
32}
33
34static size_t jffs2_trusted_listxattr(struct inode *inode, char *list, size_t list_size,
35 const char *name, size_t name_len)
36{
37 size_t retlen = XATTR_TRUSTED_PREFIX_LEN + name_len + 1;
38
39 if (list && retlen<=list_size) {
40 strcpy(list, XATTR_TRUSTED_PREFIX);
41 strcpy(list + XATTR_TRUSTED_PREFIX_LEN, name);
42 }
43
44 return retlen;
45}
46
47struct xattr_handler jffs2_trusted_xattr_handler = {
48 .prefix = XATTR_TRUSTED_PREFIX,
49 .list = jffs2_trusted_listxattr,
50 .set = jffs2_trusted_setxattr,
51 .get = jffs2_trusted_getxattr
52};
diff --git a/fs/jffs2/xattr_user.c b/fs/jffs2/xattr_user.c
new file mode 100644
index 000000000000..2f8e9aa01ea0
--- /dev/null
+++ b/fs/jffs2/xattr_user.c
@@ -0,0 +1,52 @@
1/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright (C) 2006 NEC Corporation
5 *
6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
7 *
8 * For licensing information, see the file 'LICENCE' in this directory.
9 *
10 */
11#include <linux/kernel.h>
12#include <linux/fs.h>
13#include <linux/jffs2.h>
14#include <linux/xattr.h>
15#include <linux/mtd/mtd.h>
16#include "nodelist.h"
17
18static int jffs2_user_getxattr(struct inode *inode, const char *name,
19 void *buffer, size_t size)
20{
21 if (!strcmp(name, ""))
22 return -EINVAL;
23 return do_jffs2_getxattr(inode, JFFS2_XPREFIX_USER, name, buffer, size);
24}
25
26static int jffs2_user_setxattr(struct inode *inode, const char *name, const void *buffer,
27 size_t size, int flags)
28{
29 if (!strcmp(name, ""))
30 return -EINVAL;
31 return do_jffs2_setxattr(inode, JFFS2_XPREFIX_USER, name, buffer, size, flags);
32}
33
34static size_t jffs2_user_listxattr(struct inode *inode, char *list, size_t list_size,
35 const char *name, size_t name_len)
36{
37 size_t retlen = XATTR_USER_PREFIX_LEN + name_len + 1;
38
39 if (list && retlen <= list_size) {
40 strcpy(list, XATTR_USER_PREFIX);
41 strcpy(list + XATTR_USER_PREFIX_LEN, name);
42 }
43
44 return retlen;
45}
46
47struct xattr_handler jffs2_user_xattr_handler = {
48 .prefix = XATTR_USER_PREFIX,
49 .list = jffs2_user_listxattr,
50 .set = jffs2_user_setxattr,
51 .get = jffs2_user_getxattr
52};
diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h
index 007d76d290cb..c6f70660b371 100644
--- a/include/linux/jffs2.h
+++ b/include/linux/jffs2.h
@@ -65,6 +65,18 @@
65 65
66#define JFFS2_NODETYPE_SUMMARY (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 6) 66#define JFFS2_NODETYPE_SUMMARY (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 6)
67 67
68#define JFFS2_NODETYPE_XATTR (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 8)
69#define JFFS2_NODETYPE_XREF (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 9)
70
71/* XATTR Related */
72#define JFFS2_XPREFIX_USER 1 /* for "user." */
73#define JFFS2_XPREFIX_SECURITY 2 /* for "security." */
74#define JFFS2_XPREFIX_ACL_ACCESS 3 /* for "system.posix_acl_access" */
75#define JFFS2_XPREFIX_ACL_DEFAULT 4 /* for "system.posix_acl_default" */
76#define JFFS2_XPREFIX_TRUSTED 5 /* for "trusted.*" */
77
78#define JFFS2_ACL_VERSION 0x0001
79
68// Maybe later... 80// Maybe later...
69//#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3) 81//#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3)
70//#define JFFS2_NODETYPE_OPTIONS (JFFS2_FEATURE_RWCOMPAT_COPY | JFFS2_NODE_ACCURATE | 4) 82//#define JFFS2_NODETYPE_OPTIONS (JFFS2_FEATURE_RWCOMPAT_COPY | JFFS2_NODE_ACCURATE | 4)
@@ -151,6 +163,32 @@ struct jffs2_raw_inode
151 uint8_t data[0]; 163 uint8_t data[0];
152}; 164};
153 165
166struct jffs2_raw_xattr {
167 jint16_t magic;
168 jint16_t nodetype; /* = JFFS2_NODETYPE_XATTR */
169 jint32_t totlen;
170 jint32_t hdr_crc;
171 jint32_t xid; /* XATTR identifier number */
172 jint32_t version;
173 uint8_t xprefix;
174 uint8_t name_len;
175 jint16_t value_len;
176 jint32_t data_crc;
177 jint32_t node_crc;
178 uint8_t data[0];
179} __attribute__((packed));
180
181struct jffs2_raw_xref
182{
183 jint16_t magic;
184 jint16_t nodetype; /* = JFFS2_NODETYPE_XREF */
185 jint32_t totlen;
186 jint32_t hdr_crc;
187 jint32_t ino; /* inode number */
188 jint32_t xid; /* XATTR identifier number */
189 jint32_t node_crc;
190} __attribute__((packed));
191
154struct jffs2_raw_summary 192struct jffs2_raw_summary
155{ 193{
156 jint16_t magic; 194 jint16_t magic;
@@ -169,6 +207,8 @@ union jffs2_node_union
169{ 207{
170 struct jffs2_raw_inode i; 208 struct jffs2_raw_inode i;
171 struct jffs2_raw_dirent d; 209 struct jffs2_raw_dirent d;
210 struct jffs2_raw_xattr x;
211 struct jffs2_raw_xref r;
172 struct jffs2_raw_summary s; 212 struct jffs2_raw_summary s;
173 struct jffs2_unknown_node u; 213 struct jffs2_unknown_node u;
174}; 214};