lkml.org 
[lkml]   [2004]   [Oct]   [19]   [last100]   RSS Feed
Views: [more markup]  [less markup]  [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
DateTue, 19 Oct 2004 09:21:38 +0100
FromAlex Kiernan <>
SubjectRe: Submitting patches for unmaintained areas (Solaris x86 UFS bug)
On Mon, 18 Oct 2004 11:20:16 +0100, Alex Kiernan <alex.kiernan@gmail.com> wrote:
> On Fri, 15 Oct 2004 17:35:50 +0100, Alex Kiernan <alex.kiernan@gmail.com> wrote:
> 
> 
> > On Wed, 13 Oct 2004 14:43:51 +0100,
> > viro@parcelfarce.linux.theplanet.co.uk
> > <viro@parcelfarce.linux.theplanet.co.uk> wrote:
> > > On Wed, Oct 13, 2004 at 01:10:10PM +0100, Alex Kiernan wrote:
> > >
> > >
> > > > On Wed, 13 Oct 2004 12:06:29 +0100, Alex Kiernan <alex.kiernan@gmail.com> wrote:
> > > > > I've run into a bug in the UFS reading code (on Solaris x86 the
> > > > > major/minor numbers are in 2nd indirect offset not the first), so I've
> > > > > patched it & bugzilled it
> > > > > (http://bugzilla.kernel.org/show_bug.cgi?id=3475).
> > > > >
> > > > > But where do I go from here? There doesn't seem to be a maintainer for
> > > > > UFS so I can't send it there.
> > > > >
> > > >
> > > > After advice from Alan (thanks), here's the patch which addresses the
> > > > problem I'm seeing. Specifically it appears that on x86 Solaris stores
> > > > the major/minor device numbers in the 2nd indirect block, not the
> > > > first.
> > >
> > > 1) please, move old_encode_dev()/old_decode_dev() into your helper functions.
> >
> > Will do.
> >
> > > 2) we could do a bit better now that we have large dev_t.  What are complete
> > > rules for
> > >         a) Solaris userland dev_t => on-disk data
> > >         b) major/minor => Solaris userland dev_t
> > > on sparc and x86 Solaris?
> > >
> >
> > Assuming I've followed it right...
> >
> > The kernel dev_t has 14 major device bits, 18 minor device bits (with
> > the major as the most significant bits).
> >
> > On disk there are 32 bits stored in host byte order, the device is in
> > the [0] indirect offset on Sparc, [1] on x86.
> >
> > Looking at an individual entry, if the top 16 bits are clear or
> > 0xffff, then the bottom 16 bits are the device number, with 7 bits of
> > major (most significant), 8 bits of minor (and the most significant
> > bit unused). If the top 16 bits are some other pattern, the on disk
> > mapping is the same as the kernel mapping.
> >
> 
> Attached is code to implement the code move of old_decode_dev and
> support for large dev_t (Solaris' own handling of this seems to be
> dodgy in the extreme). I've checked Solaris x86/sparc w/ both types of
> dev_t encoding for reading. I haven't checked writing as the code to
> detect clean filesystems seems to be bust for Solaris UFS filesystems.
> I'll have a look at whats wrong w/ it when I've a bit more time.
> 

The same functionality again:

Fix handling of device inodes on Solaris x86 filesystems, add support
for large dev_t against Solaris UFS filesystems

but with the helper functions moved out of inline code.

-- 
Alex Kiernan
diff -xSCCS -x'*.cmd' -x'*.o' -ur linus-2.5/fs/ufs/inode.c linux-2.5/fs/ufs/inode.c
--- linus-2.5/fs/ufs/inode.c	2004-10-13 15:04:04.000000000 +0100
+++ linux-2.5/fs/ufs/inode.c	2004-10-13 15:44:05.000000000 +0100
@@ -629,7 +629,7 @@
 		}
 	} else
 		init_special_inode(inode, inode->i_mode,
-			old_decode_dev(fs32_to_cpu(sb, ufsi->i_u1.i_data[0])));
+			ufs_get_inode_dev(sb, ufsi));
 
 	brelse (bh);
 
@@ -705,7 +705,7 @@
 		}
 	} else   /* TODO  : here ...*/
 		init_special_inode(inode, inode->i_mode,
-			old_decode_dev(fs32_to_cpu(sb, ufsi->i_u1.i_data[0])));
+			ufs_get_inode_dev(sb, ufsi));
 
 	brelse(bh);
 
diff -xSCCS -x'*.cmd' -x'*.o' -ur linus-2.5/fs/ufs/namei.c linux-2.5/fs/ufs/namei.c
--- linus-2.5/fs/ufs/namei.c	2004-10-13 15:04:04.000000000 +0100
+++ linux-2.5/fs/ufs/namei.c	2004-10-13 14:58:23.000000000 +0100
@@ -30,6 +30,7 @@
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include "swab.h"	/* will go away - see comment in mknod() */
+#include "util.h"
 
 /*
 #undef UFS_NAMEI_DEBUG
@@ -125,8 +126,7 @@
 	if (!IS_ERR(inode)) {
 		init_special_inode(inode, mode, rdev);
 		/* NOTE: that'll go when we get wide dev_t */
-		UFS_I(inode)->i_u1.i_data[0] = cpu_to_fs32(inode->i_sb,
-							old_encode_dev(rdev));
+		ufs_set_inode_dev(inode->i_sb, UFS_I(inode), rdev);
 		mark_inode_dirty(inode);
 		lock_kernel();
 		err = ufs_add_nondir(dentry, inode);
Only in linux-2.5/fs/ufs: ufs.ko
Only in linux-2.5/fs/ufs: ufs.mod.c
diff -xSCCS -x'*.cmd' -x'*.o' -ur linus-2.5/fs/ufs/util.c linux-2.5/fs/ufs/util.c
--- linus-2.5/fs/ufs/util.c	2004-10-13 15:04:04.000000000 +0100
+++ linux-2.5/fs/ufs/util.c	2004-10-19 04:48:20.000000000 +0100
@@ -202,3 +202,56 @@
 		bhno++;
 	}
 }
+
+dev_t
+ufs_get_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi)
+{
+	__fs32 fs32;
+	dev_t dev;
+
+	if ((UFS_SB(sb)->s_flags & UFS_ST_MASK) == UFS_ST_SUNx86)
+		fs32 = ufsi->i_u1.i_data[1];
+	else
+		fs32 = ufsi->i_u1.i_data[0];
+	fs32 = fs32_to_cpu(sb, fs32);
+	switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
+	case UFS_ST_SUNx86:
+	case UFS_ST_SUN:
+		if ((fs32 & 0xffff0000) == 0 ||
+		    (fs32 & 0xffff0000) == 0xffff0000)
+			dev = old_decode_dev(fs32 & 0x7fff);
+		else
+			dev = MKDEV(sysv_major(fs32), sysv_minor(fs32));
+		break;
+
+	default:
+		dev = old_decode_dev(fs32);
+		break;
+	}
+	return dev;
+}
+
+void
+ufs_set_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi, dev_t dev)
+{
+	__fs32 fs32;
+
+	switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
+	case UFS_ST_SUNx86:
+	case UFS_ST_SUN:
+		fs32 = sysv_encode_dev(dev);
+		if ((fs32 & 0xffff8000) == 0) {
+			fs32 = old_encode_dev(dev);
+		}
+		break;
+
+	default:
+		fs32 = old_encode_dev(dev);
+		break;
+	}
+	fs32 = cpu_to_fs32(sb, fs32);
+	if ((UFS_SB(sb)->s_flags & UFS_ST_MASK) == UFS_ST_SUNx86)
+		ufsi->i_u1.i_data[1] = fs32;
+	else
+		ufsi->i_u1.i_data[0] = fs32;
+}
diff -xSCCS -x'*.cmd' -x'*.o' -ur linus-2.5/fs/ufs/util.h linux-2.5/fs/ufs/util.h
--- linus-2.5/fs/ufs/util.h	2004-10-13 15:04:04.000000000 +0100
+++ linux-2.5/fs/ufs/util.h	2004-10-19 05:02:39.000000000 +0100
@@ -223,6 +223,8 @@
 	inode->ui_u1.oldids.ui_sgid =  cpu_to_fs16(sb, value);
 }
 
+extern dev_t ufs_get_inode_dev(struct super_block *, struct ufs_inode_info *);
+extern void ufs_set_inode_dev(struct super_block *, struct ufs_inode_info *, dev_t);
 
 /*
  * These functions manipulate ufs buffers
\
 
 \ /
  Last update: 2005-03-22 14:07    [from the cache]
©2003-2008