Skip to contentSkip to conversation

A few V7 fs improvements

PATCH In review Lubomir Rintel 7 participants 21 messages Jul 19, 2010 – Jul 27, 2010

lore
Share & tools
lore
#0 lore raw

I'm resending these once again, since I suspect they may have gotten lost in a spam filter due to improper MTA configuration of mine.

They basically improve usability of PC v7 filesystems; such as those of PC/IX.

#1 lore raw

PATCH 1/3 Add v7 alias

So that the module gets autoloaded when a v7 filesystem is mounted.

Cc Christoph Hellwig <[email protected]>
---
 fs/sysv/super.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
fs/sysv/super.c +1 -0
index 5a903da..bd8d141 100644
@@ -560,4 +560,5 @@ static void __exit exit_sysv_fs(void)
 
 module_init(init_sysv_fs)
 module_exit(exit_sysv_fs)
+MODULE_ALIAS("v7");
 MODULE_LICENSE("GPL");
Signature · 1 line
1.6.5.2
#2 lore raw

PATCH 2/3 V7: Adjust sanity checks for some volumes

Newly mkfs-ed filesystems from Seventh Edition have last modification time set to zero, but are otherwise perfectly valid.

Also, tighten up other sanity checks to filter out most filesystems with different bytesex than we're using.

Cc Christoph Hellwig <[email protected]>
---
 fs/sysv/super.c         |    8 +++++---
 include/linux/sysv_fs.h |   11 +++++++++++
 2 files changed, 16 insertions(+), 3 deletions(-)
fs/sysv/super.c +5 -3
index bd8d141..17ac83d 100644
@@ -470,8 +470,8 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent)
 	v7sb = (struct v7_super_block *) bh->b_data;
 	if (fs16_to_cpu(sbi, v7sb->s_nfree) > V7_NICFREE ||
 	    fs16_to_cpu(sbi, v7sb->s_ninode) > V7_NICINOD ||
-	    fs32_to_cpu(sbi, v7sb->s_time) == 0)
-		goto failed;
+	    fs32_to_cpu(sbi, v7sb->s_fsize) > V7_MAXSIZE)
+		return 0;
 
 	/* plausibility check on root inode: it is a directory,
 	   with a nonzero size that is a multiple of 16 */
@@ -480,7 +480,9 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent)
 	v7i = (struct sysv_inode *)(bh2->b_data + 64);
 	if ((fs16_to_cpu(sbi, v7i->i_mode) & ~0777) != S_IFDIR ||
 	    (fs32_to_cpu(sbi, v7i->i_size) == 0) ||
-	    (fs32_to_cpu(sbi, v7i->i_size) & 017) != 0)
+	    (fs32_to_cpu(sbi, v7i->i_size) & 017)
+	    (fs32_to_cpu(sbi, v7i->i_size) > V7_NFILES *
+	     sizeof (struct sysv_dir_entry))) {
 		goto failed;
 	brelse(bh2);
 	bh2 = NULL;
include/linux/sysv_fs.h +11 -0
index 9641130..0a7a232 100644
@@ -148,6 +148,17 @@ struct v7_super_block {
 	char    s_fname[6];     /* file system name */
 	char    s_fpack[6];     /* file system pack name */
 };
+/* Constants to aid sanity checking */
+/* This is not a hard limit, nor enforced by v7 kernel. It's actually just
+ * the limit used by Seventh Edition's ls, though is high enough to assume
+ * that no reasonable file system would have that much entries in root
+ * directory. Thus, if we see anything higher, we just probably got the
+ * endiannes wrong. */
+#define V7_NFILES	1024
+/* Indirect blocks hold just three-byte addresses, therefore if see a file
+ * system whose length has the most significant byte non-zero something is
+ * most likely wrong (not a filesystem, bad bytesex). */
+#define V7_MAXSIZE	0x00ffffff
 
 /* Coherent super-block data on disk */
 #define COH_NICINOD	100	/* number of inode cache entries */
Signature · 1 line
1.6.5.2
#3 lore raw

PATCH 3/3 V7: Add support for non-PDP11 v7 filesystems

A mount-time option was added that makes it possible to override the endianness and an attempt is made to autodetect it (which seems easy, given the disk addresses are 3-byte.

No attempt is made to detect big-endian filesystems -- were there any? Tested with PDP-11 v7 filesystems and PC-IX maintenance floppy.

Cc Christoph Hellwig <[email protected]>
---
 fs/sysv/super.c         |  116 +++++++++++++++++++++++++++++++++++++----------
 include/linux/sysv_fs.h |    6 +-
 2 files changed, 95 insertions(+), 27 deletions(-)
fs/sysv/super.c +92 -24
index 17ac83d..9cd5be0 100644
@@ -24,6 +24,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/buffer_head.h>
+#include <linux/parser.h>
 #include "sysv.h"
 
 /*
@@ -435,12 +436,55 @@ Ebadsize:
 	goto failed;
 }
 
-static int v7_fill_super(struct super_block *sb, void *data, int silent)
+static int v7_sanity_check(struct super_block *sb, struct buffer_head *bh)
 {
-	struct sysv_sb_info *sbi;
-	struct buffer_head *bh, *bh2 = NULL;
 	struct v7_super_block *v7sb;
 	struct sysv_inode *v7i;
+	struct buffer_head *bh2;
+	struct sysv_sb_info *sbi;
+
+	sbi = sb->s_fs_info;
+
+	/* plausibility check on superblock */
+	v7sb = (struct v7_super_block *) bh->b_data;
+	if (fs16_to_cpu(sbi, v7sb->s_nfree) > V7_NICFREE ||
+	    fs16_to_cpu(sbi, v7sb->s_ninode) > V7_NICINOD ||
+	    fs32_to_cpu(sbi, v7sb->s_fsize) > V7_MAXSIZE)
+		return 0;
+
+	/* plausibility check on root inode: it is a directory,
+	   with a nonzero size that is a multiple of 16 */
+	if ((bh2 = sb_bread(sb, 2)) == NULL) {
+		return 0;
+	}
+
+	v7i = (struct sysv_inode *)(bh2->b_data + 64);
+	if ((fs16_to_cpu(sbi, v7i->i_mode) & ~0777) != S_IFDIR ||
+	    (fs32_to_cpu(sbi, v7i->i_size) == 0) ||
+	    (fs32_to_cpu(sbi, v7i->i_size) & 017) ||
+	    (fs32_to_cpu(sbi, v7i->i_size) > V7_NFILES *
+             sizeof (struct sysv_dir_entry))) {
+		brelse(bh2);
+		return 0;
+	}
+
+	brelse(bh2);
+	return 1;
+}
+
+enum { Opt_err, Opt_bytesex_pdp, Opt_bytesex_le, Opt_bytesex_be };
+
+static const match_table_t v7_tokens = {
+	{Opt_bytesex_pdp, "bytesex=pdp"},
+	{Opt_bytesex_le, "bytesex=le"},
+	{Opt_bytesex_be, "bytesex=be"},
+	{Opt_err, NULL}
+};
+
+static int v7_fill_super(struct super_block *sb, void *data, int silent)
+{
+	struct sysv_sb_info *sbi;
+	struct buffer_head *bh;
 
 	if (440 != sizeof (struct v7_super_block))
 		panic("V7 FS: bad super-block size");
@@ -454,7 +498,6 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent)
 	sbi->s_sb = sb;
 	sbi->s_block_base = 0;
 	sbi->s_type = FSTYPE_V7;
-	sbi->s_bytesex = BYTESEX_PDP;
 	sb->s_fs_info = sbi;
 	
 	sb_set_blocksize(sb, 512);
@@ -466,26 +509,51 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent)
 		goto failed;
 	}
 
-	/* plausibility check on superblock */
-	v7sb = (struct v7_super_block *) bh->b_data;
-	if (fs16_to_cpu(sbi, v7sb->s_nfree) > V7_NICFREE ||
-	    fs16_to_cpu(sbi, v7sb->s_ninode) > V7_NICINOD ||
-	    fs32_to_cpu(sbi, v7sb->s_fsize) > V7_MAXSIZE)
-		return 0;
+	if (data) {
+		substring_t args[MAX_OPT_ARGS];
+		char *p;
+
+		while ((p = strsep ((char **)&data, ",")) != NULL) {
+			int token;
+			if (!*p)
+				continue;
+			token = match_token(p, v7_tokens, args);
+			switch (token) {
+			case Opt_bytesex_pdp:
+				sbi->s_bytesex = BYTESEX_PDP;
+				break;
+			case Opt_bytesex_le:
+				sbi->s_bytesex = BYTESEX_LE;
+				break;
+			case Opt_bytesex_be:
+				sbi->s_bytesex = BYTESEX_BE;
+				break;
+			default:
+				/* An unrecognized option */
+				goto failed;
+			}
+		}
+	}
 
-	/* plausibility check on root inode: it is a directory,
-	   with a nonzero size that is a multiple of 16 */
-	if ((bh2 = sb_bread(sb, 2)) == NULL)
-		goto failed;
-	v7i = (struct sysv_inode *)(bh2->b_data + 64);
-	if ((fs16_to_cpu(sbi, v7i->i_mode) & ~0777) != S_IFDIR ||
-	    (fs32_to_cpu(sbi, v7i->i_size) == 0) ||
-	    (fs32_to_cpu(sbi, v7i->i_size) & 017)
-	    (fs32_to_cpu(sbi, v7i->i_size) > V7_NFILES *
-	     sizeof (struct sysv_dir_entry))) {
-		goto failed;
-	brelse(bh2);
-	bh2 = NULL;
+	/* Endianness overridden by a mount option */
+	if (sbi->s_bytesex) {
+		if (!v7_sanity_check (sb, bh))
+			goto failed;
+		goto detected;
+	}
+
+	/* Try PDP-11 UNIX */
+	sbi->s_bytesex = BYTESEX_PDP;
+	if (v7_sanity_check (sb, bh))
+		goto detected;
+
+	/* Try PC/IX, v7/x86 */
+	sbi->s_bytesex = BYTESEX_LE;
+	if (v7_sanity_check (sb, bh))
+		goto detected;
+
+	goto failed;
+detected:
 
 	sbi->s_bh1 = bh;
 	sbi->s_bh2 = bh;
@@ -493,7 +561,7 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent)
 		return 0;
 
 failed:
-	brelse(bh2);
+	printk("VFS: could not find a valid V7 on %s.\n", sb->s_id);
 	brelse(bh);
 	kfree(sbi);
 	return -EINVAL;
include/linux/sysv_fs.h +3 -3
index 0a7a232..e47d6d9 100644
@@ -155,9 +155,9 @@ struct v7_super_block {
  * directory. Thus, if we see anything higher, we just probably got the
  * endiannes wrong. */
 #define V7_NFILES	1024
-/* Indirect blocks hold just three-byte addresses, therefore if see a file
- * system whose length has the most significant byte non-zero something is
- * most likely wrong (not a filesystem, bad bytesex). */
+/* The disk addresses are three-byte (despite direct block addresses being
+ * aligned word-wise in inode). If the most significant byte is non-zero,
+ * something is most likely wrong (not a filesystem, bad bytesex). */
 #define V7_MAXSIZE	0x00ffffff
 
 /* Coherent super-block data on disk */
Signature · 1 line
1.6.5.2
#4 lore raw

Re: [PATCH 3/3] [fs/sysv] V7: Add support for non-PDP11 v7 filesystems

Quoted 6 lines · Lubomir Rintel

A mount-time option was added that makes it possible to override the endianness and an attempt is made to autodetect it (which seems easy, given the disk addresses are 3-byte.

No attempt is made to detect big-endian filesystems -- were there any? Tested with PDP-11 v7 filesystems and PC-IX maintenance floppy.

Do you actually need the mount option? We get away just fine with it for sysv filesystems. And if not I'd be consistent and accept the options for both sysv and v7 filesystems.

fs/sysv/super.c Ebadsize: · line 459

Quoted 5 lines
fs/sysv/super.c +5 -0
+	/* plausibility check on root inode: it is a directory,
+	   with a nonzero size that is a multiple of 16 */
+	if ((bh2 = sb_bread(sb, 2)) == NULL) {
+		return 0;
+	}

A little style nitpick, this should be:

	bh2 = sb_bread(sb, 2);
	if (!bh)
		return 0;
#5 lore raw

Re: [PATCH 3/3] [fs/sysv] V7: Add support for non-PDP11 v7 filesystems

Quoted 11 lines · Christoph Hellwig
Quoted 6 lines · Lubomir Rintel

A mount-time option was added that makes it possible to override the endianness and an attempt is made to autodetect it (which seems easy, given the disk addresses are 3-byte.

No attempt is made to detect big-endian filesystems -- were there any? Tested with PDP-11 v7 filesystems and PC-IX maintenance floppy.

Do you actually need the mount option? We get away just fine with it for sysv filesystems. And if not I'd be consistent and accept the options for both sysv and v7 filesystems.

Well, there's no reliable way to detect endiannes of a v7 filesystem unless we do a deep check as fsck would do (there are cases where we can be sure that a filesystem is not of a certain bytesex, which is what the current sanity check does and what's abused for the lousy autodetection).

In super.c it looks like xenix and sysv use a magic number which the byte order can be determined from, thus the option would be useless there.

Coherent seems to always use PDP-11 bytesex. I can not check at the time, but I'm almost sure it never run on such machines (was PC and 68k only?), so I suspect the coherent kernel might have always done the translation to native byte order. I think I have some coherent (for PC) floppies at home, so I can check tomorrow.

Quoted 8 lines

fs/sysv/super.c Ebadsize: · line 459

Quoted 5 lines
fs/sysv/super.c +5 -0
+	/* plausibility check on root inode: it is a directory,
+	   with a nonzero size that is a multiple of 16 */
+	if ((bh2 = sb_bread(sb, 2)) == NULL) {
+		return 0;
+	}

A little style nitpick, this should be:

Quoted 4 lines
	bh2 = sb_bread(sb, 2);
	if (!bh)
		return 0;

I actually did not write this myself, but merely moved from v7_fill_super(). It would probably a good idea to keep it as it is (not to obfuscate the changes) and fix it up in a separate commit if is worth.

Take care,
Lubo

Signature · 2 lines
Flash is the Web2.0 version of blink and animated gifs.
                                     -- Stephen Smoogen
#6 lore raw

Re: [PATCH 3/3] [fs/sysv] V7: Add support for non-PDP11 v7 filesystems

Quoted 1 line · Lubomir Rintel

On Mon, 2010-07-19 at 16:58 +0200, Christoph Hellwig wrote:

...

Quoted 3 lines
Quoted 3 lines

Do you actually need the mount option? We get away just fine with it for sysv filesystems. And if not I'd be consistent and accept the options for both sysv and v7 filesystems.

...

Quoted 5 lines

Coherent seems to always use PDP-11 bytesex. I can not check at the time, but I'm almost sure it never run on such machines (was PC and 68k only?), so I suspect the coherent kernel might have always done the translation to native byte order. I think I have some coherent (for PC) floppies at home, so I can check tomorrow.

This was just partly correct. Coherent indeed run on PDP-11 (and not on 68k), but the PC version uses the very same bytesex as PDP-11 one, translating the byte order on the fly (_canl() routine defined in i386/as.inc file of Coherent 4.2.10 for i386 kernel is used).

Thus the mount option is really only useful with v7 filesystem and none of those handled with sysv filesystem.

Signature · 2 lines
Flash is the Web2.0 version of blink and animated gifs.
                                     -- Stephen Smoogen
#7 lore raw

PATCH 1/1 V7: Add support for non-PDP11 v7 filesystems

A mount-time option was added that makes it possible to override the endianness and an attempt is made to autodetect it (which seems easy, given the disk addresses are 3-byte.

No attempt is made to detect big-endian filesystems -- were there any? Tested with PDP-11 v7 filesystems and PC-IX maintenance floppy.

Cc Christoph Hellwig <[email protected]>
---
 fs/sysv/super.c |  116 +++++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 92 insertions(+), 24 deletions(-)
fs/sysv/super.c +92 -24
index ac7b008..ca4e8aa 100644
@@ -24,6 +24,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/buffer_head.h>
+#include <linux/parser.h>
 #include "sysv.h"
 
 /*
@@ -435,12 +436,55 @@ Ebadsize:
 	goto failed;
 }
 
-static int v7_fill_super(struct super_block *sb, void *data, int silent)
+static int v7_sanity_check(struct super_block *sb, struct buffer_head *bh)
 {
-	struct sysv_sb_info *sbi;
-	struct buffer_head *bh, *bh2 = NULL;
 	struct v7_super_block *v7sb;
 	struct sysv_inode *v7i;
+	struct buffer_head *bh2;
+	struct sysv_sb_info *sbi;
+
+	sbi = sb->s_fs_info;
+
+	/* plausibility check on superblock */
+	v7sb = (struct v7_super_block *) bh->b_data;
+	if (fs16_to_cpu(sbi, v7sb->s_nfree) > V7_NICFREE ||
+	    fs16_to_cpu(sbi, v7sb->s_ninode) > V7_NICINOD ||
+	    fs32_to_cpu(sbi, v7sb->s_fsize) > V7_MAXSIZE)
+		return 0;
+
+	/* plausibility check on root inode: it is a directory,
+	   with a nonzero size that is a multiple of 16 */
+	if ((bh2 = sb_bread(sb, 2)) == NULL) {
+		return 0;
+	}
+
+	v7i = (struct sysv_inode *)(bh2->b_data + 64);
+	if ((fs16_to_cpu(sbi, v7i->i_mode) & ~0777) != S_IFDIR ||
+	    (fs32_to_cpu(sbi, v7i->i_size) == 0) ||
+	    (fs32_to_cpu(sbi, v7i->i_size) & 017) ||
+	    (fs32_to_cpu(sbi, v7i->i_size) > V7_NFILES *
+             sizeof (struct sysv_dir_entry))) {
+		brelse(bh2);
+		return 0;
+	}
+
+	brelse(bh2);
+	return 1;
+}
+
+enum { Opt_err, Opt_bytesex_pdp, Opt_bytesex_le, Opt_bytesex_be };
+
+static const match_table_t v7_tokens = {
+	{Opt_bytesex_pdp, "bytesex=pdp"},
+	{Opt_bytesex_le, "bytesex=le"},
+	{Opt_bytesex_be, "bytesex=be"},
+	{Opt_err, NULL}
+};
+
+static int v7_fill_super(struct super_block *sb, void *data, int silent)
+{
+	struct sysv_sb_info *sbi;
+	struct buffer_head *bh;
 
 	if (440 != sizeof (struct v7_super_block))
 		panic("V7 FS: bad super-block size");
@@ -454,7 +498,6 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent)
 	sbi->s_sb = sb;
 	sbi->s_block_base = 0;
 	sbi->s_type = FSTYPE_V7;
-	sbi->s_bytesex = BYTESEX_PDP;
 	sb->s_fs_info = sbi;
 	
 	sb_set_blocksize(sb, 512);
@@ -466,34 +509,59 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent)
 		goto failed;
 	}
 
-	/* plausibility check on superblock */
-	v7sb = (struct v7_super_block *) bh->b_data;
-	if (fs16_to_cpu(sbi, v7sb->s_nfree) > V7_NICFREE ||
-	    fs16_to_cpu(sbi, v7sb->s_ninode) > V7_NICINOD ||
-	    fs32_to_cpu(sbi, v7sb->s_fsize) > V7_MAXSIZE)
-		goto failed;
+	if (data) {
+		substring_t args[MAX_OPT_ARGS];
+		char *p;
+
+		while ((p = strsep ((char **)&data, ",")) != NULL) {
+			int token;
+			if (!*p)
+				continue;
+			token = match_token(p, v7_tokens, args);
+			switch (token) {
+			case Opt_bytesex_pdp:
+				sbi->s_bytesex = BYTESEX_PDP;
+				break;
+			case Opt_bytesex_le:
+				sbi->s_bytesex = BYTESEX_LE;
+				break;
+			case Opt_bytesex_be:
+				sbi->s_bytesex = BYTESEX_BE;
+				break;
+			default:
+				/* An unrecognized option */
+				goto failed;
+			}
+		}
+	}
 
-	/* plausibility check on root inode: it is a directory,
-	   with a nonzero size that is a multiple of 16 */
-	if ((bh2 = sb_bread(sb, 2)) == NULL)
-		goto failed;
-	v7i = (struct sysv_inode *)(bh2->b_data + 64);
-	if ((fs16_to_cpu(sbi, v7i->i_mode) & ~0777) != S_IFDIR ||
-	    (fs32_to_cpu(sbi, v7i->i_size) == 0) ||
-	    (fs32_to_cpu(sbi, v7i->i_size) & 017) ||
-	    (fs32_to_cpu(sbi, v7i->i_size) > V7_NFILES *
-	     sizeof (struct sysv_dir_entry)))
-		goto failed;
-	brelse(bh2);
-	bh2 = NULL;
+	/* Endianness overridden by a mount option */
+	if (sbi->s_bytesex) {
+		if (!v7_sanity_check (sb, bh))
+			goto failed;
+		goto detected;
+	}
+
+	/* Try PDP-11 UNIX */
+	sbi->s_bytesex = BYTESEX_PDP;
+	if (v7_sanity_check (sb, bh))
+		goto detected;
+
+	/* Try PC/IX, v7/x86 */
+	sbi->s_bytesex = BYTESEX_LE;
+	if (v7_sanity_check (sb, bh))
+		goto detected;
 
+	goto failed;
+
+detected:
 	sbi->s_bh1 = bh;
 	sbi->s_bh2 = bh;
 	if (complete_read_super(sb, silent, 1))
 		return 0;
 
 failed:
-	brelse(bh2);
+	printk("VFS: could not find a valid V7 on %s.\n", sb->s_id);
 	brelse(bh);
 	kfree(sbi);
 	return -EINVAL;
Signature · 1 line
1.7.1
#8 lore raw

Re: [PATCH 3/3] [fs/sysv] V7: Add support for non-PDP11 v7 filesystems

In reply to Christoph Hellwig
Quoted 11 lines · Christoph Hellwig
Quoted 6 lines · Lubomir Rintel

A mount-time option was added that makes it possible to override the endianness and an attempt is made to autodetect it (which seems easy, given the disk addresses are 3-byte.

No attempt is made to detect big-endian filesystems -- were there any? Tested with PDP-11 v7 filesystems and PC-IX maintenance floppy.

Do you actually need the mount option? We get away just fine with it for sysv filesystems. And if not I'd be consistent and accept the options for both sysv and v7 filesystems.

Actually, it shouldn't be too hard to detect the damn thing even without magic. Look - we always have the inode table starting at block 2, so on-disk root inode is guaranteed to be found correctly. Now, suppose we'd mistaken l-e for pdp or vice versa; the half-words of i_size would get swapped. What could pass both tests? Suppose the right size is a * 65536 + b; then we have: a and b are both multiples of 16 and at least one is non-zero. So all we need is to reject root directories bigger than 1Mb. And posted patches do reject that (and lower than that, actually).

So I'd rather see a variant without that option. Simply get both bh, then try the same sanity checks with LE and PDP used for s_bytesex. And use one that works - we _know_ that it's impossible to have both pass at the same time.

I'm fine with the rest of patch series as is; Lubomir, could you redo the last one that way and resend?

#9 lore raw

PATCH 1/1 V7: Add support for non-PDP11 v7 filesystems

This adds byte order autodetection (of PDP-11 and LE filesystems). No attempt is made to detect big-endian filesystems -- were there any? Tested with PDP-11 v7 filesystems and PC-IX maintenance floppy.

Cc Christoph Hellwig <[email protected]>
Cc Al Viro <[email protected]>
---
 fs/sysv/super.c |   74 +++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 50 insertions(+), 24 deletions(-)
fs/sysv/super.c +50 -24
index ac7b008..0433f23 100644
@@ -24,6 +24,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/buffer_head.h>
+#include <linux/parser.h>
 #include "sysv.h"
 
 /*
@@ -435,12 +436,46 @@ Ebadsize:
 	goto failed;
 }
 
-static int v7_fill_super(struct super_block *sb, void *data, int silent)
+static int v7_sanity_check(struct super_block *sb, struct buffer_head *bh)
 {
-	struct sysv_sb_info *sbi;
-	struct buffer_head *bh, *bh2 = NULL;
 	struct v7_super_block *v7sb;
 	struct sysv_inode *v7i;
+	struct buffer_head *bh2;
+	struct sysv_sb_info *sbi;
+
+	sbi = sb->s_fs_info;
+
+	/* plausibility check on superblock */
+	v7sb = (struct v7_super_block *) bh->b_data;
+	if (fs16_to_cpu(sbi, v7sb->s_nfree) > V7_NICFREE ||
+	    fs16_to_cpu(sbi, v7sb->s_ninode) > V7_NICINOD ||
+	    fs32_to_cpu(sbi, v7sb->s_fsize) > V7_MAXSIZE)
+		return 0;
+
+	/* plausibility check on root inode: it is a directory,
+	   with a nonzero size that is a multiple of 16 */
+	if ((bh2 = sb_bread(sb, 2)) == NULL) {
+		return 0;
+	}
+
+	v7i = (struct sysv_inode *)(bh2->b_data + 64);
+	if ((fs16_to_cpu(sbi, v7i->i_mode) & ~0777) != S_IFDIR ||
+	    (fs32_to_cpu(sbi, v7i->i_size) == 0) ||
+	    (fs32_to_cpu(sbi, v7i->i_size) & 017) ||
+	    (fs32_to_cpu(sbi, v7i->i_size) > V7_NFILES *
+             sizeof (struct sysv_dir_entry))) {
+		brelse(bh2);
+		return 0;
+	}
+
+	brelse(bh2);
+	return 1;
+}
+
+static int v7_fill_super(struct super_block *sb, void *data, int silent)
+{
+	struct sysv_sb_info *sbi;
+	struct buffer_head *bh;
 
 	if (440 != sizeof (struct v7_super_block))
 		panic("V7 FS: bad super-block size");
@@ -454,7 +489,6 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent)
 	sbi->s_sb = sb;
 	sbi->s_block_base = 0;
 	sbi->s_type = FSTYPE_V7;
-	sbi->s_bytesex = BYTESEX_PDP;
 	sb->s_fs_info = sbi;
 	
 	sb_set_blocksize(sb, 512);
@@ -466,34 +500,26 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent)
 		goto failed;
 	}
 
-	/* plausibility check on superblock */
-	v7sb = (struct v7_super_block *) bh->b_data;
-	if (fs16_to_cpu(sbi, v7sb->s_nfree) > V7_NICFREE ||
-	    fs16_to_cpu(sbi, v7sb->s_ninode) > V7_NICINOD ||
-	    fs32_to_cpu(sbi, v7sb->s_fsize) > V7_MAXSIZE)
-		goto failed;
+	/* Try PDP-11 UNIX */
+	sbi->s_bytesex = BYTESEX_PDP;
+	if (v7_sanity_check (sb, bh))
+		goto detected;
 
-	/* plausibility check on root inode: it is a directory,
-	   with a nonzero size that is a multiple of 16 */
-	if ((bh2 = sb_bread(sb, 2)) == NULL)
-		goto failed;
-	v7i = (struct sysv_inode *)(bh2->b_data + 64);
-	if ((fs16_to_cpu(sbi, v7i->i_mode) & ~0777) != S_IFDIR ||
-	    (fs32_to_cpu(sbi, v7i->i_size) == 0) ||
-	    (fs32_to_cpu(sbi, v7i->i_size) & 017) ||
-	    (fs32_to_cpu(sbi, v7i->i_size) > V7_NFILES *
-	     sizeof (struct sysv_dir_entry)))
-		goto failed;
-	brelse(bh2);
-	bh2 = NULL;
+	/* Try PC/IX, v7/x86 */
+	sbi->s_bytesex = BYTESEX_LE;
+	if (v7_sanity_check (sb, bh))
+		goto detected;
 
+	goto failed;
+
+detected:
 	sbi->s_bh1 = bh;
 	sbi->s_bh2 = bh;
 	if (complete_read_super(sb, silent, 1))
 		return 0;
 
 failed:
-	brelse(bh2);
+	printk("VFS: could not find a valid V7 on %s.\n", sb->s_id);
 	brelse(bh);
 	kfree(sbi);
 	return -EINVAL;
Signature · 1 line
1.7.2
#10 lore raw

Re: [PATCH] V7: Add support for non-PDP11 v7 filesystems

Quoted 33 lines · On Mon, 26 Jul 2010 00:59:16 +0200 Lubomir Rintel wrote:

This adds byte order autodetection (of PDP-11 and LE filesystems). No attempt is made to detect big-endian filesystems -- were there any? Tested with PDP-11 v7 filesystems and PC-IX maintenance floppy.

Cc Christoph Hellwig <[email protected]>
Cc Al Viro <[email protected]>
---
 fs/sysv/super.c |   74 +++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 50 insertions(+), 24 deletions(-)
fs/sysv/super.c +8 -3
index ac7b008..0433f23 100644
@@ -435,12 +436,46 @@ Ebadsize:
 	goto failed;
 }
 
-static int v7_fill_super(struct super_block *sb, void *data, int silent)
+static int v7_sanity_check(struct super_block *sb, struct buffer_head *bh)
 {
-	struct sysv_sb_info *sbi;
-	struct buffer_head *bh, *bh2 = NULL;
 	struct v7_super_block *v7sb;
 	struct sysv_inode *v7i;
+	struct buffer_head *bh2;
+	struct sysv_sb_info *sbi;
+
+	sbi = sb->s_fs_info;
+
+	/* plausibility check on superblock */
+	v7sb = (struct v7_super_block *) bh->b_data;

fs/sysv/super.c Ebadsize: · line 459

Quoted 10 lines
fs/sysv/super.c +10 -0
+	if (fs16_to_cpu(sbi, v7sb->s_nfree) > V7_NICFREE ||
+	    fs16_to_cpu(sbi, v7sb->s_ninode) > V7_NICINOD ||
+	    fs32_to_cpu(sbi, v7sb->s_fsize) > V7_MAXSIZE)
+		return 0;
+
+	/* plausibility check on root inode: it is a directory,
+	   with a nonzero size that is a multiple of 16 */
+	if ((bh2 = sb_bread(sb, 2)) == NULL) {
+		return 0;
+	}

Don't need the braces.

fs/sysv/super.c Ebadsize: · line 466

Quoted 7 lines
fs/sysv/super.c +7 -0
+
+	v7i = (struct sysv_inode *)(bh2->b_data + 64);
+	if ((fs16_to_cpu(sbi, v7i->i_mode) & ~0777) != S_IFDIR ||
+	    (fs32_to_cpu(sbi, v7i->i_size) == 0) ||
+	    (fs32_to_cpu(sbi, v7i->i_size) & 017) ||
+	    (fs32_to_cpu(sbi, v7i->i_size) > V7_NFILES *
+             sizeof (struct sysv_dir_entry))) {
	        sizeof(struct sysv_dir_entry))) {
Quoted 57 lines
fs/sysv/super.c +21 -20
+		brelse(bh2);
+		return 0;
+	}
+
+	brelse(bh2);
+	return 1;
+}
+
+static int v7_fill_super(struct super_block *sb, void *data, int silent)
+{
+	struct sysv_sb_info *sbi;
+	struct buffer_head *bh;
 
 	if (440 != sizeof (struct v7_super_block))
 		panic("V7 FS: bad super-block size");
@@ -454,7 +489,6 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent)
 	sbi->s_sb = sb;
 	sbi->s_block_base = 0;
 	sbi->s_type = FSTYPE_V7;
-	sbi->s_bytesex = BYTESEX_PDP;
 	sb->s_fs_info = sbi;
 
 	sb_set_blocksize(sb, 512);
@@ -466,34 +500,26 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent)
 		goto failed;
 	}
 
-	/* plausibility check on superblock */
-	v7sb = (struct v7_super_block *) bh->b_data;
-	if (fs16_to_cpu(sbi, v7sb->s_nfree) > V7_NICFREE ||
-	    fs16_to_cpu(sbi, v7sb->s_ninode) > V7_NICINOD ||
-	    fs32_to_cpu(sbi, v7sb->s_fsize) > V7_MAXSIZE)
-		goto failed;
+	/* Try PDP-11 UNIX */
+	sbi->s_bytesex = BYTESEX_PDP;
+	if (v7_sanity_check (sb, bh))
+		goto detected;
 
-	/* plausibility check on root inode: it is a directory,
-	   with a nonzero size that is a multiple of 16 */
-	if ((bh2 = sb_bread(sb, 2)) == NULL)
-		goto failed;
-	v7i = (struct sysv_inode *)(bh2->b_data + 64);
-	if ((fs16_to_cpu(sbi, v7i->i_mode) & ~0777) != S_IFDIR ||
-	    (fs32_to_cpu(sbi, v7i->i_size) == 0) ||
-	    (fs32_to_cpu(sbi, v7i->i_size) & 017) ||
-	    (fs32_to_cpu(sbi, v7i->i_size) > V7_NFILES *
-	     sizeof (struct sysv_dir_entry)))
-		goto failed;
-	brelse(bh2);
-	bh2 = NULL;
+	/* Try PC/IX, v7/x86 */
+	sbi->s_bytesex = BYTESEX_LE;
+	if (v7_sanity_check (sb, bh))
+		goto detected;
 
+	goto failed;

fs/sysv/super.c static int v7_fill_super(struct super_block *sb, void *data, int silent) · line 522

Quoted 10 lines
fs/sysv/super.c +3 -1
+
+detected:
 	sbi->s_bh1 = bh;
 	sbi->s_bh2 = bh;
 	if (complete_read_super(sb, silent, 1))
 		return 0;
 
 failed:
-	brelse(bh2);
+	printk("VFS: could not find a valid V7 on %s.\n", sb->s_id);

V7 fs (or V7 filesystem)

fs/sysv/super.c static int v7_fill_super(struct super_block *sb, void *data, int silent) · line 525

Quoted 4 lines
fs/sysv/super.c +0 -0
 	brelse(bh);
 	kfree(sbi);
 	return -EINVAL;

---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***

#11 lore raw

Re: [PATCH] V7: Add support for non-PDP11 v7 filesystems

In reply to Lubomir Rintel
Quoted 3 lines · On Mon, 26 Jul 2010 00:59:16 +0200 Lubomir Rintel <[email protected]> wrote:

This adds byte order autodetection (of PDP-11 and LE filesystems). No attempt is made to detect big-endian filesystems -- were there any? Tested with PDP-11 v7 filesystems and PC-IX maintenance floppy.

Which kernel is this against? My v7_fill_super() is significantly different from yours.

#12 lore raw

Re: [PATCH] V7: Add support for non-PDP11 v7 filesystems

Quoted 9 lines · Andrew Morton
Quoted 3 lines · On Mon, 26 Jul 2010 00:59:16 +0200 Lubomir Rintel <[email protected]> wrote:

This adds byte order autodetection (of PDP-11 and LE filesystems). No attempt is made to detect big-endian filesystems -- were there any? Tested with PDP-11 v7 filesystems and PC-IX maintenance floppy.

Which kernel is this against? My v7_fill_super() is significantly different from yours.

This depends on [PATCH] V7: Adjust sanity checks for some volumes <[email protected]>.

It might be that I've messed up something in the communication so that the dependency was not immediately clear. To be honest, I'm not very familiar with the way reviews and adjustements to patches are tracked. What have I done wrong, here? How am I supposed to follow up with a change to a single patch of a multi-patch (be it just two in this case) set?

Signature · 2 lines
Flash is the Web2.0 version of blink and animated gifs.
                                     -- Stephen Smoogen
#13 lore raw

Re: [PATCH] V7: Add support for non-PDP11 v7 filesystems

Quoted 14 lines · On Tue, 27 Jul 2010 02:19:15 +0200 Lubomir Rintel <[email protected]> wrote:
Quoted 9 lines · Andrew Morton
Quoted 3 lines · On Mon, 26 Jul 2010 00:59:16 +0200 Lubomir Rintel <[email protected]> wrote:

This adds byte order autodetection (of PDP-11 and LE filesystems). No attempt is made to detect big-endian filesystems -- were there any? Tested with PDP-11 v7 filesystems and PC-IX maintenance floppy.

Which kernel is this against? My v7_fill_super() is significantly different from yours.

This depends on [PATCH] V7: Adjust sanity checks for some volumes <[email protected]>.

Quoted 6 lines

It might be that I've messed up something in the communication so that the dependency was not immediately clear. To be honest, I'm not very familiar with the way reviews and adjustements to patches are tracked. What have I done wrong, here? How am I supposed to follow up with a change to a single patch of a multi-patch (be it just two in this case) set?

ah, OK, I managed to confuse myself with fs-sysv-v7-adjust-sanity-checks-for-some-volumes-checkpatch-fixes.patch.

This new patch triggers many warnings also:

ERROR: do not use assignment in if condition
#52: FILE: fs/sysv/super.c:456:
+ if ((bh2 = sb_bread(sb, 2)) == NULL) {

WARNING: braces {} are not necessary for single statement blocks #52: FILE: fs/sysv/super.c:456:
+ if ((bh2 = sb_bread(sb, 2)) == NULL) {
+ return 0;
+ }

ERROR: code indent should use tabs where possible
#61: FILE: fs/sysv/super.c:465:
+ sizeof (struct sysv_dir_entry))) {$

WARNING: please, no space for starting a line,
excluding comments
#61: FILE: fs/sysv/super.c:465:
+ sizeof (struct sysv_dir_entry))) {$

WARNING: space prohibited between function name and open parenthesis '(' #61: FILE: fs/sysv/super.c:465:
+ sizeof (struct sysv_dir_entry))) {

WARNING: space prohibited between function name and open parenthesis '(' #97: FILE: fs/sysv/super.c:504:
+ if (v7_sanity_check (sb, bh))

WARNING: space prohibited between function name and open parenthesis '(' #115: FILE: fs/sysv/super.c:509:
+ if (v7_sanity_check (sb, bh))

WARNING: printk() should include KERN_ facility level #128: FILE: fs/sysv/super.c:521:
+ printk("VFS: could not find a valid V7 on %s.\n", sb->s_id);

total: 2 errors, 6 warnings, 109 lines checked

./patches/v7-add-support-for-non-pdp11-v7-filesystems.patch has style problems, please review. If any of these errors are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

fs/sysv/super.c renamed from fs/sysv/super.c~fs-sysv-superc-add-support-for-non-pdp11-v7-filesystems-checkpatch-fixes +7 -6
@@ -453,16 +453,16 @@ static int v7_sanity_check(struct super_
 
 	/* plausibility check on root inode: it is a directory,
 	   with a nonzero size that is a multiple of 16 */
-	if ((bh2 = sb_bread(sb, 2)) == NULL) {
+	bh2 = sb_bread(sb, 2);
+	if (bh2 == NULL)
 		return 0;
-	}
 
 	v7i = (struct sysv_inode *)(bh2->b_data + 64);
 	if ((fs16_to_cpu(sbi, v7i->i_mode) & ~0777) != S_IFDIR ||
 	    (fs32_to_cpu(sbi, v7i->i_size) == 0) ||
 	    (fs32_to_cpu(sbi, v7i->i_size) & 017) ||
 	    (fs32_to_cpu(sbi, v7i->i_size) > V7_NFILES *
-             sizeof (struct sysv_dir_entry))) {
+	     sizeof(struct sysv_dir_entry))) {
 		brelse(bh2);
 		return 0;
 	}
@@ -501,12 +501,12 @@ static int v7_fill_super(struct super_bl
 
 	/* Try PDP-11 UNIX */
 	sbi->s_bytesex = BYTESEX_PDP;
-	if (v7_sanity_check (sb, bh))
+	if (v7_sanity_check(sb, bh))
 		goto detected;
 
 	/* Try PC/IX, v7/x86 */
 	sbi->s_bytesex = BYTESEX_LE;
-	if (v7_sanity_check (sb, bh))
+	if (v7_sanity_check(sb, bh))
 		goto detected;
 
 	goto failed;
@@ -518,7 +518,8 @@ detected:
 		return 0;
 
 failed:
-	printk("VFS: could not find a valid V7 on %s.\n", sb->s_id);
+	printk(KERN_ERR "VFS: could not find a valid V7 on %s.\n",
+		sb->s_id);
 	brelse(bh);
 	kfree(sbi);
 	return -EINVAL;

_

#14 lore raw

Re: [PATCH 2/3] [fs/sysv] V7: Adjust sanity checks for some volumes

In reply to Lubomir Rintel

fs/sysv/super.c static int v7_fill_super(struct super_block *sb, void *data, int silent) · line 474

Quoted 6 lines
fs/sysv/super.c +2 -2
 	if (fs16_to_cpu(sbi, v7sb->s_nfree) > V7_NICFREE ||
 	    fs16_to_cpu(sbi, v7sb->s_ninode) > V7_NICINOD ||
-	    fs32_to_cpu(sbi, v7sb->s_time) == 0)
-		goto failed;
+	    fs32_to_cpu(sbi, v7sb->s_fsize) > V7_MAXSIZE)
+		return 0;

Ok.

fs/sysv/super.c static int v7_fill_super(struct super_block *sb, void *data, int silent) · line 485

Quoted 7 lines
fs/sysv/super.c +3 -1
 	v7i = (struct sysv_inode *)(bh2->b_data + 64);
 	if ((fs16_to_cpu(sbi, v7i->i_mode) & ~0777) != S_IFDIR ||
 	    (fs32_to_cpu(sbi, v7i->i_size) == 0) ||
-	    (fs32_to_cpu(sbi, v7i->i_size) & 017) != 0)
+	    (fs32_to_cpu(sbi, v7i->i_size) & 017)
+	    (fs32_to_cpu(sbi, v7i->i_size) > V7_NFILES *
+	     sizeof (struct sysv_dir_entry))) {

Maybe I'm missing something, but without and additional || on the first line you added this doesn't look like it will compile.

#15 lore raw

Re: [PATCH 2/3] [fs/sysv] V7: Adjust sanity checks for some volumes

Quoted 10 lines · Christoph Hellwig

fs/sysv/super.c static int v7_fill_super(struct super_block *sb, void *data, int silent) · line 485

Quoted 7 lines
fs/sysv/super.c +3 -1
 	v7i = (struct sysv_inode *)(bh2->b_data + 64);
 	if ((fs16_to_cpu(sbi, v7i->i_mode) & ~0777) != S_IFDIR ||
 	    (fs32_to_cpu(sbi, v7i->i_size) == 0) ||
-	    (fs32_to_cpu(sbi, v7i->i_size) & 017) != 0)
+	    (fs32_to_cpu(sbi, v7i->i_size) & 017)
+	    (fs32_to_cpu(sbi, v7i->i_size) > V7_NFILES *
+	     sizeof (struct sysv_dir_entry))) {

Maybe I'm missing something, but without and additional || on the first line you added this doesn't look like it will compile.

You're right. In fact this hunk is fixed in a commit that followed it, I probably incorrectly merged the fixups in git (the latter commit also had an useless comment change and such).

I'll follow up with a fixed commit tomorrow, since I'm unable to test it now.

Thanks,
Lubo

Signature · 2 lines
Flash is the Web2.0 version of blink and animated gifs.
                                     -- Stephen Smoogen
#16 lore raw

PATCH 1/1 V7: Adjust sanity checks for some volumes

Newly mkfs-ed filesystems from Seventh Edition have last modification time set to zero, but are otherwise perfectly valid.

Also, tighten up other sanity checks to filter out most filesystems with different bytesex than we're using.

Cc Christoph Hellwig <[email protected]>
---
 fs/sysv/super.c         |    6 ++++--
 include/linux/sysv_fs.h |   11 +++++++++++
 2 files changed, 15 insertions(+), 2 deletions(-)
fs/sysv/super.c +4 -2
index bd8d141..ac7b008 100644
@@ -470,7 +470,7 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent)
 	v7sb = (struct v7_super_block *) bh->b_data;
 	if (fs16_to_cpu(sbi, v7sb->s_nfree) > V7_NICFREE ||
 	    fs16_to_cpu(sbi, v7sb->s_ninode) > V7_NICINOD ||
-	    fs32_to_cpu(sbi, v7sb->s_time) == 0)
+	    fs32_to_cpu(sbi, v7sb->s_fsize) > V7_MAXSIZE)
 		goto failed;
 
 	/* plausibility check on root inode: it is a directory,
@@ -480,7 +480,9 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent)
 	v7i = (struct sysv_inode *)(bh2->b_data + 64);
 	if ((fs16_to_cpu(sbi, v7i->i_mode) & ~0777) != S_IFDIR ||
 	    (fs32_to_cpu(sbi, v7i->i_size) == 0) ||
-	    (fs32_to_cpu(sbi, v7i->i_size) & 017) != 0)
+	    (fs32_to_cpu(sbi, v7i->i_size) & 017) ||
+	    (fs32_to_cpu(sbi, v7i->i_size) > V7_NFILES *
+	     sizeof (struct sysv_dir_entry)))
 		goto failed;
 	brelse(bh2);
 	bh2 = NULL;
include/linux/sysv_fs.h +11 -0
index 9641130..e47d6d9 100644
@@ -148,6 +148,17 @@ struct v7_super_block {
 	char    s_fname[6];     /* file system name */
 	char    s_fpack[6];     /* file system pack name */
 };
+/* Constants to aid sanity checking */
+/* This is not a hard limit, nor enforced by v7 kernel. It's actually just
+ * the limit used by Seventh Edition's ls, though is high enough to assume
+ * that no reasonable file system would have that much entries in root
+ * directory. Thus, if we see anything higher, we just probably got the
+ * endiannes wrong. */
+#define V7_NFILES	1024
+/* The disk addresses are three-byte (despite direct block addresses being
+ * aligned word-wise in inode). If the most significant byte is non-zero,
+ * something is most likely wrong (not a filesystem, bad bytesex). */
+#define V7_MAXSIZE	0x00ffffff
 
 /* Coherent super-block data on disk */
 #define COH_NICINOD	100	/* number of inode cache entries */
Signature · 1 line
1.7.1
#18 lore raw
In reply to Lubomir Rintel
Quoted 2 lines · Lubomir Rintel

I'm resending these once again, since I suspect they may have gotten lost in a spam filter due to improper MTA configuration of mine.

Yes, I don't think I got them before.

#19 lore raw
In reply to Lubomir Rintel
Quoted 6 lines · Lubomir Rintel

I'm resending these once again, since I suspect they may have gotten lost in a spam filter due to improper MTA configuration of mine.

They basically improve usability of PC v7 filesystems; such as those of PC/IX.

I remember PC/IX fondly, I had people using it on an old XT for data entry. Wish I still had an install kit, I bet the AT version would install nicely in a VM. Would be a good teaching tool.

Signature · 3 lines
Bill Davidsen <[email protected]>
  "We have more to fear from the bungling of the incompetent than from
the machinations of the wicked."  - from Slashdot
#20 lore raw
In reply to Lubomir Rintel
Quoted 5 lines · Lubomir Rintel

I'm resending these once again, since I suspect they may have gotten lost in a spam filter due to improper MTA configuration of mine.

They basically improve usability of PC v7 filesystems; such as those of PC/IX.

Hi, do you by any chance know where I can find some docs about what we have in fs/sysv ? I saw issues there, but could not fix them because I could not find any docs. There are several flavors of FSes which fs/sysv supports, do you have anything which makes sense out of it and describes what exactly we support, what are the differences, what is the FS layout, etc.

Thanks.

Signature · 2 lines
Best Regards,
Artem Bityutskiy (Артём Битюцкий)