[JFFS2] Support new device nodes
Linux-MTD Mailing List
linux-mtd at lists.infradead.org
Thu May 18 19:59:02 EDT 2006
Commit: aef9ab47841af45888d950baa6448072cc70bdd5
Parent: f6a673b3f4f93c1c50e1b18f29254b0531b722a8
Author: David Woodhouse <dwmw2 at infradead.org>
AuthorDate: Fri May 19 00:28:49 2006 +0100
Commit: David Woodhouse <dwmw2 at infradead.org>
CommitDate: Fri May 19 00:28:49 2006 +0100
[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 at infradead.org>
fs/jffs2/dir.c | 12 +++++-------
fs/jffs2/fs.c | 25 ++++++++++++++++++-------
fs/jffs2/gc.c | 7 ++-----
fs/jffs2/nodelist.h | 11 +++++++++++
fs/jffs2/os-linux.h | 4 +---
include/linux/jffs2.h | 6 ++++++
6 files changed, 43 insertions(+), 22 deletions(-)
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index 1c8e8c0..a6c11ce 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -591,12 +591,12 @@ static int jffs2_mknod (struct inode *di
struct jffs2_full_dnode *fn;
struct jffs2_full_dirent *fd;
int namelen;
- jint16_t dev;
+ union jffs2_device_node dev;
int devlen = 0;
uint32_t alloclen, phys_ofs;
int ret;
- if (!old_valid_dev(rdev))
+ if (!new_valid_dev(rdev))
return -EINVAL;
ri = jffs2_alloc_raw_inode();
@@ -605,17 +605,15 @@ static int jffs2_mknod (struct inode *di
c = JFFS2_SB_INFO(dir_i->i_sb);
- if (S_ISBLK(mode) || S_ISCHR(mode)) {
- dev = cpu_to_je16(old_encode_dev(rdev));
- devlen = sizeof(dev);
- }
+ if (S_ISBLK(mode) || S_ISCHR(mode))
+ devlen = jffs2_encode_dev(&dev, rdev);
/* Try to reserve enough space for both node and dirent.
* Just the node will do for now, though
*/
namelen = dentry->d_name.len;
ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &phys_ofs, &alloclen,
- ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
+ ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
if (ret) {
jffs2_free_raw_inode(ri);
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index ea1f37d..24cb4c6 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -33,7 +33,7 @@ static int jffs2_do_setattr (struct inod
struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
struct jffs2_raw_inode *ri;
- unsigned short dev;
+ union jffs2_device_node dev;
unsigned char *mdata = NULL;
int mdatalen = 0;
unsigned int ivalid;
@@ -51,9 +51,8 @@ static int jffs2_do_setattr (struct inod
it out again with the appropriate data attached */
if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
/* For these, we don't actually need to read the old node */
- dev = old_encode_dev(inode->i_rdev);
+ mdatalen = jffs2_encode_dev(&dev, inode->i_rdev);
mdata = (char *)&dev;
- mdatalen = sizeof(dev);
D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen));
} else if (S_ISLNK(inode->i_mode)) {
down(&f->sem);
@@ -232,6 +231,8 @@ void jffs2_read_inode (struct inode *ino
struct jffs2_inode_info *f;
struct jffs2_sb_info *c;
struct jffs2_raw_inode latest_node;
+ union jffs2_device_node jdev;
+ dev_t rdev = 0;
int ret;
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 *ino
inode->i_blocks = (inode->i_size + 511) >> 9;
switch (inode->i_mode & S_IFMT) {
- jint16_t rdev;
case S_IFLNK:
inode->i_op = &jffs2_symlink_inode_operations;
@@ -297,8 +297,16 @@ void jffs2_read_inode (struct inode *ino
case S_IFBLK:
case S_IFCHR:
/* Read the device numbers from the media */
+ if (f->metadata->size != sizeof(jdev.old) &&
+ f->metadata->size != sizeof(jdev.new)) {
+ printk(KERN_NOTICE "Device node has strange size %d\n", f->metadata->size);
+ up(&f->sem);
+ jffs2_do_clear_inode(c, f);
+ make_bad_inode(inode);
+ return;
+ }
D1(printk(KERN_DEBUG "Reading device numbers from flash\n"));
- if (jffs2_read_dnode(c, f, f->metadata, (char *)&rdev, 0, sizeof(rdev)) < 0) {
+ if (jffs2_read_dnode(c, f, f->metadata, (char *)&jdev, 0, f->metadata->size) < 0) {
/* Eep */
printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino);
up(&f->sem);
@@ -306,12 +314,15 @@ void jffs2_read_inode (struct inode *ino
make_bad_inode(inode);
return;
}
+ if (f->metadata->size == sizeof(jdev.old))
+ rdev = old_decode_dev(je16_to_cpu(jdev.old));
+ else
+ rdev = new_decode_dev(je32_to_cpu(jdev.new));
case S_IFSOCK:
case S_IFIFO:
inode->i_op = &jffs2_file_inode_operations;
- init_special_inode(inode, inode->i_mode,
- old_decode_dev((je16_to_cpu(rdev))));
+ init_special_inode(inode, inode->i_mode, rdev);
break;
default:
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index 967fb2c..77d3070 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -679,7 +679,7 @@ static int jffs2_garbage_collect_metadat
struct jffs2_full_dnode *new_fn;
struct jffs2_raw_inode ri;
struct jffs2_node_frag *last_frag;
- jint16_t dev;
+ union jffs2_device_node dev;
char *mdata = NULL, mdatalen = 0;
uint32_t alloclen, phys_ofs, ilen;
int ret;
@@ -687,11 +687,8 @@ static int jffs2_garbage_collect_metadat
if (S_ISBLK(JFFS2_F_I_MODE(f)) ||
S_ISCHR(JFFS2_F_I_MODE(f)) ) {
/* For these, we don't actually need to read the old node */
- /* FIXME: for minor or major > 255. */
- dev = cpu_to_je16(((JFFS2_F_I_RDEV_MAJ(f) << 8) |
- JFFS2_F_I_RDEV_MIN(f)));
+ mdatalen = jffs2_encode_dev(&dev, JFFS2_F_I_RDEV(f));
mdata = (char *)&dev;
- mdatalen = sizeof(dev);
D1(printk(KERN_DEBUG "jffs2_garbage_collect_metadata(): Writing %d bytes of kdev_t\n", mdatalen));
} else if (S_ISLNK(JFFS2_F_I_MODE(f))) {
mdatalen = fn->size;
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index f6645af..24e0f28 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -268,6 +268,17 @@ #define ISDIRTY(size) ((size) > sizeof
#define PAD(x) (((x)+3)&~3)
+static inline int jffs2_encode_dev(union jffs2_device_node *jdev, dev_t rdev)
+{
+ if (old_valid_dev(rdev)) {
+ jdev->old = cpu_to_je16(old_encode_dev(rdev));
+ return sizeof(jdev->old);
+ } else {
+ jdev->new = cpu_to_je32(new_encode_dev(rdev));
+ return sizeof(jdev->new);
+ }
+}
+
static inline struct jffs2_inode_cache *jffs2_raw_ref_to_ic(struct jffs2_raw_node_ref *raw)
{
while(raw->next_in_ino) {
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index d307cf5..a10eb03 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -31,9 +31,7 @@ #define JFFS2_F_I_SIZE(f) (OFNI_EDONI_2S
#define JFFS2_F_I_MODE(f) (OFNI_EDONI_2SFFJ(f)->i_mode)
#define JFFS2_F_I_UID(f) (OFNI_EDONI_2SFFJ(f)->i_uid)
#define JFFS2_F_I_GID(f) (OFNI_EDONI_2SFFJ(f)->i_gid)
-
-#define JFFS2_F_I_RDEV_MIN(f) (iminor(OFNI_EDONI_2SFFJ(f)))
-#define JFFS2_F_I_RDEV_MAJ(f) (imajor(OFNI_EDONI_2SFFJ(f)))
+#define JFFS2_F_I_RDEV(f) (OFNI_EDONI_2SFFJ(f)->i_rdev)
#define ITIME(sec) ((struct timespec){sec, 0})
#define I_SEC(tv) ((tv).tv_sec)
diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h
index a26fbd4..007d76d 100644
--- a/include/linux/jffs2.h
+++ b/include/linux/jffs2.h
@@ -173,4 +173,10 @@ union jffs2_node_union
struct jffs2_unknown_node u;
};
+/* Data payload for device nodes. */
+union jffs2_device_node {
+ jint16_t old;
+ jint32_t new;
+};
+
#endif /* __LINUX_JFFS2_H__ */
More information about the linux-mtd-cvs
mailing list