diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-03-17 22:05:47 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-03-17 22:05:47 +0000 |
commit | 27cfca1ec98e91261b1a5355d10a8996464b63af (patch) | |
tree | 8e895a53e372fa682b4c0a585b9377d67ed70d0e /fs/ufs | |
parent | 6a76fb7214c477ccf6582bd79c5b4ccc4f9c41b1 (diff) |
Look Ma' what I found on my harddisk ...
o New faster syscalls for 2.1.x, too
o Upgrade to 2.1.89.
Don't try to run this. It's flaky as hell. But feel free to debug ...
Diffstat (limited to 'fs/ufs')
-rw-r--r-- | fs/ufs/.cvsignore | 1 | ||||
-rw-r--r-- | fs/ufs/ufs_dir.c | 32 | ||||
-rw-r--r-- | fs/ufs/ufs_inode.c | 116 | ||||
-rw-r--r-- | fs/ufs/ufs_namei.c | 86 | ||||
-rw-r--r-- | fs/ufs/ufs_super.c | 221 | ||||
-rw-r--r-- | fs/ufs/ufs_swab.c | 56 | ||||
-rw-r--r-- | fs/ufs/ufs_swab.h | 84 | ||||
-rw-r--r-- | fs/ufs/ufs_symlink.c | 32 |
8 files changed, 410 insertions, 218 deletions
diff --git a/fs/ufs/.cvsignore b/fs/ufs/.cvsignore index 4671378ae..857dd22e9 100644 --- a/fs/ufs/.cvsignore +++ b/fs/ufs/.cvsignore @@ -1 +1,2 @@ .depend +.*.flags diff --git a/fs/ufs/ufs_dir.c b/fs/ufs/ufs_dir.c index c64f38684..e6d27c217 100644 --- a/fs/ufs/ufs_dir.c +++ b/fs/ufs/ufs_dir.c @@ -8,6 +8,9 @@ * * swab support by Francois-Rene Rideau <rideau@ens.fr> 19970406 * + * 4.4BSD (FreeBSD) support added on February 1st 1998 by + * Niels Kristian Bech Jensen <nkbj@image.dk> partially based + * on code by Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>. */ #include <linux/fs.h> @@ -28,17 +31,18 @@ ufs_readdir (struct file * filp, void * dirent, filldir_t filldir) struct ufs_direct * de; struct super_block * sb; int de_reclen; - __u32 s_flags, bytesex; + __u32 flags; - /* Isn't that already done but the upper layer??? */ + /* Isn't that already done in the upper layer??? + * the VFS layer really needs some explicit documentation! + */ if (!inode || !S_ISDIR(inode->i_mode)) return -EBADF; sb = inode->i_sb; - s_flags = sb->u.ufs_sb.s_flags; - bytesex = s_flags & UFS_BYTESEX; + flags = sb->u.ufs_sb.s_flags; - if (s_flags & UFS_DEBUG) { + if (flags & UFS_DEBUG) { printk("ufs_readdir: ino %lu f_pos %lu\n", inode->i_ino, (unsigned long) filp->f_pos); ufs_print_inode(inode); @@ -92,20 +96,23 @@ revalidate: && offset < sb->s_blocksize) { de = (struct ufs_direct *) (bh->b_data + offset); /* XXX - put in a real ufs_check_dir_entry() */ - if ((de->d_reclen == 0) || (de->d_namlen == 0)) { + if ((de->d_reclen == 0) || (NAMLEN(de) == 0)) { /* SWAB16() was unneeded -- compare to 0 */ - filp->f_pos = (filp->f_pos & (sb->s_blocksize - 1)) + sb->s_blocksize; + filp->f_pos = (filp->f_pos & + (sb->s_blocksize - 1)) + + sb->s_blocksize; brelse(bh); return stored; } -#if 0 +#if 0 /* XXX */ if (!ext2_check_dir_entry ("ext2_readdir", inode, de, /* XXX - beware about de having to be swabped somehow */ bh, offset)) { /* On error, skip the f_pos to the next block. */ - filp->f_pos = (filp->f_pos & (sb->s_blocksize - 1)) - + sb->s_blocksize; + filp->f_pos = (filp->f_pos & + (sb->s_blocksize - 1)) + + sb->s_blocksize; brelse (bh); return stored; } @@ -121,11 +128,12 @@ revalidate: * during the copy operation. */ unsigned long version = inode->i_version; - if (s_flags & UFS_DEBUG) { + if (flags & UFS_DEBUG) { printk("ufs_readdir: filldir(%s,%u)\n", de->d_name, SWAB32(de->d_ino)); } - error = filldir(dirent, de->d_name, SWAB16(de->d_namlen), filp->f_pos, SWAB32(de->d_ino)); + error = filldir(dirent, de->d_name, NAMLEN(de), + filp->f_pos, SWAB32(de->d_ino)); if (error) break; if (version != inode->i_version) diff --git a/fs/ufs/ufs_inode.c b/fs/ufs/ufs_inode.c index 75329c584..2011a0be8 100644 --- a/fs/ufs/ufs_inode.c +++ b/fs/ufs/ufs_inode.c @@ -9,8 +9,18 @@ * Clean swab support on 19970406 * by Francois-Rene Rideau <rideau@ens.fr> * + * 4.4BSD (FreeBSD) support added on February 1st 1998 by + * Niels Kristian Bech Jensen <nkbj@image.dk> partially based + * on code by Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>. + * + * NeXTstep support added on February 5th 1998 by + * Niels Kristian Bech Jensen <nkbj@image.dk>. */ +#undef DEBUG_UFS_INODE +/*#define DEBUG_UFS_INODE 1*/ +/* Uncomment the line above when hacking ufs inode code */ + #include <linux/fs.h> #include <linux/ufs_fs.h> #include <linux/sched.h> @@ -25,29 +35,30 @@ void ufs_print_inode(struct inode * inode) inode->i_gid, inode->i_size, inode->i_blocks, inode->i_count); printk(" db <0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x" " 0x%x 0x%x 0x%x 0x%x>\n", - inode->u.ufs_i.i_data[0], inode->u.ufs_i.i_data[1], - inode->u.ufs_i.i_data[2], inode->u.ufs_i.i_data[3], - inode->u.ufs_i.i_data[4], inode->u.ufs_i.i_data[5], - inode->u.ufs_i.i_data[6], inode->u.ufs_i.i_data[7], - inode->u.ufs_i.i_data[8], inode->u.ufs_i.i_data[9], - inode->u.ufs_i.i_data[10], inode->u.ufs_i.i_data[11]); + inode->u.ufs_i.i_u1.i_data[0], inode->u.ufs_i.i_u1.i_data[1], + inode->u.ufs_i.i_u1.i_data[2], inode->u.ufs_i.i_u1.i_data[3], + inode->u.ufs_i.i_u1.i_data[4], inode->u.ufs_i.i_u1.i_data[5], + inode->u.ufs_i.i_u1.i_data[6], inode->u.ufs_i.i_u1.i_data[7], + inode->u.ufs_i.i_u1.i_data[8], inode->u.ufs_i.i_u1.i_data[9], + inode->u.ufs_i.i_u1.i_data[10], inode->u.ufs_i.i_u1.i_data[11]); printk(" gen 0x%8.8x ib <0x%x 0x%x 0x%x>\n", inode->u.ufs_i.i_gen, - inode->u.ufs_i.i_data[UFS_IND_BLOCK], - inode->u.ufs_i.i_data[UFS_DIND_BLOCK], - inode->u.ufs_i.i_data[UFS_TIND_BLOCK]); + inode->u.ufs_i.i_u1.i_data[UFS_IND_BLOCK], + inode->u.ufs_i.i_u1.i_data[UFS_DIND_BLOCK], + inode->u.ufs_i.i_u1.i_data[UFS_TIND_BLOCK]); } -#define inode_bmap(inode, nr) ((inode)->u.ufs_i.i_data[(nr)]) +#define inode_bmap(inode, nr) ((inode)->u.ufs_i.i_u1.i_data[(nr)]) static inline int block_bmap (struct inode *inode, int block, int nr) { struct buffer_head *bh; int tmp; - __u32 bytesex = inode->i_sb->u.ufs_sb.s_flags & UFS_BYTESEX; + __u32 flags = inode->i_sb->u.ufs_sb.s_flags; /* XXX Split in fsize big blocks (Can't bread 8Kb). */ tmp = nr >> (inode->i_sb->u.ufs_sb.s_fshift - 2); - bh = bread (inode->i_dev, block + tmp, inode->i_sb->u.ufs_sb.s_fsize); + bh = bread (inode->i_dev, inode->i_sb->u.ufs_sb.s_blockbase + block + + tmp, inode->i_sb->s_blocksize); if (!bh) return 0; nr &= ~(inode->i_sb->u.ufs_sb.s_fmask) >> 2; @@ -75,13 +86,16 @@ int ufs_bmap (struct inode * inode, int block) return 0; } if (lbn < UFS_NDADDR) - return ufs_dbn (inode->i_sb, inode_bmap (inode, lbn), boff); + return (inode->i_sb->u.ufs_sb.s_blockbase + + ufs_dbn (inode->i_sb, inode_bmap (inode, lbn), boff)); lbn -= UFS_NDADDR; if (lbn < addr_per_block) { i = inode_bmap (inode, UFS_IND_BLOCK); if (!i) return 0; - return ufs_dbn (inode->i_sb, block_bmap (inode, i, lbn), boff); + return (inode->i_sb->u.ufs_sb.s_blockbase + + ufs_dbn (inode->i_sb, + block_bmap (inode, i, lbn), boff)); } lbn -= addr_per_block; if (lbn < (1 << (addr_per_block_bits * 2))) { @@ -91,9 +105,10 @@ int ufs_bmap (struct inode * inode, int block) i = block_bmap (inode, i, lbn >> addr_per_block_bits); if (!i) return 0; - return ufs_dbn (inode->i_sb, + return (inode->i_sb->u.ufs_sb.s_blockbase + + ufs_dbn (inode->i_sb, block_bmap (inode, i, lbn & (addr_per_block-1)), - boff); + boff)); } lbn -= (1 << (addr_per_block_bits * 2)); i = inode_bmap (inode, UFS_TIND_BLOCK); @@ -106,8 +121,9 @@ int ufs_bmap (struct inode * inode, int block) (lbn >> addr_per_block_bits) & (addr_per_block - 1)); if (!i) return 0; - return ufs_dbn (inode->i_sb, - block_bmap (inode, i, lbn & (addr_per_block-1)), boff); + return (inode->i_sb->u.ufs_sb.s_blockbase + + ufs_dbn (inode->i_sb, + block_bmap (inode, i, lbn & (addr_per_block-1)), boff)); } /* XXX - ufs_read_inode is a mess */ @@ -116,28 +132,30 @@ void ufs_read_inode(struct inode * inode) struct super_block * sb; struct ufs_inode * ufsip; struct buffer_head * bh; - __u32 bytesex = inode->i_sb->u.ufs_sb.s_flags & UFS_BYTESEX; + __u32 flags = inode->i_sb->u.ufs_sb.s_flags; sb = inode->i_sb; if (ufs_ino_ok(inode)) { - printk("ufs_read_inode: bad inum %lu", inode->i_ino); + printk("ufs_read_inode: bad inum %lu\n", inode->i_ino); return; } -#if 0 +#ifdef DEBUG_UFS_INODE printk("ufs_read_inode: ino %lu cg %u cgino %u ipg %u inopb %u\n", inode->i_ino, ufs_ino2cg(inode), (inode->i_ino%sb->u.ufs_sb.s_inopb), sb->u.ufs_sb.s_ipg, sb->u.ufs_sb.s_inopb); #endif bh = bread(inode->i_dev, + inode->i_sb->u.ufs_sb.s_blockbase + ufs_cgimin(inode->i_sb, ufs_ino2cg(inode)) + - (inode->i_ino%sb->u.ufs_sb.s_ipg)/(sb->u.ufs_sb.s_inopb/sb->u.ufs_sb.s_fsfrag), - BLOCK_SIZE); + (inode->i_ino%sb->u.ufs_sb.s_ipg)/ + (sb->u.ufs_sb.s_inopb/sb->u.ufs_sb.s_fsfrag), + sb->s_blocksize); if (!bh) { - printk("ufs_read_inode: can't read inode %lu from dev %d/%d", + printk("ufs_read_inode: can't read inode %lu from dev %d/%d\n", inode->i_ino, MAJOR(inode->i_dev), MINOR(inode->i_dev)); return; } @@ -176,23 +194,21 @@ void ufs_read_inode(struct inode * inode) * random users can't get at these files, since they get dynamically * "chown()ed" to root. */ - if (SWAB16(ufsip->ui_suid) == UFS_USEEFT) { - /* EFT */ + if (UFS_UID(ufsip) >= UFS_USEEFT) { inode->i_uid = 0; printk("ufs_read_inode: EFT uid %u ino %lu dev %u/%u, using %u\n", - SWAB32(ufsip->ui_uid), inode->i_ino, MAJOR(inode->i_dev), MINOR(inode->i_dev), - inode->i_uid); + UFS_UID(ufsip), inode->i_ino, MAJOR(inode->i_dev), + MINOR(inode->i_dev), inode->i_uid); } else { - inode->i_uid = SWAB16(ufsip->ui_suid); + inode->i_uid = UFS_UID(ufsip); } - if (SWAB16(ufsip->ui_sgid) == UFS_USEEFT) { - /* EFT */ + if (UFS_GID(ufsip) >= UFS_USEEFT) { inode->i_gid = 0; printk("ufs_read_inode: EFT gid %u ino %lu dev %u/%u, using %u\n", - SWAB32(ufsip->ui_gid), inode->i_ino, MAJOR(inode->i_dev), MINOR(inode->i_dev), - inode->i_gid); + UFS_GID(ufsip), inode->i_ino, MAJOR(inode->i_dev), + MINOR(inode->i_dev), inode->i_gid); } else { - inode->i_gid = SWAB16(ufsip->ui_sgid); + inode->i_gid = UFS_GID(ufsip); } /* @@ -249,13 +265,19 @@ void ufs_read_inode(struct inode * inode) S_ISLNK(inode->i_mode)) { int i; - for (i = 0; i < UFS_NDADDR; i++) { - inode->u.ufs_i.i_data[i] = SWAB32(ufsip->ui_db[i]); - } - for (i = 0; i < UFS_NINDIR; i++) { - inode->u.ufs_i.i_data[UFS_IND_BLOCK + i] = - SWAB32(ufsip->ui_ib[i]); - } + if (inode->i_blocks) { + for (i = 0; i < UFS_NDADDR; i++) { + inode->u.ufs_i.i_u1.i_data[i] = + SWAB32(ufsip->ui_u2.ui_addr.ui_db[i]); + } + for (i = 0; i < UFS_NINDIR; i++) { + inode->u.ufs_i.i_u1.i_data[UFS_IND_BLOCK + i] = + SWAB32(ufsip->ui_u2.ui_addr.ui_ib[i]); + } + } else /* fast symlink */ { + memcpy(inode->u.ufs_i.i_u1.i_symlink, + ufsip->ui_u2.ui_symlink, 60); + } } /* KRR - I need to check the SunOS header files, but for the time @@ -265,17 +287,15 @@ void ufs_read_inode(struct inode * inode) * the code. */ if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { - inode->i_rdev = (kdev_t)SWAB64(*(__u64*)&ufsip->ui_db); + inode->i_rdev = (kdev_t)SWAB64(*(__u64*)&ufsip->ui_u2.ui_addr.ui_db); } - /* XXX - implement fast and slow symlinks */ - inode->u.ufs_i.i_flags = SWAB32(ufsip->ui_flags); inode->u.ufs_i.i_gen = SWAB32(ufsip->ui_gen); /* XXX - is this i_version? */ - inode->u.ufs_i.i_shadow = SWAB32(ufsip->ui_shadow); /* XXX */ - inode->u.ufs_i.i_uid = SWAB32(ufsip->ui_uid); - inode->u.ufs_i.i_gid = SWAB32(ufsip->ui_gid); - inode->u.ufs_i.i_oeftflag = SWAB32(ufsip->ui_oeftflag); + inode->u.ufs_i.i_shadow = SWAB32(ufsip->ui_u3.ui_sun.ui_shadow); /* XXX */ + inode->u.ufs_i.i_uid = SWAB32(ufsip->ui_u3.ui_sun.ui_uid); + inode->u.ufs_i.i_gid = SWAB32(ufsip->ui_u3.ui_sun.ui_gid); + inode->u.ufs_i.i_oeftflag = SWAB32(ufsip->ui_u3.ui_sun.ui_oeftflag); brelse(bh); diff --git a/fs/ufs/ufs_namei.c b/fs/ufs/ufs_namei.c index 6cf8c6c39..021b85442 100644 --- a/fs/ufs/ufs_namei.c +++ b/fs/ufs/ufs_namei.c @@ -9,6 +9,9 @@ * Clean swab support by Francois-Rene Rideau <rideau@ens.fr> 19970406 * Ported to 2.1.62 by Francois-Rene Rideau <rideau@ens.fr> 19971109 * + * 4.4BSD (FreeBSD) support added on February 1st 1998 by + * Niels Kristian Bech Jensen <nkbj@image.dk> partially based + * on code by Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>. */ #include <linux/fs.h> @@ -17,20 +20,21 @@ #include "ufs_swab.h" /* - * NOTE! unlike strncmp, ext2_match returns 1 for success, 0 for failure. - * stolen from ext2fs + * NOTE1: unlike strncmp, ufs_match returns 1 for success, 0 for failure + * (stolen from ext2fs.) + * NOTE2: flags *is* used, though this is hidden by macros like NAMLEN. */ -static int ufs_match (int len, const char * const name, struct ufs_direct * d, __u32 bytesex) +static int ufs_match (int len, const char * const name, struct ufs_direct * d, __u32 flags) { if (!d || len > UFS_MAXNAMLEN) /* XXX - name space */ return 0; /* * "" means "." ---> so paths like "/usr/lib//libc.a" work */ - if (!len && (SWAB16(d->d_namlen) == 1) && (d->d_name[0] == '.') && + if (!len && (NAMLEN(d) == 1) && (d->d_name[0] == '.') && (d->d_name[1] == '\0')) return 1; - if (len != SWAB16(d->d_namlen)) + if (len != NAMLEN(d)) return 0; return !memcmp(name, d->d_name, len); } @@ -38,89 +42,88 @@ static int ufs_match (int len, const char * const name, struct ufs_direct * d, _ int ufs_lookup (struct inode *dir, struct dentry *dentry) { /* XXX - this is all fucked up! */ - /* XXX - and it's been broken since linux has this new dentry interface: - * allows reading of files, but screws the whole dcache, even outside - * of the ufs partition, so that umount'ing won't suffice to fix it -- - * reboot needed - */ unsigned long int lfragno, fragno; struct buffer_head * bh; struct ufs_direct * d; + struct super_block * sb = dir->i_sb; const char *name = dentry->d_name.name; int len = dentry->d_name.len; - __u32 bytesex; + __u32 flags; struct inode *inode; /* XXX - isn't that already done by the upper layer? */ if (!dir || !S_ISDIR(dir->i_mode)) return -EBADF; - bytesex = dir->i_sb->u.ufs_sb.s_flags & UFS_BYTESEX; + flags = sb->u.ufs_sb.s_flags; - if (dir->i_sb->u.ufs_sb.s_flags & UFS_DEBUG) + if (flags & UFS_DEBUG) printk("Passed name: %s\nPassed length: %d\n", name, len); - /* debugging hacks: * Touching /xyzzy in a filesystem toggles debugging messages. */ if ((len == 5) && !(memcmp(name, "xyzzy", len)) && (dir->i_ino == UFS_ROOTINO)) { - dir->i_sb->u.ufs_sb.s_flags ^= UFS_DEBUG; + sb->u.ufs_sb.s_flags ^= UFS_DEBUG; printk("UFS debugging %s\n", - (dir->i_sb->u.ufs_sb.s_flags & UFS_DEBUG) ? + (sb->u.ufs_sb.s_flags & UFS_DEBUG) ? "on": "off"); goto not_found; /*return(-ENOENT);*/ } /* - * Touching /xyzzy.i in a filesystem toggles debugging for ufs_inode.c. + * Touching /xyzzy.i in a filesystem toggles debugging for ufs_inode.c */ if ((len == 7) && !(memcmp(name, "xyzzy.i", len)) && (dir->i_ino == UFS_ROOTINO)) { - dir->i_sb->u.ufs_sb.s_flags ^= UFS_DEBUG_INODE; + sb->u.ufs_sb.s_flags ^= UFS_DEBUG_INODE; printk("UFS inode debugging %s\n", - (dir->i_sb->u.ufs_sb.s_flags & UFS_DEBUG_INODE) ? + (sb->u.ufs_sb.s_flags & UFS_DEBUG_INODE) ? "on": "off"); goto not_found; /*return(-ENOENT);*/ } + /* + * Touching /xyzzy.n in a filesystem toggles debugging for ufs_namei.c + */ if ((len == 7) && !(memcmp(name, "xyzzy.n", len)) && (dir->i_ino == UFS_ROOTINO)) { - dir->i_sb->u.ufs_sb.s_flags ^= UFS_DEBUG_NAMEI; + sb->u.ufs_sb.s_flags ^= UFS_DEBUG_NAMEI; printk("UFS namei debugging %s\n", - (dir->i_sb->u.ufs_sb.s_flags & UFS_DEBUG_NAMEI) ? + (sb->u.ufs_sb.s_flags & UFS_DEBUG_NAMEI) ? "on": "off"); goto not_found; /*return(-ENOENT);*/ } + /* + * Touching /xyzzy.l in a filesystem toggles debugging for ufs_symlink.c + */ if ((len == 7) && !(memcmp(name, "xyzzy.l", len)) && (dir->i_ino == UFS_ROOTINO)) { - dir->i_sb->u.ufs_sb.s_flags ^= UFS_DEBUG_LINKS; + sb->u.ufs_sb.s_flags ^= UFS_DEBUG_LINKS; printk("UFS symlink debugging %s\n", - (dir->i_sb->u.ufs_sb.s_flags & UFS_DEBUG_LINKS) ? + (sb->u.ufs_sb.s_flags & UFS_DEBUG_LINKS) ? "on": "off"); goto not_found; /*return(-ENOENT);*/ } - /* Now for the real thing */ - if (dir->i_sb->u.ufs_sb.s_flags & (UFS_DEBUG|UFS_DEBUG_NAMEI)) { + if (flags & (UFS_DEBUG|UFS_DEBUG_NAMEI)) { printk("ufs_lookup: called for ino %lu name %s\n", dir->i_ino, name); } - /* XXX - do I want i_blocks in 512-blocks or 1024-blocks? */ - for (lfragno = 0; lfragno < (dir->i_blocks)>>1; lfragno++) { + for (lfragno = 0; lfragno < dir->i_blocks; lfragno++) { fragno = ufs_bmap(dir, lfragno); + /* ufs_bmap() reads the block (frag) size in s_blocksize */ /* XXX - ufs_bmap() call needs error checking */ - /* XXX - s_blocksize is actually the UFS frag size */ - if (dir->i_sb->u.ufs_sb.s_flags & UFS_DEBUG) { + if (flags & UFS_DEBUG) { printk("ufs_lookup: ino %lu lfragno %lu fragno %lu\n", dir->i_ino, lfragno, fragno); } @@ -129,7 +132,7 @@ int ufs_lookup (struct inode *dir, struct dentry *dentry) goto not_found; /*return(-ENOENT);*/ } - bh = bread(dir->i_dev, fragno, dir->i_sb->s_blocksize); + bh = bread(dir->i_dev, fragno, sb->s_blocksize); if (bh == NULL) { printk("ufs_lookup: bread failed: " "ino %lu, lfragno %lu", @@ -138,17 +141,17 @@ int ufs_lookup (struct inode *dir, struct dentry *dentry) } d = (struct ufs_direct *)(bh->b_data); while (((char *)d - bh->b_data + SWAB16(d->d_reclen)) <= - dir->i_sb->s_blocksize) { + sb->s_blocksize) { /* XXX - skip block if d_reclen or d_namlen is 0 */ - if ((d->d_reclen == 0) || (d->d_namlen == 0)) { + if ((d->d_reclen == 0) || (NAMLEN(d) == 0)) { /* no need to SWAB16(): test against 0 */ - if (dir->i_sb->u.ufs_sb.s_flags & UFS_DEBUG) { + if (flags & UFS_DEBUG) { printk("ufs_lookup: skipped space in directory, ino %lu\n", dir->i_ino); } break; } - if (dir->i_sb->u.ufs_sb.s_flags & UFS_DEBUG) { + if (flags & UFS_DEBUG) { printk("lfragno 0x%lx " "direct d 0x%x " "d_ino %u " @@ -158,30 +161,31 @@ int ufs_lookup (struct inode *dir, struct dentry *dentry) (unsigned int)((unsigned long)d), SWAB32(d->d_ino), SWAB16(d->d_reclen), - SWAB16(d->d_namlen),d->d_name); + NAMLEN(d),d->d_name); } - if ((SWAB16(d->d_namlen) == len) && + if ((NAMLEN(d) == len) && /* XXX - don't use strncmp() - see ext2fs */ - (ufs_match(len, name, d, bytesex))) { + (ufs_match(len, name, d, flags))) { /* We have a match */ /* XXX - I only superficially understand how things work, * so use at your own risk... -- Fare' */ - inode = iget(dir->i_sb, SWAB32(d->d_ino)); + inode = iget(sb, SWAB32(d->d_ino)); brelse(bh); if(!inode) { return -EACCES; } d_add(dentry,inode); return(0); } else { /* XXX - bounds checking */ - if (dir->i_sb->u.ufs_sb.s_flags & UFS_DEBUG) { + if (flags & UFS_DEBUG) { printk("ufs_lookup: " "wanted (%s,%d) got (%s,%d)\n", name, len, - d->d_name, SWAB16(d->d_namlen)); + d->d_name, NAMLEN(d)); } } - d = (struct ufs_direct *)((char *)d + SWAB16(d->d_reclen)); + d = (struct ufs_direct *)((char *)d + + SWAB16(d->d_reclen)); } brelse(bh); } diff --git a/fs/ufs/ufs_super.c b/fs/ufs/ufs_super.c index a3c32ccce..6a378fb13 100644 --- a/fs/ufs/ufs_super.c +++ b/fs/ufs/ufs_super.c @@ -19,9 +19,19 @@ * * Clean swab support on 19970406 by * Francois-Rene Rideau <rideau@ens.fr> + * + * 4.4BSD (FreeBSD) support added on February 1st 1998 by + * Niels Kristian Bech Jensen <nkbj@image.dk> partially based + * on code by Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>. + * + * NeXTstep support added on February 5th 1998 by + * Niels Kristian Bech Jensen <nkbj@image.dk>. */ -#include <linux/config.h> +#undef DEBUG_UFS_SUPER +/*#define DEBUG_UFS_SUPER 1*/ +/* Uncomment the line above when hacking ufs superblock code */ + #include <linux/module.h> #include <linux/kernel.h> @@ -42,7 +52,7 @@ static struct super_operations ufs_super_ops = { NULL, /* XXX - ufs_write_inode() */ ufs_put_inode, NULL, /* XXX - ufs_delete_inode() */ - NULL, /* notify_change() */ + NULL, /* XXX - notify_change() */ ufs_put_super, NULL, /* XXX - ufs_write_super() */ ufs_statfs, @@ -89,23 +99,26 @@ void ufs_warning (struct super_block * sb, const char * function, kdevname(sb->s_dev), function, error_buf); } -#if 0 /* unused */ +#ifdef DEBUG_UFS_SUPER static void ufs_print_super_stuff(struct super_block * sb, struct ufs_superblock * usb) { + __u32 flags = sb->u.ufs_sb.s_flags; printk("fs_sblkno: 0x%8.8x\n", usb->fs_sblkno); - printk("fs_size: 0x%8.8x\n", usb->fs_size); - printk("fs_ncg: 0x%8.8x\n", usb->fs_ncg); - printk("fs_bsize: 0x%8.8x\n", usb->fs_bsize); - printk("fs_frag: 0x%8.8x\n", usb->fs_frag); + printk("fs_size: 0x%8.8x\n", usb->fs_size); + printk("fs_ncg: 0x%8.8x\n", usb->fs_ncg); + printk("fs_bsize: 0x%8.8x\n", usb->fs_bsize); + printk("fs_fsize: 0x%8.8x\n", usb->fs_fsize); + printk("fs_frag: 0x%8.8x\n", usb->fs_frag); printk("fs_nindir: 0x%8.8x\n", usb->fs_nindir); - printk("fs_inopb: 0x%8.8x\n", usb->fs_inopb); - printk("fs_optim: 0x%8.8x\n", usb->fs_optim); - printk("fs_ncyl: 0x%8.8x\n", usb->fs_ncyl); - printk("fs_state: 0x%8.8x\n", usb->fs_state); - printk("fs_magic: 0x%8.8x\n", usb->fs_magic); - printk("fs_fsmnt: `%s'\n", usb->fs_fsmnt); + printk("fs_inopb: 0x%8.8x\n", usb->fs_inopb); + printk("fs_optim: 0x%8.8x\n", usb->fs_optim); + printk("fs_ncyl: 0x%8.8x\n", usb->fs_ncyl); + printk("fs_clean: 0x%8.8x\n", usb->fs_clean); + printk("fs_state: 0x%8.8x\n", UFS_STATE(usb)); + printk("fs_magic: 0x%8.8x\n", usb->fs_magic); + printk("fs_fsmnt: `%s'\n", usb->fs_fsmnt); return; } @@ -116,7 +129,9 @@ ufs_read_super(struct super_block * sb, void * data, int silent) { struct ufs_superblock * usb; /* normalized to local byteorder */ struct buffer_head * bh1, *bh2; - __u32 bytesex = 0; + __u32 flags = UFS_DEBUG_INITIAL; /* for sb->u.ufs_sb.s_flags */ + static int offsets[] = { 0, 96, 160 }; /* different superblock locations */ + int i; /* sb->s_dev and sb->s_flags are set by our caller * data is the mystery argument to sys_mount() @@ -127,102 +142,137 @@ ufs_read_super(struct super_block * sb, void * data, int silent) MOD_INC_USE_COUNT; lock_super (sb); + set_blocksize (sb->s_dev, BLOCK_SIZE); /* XXX - make everything read only for testing */ sb->s_flags |= MS_RDONLY; - if (!(bh1 = bread(sb->s_dev, UFS_SBLOCK/BLOCK_SIZE, BLOCK_SIZE)) || - !(bh2 = bread(sb->s_dev, (UFS_SBLOCK + BLOCK_SIZE)/BLOCK_SIZE, - BLOCK_SIZE))) { - brelse(bh1); - printk ("ufs_read_super: unable to read superblock\n"); + for (i = 0; i < sizeof(offsets)/sizeof(offsets[0]); i++) { + if (!(bh1 = bread(sb->s_dev, offsets[i] + UFS_SBLOCK/BLOCK_SIZE, + BLOCK_SIZE)) || + !(bh2 = bread(sb->s_dev, offsets[i] + + UFS_SBLOCK/BLOCK_SIZE + 1, BLOCK_SIZE))) { + brelse(bh1); + printk ("ufs_read_super: unable to read superblock\n"); + goto ufs_read_super_lose; + } + /* XXX - redo this so we can free it later... */ + usb = (struct ufs_superblock *)__get_free_page(GFP_KERNEL); + if (usb == NULL) { + brelse(bh1); + brelse(bh2); + printk ("ufs_read_super: get_free_page() failed\n"); + goto ufs_read_super_lose; + } + + memcpy((char *)usb, bh1->b_data, BLOCK_SIZE); + memcpy((char *)usb + BLOCK_SIZE, bh2->b_data, + sizeof(struct ufs_superblock) - BLOCK_SIZE); - goto ufs_read_super_lose; - } - /* XXX - redo this so we can free it later... */ - usb = (struct ufs_superblock *)__get_free_page(GFP_KERNEL); - if (usb == NULL) { brelse(bh1); brelse(bh2); - printk ("ufs_read_super: get_free_page() failed\n"); - - goto ufs_read_super_lose; - } - memcpy((char *)usb, bh1->b_data, BLOCK_SIZE); - memcpy((char *)usb + BLOCK_SIZE, bh2->b_data, - sizeof(struct ufs_superblock) - BLOCK_SIZE); - - brelse(bh1); - brelse(bh2); - - switch (le32_to_cpup(&usb->fs_magic)) { - case UFS_MAGIC: - bytesex = UFS_LITTLE_ENDIAN; - ufs_superblock_le_to_cpus(usb); - break; - case UFS_CIGAM: - bytesex = UFS_BIG_ENDIAN; - ufs_superblock_be_to_cpus(usb); - break; - /* usb is now normalized to local byteorder */ - default: - printk ("ufs_read_super: bad magic number 0x%8.8x " - "on dev %d/%d\n", usb->fs_magic, - MAJOR(sb->s_dev), MINOR(sb->s_dev)); - goto ufs_read_super_lose; + switch (le32_to_cpup(&usb->fs_magic)) { + case UFS_MAGIC: + flags |= UFS_LITTLE_ENDIAN; + ufs_superblock_le_to_cpus(usb); + goto found; + case UFS_CIGAM: + flags |= UFS_BIG_ENDIAN; + ufs_superblock_be_to_cpus(usb); + goto found; + /* usb is now normalized to local byteorder */ + default: + } } - + printk ("ufs_read_super: bad magic number 0x%8.8x " + "on dev %d/%d\n", usb->fs_magic, + MAJOR(sb->s_dev), MINOR(sb->s_dev)); + goto ufs_read_super_lose; +found: +#ifdef DEBUG_UFS_SUPER + printk("ufs_read_super: superblock offset 0x%2.2x\n", offsets[i]); +#endif /* We found a UFS filesystem on this device. */ /* XXX - parse args */ - if (usb->fs_bsize != UFS_BSIZE) { - printk("ufs_read_super: fs_bsize %d != %d\n", usb->fs_bsize, - UFS_BSIZE); + if ((usb->fs_bsize != 4096) && (usb->fs_bsize != 8192)) { + printk("ufs_read_super: invalid fs_bsize = %d\n", + usb->fs_bsize); goto ufs_read_super_lose; } - if (usb->fs_fsize != UFS_FSIZE) { - printk("ufs_read_super: fs_fsize %d != %d\n", usb->fs_fsize, - UFS_FSIZE); + if ((usb->fs_fsize != 512) && (usb->fs_fsize != 1024)) { + printk("ufs_read_super: invalid fs_fsize = %d\n", + usb->fs_fsize); goto ufs_read_super_lose; } + if (usb->fs_fsize != BLOCK_SIZE) { + set_blocksize (sb->s_dev, usb->fs_fsize); + } + flags |= UFS_VANILLA; + /* XXX more consistency check */ #ifdef DEBUG_UFS_SUPER - printk("ufs_read_super: fs last mounted on \"%s\"\n", usb->fs_fsmnt); + printk("ufs_read_super: maxsymlinklen 0x%8.8x\n", + usb->fs_u.fs_44.fs_maxsymlinklen); #endif + if (usb->fs_u.fs_44.fs_maxsymlinklen >= 0) { + if (usb->fs_u.fs_44.fs_inodefmt >= UFS_44INODEFMT) { + flags |= UFS_44BSD; + } else { + flags |= UFS_OLD; /* 4.2BSD */ + } + } else if (offsets[i] > 0) { + flags |= UFS_NEXT; + } else { + flags |= UFS_SUN; + } - if (usb->fs_state == UFS_FSOK - usb->fs_time) { - switch(usb->fs_clean) { - case UFS_FSCLEAN: #ifdef DEBUG_UFS_SUPER - printk("ufs_read_super: fs is clean\n"); + ufs_print_super_stuff(sb, usb); +#endif + if ( ((flags&UFS_ST_MASK)==UFS_ST_44BSD) + || ((flags&UFS_ST_MASK)==UFS_ST_OLD) + || ((flags&UFS_ST_MASK)==UFS_ST_NEXT) + || ( ((flags&UFS_ST_MASK)==UFS_ST_SUN) + && UFS_STATE(usb) == UFS_FSOK - usb->fs_time)) { + switch(usb->fs_clean) { + case UFS_FSACTIVE: /* 0x00 */ + printk("ufs_read_super: fs is active\n"); + sb->s_flags |= MS_RDONLY; + break; + case UFS_FSCLEAN: /* 0x01 */ +#ifdef DEBUG_UFS_SUPER + printk("ufs_read_super: fs is clean\n"); +#endif + break; + case UFS_FSSTABLE: /* 0x02 */ +#ifdef DEBUG_UFS_SUPER + printk("ufs_read_super: fs is stable\n"); #endif - break; - case UFS_FSSTABLE: + break; + case UFS_FSOSF1: /* 0x03 */ + /* XXX is this correct for DEC OSF/1? */ #ifdef DEBUG_UFS_SUPER - printk("ufs_read_super: fs is stable\n"); + printk("ufs_read_super: fs is clean and stable (OSF/1)\n"); #endif - break; - case UFS_FSACTIVE: - printk("ufs_read_super: fs is active\n"); - sb->s_flags |= MS_RDONLY; - break; - case UFS_FSBAD: - printk("ufs_read_super: fs is bad\n"); - sb->s_flags |= MS_RDONLY; - break; - default: - printk("ufs_read_super: can't grok fs_clean 0x%x\n", - usb->fs_clean); - sb->s_flags |= MS_RDONLY; - break; - } + break; + case UFS_FSBAD: /* 0xFF */ + printk("ufs_read_super: fs is bad\n"); + sb->s_flags |= MS_RDONLY; + break; + default: + printk("ufs_read_super: can't grok fs_clean 0x%x\n", + usb->fs_clean); + sb->s_flags |= MS_RDONLY; + break; + } } else { - printk("ufs_read_super: fs needs fsck\n"); - sb->s_flags |= MS_RDONLY; - /* XXX - make it read only or barf if it's not (/, /usr) */ + printk("ufs_read_super: fs needs fsck\n"); + sb->s_flags |= MS_RDONLY; + /* XXX - make it read only or barf if it's not (/, /usr) */ } /* XXX - sanity check sb fields */ @@ -238,7 +288,7 @@ ufs_read_super(struct super_block * sb, void * data, int silent) /* sb->s_wait */ /* XXX - sb->u.ufs_sb */ sb->u.ufs_sb.s_raw_sb = usb; /* XXX - maybe move this to the top */ - sb->u.ufs_sb.s_flags = bytesex | UFS_DEBUG_INITIAL ; + sb->u.ufs_sb.s_flags = flags ; sb->u.ufs_sb.s_ncg = usb->fs_ncg; sb->u.ufs_sb.s_ipg = usb->fs_ipg; sb->u.ufs_sb.s_fpg = usb->fs_fpg; @@ -257,6 +307,7 @@ ufs_read_super(struct super_block * sb, void * data, int silent) sb->u.ufs_sb.s_lmask = ~((usb->fs_fmask - usb->fs_bmask) >> usb->fs_fshift); sb->u.ufs_sb.s_fsfrag = usb->fs_frag; /* XXX - rename this later */ + sb->u.ufs_sb.s_blockbase = offsets[i]; sb->s_root = d_alloc_root(iget(sb, UFS_ROOTINO), NULL); #ifdef DEBUG_UFS_SUPER @@ -271,6 +322,7 @@ ufs_read_super(struct super_block * sb, void * data, int silent) ufs_read_super_lose: /* XXX - clean up */ + set_blocksize (sb->s_dev, BLOCK_SIZE); sb->s_dev = 0; unlock_super (sb); MOD_DEC_USE_COUNT; @@ -285,6 +337,7 @@ void ufs_put_super (struct super_block * sb) lock_super (sb); /* XXX - sync fs data, set state to ok, and flush buffers */ + set_blocksize (sb->s_dev, BLOCK_SIZE); sb->s_dev = 0; /* XXX - free allocated kernel memory */ diff --git a/fs/ufs/ufs_swab.c b/fs/ufs/ufs_swab.c index 2dc4061a0..261d16de9 100644 --- a/fs/ufs/ufs_swab.c +++ b/fs/ufs/ufs_swab.c @@ -36,6 +36,10 @@ * 2) instead of byteswapping, use [bl]e_to_cpu: * it might be that we run on a VAX! * + * 4.4BSD (FreeBSD) support added on February 1st 1998 by + * Niels Kristian Bech Jensen <nkbj@image.dk> partially based + * on code by Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>. + * * HOWTO continue adding swab support: * basically, anywhere metadata is bread() (i.e. mapped to block device), * data should either be SWAB()ed on the fly, @@ -106,33 +110,69 @@ static __inline__ void n_le32_to_cpus(__u32*p,unsigned n) { /* * Here are the whole-structure swabping routines... + * They were fun to design, but I don't understand why we + * need a copy of the superblock, anyway. -- Fare' */ extern void ufs_superblock_be_to_cpus(struct ufs_superblock * usb) { #ifndef __BIG_ENDIAN + __u16 sb_type = 1; /* SUN type superblock */ + + if (usb->fs_u.fs_44.fs_maxsymlinklen >= 0) + sb_type = 0; /* 4.4BSD (FreeBSD) type superblock */ + be32_to_cpus__between(*usb,fs_link,fs_fmod); /* XXX - I dunno what to do w/ fs_csp, * but it is unused by the current code, so that's ok for now. */ be32_to_cpus(&usb->fs_cpc); - be16_to_cpus__between(*usb,fs_opostbl,fs_sparecon); - be32_to_cpus__between(*usb,fs_sparecon,fs_qbmask); - be64_to_cpus(&usb->fs_qbmask); - be64_to_cpus(&usb->fs_qfmask); + if (sb_type) { + be16_to_cpus__between(*usb,fs_opostbl,fs_u.fs_sun.fs_sparecon); + be32_to_cpus__between(*usb,fs_u.fs_sun.fs_sparecon,fs_u.fs_sun.fs_qbmask); + /* Might fail on strictly aligning 64-bit big-endian + * architectures. Ouch! + */ + be64_to_cpus((__u64 *) &usb->fs_u.fs_sun.fs_qbmask); + be64_to_cpus((__u64 *) &usb->fs_u.fs_sun.fs_qfmask); + } else { + be16_to_cpus__between(*usb,fs_opostbl,fs_u.fs_44.fs_sparecon); + be32_to_cpus__between(*usb,fs_u.fs_sun.fs_sparecon,fs_u.fs_44.fs_maxfilesize); + be64_to_cpus((__u64 *) &usb->fs_u.fs_44.fs_maxfilesize); + be64_to_cpus((__u64 *) &usb->fs_u.fs_44.fs_qbmask); + be64_to_cpus((__u64 *) &usb->fs_u.fs_44.fs_qfmask); + be32_to_cpus((__s32 *) &usb->fs_u.fs_44.fs_state); + } be32_to_cpus__between(*usb,fs_postblformat,fs_magic); #endif } extern void ufs_superblock_le_to_cpus(struct ufs_superblock * usb) { #ifndef __LITTLE_ENDIAN + __u16 sb_type = 1; /* SUN type superblock */ + + if (usb->fs_u.fs_44.fs_maxsymlinklen >= 0) + sb_type = 0; /* 4.4BSD (FreeBSD) type superblock */ + le32_to_cpus__between(*usb,fs_link,fs_fmod); /* XXX - I dunno what to do w/ fs_csp, * but it is unused by the current code, so that's ok for now. */ le32_to_cpus(&usb->fs_cpc); - le16_to_cpus__between(*usb,fs_opostbl,fs_sparecon); - le32_to_cpus__between(*usb,fs_sparecon,fs_qbmask); - le64_to_cpus(&usb->fs_qbmask); - le64_to_cpus(&usb->fs_qfmask); + if (sb_type) { + le16_to_cpus__between(*usb,fs_opostbl,fs_u.fs_sun.fs_sparecon); + le32_to_cpus__between(*usb,fs_u.fs_sun.fs_sparecon,fs_u.fs_sun.fs_qbmask); + /* Might fail on strictly aligning 64-bit big-endian + * architectures. Ouch! + */ + le64_to_cpus((__u64 *) &usb->fs_u.fs_sun.fs_qbmask); + le64_to_cpus((__u64 *) &usb->fs_u.fs_sun.fs_qfmask); + } else { + le16_to_cpus__between(*usb,fs_opostbl,fs_u.fs_44.fs_sparecon); + le32_to_cpus__between(*usb,fs_u.fs_sun.fs_sparecon,fs_u.fs_44.fs_maxfilesize); + le64_to_cpus((__u64 *) &usb->fs_u.fs_44.fs_maxfilesize); + le64_to_cpus((__u64 *) &usb->fs_u.fs_44.fs_qbmask); + le64_to_cpus((__u64 *) &usb->fs_u.fs_44.fs_qfmask); + le32_to_cpus((__s32 *) &usb->fs_u.fs_44.fs_state); + } le32_to_cpus__between(*usb,fs_postblformat,fs_magic); #endif } diff --git a/fs/ufs/ufs_swab.h b/fs/ufs/ufs_swab.h index 921fb3d79..f8e9fd898 100644 --- a/fs/ufs/ufs_swab.h +++ b/fs/ufs/ufs_swab.h @@ -18,42 +18,104 @@ * to support them. * (2) for a read/write ufs driver, we should distinguish * between byteswapping for read or write accesses! + * naming should then be UFS16_TO_CPU and suches. + * + * 4.4BSD (FreeBSD) support added on February 1st 1998 by + * Niels Kristian Bech Jensen <nkbj@image.dk> partially based + * on code by Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>. */ #include <linux/ufs_fs.h> #include <asm/byteorder.h> /* - * These are only valid inside ufs routines, - * after bytesex has been initialized to sb->u.ufs_sb.s_flags&UFS_BYTESEX + * These are only valid inside ufs routines, after a variable named flags + * has been made visible in current scope and properly initialized: + __u32 flags = sb->u.ufs_sb.s_flags ; */ -#define SWAB16(x) ufs_swab16(bytesex,x) -#define SWAB32(x) ufs_swab32(bytesex,x) -#define SWAB64(x) ufs_swab64(bytesex,x) +#define SWAB16(x) ufs_swab16(flags,x) +#define SWAB32(x) ufs_swab32(flags,x) +#define SWAB64(x) ufs_swab64(flags,x) -extern __inline__ __const__ __u16 ufs_swab16(__u32 bytesex, __u16 x) { - if (bytesex == UFS_LITTLE_ENDIAN) { +extern __inline__ __const__ __u16 ufs_swab16(__u32 flags, __u16 x) { + if ((flags&UFS_BYTESEX) == UFS_LITTLE_ENDIAN) { return le16_to_cpu(x); } else { return be16_to_cpu(x); } } -extern __inline__ __const__ __u32 ufs_swab32(__u32 bytesex, __u32 x) { - if (bytesex == UFS_LITTLE_ENDIAN) { +extern __inline__ __const__ __u32 ufs_swab32(__u32 flags, __u32 x) { + if ((flags&UFS_BYTESEX) == UFS_LITTLE_ENDIAN) { return le32_to_cpu(x); } else { return be32_to_cpu(x); } } -extern __inline__ __const__ __u64 ufs_swab64(__u32 bytesex, __u64 x) { - if (bytesex == UFS_LITTLE_ENDIAN) { +extern __inline__ __const__ __u64 ufs_swab64(__u32 flags, __u64 x) { + if ((flags&UFS_BYTESEX) == UFS_LITTLE_ENDIAN) { return le64_to_cpu(x); } else { return be64_to_cpu(x); } } + +/* + * These are for in-core superblock normalization. + * It might or not be a bad idea once we go to a read/write driver, + * as all critical info should be copied to the sb info structure anyway. + * So better replace them with a static inline function + * ufs_superblock_to_sb_info() in ufs_super.c + */ extern void ufs_superblock_le_to_cpus(struct ufs_superblock * usb); extern void ufs_superblock_be_to_cpus(struct ufs_superblock * usb); + +/* + * These also implicitly depend on variable flags... + * NAMLEN(foo) is already normalized to local format, so don't SWAB16() it! + */ + +#define NAMLEN(direct) ufs_namlen(flags,direct) +extern __inline__ __u16 ufs_namlen(__u32 flags, struct ufs_direct * direct) { + if ( (flags&UFS_DE_MASK) == UFS_DE_OLD) { + return SWAB16(direct->d_u.d_namlen); + } else /* UFS_DE_44BSD */ { + return direct->d_u.d_44.d_namlen; + } +} + +/* Here is how the uid is computed: + if the file system is 4.2BSD, get it from oldids. + if it has sun extension and oldids is USEEFT, get it from ui_sun. + if it is 4.4 or Hurd, get it from ui_44 (which is the same as ui_hurd). + depends on implicit variable flags being initialized from + __u32 flags = sb->u.ufs_sb.s_flags; +*/ +#define UFS_UID(ino) ufs_uid(flags,ino) +#define UFS_GID(ino) ufs_gid(flags,ino) + +extern __inline__ __u32 ufs_uid(__u32 flags,struct ufs_inode * ino) { + switch(flags&UFS_UID_MASK) { + case UFS_UID_EFT: + return SWAB32(ino->ui_u3.ui_sun.ui_uid) ; + case UFS_UID_44BSD: + return SWAB32(ino->ui_u3.ui_44.ui_uid) ; + case UFS_UID_OLD: + default: + return SWAB16(ino->ui_u1.oldids.suid) ; + } +} +extern __inline__ __u32 ufs_gid(__u32 flags,struct ufs_inode * ino) { + switch(flags&UFS_UID_MASK) { + case UFS_UID_EFT: + return SWAB32(ino->ui_u3.ui_sun.ui_gid) ; + case UFS_UID_44BSD: + return SWAB32(ino->ui_u3.ui_44.ui_gid) ; + case UFS_UID_OLD: + default: + return SWAB16(ino->ui_u1.oldids.sgid) ; + } +} + #endif /* _UFS_SWAB_H */ diff --git a/fs/ufs/ufs_symlink.c b/fs/ufs/ufs_symlink.c index 76d5fbf11..e19abe44d 100644 --- a/fs/ufs/ufs_symlink.c +++ b/fs/ufs/ufs_symlink.c @@ -8,6 +8,9 @@ * * Ported to 2.1.62 by Francois-Rene Rideau <rideau@ens.fr> 19971109 * + * 4.4BSD (FreeBSD) support added on February 1st 1998 by + * Niels Kristian Bech Jensen <nkbj@image.dk> partially based + * on code by Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>. */ #include <linux/fs.h> @@ -19,15 +22,17 @@ extern int ufs_bmap (struct inode *, int); static int -ufs_readlink(struct inode * inode, char * buffer, int buflen) +ufs_readlink(struct dentry * dentry, char * buffer, int buflen) { + struct inode * inode = dentry->d_inode; + struct super_block * sb = inode->i_sb; unsigned long int block; struct buffer_head * bh = NULL; char * link; int i; char c; - if (inode->i_sb->u.ufs_sb.s_flags & (UFS_DEBUG|UFS_DEBUG_LINKS)) { + if (sb->u.ufs_sb.s_flags & (UFS_DEBUG|UFS_DEBUG_LINKS)) { printk("ufs_readlink: called on ino %lu dev %u/%u\n", inode->i_ino, MAJOR(inode->i_dev), MINOR(inode->i_dev)); } @@ -36,16 +41,16 @@ ufs_readlink(struct inode * inode, char * buffer, int buflen) return -EINVAL; } - if (buflen > inode->i_sb->s_blocksize - 1) - buflen = inode->i_sb->s_blocksize - 1; + if (buflen > sb->s_blocksize - 1) + buflen = sb->s_blocksize - 1; if (inode->i_blocks) { /* XXX - error checking */ block = ufs_bmap(inode, 0); - if (inode->i_sb->u.ufs_sb.s_flags &(UFS_DEBUG|UFS_DEBUG_LINKS)) { + if (sb->u.ufs_sb.s_flags &(UFS_DEBUG|UFS_DEBUG_LINKS)) { printk("ufs_readlink: bmap got %lu for ino %lu\n", block, inode->i_ino); } - bh = bread(inode->i_dev, block, BLOCK_SIZE); + bh = bread(inode->i_dev, block, sb->s_blocksize); if (!bh) { printk("ufs_readlink: can't read block 0 for ino %lu on dev %u/%u\n", inode->i_ino, MAJOR(inode->i_dev), @@ -54,9 +59,8 @@ ufs_readlink(struct inode * inode, char * buffer, int buflen) } link = bh->b_data; /* no need to bswap */ - } - else { - link = (char *)&(inode->u.ufs_i.i_data[0]); + } else /* fast symlink */ { + link = (char *)&(inode->u.ufs_i.i_u1.i_symlink[0]); } i = 0; while (i < buflen && (c = link[i])) { @@ -71,8 +75,9 @@ ufs_readlink(struct inode * inode, char * buffer, int buflen) * XXX - blatantly stolen from minix fs */ static struct dentry * -ufs_follow_link(struct inode * inode, struct dentry * base) +ufs_follow_link(struct dentry * dentry, struct dentry * base) { + struct inode * inode = dentry->d_inode; unsigned long int block; struct buffer_head * bh = NULL; char * link; @@ -86,7 +91,7 @@ ufs_follow_link(struct inode * inode, struct dentry * base) /* read the link from disk */ /* XXX - error checking */ block = ufs_bmap(inode, 0); - bh = bread(inode->i_dev, block, BLOCK_SIZE); + bh = bread(inode->i_dev, block, inode->i_sb->s_blocksize); if (bh == NULL) { printk("ufs_follow_link: can't read block 0 for ino %lu on dev %u/%u\n", inode->i_ino, MAJOR(inode->i_dev), @@ -95,9 +100,8 @@ ufs_follow_link(struct inode * inode, struct dentry * base) return ERR_PTR(-EIO); } link = bh->b_data; - } else { - /* fast symlink */ - link = (char *)&(inode->u.ufs_i.i_data[0]); + } else /* fast symlink */ { + link = (char *)&(inode->u.ufs_i.i_u1.i_symlink[0]); } base = lookup_dentry(link, base, 1); brelse (bh); |