aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2006-05-18 19:28:49 -0400
committerDavid Woodhouse <dwmw2@infradead.org>2006-05-18 19:28:49 -0400
commitaef9ab47841af45888d950baa6448072cc70bdd5 (patch)
tree79545ddc225f64bc38fa04525ac4125c86202cb8
parentf6a673b3f4f93c1c50e1b18f29254b0531b722a8 (diff)
[JFFS2] Support new device nodes
Device node major/minor numbers are just stored in the payload of a single data node. Just extend that to 4 bytes and use new_encode_dev() for it. We only use the 4-byte format if we _need_ to, if !old_valid_dev(foo). This preserves backwards compatibility with older code as much as possible. If we do make devices with major or minor numbers above 255, and then mount the file system with the old code, it'll just read the first two bytes and get the numbers wrong. If it comes to garbage-collect it, it'll then write back those wrong numbers. But that's about the best we can expect. Signed-off-by: David Woodhouse <dwmw2@infradead.org>
-rw-r--r--fs/jffs2/dir.c12
-rw-r--r--fs/jffs2/fs.c25
-rw-r--r--fs/jffs2/gc.c7
-rw-r--r--fs/jffs2/nodelist.h11
-rw-r--r--fs/jffs2/os-linux.h4
-rw-r--r--include/linux/jffs2.h6
6 files changed, 43 insertions, 22 deletions
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index 1c8e8c0f6cea..a6c11cef1b73 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -591,12 +591,12 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
591 struct jffs2_full_dnode *fn; 591 struct jffs2_full_dnode *fn;
592 struct jffs2_full_dirent *fd; 592 struct jffs2_full_dirent *fd;
593 int namelen; 593 int namelen;
594 jint16_t dev; 594 union jffs2_device_node dev;
595 int devlen = 0; 595 int devlen = 0;
596 uint32_t alloclen, phys_ofs; 596 uint32_t alloclen, phys_ofs;
597 int ret; 597 int ret;
598 598
599 if (!old_valid_dev(rdev)) 599 if (!new_valid_dev(rdev))
600 return -EINVAL; 600 return -EINVAL;
601 601
602 ri = jffs2_alloc_raw_inode(); 602 ri = jffs2_alloc_raw_inode();
@@ -605,17 +605,15 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
605 605
606 c = JFFS2_SB_INFO(dir_i->i_sb); 606 c = JFFS2_SB_INFO(dir_i->i_sb);
607 607
608 if (S_ISBLK(mode) || S_ISCHR(mode)) { 608 if (S_ISBLK(mode) || S_ISCHR(mode))
609 dev = cpu_to_je16(old_encode_dev(rdev)); 609 devlen = jffs2_encode_dev(&dev, rdev);
610 devlen = sizeof(dev);
611 }
612 610
613 /* Try to reserve enough space for both node and dirent. 611 /* Try to reserve enough space for both node and dirent.
614 * Just the node will do for now, though 612 * Just the node will do for now, though
615 */ 613 */
616 namelen = dentry->d_name.len; 614 namelen = dentry->d_name.len;
617 ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &phys_ofs, &alloclen, 615 ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &phys_ofs, &alloclen,
618 ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); 616 ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
619 617
620 if (ret) { 618 if (ret) {
621 jffs2_free_raw_inode(ri); 619 jffs2_free_raw_inode(ri);
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index ea1f37d4fc58..24cb4c688efc 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -33,7 +33,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
33 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); 33 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
34 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); 34 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
35 struct jffs2_raw_inode *ri; 35 struct jffs2_raw_inode *ri;
36 unsigned short dev; 36 union jffs2_device_node dev;
37 unsigned char *mdata = NULL; 37 unsigned char *mdata = NULL;
38 int mdatalen = 0; 38 int mdatalen = 0;
39 unsigned int ivalid; 39 unsigned int ivalid;
@@ -51,9 +51,8 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
51 it out again with the appropriate data attached */ 51 it out again with the appropriate data attached */
52 if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { 52 if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
53 /* For these, we don't actually need to read the old node */ 53 /* For these, we don't actually need to read the old node */
54 dev = old_encode_dev(inode->i_rdev); 54 mdatalen = jffs2_encode_dev(&dev, inode->i_rdev);
55 mdata = (char *)&dev; 55 mdata = (char *)&dev;
56 mdatalen = sizeof(dev);
57 D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen)); 56 D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen));
58 } else if (S_ISLNK(inode->i_mode)) { 57 } else if (S_ISLNK(inode->i_mode)) {
59 down(&f->sem); 58 down(&f->sem);
@@ -232,6 +231,8 @@ void jffs2_read_inode (struct inode *inode)
232 struct jffs2_inode_info *f; 231 struct jffs2_inode_info *f;
233 struct jffs2_sb_info *c; 232 struct jffs2_sb_info *c;
234 struct jffs2_raw_inode latest_node; 233 struct jffs2_raw_inode latest_node;
234 union jffs2_device_node jdev;
235 dev_t rdev = 0;
235 int ret; 236 int ret;
236 237
237 D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino)); 238 D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino));
@@ -263,7 +264,6 @@ void jffs2_read_inode (struct inode *inode)
263 inode->i_blocks = (inode->i_size + 511) >> 9; 264 inode->i_blocks = (inode->i_size + 511) >> 9;
264 265
265 switch (inode->i_mode & S_IFMT) { 266 switch (inode->i_mode & S_IFMT) {
266 jint16_t rdev;
267 267
268 case S_IFLNK: 268 case S_IFLNK:
269 inode->i_op = &jffs2_symlink_inode_operations; 269 inode->i_op = &jffs2_symlink_inode_operations;
@@ -297,8 +297,16 @@ void jffs2_read_inode (struct inode *inode)
297 case S_IFBLK: 297 case S_IFBLK:
298 case S_IFCHR: 298 case S_IFCHR:
299 /* Read the device numbers from the media */ 299 /* Read the device numbers from the media */
300 if (f->metadata->size != sizeof(jdev.old) &&
301 f->metadata->size != sizeof(jdev.new)) {
302 printk(KERN_NOTICE "Device node has strange size %d\n", f->metadata->size);
303 up(&f->sem);
304 jffs2_do_clear_inode(c, f);
305 make_bad_inode(inode);
306 return;
307 }
300 D1(printk(KERN_DEBUG "Reading device numbers from flash\n")); 308 D1(printk(KERN_DEBUG "Reading device numbers from flash\n"));
301 if (jffs2_read_dnode(c, f, f->metadata, (char *)&rdev, 0, sizeof(rdev)) < 0) { 309 if (jffs2_read_dnode(c, f, f->metadata, (char *)&jdev, 0, f->metadata->size) < 0) {
302 /* Eep */ 310 /* Eep */
303 printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino); 311 printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino);
304 up(&f->sem); 312 up(&f->sem);
@@ -306,12 +314,15 @@ void jffs2_read_inode (struct inode *inode)
306 make_bad_inode(inode); 314 make_bad_inode(inode);
307 return; 315 return;
308 } 316 }
317 if (f->metadata->size == sizeof(jdev.old))
318 rdev = old_decode_dev(je16_to_cpu(jdev.old));
319 else
320 rdev = new_decode_dev(je32_to_cpu(jdev.new));
309 321
310 case S_IFSOCK: 322 case S_IFSOCK:
311 case S_IFIFO: 323 case S_IFIFO:
312 inode->i_op = &jffs2_file_inode_operations; 324 inode->i_op = &jffs2_file_inode_operations;
313 init_special_inode(inode, inode->i_mode, 325 init_special_inode(inode, inode->i_mode, rdev);
314 old_decode_dev((je16_to_cpu(rdev))));
315 break; 326 break;
316 327
317 default: 328 default:
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index 967fb2cf8e21..77d30707de56 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -679,7 +679,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_
679 struct jffs2_full_dnode *new_fn; 679 struct jffs2_full_dnode *new_fn;
680 struct jffs2_raw_inode ri; 680 struct jffs2_raw_inode ri;
681 struct jffs2_node_frag *last_frag; 681 struct jffs2_node_frag *last_frag;
682 jint16_t dev; 682 union jffs2_device_node dev;
683 char *mdata = NULL, mdatalen = 0; 683 char *mdata = NULL, mdatalen = 0;
684 uint32_t alloclen, phys_ofs, ilen; 684 uint32_t alloclen, phys_ofs, ilen;
685 int ret; 685 int ret;
@@ -687,11 +687,8 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_
687 if (S_ISBLK(JFFS2_F_I_MODE(f)) || 687 if (S_ISBLK(JFFS2_F_I_MODE(f)) ||
688 S_ISCHR(JFFS2_F_I_MODE(f)) ) { 688 S_ISCHR(JFFS2_F_I_MODE(f)) ) {
689 /* For these, we don't actually need to read the old node */ 689 /* For these, we don't actually need to read the old node */
690 /* FIXME: for minor or major > 255. */ 690 mdatalen = jffs2_encode_dev(&dev, JFFS2_F_I_RDEV(f));
691 dev = cpu_to_je16(((JFFS2_F_I_RDEV_MAJ(f) << 8) |
692 JFFS2_F_I_RDEV_MIN(f)));
693 mdata = (char *)&dev; 691 mdata = (char *)&dev;
694 mdatalen = sizeof(dev);
695 D1(printk(KERN_DEBUG "jffs2_garbage_collect_metadata(): Writing %d bytes of kdev_t\n", mdatalen)); 692 D1(printk(KERN_DEBUG "jffs2_garbage_collect_metadata(): Writing %d bytes of kdev_t\n", mdatalen));
696 } else if (S_ISLNK(JFFS2_F_I_MODE(f))) { 693 } else if (S_ISLNK(JFFS2_F_I_MODE(f))) {
697 mdatalen = fn->size; 694 mdatalen = fn->size;
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index f6645afe88e4..24e0f28a8bac 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -268,6 +268,17 @@ static inline uint32_t ref_totlen(struct jffs2_sb_info *c,
268 268
269#define PAD(x) (((x)+3)&~3) 269#define PAD(x) (((x)+3)&~3)
270 270
271static inline int jffs2_encode_dev(union jffs2_device_node *jdev, dev_t rdev)
272{
273 if (old_valid_dev(rdev)) {
274 jdev->old = cpu_to_je16(old_encode_dev(rdev));
275 return sizeof(jdev->old);
276 } else {
277 jdev->new = cpu_to_je32(new_encode_dev(rdev));
278 return sizeof(jdev->new);
279 }
280}
281
271static inline struct jffs2_inode_cache *jffs2_raw_ref_to_ic(struct jffs2_raw_node_ref *raw) 282static inline struct jffs2_inode_cache *jffs2_raw_ref_to_ic(struct jffs2_raw_node_ref *raw)
272{ 283{
273 while(raw->next_in_ino) { 284 while(raw->next_in_ino) {
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index d307cf548625..a10eb03ac95b 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -31,9 +31,7 @@ struct kvec;
31#define JFFS2_F_I_MODE(f) (OFNI_EDONI_2SFFJ(f)->i_mode) 31#define JFFS2_F_I_MODE(f) (OFNI_EDONI_2SFFJ(f)->i_mode)
32#define JFFS2_F_I_UID(f) (OFNI_EDONI_2SFFJ(f)->i_uid) 32#define JFFS2_F_I_UID(f) (OFNI_EDONI_2SFFJ(f)->i_uid)
33#define JFFS2_F_I_GID(f) (OFNI_EDONI_2SFFJ(f)->i_gid) 33#define JFFS2_F_I_GID(f) (OFNI_EDONI_2SFFJ(f)->i_gid)
34 34#define JFFS2_F_I_RDEV(f) (OFNI_EDONI_2SFFJ(f)->i_rdev)
35#define JFFS2_F_I_RDEV_MIN(f) (iminor(OFNI_EDONI_2SFFJ(f)))
36#define JFFS2_F_I_RDEV_MAJ(f) (imajor(OFNI_EDONI_2SFFJ(f)))
37 35
38#define ITIME(sec) ((struct timespec){sec, 0}) 36#define ITIME(sec) ((struct timespec){sec, 0})
39#define I_SEC(tv) ((tv).tv_sec) 37#define I_SEC(tv) ((tv).tv_sec)
diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h
index a26fbd498c79..007d76d290cb 100644
--- a/include/linux/jffs2.h
+++ b/include/linux/jffs2.h
@@ -173,4 +173,10 @@ union jffs2_node_union
173 struct jffs2_unknown_node u; 173 struct jffs2_unknown_node u;
174}; 174};
175 175
176/* Data payload for device nodes. */
177union jffs2_device_node {
178 jint16_t old;
179 jint32_t new;
180};
181
176#endif /* __LINUX_JFFS2_H__ */ 182#endif /* __LINUX_JFFS2_H__ */