aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2/nodelist.h
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jffs2/nodelist.h')
-rw-r--r--fs/jffs2/nodelist.h190
1 files changed, 115 insertions, 75 deletions
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index 23a67bb3052f..b16c60bbcf6e 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -18,8 +18,10 @@
18#include <linux/fs.h> 18#include <linux/fs.h>
19#include <linux/types.h> 19#include <linux/types.h>
20#include <linux/jffs2.h> 20#include <linux/jffs2.h>
21#include <linux/jffs2_fs_sb.h> 21#include "jffs2_fs_sb.h"
22#include <linux/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
@@ -75,14 +77,50 @@
75struct jffs2_raw_node_ref 77struct jffs2_raw_node_ref
76{ 78{
77 struct jffs2_raw_node_ref *next_in_ino; /* Points to the next raw_node_ref 79 struct jffs2_raw_node_ref *next_in_ino; /* Points to the next raw_node_ref
78 for this inode. If this is the last, it points to the inode_cache 80 for this object. If this _is_ the last, it points to the inode_cache,
79 for this inode instead. The inode_cache will have NULL in the first 81 xattr_ref or xattr_datum instead. The common part of those structures
80 word so you know when you've got there :) */ 82 has NULL in the first word. See jffs2_raw_ref_to_ic() below */
81 struct jffs2_raw_node_ref *next_phys;
82 uint32_t flash_offset; 83 uint32_t flash_offset;
84#define TEST_TOTLEN
85#ifdef TEST_TOTLEN
83 uint32_t __totlen; /* This may die; use ref_totlen(c, jeb, ) below */ 86 uint32_t __totlen; /* This may die; use ref_totlen(c, jeb, ) below */
87#endif
84}; 88};
85 89
90#define REF_LINK_NODE ((int32_t)-1)
91#define REF_EMPTY_NODE ((int32_t)-2)
92
93/* Use blocks of about 256 bytes */
94#define REFS_PER_BLOCK ((255/sizeof(struct jffs2_raw_node_ref))-1)
95
96static inline struct jffs2_raw_node_ref *ref_next(struct jffs2_raw_node_ref *ref)
97{
98 ref++;
99
100 /* Link to another block of refs */
101 if (ref->flash_offset == REF_LINK_NODE) {
102 ref = ref->next_in_ino;
103 if (!ref)
104 return ref;
105 }
106
107 /* End of chain */
108 if (ref->flash_offset == REF_EMPTY_NODE)
109 return NULL;
110
111 return ref;
112}
113
114static inline struct jffs2_inode_cache *jffs2_raw_ref_to_ic(struct jffs2_raw_node_ref *raw)
115{
116 while(raw->next_in_ino)
117 raw = raw->next_in_ino;
118
119 /* NB. This can be a jffs2_xattr_datum or jffs2_xattr_ref and
120 not actually a jffs2_inode_cache. Check ->class */
121 return ((struct jffs2_inode_cache *)raw);
122}
123
86 /* flash_offset & 3 always has to be zero, because nodes are 124 /* flash_offset & 3 always has to be zero, because nodes are
87 always aligned at 4 bytes. So we have a couple of extra bits 125 always aligned at 4 bytes. So we have a couple of extra bits
88 to play with, which indicate the node's status; see below: */ 126 to play with, which indicate the node's status; see below: */
@@ -95,6 +133,11 @@ struct jffs2_raw_node_ref
95#define ref_obsolete(ref) (((ref)->flash_offset & 3) == REF_OBSOLETE) 133#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) 134#define mark_ref_normal(ref) do { (ref)->flash_offset = ref_offset(ref) | REF_NORMAL; } while(0)
97 135
136/* NB: REF_PRISTINE for an inode-less node (ref->next_in_ino == NULL) indicates
137 it is an unknown node of type JFFS2_NODETYPE_RWCOMPAT_COPY, so it'll get
138 copied. If you need to do anything different to GC inode-less nodes, then
139 you need to modify gc.c accordingly. */
140
98/* For each inode in the filesystem, we need to keep a record of 141/* 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 142 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 143 at read_inode() time to calculate it, and to keep sufficient information
@@ -103,15 +146,27 @@ struct jffs2_raw_node_ref
103 a pointer to the first physical node which is part of this inode, too. 146 a pointer to the first physical node which is part of this inode, too.
104*/ 147*/
105struct jffs2_inode_cache { 148struct jffs2_inode_cache {
149 /* First part of structure is shared with other objects which
150 can terminate the raw node refs' next_in_ino list -- which
151 currently struct jffs2_xattr_datum and struct jffs2_xattr_ref. */
152
106 struct jffs2_full_dirent *scan_dents; /* Used during scan to hold 153 struct jffs2_full_dirent *scan_dents; /* Used during scan to hold
107 temporary lists of dirents, and later must be set to 154 temporary lists of dirents, and later must be set to
108 NULL to mark the end of the raw_node_ref->next_in_ino 155 NULL to mark the end of the raw_node_ref->next_in_ino
109 chain. */ 156 chain. */
110 struct jffs2_inode_cache *next;
111 struct jffs2_raw_node_ref *nodes; 157 struct jffs2_raw_node_ref *nodes;
158 uint8_t class; /* It's used for identification */
159
160 /* end of shared structure */
161
162 uint8_t flags;
163 uint16_t state;
112 uint32_t ino; 164 uint32_t ino;
165 struct jffs2_inode_cache *next;
166#ifdef CONFIG_JFFS2_FS_XATTR
167 struct jffs2_xattr_ref *xref;
168#endif
113 int nlink; 169 int nlink;
114 int state;
115}; 170};
116 171
117/* Inode states for 'state' above. We need the 'GC' state to prevent 172/* Inode states for 'state' above. We need the 'GC' state to prevent
@@ -125,8 +180,16 @@ struct jffs2_inode_cache {
125#define INO_STATE_READING 5 /* In read_inode() */ 180#define INO_STATE_READING 5 /* In read_inode() */
126#define INO_STATE_CLEARING 6 /* In clear_inode() */ 181#define INO_STATE_CLEARING 6 /* In clear_inode() */
127 182
183#define INO_FLAGS_XATTR_CHECKED 0x01 /* has no duplicate xattr_ref */
184
185#define RAWNODE_CLASS_INODE_CACHE 0
186#define RAWNODE_CLASS_XATTR_DATUM 1
187#define RAWNODE_CLASS_XATTR_REF 2
188
128#define INOCACHE_HASHSIZE 128 189#define INOCACHE_HASHSIZE 128
129 190
191#define write_ofs(c) ((c)->nextblock->offset + (c)->sector_size - (c)->nextblock->free_size)
192
130/* 193/*
131 Larger representation of a raw node, kept in-core only when the 194 Larger representation of a raw node, kept in-core only when the
132 struct inode for this particular ino is instantiated. 195 struct inode for this particular ino is instantiated.
@@ -192,6 +255,7 @@ struct jffs2_eraseblock
192 uint32_t wasted_size; 255 uint32_t wasted_size;
193 uint32_t free_size; /* Note that sector_size - free_size 256 uint32_t free_size; /* Note that sector_size - free_size
194 is the address of the first free space */ 257 is the address of the first free space */
258 uint32_t allocated_refs;
195 struct jffs2_raw_node_ref *first_node; 259 struct jffs2_raw_node_ref *first_node;
196 struct jffs2_raw_node_ref *last_node; 260 struct jffs2_raw_node_ref *last_node;
197 261
@@ -203,57 +267,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); 267 return ((c->flash_size / c->sector_size) * sizeof (struct jffs2_eraseblock)) > (128 * 1024);
204} 268}
205 269
206/* Calculate totlen from surrounding nodes or eraseblock */ 270#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 271
258#define ALLOC_NORMAL 0 /* Normal allocation */ 272#define ALLOC_NORMAL 0 /* Normal allocation */
259#define ALLOC_DELETION 1 /* Deletion node. Best to allow it */ 273#define ALLOC_DELETION 1 /* Deletion node. Best to allow it */
@@ -268,13 +282,15 @@ static inline uint32_t ref_totlen(struct jffs2_sb_info *c,
268 282
269#define PAD(x) (((x)+3)&~3) 283#define PAD(x) (((x)+3)&~3)
270 284
271static inline struct jffs2_inode_cache *jffs2_raw_ref_to_ic(struct jffs2_raw_node_ref *raw) 285static inline int jffs2_encode_dev(union jffs2_device_node *jdev, dev_t rdev)
272{ 286{
273 while(raw->next_in_ino) { 287 if (old_valid_dev(rdev)) {
274 raw = raw->next_in_ino; 288 jdev->old = cpu_to_je16(old_encode_dev(rdev));
289 return sizeof(jdev->old);
290 } else {
291 jdev->new = cpu_to_je32(new_encode_dev(rdev));
292 return sizeof(jdev->new);
275 } 293 }
276
277 return ((struct jffs2_inode_cache *)raw);
278} 294}
279 295
280static inline struct jffs2_node_frag *frag_first(struct rb_root *root) 296static inline struct jffs2_node_frag *frag_first(struct rb_root *root)
@@ -299,7 +315,6 @@ static inline struct jffs2_node_frag *frag_last(struct rb_root *root)
299 return rb_entry(node, struct jffs2_node_frag, rb); 315 return rb_entry(node, struct jffs2_node_frag, rb);
300} 316}
301 317
302#define rb_parent(rb) ((rb)->rb_parent)
303#define frag_next(frag) rb_entry(rb_next(&(frag)->rb), struct jffs2_node_frag, rb) 318#define frag_next(frag) rb_entry(rb_next(&(frag)->rb), struct jffs2_node_frag, rb)
304#define frag_prev(frag) rb_entry(rb_prev(&(frag)->rb), struct jffs2_node_frag, rb) 319#define frag_prev(frag) rb_entry(rb_prev(&(frag)->rb), struct jffs2_node_frag, rb)
305#define frag_parent(frag) rb_entry(rb_parent(&(frag)->rb), struct jffs2_node_frag, rb) 320#define frag_parent(frag) rb_entry(rb_parent(&(frag)->rb), struct jffs2_node_frag, rb)
@@ -324,28 +339,44 @@ void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *t
324int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); 339int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn);
325void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); 340void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size);
326int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn); 341int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn);
342struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c,
343 struct jffs2_eraseblock *jeb,
344 uint32_t ofs, uint32_t len,
345 struct jffs2_inode_cache *ic);
346extern uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c,
347 struct jffs2_eraseblock *jeb,
348 struct jffs2_raw_node_ref *ref);
327 349
328/* nodemgmt.c */ 350/* nodemgmt.c */
329int jffs2_thread_should_wake(struct jffs2_sb_info *c); 351int jffs2_thread_should_wake(struct jffs2_sb_info *c);
330int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, 352int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
331 uint32_t *len, int prio, uint32_t sumsize); 353 uint32_t *len, int prio, uint32_t sumsize);
332int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, 354int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize,
333 uint32_t *len, uint32_t sumsize); 355 uint32_t *len, uint32_t sumsize);
334int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new); 356struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c,
357 uint32_t ofs, uint32_t len,
358 struct jffs2_inode_cache *ic);
335void jffs2_complete_reservation(struct jffs2_sb_info *c); 359void jffs2_complete_reservation(struct jffs2_sb_info *c);
336void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw); 360void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw);
337 361
338/* write.c */ 362/* write.c */
339int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri); 363int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri);
340 364
341struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode); 365struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
342struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_dirent *rd, const unsigned char *name, uint32_t namelen, uint32_t flash_ofs, int alloc_mode); 366 struct jffs2_raw_inode *ri, const unsigned char *data,
367 uint32_t datalen, int alloc_mode);
368struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
369 struct jffs2_raw_dirent *rd, const unsigned char *name,
370 uint32_t namelen, int alloc_mode);
343int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, 371int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
344 struct jffs2_raw_inode *ri, unsigned char *buf, 372 struct jffs2_raw_inode *ri, unsigned char *buf,
345 uint32_t offset, uint32_t writelen, uint32_t *retlen); 373 uint32_t offset, uint32_t writelen, uint32_t *retlen);
346int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const char *name, int namelen); 374int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f,
347int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, int namelen, struct jffs2_inode_info *dead_f, uint32_t time); 375 struct jffs2_raw_inode *ri, const char *name, int namelen);
348int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen, uint32_t time); 376int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name,
377 int namelen, struct jffs2_inode_info *dead_f, uint32_t time);
378int jffs2_do_link(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino,
379 uint8_t type, const char *name, int namelen, uint32_t time);
349 380
350 381
351/* readinode.c */ 382/* readinode.c */
@@ -368,12 +399,19 @@ struct jffs2_raw_inode *jffs2_alloc_raw_inode(void);
368void jffs2_free_raw_inode(struct jffs2_raw_inode *); 399void jffs2_free_raw_inode(struct jffs2_raw_inode *);
369struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void); 400struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void);
370void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *); 401void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *);
371struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void); 402int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c,
372void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *); 403 struct jffs2_eraseblock *jeb, int nr);
404void jffs2_free_refblock(struct jffs2_raw_node_ref *);
373struct jffs2_node_frag *jffs2_alloc_node_frag(void); 405struct jffs2_node_frag *jffs2_alloc_node_frag(void);
374void jffs2_free_node_frag(struct jffs2_node_frag *); 406void jffs2_free_node_frag(struct jffs2_node_frag *);
375struct jffs2_inode_cache *jffs2_alloc_inode_cache(void); 407struct jffs2_inode_cache *jffs2_alloc_inode_cache(void);
376void jffs2_free_inode_cache(struct jffs2_inode_cache *); 408void jffs2_free_inode_cache(struct jffs2_inode_cache *);
409#ifdef CONFIG_JFFS2_FS_XATTR
410struct jffs2_xattr_datum *jffs2_alloc_xattr_datum(void);
411void jffs2_free_xattr_datum(struct jffs2_xattr_datum *);
412struct jffs2_xattr_ref *jffs2_alloc_xattr_ref(void);
413void jffs2_free_xattr_ref(struct jffs2_xattr_ref *);
414#endif
377 415
378/* gc.c */ 416/* gc.c */
379int jffs2_garbage_collect_pass(struct jffs2_sb_info *c); 417int jffs2_garbage_collect_pass(struct jffs2_sb_info *c);
@@ -393,12 +431,14 @@ int jffs2_fill_scan_buf(struct jffs2_sb_info *c, void *buf,
393 uint32_t ofs, uint32_t len); 431 uint32_t ofs, uint32_t len);
394struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino); 432struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino);
395int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); 433int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
434int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t size);
396 435
397/* build.c */ 436/* build.c */
398int jffs2_do_mount_fs(struct jffs2_sb_info *c); 437int jffs2_do_mount_fs(struct jffs2_sb_info *c);
399 438
400/* erase.c */ 439/* erase.c */
401void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count); 440void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count);
441void jffs2_free_jeb_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
402 442
403#ifdef CONFIG_JFFS2_FS_WRITEBUFFER 443#ifdef CONFIG_JFFS2_FS_WRITEBUFFER
404/* wbuf.c */ 444/* wbuf.c */