lkml.org 
[lkml]   [2004]   [Oct]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectRe: Submitting patches for unmaintained areas (Solaris x86 UFS bug)
    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.

    Because of the different Solaris/Linux large dev encodings, what
    should I be doing in get/set inode_dev when the required things won't
    fit?

    --
    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.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-18 11:12:52.002280119 +0100
    @@ -223,6 +223,58 @@
    inode->ui_u1.oldids.ui_sgid = cpu_to_fs16(sb, value);
    }

    +static inline 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;
    +}
    +
    +static inline 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;
    +}

    /*
    * These functions manipulate ufs buffers
    \
     
     \ /
      Last update: 2005-03-22 14:07    [W:0.036 / U:28.752 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site