diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-01-04 16:03:48 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-01-04 16:03:48 +0000 |
commit | 78c388aed2b7184182c08428db1de6c872d815f5 (patch) | |
tree | 4b2003b1b4ceb241a17faa995da8dd1004bb8e45 /fs/ufs/super.c | |
parent | eb7a5bf93aaa4be1d7c6181100ab7639e74d67f7 (diff) |
Merge with Linux 2.1.131 and more MIPS goodies.
(Did I mention that CVS is buggy ...)
Diffstat (limited to 'fs/ufs/super.c')
-rw-r--r-- | fs/ufs/super.c | 939 |
1 files changed, 565 insertions, 374 deletions
diff --git a/fs/ufs/super.c b/fs/ufs/super.c index d4426ad5d..dd4815469 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -1,6 +1,35 @@ /* * linux/fs/ufs/super.c * + * Copyright (C) 1998 + * Daniel Pirkl <daniel.pirkl@email.cz> + * Charles University, Faculty of Mathematics and Physics + */ + +/* Derivated from + * + * linux/fs/ext2/super.c + * + * Copyright (C) 1992, 1993, 1994, 1995 + * Remy Card (card@masi.ibp.fr) + * Laboratoire MASI - Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * from + * + * linux/fs/minix/inode.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + * + * Big-endian to little-endian byte-swapping/bitmaps by + * David S. Miller (davem@caip.rutgers.edu), 1995 + */ + +/* + * Inspirated by + * + * linux/fs/ufs/super.c + * * Copyright (C) 1996 * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu) * Laboratory for Computer Science Research Computing Facility @@ -28,20 +57,29 @@ * */ + #include <linux/module.h> -#include <linux/init.h> -#include <linux/kernel.h> +#include <stdarg.h> + +#include <asm/bitops.h> +#include <asm/uaccess.h> +#include <asm/system.h> + +#include <linux/errno.h> #include <linux/fs.h> #include <linux/ufs_fs.h> -#include <linux/locks.h> -#include <asm/uaccess.h> #include <linux/malloc.h> +#include <linux/sched.h> +#include <linux/stat.h> +#include <linux/string.h> +#include <linux/locks.h> +#include <linux/blkdev.h> +#include <linux/init.h> #include "swab.h" #include "util.h" - #undef UFS_SUPER_DEBUG #undef UFS_SUPER_DEBUG_MORE @@ -59,39 +97,41 @@ void ufs_print_super_stuff(struct ufs_super_block_first * usb1, struct ufs_super_block_second * usb2, struct ufs_super_block_third * usb3, unsigned swab) { - printk("\nufs_print_super_stuff\n"); - printk("size of usb: %lu\n", sizeof(struct ufs_super_block)); - printk(" magic: 0x%x\n", SWAB32(usb3->fs_magic)); - printk(" sblkno: %u\n", SWAB32(usb1->fs_sblkno)); - printk(" cblkno: %u\n", SWAB32(usb1->fs_cblkno)); - printk(" iblkno: %u\n", SWAB32(usb1->fs_iblkno)); - printk(" dblkno: %u\n", SWAB32(usb1->fs_dblkno)); - printk(" cgoffset: %u\n", SWAB32(usb1->fs_cgoffset)); - printk(" ~cgmask: 0x%x\n", ~SWAB32(usb1->fs_cgmask)); - printk(" size: %u\n", SWAB32(usb1->fs_size)); - printk(" dsize: %u\n", SWAB32(usb1->fs_dsize)); - printk(" ncg: %u\n", SWAB32(usb1->fs_ncg)); - printk(" bsize: %u\n", SWAB32(usb1->fs_bsize)); - printk(" fsize: %u\n", SWAB32(usb1->fs_fsize)); - printk(" frag: %u\n", SWAB32(usb1->fs_frag)); - printk(" fragshift: %u\n", SWAB32(usb1->fs_fragshift)); - printk(" ~fmask: %u\n", ~SWAB32(usb1->fs_fmask)); - printk(" fshift: %u\n", SWAB32(usb1->fs_fshift)); - printk(" sbsize: %u\n", SWAB32(usb1->fs_sbsize)); - printk(" spc: %u\n", SWAB32(usb1->fs_spc)); - printk(" cpg: %u\n", SWAB32(usb1->fs_cpg)); - printk(" ipg: %u\n", SWAB32(usb1->fs_ipg)); - printk(" fpg: %u\n", SWAB32(usb1->fs_fpg)); - printk(" csaddr: %u\n", SWAB32(usb1->fs_csaddr)); - printk(" cssize: %u\n", SWAB32(usb1->fs_cssize)); - printk(" cgsize: %u\n", SWAB32(usb1->fs_cgsize)); - printk(" fstodb: %u\n", SWAB32(usb1->fs_fsbtodb)); - printk(" postblformat: %u\n", SWAB32(usb3->fs_postblformat)); - printk(" nrpos: %u\n", SWAB32(usb3->fs_nrpos)); - printk(" ndir %u\n", SWAB32(usb1->fs_cstotal.cs_ndir)); - printk(" nifree %u\n", SWAB32(usb1->fs_cstotal.cs_nifree)); - printk(" nbfree %u\n", SWAB32(usb1->fs_cstotal.cs_nbfree)); - printk(" nffree %u\n", SWAB32(usb1->fs_cstotal.cs_nffree)); + printk("ufs_print_super_stuff\n"); + printk("size of usb: %u\n", sizeof(struct ufs_super_block)); + printk(" magic: 0x%x\n", SWAB32(usb3->fs_magic)); + printk(" sblkno: %u\n", SWAB32(usb1->fs_sblkno)); + printk(" cblkno: %u\n", SWAB32(usb1->fs_cblkno)); + printk(" iblkno: %u\n", SWAB32(usb1->fs_iblkno)); + printk(" dblkno: %u\n", SWAB32(usb1->fs_dblkno)); + printk(" cgoffset: %u\n", SWAB32(usb1->fs_cgoffset)); + printk(" ~cgmask: 0x%x\n", ~SWAB32(usb1->fs_cgmask)); + printk(" size: %u\n", SWAB32(usb1->fs_size)); + printk(" dsize: %u\n", SWAB32(usb1->fs_dsize)); + printk(" ncg: %u\n", SWAB32(usb1->fs_ncg)); + printk(" bsize: %u\n", SWAB32(usb1->fs_bsize)); + printk(" fsize: %u\n", SWAB32(usb1->fs_fsize)); + printk(" frag: %u\n", SWAB32(usb1->fs_frag)); + printk(" fragshift: %u\n", SWAB32(usb1->fs_fragshift)); + printk(" ~fmask: %u\n", ~SWAB32(usb1->fs_fmask)); + printk(" fshift: %u\n", SWAB32(usb1->fs_fshift)); + printk(" sbsize: %u\n", SWAB32(usb1->fs_sbsize)); + printk(" spc: %u\n", SWAB32(usb1->fs_spc)); + printk(" cpg: %u\n", SWAB32(usb1->fs_cpg)); + printk(" ipg: %u\n", SWAB32(usb1->fs_ipg)); + printk(" fpg: %u\n", SWAB32(usb1->fs_fpg)); + printk(" csaddr: %u\n", SWAB32(usb1->fs_csaddr)); + printk(" cssize: %u\n", SWAB32(usb1->fs_cssize)); + printk(" cgsize: %u\n", SWAB32(usb1->fs_cgsize)); + printk(" fstodb: %u\n", SWAB32(usb1->fs_fsbtodb)); + printk(" contigsumsize: %d\n", SWAB32(usb3->fs_u.fs_44.fs_contigsumsize)); + printk(" postblformat: %u\n", SWAB32(usb3->fs_postblformat)); + printk(" nrpos: %u\n", SWAB32(usb3->fs_nrpos)); + printk(" ndir %u\n", SWAB32(usb1->fs_cstotal.cs_ndir)); + printk(" nifree %u\n", SWAB32(usb1->fs_cstotal.cs_nifree)); + printk(" nbfree %u\n", SWAB32(usb1->fs_cstotal.cs_nbfree)); + printk(" nffree %u\n", SWAB32(usb1->fs_cstotal.cs_nffree)); + printk("\n"); } @@ -101,107 +141,411 @@ void ufs_print_super_stuff(struct ufs_super_block_first * usb1, void ufs_print_cylinder_stuff(struct ufs_cylinder_group *cg, unsigned swab) { printk("\nufs_print_cylinder_stuff\n"); - printk("size of ucg: %lu\n", sizeof(struct ufs_cylinder_group)); - printk(" magic: %x\n", SWAB32(cg->cg_magic)); - printk(" time: %u\n", SWAB32(cg->cg_time)); - printk(" cgx: %u\n", SWAB32(cg->cg_cgx)); - printk(" ncyl: %u\n", SWAB16(cg->cg_ncyl)); - printk(" niblk: %u\n", SWAB16(cg->cg_niblk)); - printk(" ndblk: %u\n", SWAB32(cg->cg_ndblk)); - printk(" cs_ndir: %u\n", SWAB32(cg->cg_cs.cs_ndir)); - printk(" cs_nbfree: %u\n", SWAB32(cg->cg_cs.cs_nbfree)); - printk(" cs_nifree: %u\n", SWAB32(cg->cg_cs.cs_nifree)); - printk(" cs_nffree: %u\n", SWAB32(cg->cg_cs.cs_nffree)); - printk(" rotor: %u\n", SWAB32(cg->cg_rotor)); - printk(" frotor: %u\n", SWAB32(cg->cg_frotor)); - printk(" irotor: %u\n", SWAB32(cg->cg_irotor)); - printk(" frsum: %u, %u, %u, %u, %u, %u, %u, %u\n", + printk("size of ucg: %u\n", sizeof(struct ufs_cylinder_group)); + printk(" magic: %x\n", SWAB32(cg->cg_magic)); + printk(" time: %u\n", SWAB32(cg->cg_time)); + printk(" cgx: %u\n", SWAB32(cg->cg_cgx)); + printk(" ncyl: %u\n", SWAB16(cg->cg_ncyl)); + printk(" niblk: %u\n", SWAB16(cg->cg_niblk)); + printk(" ndblk: %u\n", SWAB32(cg->cg_ndblk)); + printk(" cs_ndir: %u\n", SWAB32(cg->cg_cs.cs_ndir)); + printk(" cs_nbfree: %u\n", SWAB32(cg->cg_cs.cs_nbfree)); + printk(" cs_nifree: %u\n", SWAB32(cg->cg_cs.cs_nifree)); + printk(" cs_nffree: %u\n", SWAB32(cg->cg_cs.cs_nffree)); + printk(" rotor: %u\n", SWAB32(cg->cg_rotor)); + printk(" frotor: %u\n", SWAB32(cg->cg_frotor)); + printk(" irotor: %u\n", SWAB32(cg->cg_irotor)); + printk(" frsum: %u, %u, %u, %u, %u, %u, %u, %u\n", SWAB32(cg->cg_frsum[0]), SWAB32(cg->cg_frsum[1]), SWAB32(cg->cg_frsum[2]), SWAB32(cg->cg_frsum[3]), SWAB32(cg->cg_frsum[4]), SWAB32(cg->cg_frsum[5]), SWAB32(cg->cg_frsum[6]), SWAB32(cg->cg_frsum[7])); - printk(" btotoff: %u\n", SWAB32(cg->cg_btotoff)); - printk(" boff: %u\n", SWAB32(cg->cg_boff)); - printk(" iuseoff: %u\n", SWAB32(cg->cg_iusedoff)); - printk(" freeoff: %u\n", SWAB32(cg->cg_freeoff)); - printk(" nextfreeoff: %u\n", SWAB32(cg->cg_nextfreeoff)); + printk(" btotoff: %u\n", SWAB32(cg->cg_btotoff)); + printk(" boff: %u\n", SWAB32(cg->cg_boff)); + printk(" iuseoff: %u\n", SWAB32(cg->cg_iusedoff)); + printk(" freeoff: %u\n", SWAB32(cg->cg_freeoff)); + printk(" nextfreeoff: %u\n", SWAB32(cg->cg_nextfreeoff)); + printk(" clustersumoff %u\n", SWAB32(cg->cg_u.cg_44.cg_clustersumoff)); + printk(" clusteroff %u\n", SWAB32(cg->cg_u.cg_44.cg_clusteroff)); + printk(" nclusterblks %u\n", SWAB32(cg->cg_u.cg_44.cg_nclusterblks)); + printk("\n"); } #endif /* UFS_SUPER_DEBUG_MORE */ +static char error_buf[1024]; + +void ufs_error (struct super_block * sb, const char * function, + const char * fmt, ...) +{ + struct ufs_sb_private_info * uspi; + struct ufs_super_block_first * usb1; + va_list args; + + uspi = sb->u.ufs_sb.s_uspi; + usb1 = ubh_get_usb_first(USPI_UBH); + + if (!(sb->s_flags & MS_RDONLY)) { + usb1->fs_clean = UFS_FSBAD; + ubh_mark_buffer_dirty(USPI_UBH, 1); + sb->s_dirt = 1; + sb->s_flags |= MS_RDONLY; + } + va_start (args, fmt); + vsprintf (error_buf, fmt, args); + va_end (args); + switch (sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_ONERROR) { + case UFS_MOUNT_ONERROR_PANIC: + panic ("UFS-fs panic (device %s): %s: %s\n", + kdevname(sb->s_dev), function, error_buf); + + case UFS_MOUNT_ONERROR_LOCK: + case UFS_MOUNT_ONERROR_UMOUNT: + case UFS_MOUNT_ONERROR_REPAIR: + printk (KERN_CRIT "UFS-fs error (device %s): %s: %s\n", + kdevname(sb->s_dev), function, error_buf); + } +} + +void ufs_panic (struct super_block * sb, const char * function, + const char * fmt, ...) +{ + struct ufs_sb_private_info * uspi; + struct ufs_super_block_first * usb1; + va_list args; + + uspi = sb->u.ufs_sb.s_uspi; + usb1 = ubh_get_usb_first(USPI_UBH); + + if (!(sb->s_flags & MS_RDONLY)) { + usb1->fs_clean = UFS_FSBAD; + ubh_mark_buffer_dirty(USPI_UBH, 1); + sb->s_dirt = 1; + } + va_start (args, fmt); + vsprintf (error_buf, fmt, args); + va_end (args); + /* this is to prevent panic from syncing this filesystem */ + if (sb->s_lock) + sb->s_lock = 0; + sb->s_flags |= MS_RDONLY; + printk (KERN_CRIT "UFS-fs panic (device %s): %s: %s\n", + kdevname(sb->s_dev), function, error_buf); +/*** + panic ("UFS-fs panic (device %s): %s: %s\n", + kdevname(sb->s_dev), function, error_buf); +***/ +} + +void ufs_warning (struct super_block * sb, const char * function, + const char * fmt, ...) +{ + va_list args; + + va_start (args, fmt); + vsprintf (error_buf, fmt, args); + va_end (args); + printk (KERN_WARNING "UFS-fs warning (device %s): %s: %s\n", + kdevname(sb->s_dev), function, error_buf); +} + +static int ufs_parse_options (char * options, unsigned * mount_options) +{ + char * this_char; + char * value; + + UFSD(("ENTER\n")) + + if (!options) + return 1; + + for (this_char = strtok (options, ","); + this_char != NULL; + this_char = strtok (NULL, ",")) { + + if ((value = strchr (this_char, '=')) != NULL) + *value++ = 0; + if (!strcmp (this_char, "ufstype")) { + ufs_clear_opt (*mount_options, UFSTYPE); + if (!strcmp (value, "old")) + ufs_set_opt (*mount_options, UFSTYPE_OLD); + else if (!strcmp (value, "sun")) + ufs_set_opt (*mount_options, UFSTYPE_SUN); + else if (!strcmp (value, "44bsd")) + ufs_set_opt (*mount_options, UFSTYPE_44BSD); + else if (!strcmp (value, "next")) + ufs_set_opt (*mount_options, UFSTYPE_NEXT); + else { + printk ("UFS-fs: Invalid type option: %s\n", value); + return 0; + } + } + else if (!strcmp (this_char, "onerror")) { + ufs_clear_opt (*mount_options, ONERROR); + if (!strcmp (value, "panic")) + ufs_set_opt (*mount_options, ONERROR_PANIC); + else if (!strcmp (value, "lock")) + ufs_set_opt (*mount_options, ONERROR_LOCK); + else if (!strcmp (value, "umount")) + ufs_set_opt (*mount_options, ONERROR_UMOUNT); + else if (!strcmp (value, "repair")) { + printk("UFS-fs: Unable to do repair on error, " + "will lock lock instead \n"); + ufs_set_opt (*mount_options, ONERROR_REPAIR); + } + else { + printk ("UFS-fs: Invalid action onerror: %s\n", value); + return 0; + } + } + else { + printk("UFS-fs: Invalid option: %s\n", this_char); + return 0; + } + } + return 1; +} + +/* + * Read on-disk structures asscoiated with cylinder groups + */ +int ufs_read_cylinder_structures (struct super_block * sb) { + struct ufs_sb_private_info * uspi; + struct ufs_buffer_head * ubh; + unsigned char * base, * space; + unsigned size, blks, i; + unsigned swab; + + UFSD(("ENTER\n")) + + uspi = sb->u.ufs_sb.s_uspi; + swab = sb->u.ufs_sb.s_swab; + + /* + * Read cs structures from (usually) first data block + * on the device. + */ + size = uspi->s_cssize; + blks = howmany(size, uspi->s_fsize); + base = space = kmalloc(size, GFP_KERNEL); + if (!base) + goto failed; + for (i = 0; i < blks; i += uspi->s_fpb) { + size = uspi->s_bsize; + if (i + uspi->s_fpb > blks) + size = (blks - i) * uspi->s_fsize; + ubh = ubh_bread(sb->s_dev, uspi->s_csaddr + i, size); + if (!ubh) + goto failed; + ubh_ubhcpymem (space, ubh, size); + sb->u.ufs_sb.s_csp[ufs_fragstoblks(i)] = (struct ufs_csum *)space; + space += size; + ubh_brelse (ubh); + ubh = NULL; + } + + /* + * Read cylinder group (we read only first fragment from block + * at this time) and prepare internal data structures for cg caching. + */ + if (!(sb->u.ufs_sb.s_ucg = kmalloc (sizeof(struct buffer_head *) * uspi->s_ncg, GFP_KERNEL))) + goto failed; + for (i = 0; i < uspi->s_ncg; i++) + sb->u.ufs_sb.s_ucg[i] = NULL; + for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) { + sb->u.ufs_sb.s_ucpi[i] = NULL; + sb->u.ufs_sb.s_cgno[i] = UFS_CGNO_EMPTY; + } + for (i = 0; i < uspi->s_ncg; i++) { + UFSD(("read cg %u\n", i)) + if (!(sb->u.ufs_sb.s_ucg[i] = bread (sb->s_dev, ufs_cgcmin(i), sb->s_blocksize))) + goto failed; + if (!ufs_cg_chkmagic ((struct ufs_cylinder_group *) sb->u.ufs_sb.s_ucg[i]->b_data)) + goto failed; +#ifdef UFS_SUPER_DEBUG_MORE + ufs_print_cylinder_stuff((struct ufs_cylinder_group *) sb->u.ufs_sb.s_ucg[i]->b_data, swab); +#endif + } + for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) { + if (!(sb->u.ufs_sb.s_ucpi[i] = kmalloc (sizeof(struct ufs_cg_private_info), GFP_KERNEL))) + goto failed; + sb->u.ufs_sb.s_cgno[i] = UFS_CGNO_EMPTY; + } + sb->u.ufs_sb.s_cg_loaded = 0; + UFSD(("EXIT\n")) + return 1; + +failed: + if (base) kfree (base); + if (sb->u.ufs_sb.s_ucg) { + for (i = 0; i < uspi->s_ncg; i++) + if (sb->u.ufs_sb.s_ucg[i]) brelse (sb->u.ufs_sb.s_ucg[i]); + kfree (sb->u.ufs_sb.s_ucg); + for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) + if (sb->u.ufs_sb.s_ucpi[i]) kfree (sb->u.ufs_sb.s_ucpi[i]); + } + UFSD(("EXIT (FAILED)\n")) + return 0; +} + /* - * Called while file system is mounted, read super block - * and create important internal structures. + * Put on-disk structures associated with cylidner groups and + * write them back to disk */ -struct super_block * ufs_read_super ( - struct super_block * sb, - void * data, +void ufs_put_cylinder_structures (struct super_block * sb) { + struct ufs_sb_private_info * uspi; + struct ufs_buffer_head * ubh; + unsigned char * base, * space; + unsigned blks, size, i; + + UFSD(("ENTER\n")) + + uspi = sb->u.ufs_sb.s_uspi; + + size = uspi->s_cssize; + blks = howmany(size, uspi->s_fsize); + base = space = (char*) sb->u.ufs_sb.s_csp[0]; + for (i = 0; i < blks; i += uspi->s_fpb) { + size = uspi->s_bsize; + if (i + uspi->s_fpb > blks) + size = (blks - i) * uspi->s_fsize; + ubh = ubh_bread (sb->s_dev, uspi->s_csaddr + i, size); + ubh_memcpyubh (ubh, space, size); + space += size; + ubh_mark_buffer_uptodate (ubh, 1); + ubh_mark_buffer_dirty (ubh, 0); + ubh_brelse (ubh); + } + for (i = 0; i < sb->u.ufs_sb.s_cg_loaded; i++) { + ufs_put_cylinder (sb, i); + kfree (sb->u.ufs_sb.s_ucpi[i]); + } + for (; i < UFS_MAX_GROUP_LOADED; i++) + kfree (sb->u.ufs_sb.s_ucpi[i]); + for (i = 0; i < uspi->s_ncg; i++) + brelse (sb->u.ufs_sb.s_ucg[i]); + kfree (sb->u.ufs_sb.s_ucg); + kfree (base); + UFSD(("EXIT\n")) +} + +struct super_block * ufs_read_super (struct super_block * sb, void * data, int silent) { struct ufs_sb_private_info * uspi; struct ufs_super_block_first * usb1; struct ufs_super_block_second * usb2; struct ufs_super_block_third * usb3; - struct ufs_buffer_head * ubh; - unsigned char * base, * space; - unsigned size, blks, i; + struct ufs_buffer_head * ubh; unsigned block_size, super_block_size; unsigned flags, swab; - s64 tmp; - static unsigned offsets[] = {0, 96, 160}; /* different superblock locations */ - - UFSD(("ENTER\n")) - + uspi = NULL; ubh = NULL; - base = space = NULL; - sb->u.ufs_sb.s_ucg = NULL; flags = 0; + swab = 0; - /* sb->s_dev and sb->s_flags are set by our caller - * data is the mystery argument to sys_mount() - * - * Our caller also sets s_dev, s_covered, s_rd_only, s_dirt, - * and s_type when we return. - */ - + UFSD(("ENTER\n")) + MOD_INC_USE_COUNT; lock_super (sb); - sb->u.ufs_sb.s_uspi = uspi = + /* + * Set default mount options + * Parse mount options + */ + sb->u.ufs_sb.s_mount_opt = 0; + ufs_set_opt (sb->u.ufs_sb.s_mount_opt, ONERROR_LOCK); + if (!ufs_parse_options ((char *) data, &sb->u.ufs_sb.s_mount_opt)) { + printk("wrong mount options\n"); + goto failed; + } + if (!(sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE)) { + printk("You didn't specify type of your ufs file system\n\n" + " mount -t ufs -o ufstype=sun|44bsd|old|next ....\n\n" + "!!! WARNING !!! wrong value may corrupt you file system\n" + "default value is ufstype=old\n"); + ufs_set_opt (sb->u.ufs_sb.s_mount_opt, UFSTYPE_OLD); + } + + sb->u.ufs_sb.s_uspi = uspi = kmalloc (sizeof(struct ufs_sb_private_info), GFP_KERNEL); if (!uspi) goto failed; + + switch (sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE) { + case UFS_MOUNT_UFSTYPE_44BSD: + UFSD(("44bsd ufstype\n")) + uspi->s_fsize = block_size = 512; + uspi->s_fmask = ~(512 - 1); + uspi->s_fshift = 9; + uspi->s_sbsize = super_block_size = 1536; + uspi->s_sbbase = 0; + flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; + break; + + case UFS_MOUNT_UFSTYPE_SUN: + UFSD(("sun ufstype\n")) + uspi->s_fsize = block_size = 1024; + uspi->s_fmask = ~(1024 - 1); + uspi->s_fshift = 10; + uspi->s_sbsize = super_block_size = 2048; + uspi->s_sbbase = 0; + flags |= UFS_DE_OLD | UFS_UID_EFT | UFS_ST_SUN | UFS_CG_SUN; + break; + + case UFS_MOUNT_UFSTYPE_OLD: + UFSD(("old ufstype\n")) + uspi->s_fsize = block_size = 1024; + uspi->s_fmask = ~(1024 - 1); + uspi->s_fshift = 10; + uspi->s_sbsize = super_block_size = 2048; + uspi->s_sbbase = 0; + flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; + if (!(sb->s_flags & MS_RDONLY)) { + printk("old type of ufs is supported read-only\n"); + goto failed; + } + break; - block_size = BLOCK_SIZE; - super_block_size = BLOCK_SIZE * 2; + case UFS_MOUNT_UFSTYPE_NEXT: + UFSD(("next ufstype\n")) + uspi->s_fsize = block_size = 1024; + uspi->s_fmask = ~(1024 - 1); + uspi->s_fshift = 10; + uspi->s_sbsize = super_block_size = 2048; + uspi->s_sbbase = 0; + flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD; + if (!(sb->s_flags & MS_RDONLY)) { + printk("nextstep type of ufs is supported read-only\n"); + goto failed; + } + break; - uspi->s_fsize = block_size; - uspi->s_fmask = ~(BLOCK_SIZE - 1); - uspi->s_fshift = BLOCK_SIZE_BITS; - uspi->s_sbsize = super_block_size; - i = 0; - uspi->s_sbbase = offsets[i]; -again: + default: + printk("this fs type of ufs is not supported\n"); + goto failed; + } + + if (!(sb->s_flags & MS_RDONLY)) + printk("!!! warning !!! write support of ufs is still in experimental state\n"); + +again: set_blocksize (sb->s_dev, block_size); /* * read ufs super block from device */ - ubh = ubh_bread2 (sb->s_dev, uspi->s_sbbase + UFS_SBLOCK/block_size, super_block_size); + ubh = ubh_bread_uspi (uspi, sb->s_dev, uspi->s_sbbase + UFS_SBLOCK/block_size, super_block_size); if (!ubh) goto failed; usb1 = ubh_get_usb_first(USPI_UBH); usb2 = ubh_get_usb_second(USPI_UBH); usb3 = ubh_get_usb_third(USPI_UBH); - + /* * Check ufs magic number - * This code uses goto, because it's a lesser evil than unbalanced - * structure in conditional code. Brought to you by Fare' as a minimal - * hack to live with Daniel's (unnecessary, IMNSHO) manual swab - * optimization -- see swab.h. */ #if defined(__LITTLE_ENDIAN) || defined(__BIG_ENDIAN) /* sane bytesex */ switch (usb3->fs_magic) { @@ -222,108 +566,68 @@ again: goto magic_found; } #endif - /* - * Magic number not found -- try another super block location - */ - if (++i < sizeof(offsets)/sizeof(unsigned)) { - ubh_brelse2(ubh); + + if ((sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE) == + UFS_MOUNT_UFSTYPE_NEXT && uspi->s_sbbase < 256) { + ubh_brelse_uspi(uspi); ubh = NULL; - uspi->s_sbbase = offsets[i]; + uspi->s_sbbase += 8; goto again; - } else { - printk("ufs_read_super: " - "super block location not in " - "{ 0, 96, 160} " - "or bad magic number\n"); - goto failed; } - magic_found: + printk("ufs_read_super: bad magic number\n"); + goto failed; +magic_found: /* * Check block and fragment sizes */ uspi->s_bsize = SWAB32(usb1->fs_bsize); uspi->s_fsize = SWAB32(usb1->fs_fsize); uspi->s_sbsize = SWAB32(usb1->fs_sbsize); + uspi->s_fmask = SWAB32(usb1->fs_fmask); + uspi->s_fshift = SWAB32(usb1->fs_fshift); if (uspi->s_bsize != 4096 && uspi->s_bsize != 8192) { - printk("ufs_read_super: fs_bsize %u != {4096, 8192}\n", - uspi->s_bsize); + printk("ufs_read_super: fs_bsize %u != {4096, 8192}\n", uspi->s_bsize); goto failed; } if (uspi->s_fsize != 512 && uspi->s_fsize != 1024) { - printk("ufs_read_super: fs_fsize %u != {512, 1024}\n", - uspi->s_fsize); + printk("ufs_read_super: fs_fsize %u != {512, 1024}\n", uspi->s_fsize); goto failed; } - - /* - * Block size is not 1024. Free buffers, set block_size and - * super_block_size to superblock-declared values, and try again. - */ if (uspi->s_fsize != block_size || uspi->s_sbsize != super_block_size) { - ubh_brelse2(ubh); + ubh_brelse_uspi(uspi); ubh = NULL; - uspi->s_fmask = SWAB32(usb1->fs_fmask); - uspi->s_fshift = SWAB32(usb1->fs_fshift); block_size = uspi->s_fsize; super_block_size = uspi->s_sbsize; + UFSD(("another value of block_size or super_block_size %u, %u\n", block_size, super_block_size)) goto again; } #ifdef UFS_SUPER_DEBUG_MORE ufs_print_super_stuff (usb1, usb2, usb3, swab); #endif - /* - * Check file system flavor - */ - flags |= UFS_VANILLA; - /* XXX more consistency check */ - UFSD(("ufs_read_super: maxsymlinklen 0x%8.8x\n", usb3->fs_u.fs_44.fs_maxsymlinklen)) - if (usb3->fs_u.fs_44.fs_maxsymlinklen >= 0) { - if (usb3->fs_u.fs_44.fs_inodefmt >= UFS_44INODEFMT) { - UFSD(("Flavor: 44BSD\n")) - flags |= UFS_44BSD; - sb->s_flags |= MS_RDONLY; - } else { - UFSD(("Flavor: OLD\n")) - sb->s_flags |= UFS_OLD; /* 4.2BSD */ - } - } else if (uspi->s_sbbase > 0) { - UFSD(("Flavor: NEXT\n")) - flags |= UFS_NEXT; - sb->s_flags |= MS_RDONLY; - } else { - UFSD(("Flavor: SUN\n")) - flags |= UFS_SUN; - } /* - * Check whether file system was correctly unmounted. + * Check, if file system was correctly unmounted. * If not, make it read only. */ 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(usb3) == UFS_FSOK - usb1->fs_time)) { + (((flags & UFS_ST_MASK) == UFS_ST_SUN) && + (ufs_get_fs_state(usb3) == (UFS_FSOK - SWAB32(usb1->fs_time))))) { switch(usb1->fs_clean) { - case UFS_FSACTIVE: /* 0x00 */ - printk("ufs_read_super: fs is active\n"); - sb->s_flags |= MS_RDONLY; - break; - case UFS_FSCLEAN: /* 0x01 */ - UFSD(("ufs_read_super: fs is clean\n")) + case UFS_FSCLEAN: + UFSD(("fs is clean\n")) break; case UFS_FSSTABLE: - UFSD(("ufs_read_super: fs is stable\n")) + UFSD(("fs is stable\n")) break; - case UFS_FSOSF1: /* 0x03 */ - /* XXX - is this the correct interpretation under DEC OSF/1? */ - printk("ufs_read_super: " - "fs is clean and stable (OSF/1)\n"); + case UFS_FSACTIVE: + printk("ufs_read_super: fs is active\n"); + sb->s_flags |= MS_RDONLY; break; - case UFS_FSBAD: /* 0xFF */ + case UFS_FSBAD: printk("ufs_read_super: fs is bad\n"); sb->s_flags |= MS_RDONLY; break; @@ -333,19 +637,19 @@ again: sb->s_flags |= MS_RDONLY; break; } - } else { + } + else { printk("ufs_read_super: fs needs fsck\n"); sb->s_flags |= MS_RDONLY; } - sb->s_flags &= ~MS_RDONLY; /* * Read ufs_super_block into internal data structures */ sb->s_blocksize = SWAB32(usb1->fs_fsize); sb->s_blocksize_bits = SWAB32(usb1->fs_fshift); sb->s_op = &ufs_super_ops; - sb->dq_op = 0; /* XXX */ + sb->dq_op = NULL; /***/ sb->s_magic = SWAB32(usb3->fs_magic); uspi->s_sblkno = SWAB32(usb1->fs_sblkno); @@ -385,12 +689,9 @@ again: uspi->s_ipg = SWAB32(usb1->fs_ipg); uspi->s_fpg = SWAB32(usb1->fs_fpg); uspi->s_cpc = SWAB32(usb2->fs_cpc); - ((u32 *)&tmp)[0] = usb3->fs_u.fs_sun.fs_qbmask[0]; - ((u32 *)&tmp)[1] = usb3->fs_u.fs_sun.fs_qbmask[1]; - uspi->s_qbmask = SWAB64(tmp); - ((u32 *)&tmp)[0] = usb3->fs_u.fs_sun.fs_qfmask[0]; - ((u32 *)&tmp)[1] = usb3->fs_u.fs_sun.fs_qfmask[1]; - uspi->s_qfmask = SWAB64(tmp); + uspi->s_contigsumsize = SWAB32(usb3->fs_u.fs_44.fs_contigsumsize); + uspi->s_qbmask = ufs_get_fs_qbmask(usb3); + uspi->s_qfmask = ufs_get_fs_qfmask(usb3); uspi->s_postblformat = SWAB32(usb3->fs_postblformat); uspi->s_nrpos = SWAB32(usb3->fs_nrpos); uspi->s_postbloff = SWAB32(usb3->fs_postbloff); @@ -410,86 +711,32 @@ again: uspi->s_nspfshift = uspi->s_fshift - UFS_SECTOR_BITS; uspi->s_nspb = uspi->s_nspf << uspi->s_fpbshift; uspi->s_inopf = uspi->s_inopb >> uspi->s_fpbshift; - - /* we could merge back s_swab and s_flags by having - foo.s_flags = flags | swab; here, and #defining - s_swab to s_flags & UFS_BYTESEX in swab.h */ + uspi->s_bpf = uspi->s_fsize << 3; + uspi->s_bpfshift = uspi->s_fshift + 3; + uspi->s_bpfmask = uspi->s_bpf - 1; + sb->u.ufs_sb.s_flags = flags; sb->u.ufs_sb.s_swab = swab; sb->u.ufs_sb.s_rename_lock = 0; sb->u.ufs_sb.s_rename_wait = NULL; - + sb->s_root = d_alloc_root(iget(sb, UFS_ROOTINO), NULL); - /* - * Read cs structures from (usually) first data block - * on the device. - */ - size = uspi->s_cssize; - blks = howmany(size, uspi->s_fsize); - base = space = kmalloc(size, GFP_KERNEL); - if (!base) - goto failed; - for (i = 0; i < blks; i += uspi->s_fpb) { - size = uspi->s_bsize; - if (i + uspi->s_fpb > blks) - size = (blks - i) * uspi->s_fsize; - ubh = ubh_bread(sb->s_dev, uspi->s_csaddr + i, size); - if (!ubh) - goto failed; - ubh_ubhcpymem (space, ubh, size); - sb->u.ufs_sb.s_csp[ufs_fragstoblks(i)] = (struct ufs_csum *)space; - space += size; - ubh_brelse (ubh); - ubh = NULL; - } /* - * Read cylinder group (we read only first fragment from block - * at this time) and prepare internal data structures for cg caching. - * XXX - something here fails on CDROMs from DEC! + * Read cylinder group structures */ - if (!(sb->u.ufs_sb.s_ucg = kmalloc (sizeof(struct buffer_head *) * uspi->s_ncg, GFP_KERNEL))) - goto failed; - for (i = 0; i < uspi->s_ncg; i++) - sb->u.ufs_sb.s_ucg[i] = NULL; - for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) { - sb->u.ufs_sb.s_ucpi[i] = NULL; - sb->u.ufs_sb.s_cgno[i] = UFS_CGNO_EMPTY; - } - for (i = 0; i < uspi->s_ncg; i++) { - UFSD(("read cg %u\n", i)) - if (!(sb->u.ufs_sb.s_ucg[i] = bread (sb->s_dev, ufs_cgcmin(i), sb->s_blocksize))) - goto failed; - if (!ufs_cg_chkmagic ((struct ufs_cylinder_group *) sb->u.ufs_sb.s_ucg[i]->b_data)) - goto failed; -#ifdef UFS_SUPER_DEBUG_MORE - ufs_print_cylinder_stuff((struct ufs_cylinder_group *) sb->u.ufs_sb.s_ucg[i]->b_data, swab); -#endif - } - for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) { - if (!(sb->u.ufs_sb.s_ucpi[i] = kmalloc (sizeof(struct ufs_cg_private_info), GFP_KERNEL))) + if (!(sb->s_flags & MS_RDONLY)) + if (!ufs_read_cylinder_structures(sb)) goto failed; - sb->u.ufs_sb.s_cgno[i] = UFS_CGNO_EMPTY; - } - sb->u.ufs_sb.s_cg_loaded = 0; unlock_super(sb); UFSD(("EXIT\n")) return(sb); failed: - if (ubh) ubh_brelse2 (ubh); + if (ubh) ubh_brelse_uspi (uspi); if (uspi) kfree (uspi); - if (base) kfree (base); - - if (sb->u.ufs_sb.s_ucg) { - for (i = 0; i < uspi->s_ncg; i++) - if (sb->u.ufs_sb.s_ucg[i]) brelse (sb->u.ufs_sb.s_ucg[i]); - kfree (sb->u.ufs_sb.s_ucg); - for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) - if (sb->u.ufs_sb.s_ucpi[i]) kfree (sb->u.ufs_sb.s_ucpi[i]); - } sb->s_dev = 0; unlock_super (sb); MOD_DEC_USE_COUNT; @@ -497,187 +744,132 @@ failed: return(NULL); } -/* - * Put super block, release internal structures - */ -void ufs_put_super (struct super_block * sb) -{ - struct ufs_sb_private_info * uspi; - struct ufs_buffer_head * ubh; - unsigned char * base, * space; - unsigned size, blks, i; - - UFSD(("ENTER\n")) - - uspi = sb->u.ufs_sb.s_uspi; - size = uspi->s_cssize; - blks = howmany(size, uspi->s_fsize); - base = space = (char*) sb->u.ufs_sb.s_csp[0]; - for (i = 0; i < blks; i += uspi->s_fpb) { - size = uspi->s_bsize; - if (i + uspi->s_fpb > blks) - size = (blks - i) * uspi->s_fsize; - ubh = ubh_bread (sb->s_dev, uspi->s_csaddr + i, size); - if (!ubh) - goto go_on; - ubh_memcpyubh (ubh, space, size); - space += size; - ubh_mark_buffer_uptodate (ubh, 1); - ubh_mark_buffer_dirty (ubh, 0); - ubh_brelse (ubh); - } - -go_on: - for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) { - ufs_put_cylinder (sb, i); - kfree (sb->u.ufs_sb.s_ucpi[i]); - } - for (i = 0; i < uspi->s_ncg; i++) - brelse (sb->u.ufs_sb.s_ucg[i]); - kfree (sb->u.ufs_sb.s_ucg); - kfree (base); - ubh_brelse2 (USPI_UBH); - kfree (sb->u.ufs_sb.s_uspi); - sb->s_dev = 0; - MOD_DEC_USE_COUNT; - return; -} - -/* - * Write super block to device - */ void ufs_write_super (struct super_block * sb) { struct ufs_sb_private_info * uspi; struct ufs_super_block_first * usb1; struct ufs_super_block_third * usb3; - unsigned swab; - + unsigned flags, swab; + UFSD(("ENTER\n")) swab = sb->u.ufs_sb.s_swab; + flags = sb->u.ufs_sb.s_flags; uspi = sb->u.ufs_sb.s_uspi; usb1 = ubh_get_usb_first(USPI_UBH); usb3 = ubh_get_usb_third(USPI_UBH); - + if (!(sb->s_flags & MS_RDONLY)) { - if (SWAB16(usb3->fs_u.fs_sun.fs_state) & UFS_FSOK) - usb3->fs_u.fs_sun.fs_state = SWAB16(SWAB16(usb3->fs_u.fs_sun.fs_state) & ~UFS_FSOK); usb1->fs_time = SWAB32(CURRENT_TIME); - usb3->fs_u.fs_sun.fs_state = SWAB32(UFS_FSOK - SWAB32(usb1->fs_time)); + if (usb1->fs_clean == UFS_FSCLEAN && (flags&UFS_ST_MASK) == UFS_ST_SUN) + ufs_set_fs_state(usb3, UFS_FSOK - SWAB32(usb1->fs_time)); ubh_mark_buffer_dirty (USPI_UBH, 1); } sb->s_dirt = 0; UFSD(("EXIT\n")) } -/* - * Copy some info about file system to user - */ -int ufs_statfs(struct super_block * sb, struct statfs * buf, int bufsiz) +void ufs_put_super (struct super_block * sb) { struct ufs_sb_private_info * uspi; - struct ufs_super_block_first * usb1; - struct statfs tmp; - struct statfs *sp = &tmp; - unsigned long used, avail; unsigned swab; - + UFSD(("ENTER\n")) - - swab = sb->u.ufs_sb.s_swab; - uspi = sb->u.ufs_sb.s_uspi; - usb1 = ubh_get_usb_first (USPI_UBH); - sp->f_type = UFS_MAGIC; - sp->f_bsize = sb->s_blocksize; - sp->f_blocks = uspi->s_dsize; - sp->f_bfree = (SWAB32(usb1->fs_cstotal.cs_nbfree) << uspi->s_fpbshift )+ - SWAB32(usb1->fs_cstotal.cs_nffree); + uspi = sb->u.ufs_sb.s_uspi; + swab = sb->u.ufs_sb.s_swab; - avail = sp->f_blocks - (sp->f_blocks / 100) * uspi->s_minfree; - used = sp->f_blocks - sp->f_bfree; - if (avail > used) - sp->f_bavail = avail - used; - else - sp->f_bavail = 0; - sp->f_files = uspi->s_ncg * uspi->s_ipg; - sp->f_ffree = SWAB32(usb1->fs_cstotal.cs_nifree); - sp->f_fsid.val[0] = SWAB32(usb1->fs_id[0]); - sp->f_fsid.val[1] = SWAB32(usb1->fs_id[1]); - sp->f_namelen = UFS_MAXNAMLEN; + if (!(sb->s_flags & MS_RDONLY)) + ufs_put_cylinder_structures (sb); - UFSD(("EXIT\n")) - - return copy_to_user(buf, sp, bufsiz) ? -EFAULT : 0; + ubh_brelse_uspi (uspi); + kfree (sb->u.ufs_sb.s_uspi); + sb->s_dev = 0; + MOD_DEC_USE_COUNT; + return; } -static char error_buf[1024]; - -void ufs_warning (struct super_block * sb, const char * function, - const char * fmt, ...) -{ - va_list args; - - va_start (args, fmt); - vsprintf (error_buf, fmt, args); - va_end (args); - printk (KERN_WARNING "UFS-fs warning (device %s): %s: %s\n", - kdevname(sb->s_dev), function, error_buf); -} - -void ufs_error (struct super_block * sb, const char * function, - const char * fmt, ...) +int ufs_remount (struct super_block * sb, int * mount_flags, char * data) { struct ufs_sb_private_info * uspi; struct ufs_super_block_first * usb1; - va_list args; - + struct ufs_super_block_third * usb3; + unsigned new_mount_opt, ufstype; + unsigned flags, swab; + uspi = sb->u.ufs_sb.s_uspi; + flags = sb->u.ufs_sb.s_flags; + swab = sb->u.ufs_sb.s_swab; usb1 = ubh_get_usb_first(USPI_UBH); + usb3 = ubh_get_usb_third(USPI_UBH); - if (!(sb->s_flags & MS_RDONLY)) { - usb1->fs_clean = UFS_FSBAD; - ubh_mark_buffer_dirty(USPI_UBH, 1); - sb->s_dirt = 1; + /* + * Allow the "check" option to be passed as a remount option. + * It is not possible to change ufstype option during remount + */ + ufstype = sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE; + new_mount_opt = 0; + ufs_set_opt (new_mount_opt, ONERROR_LOCK); + if (!ufs_parse_options (data, &new_mount_opt)) + return -EINVAL; + if (!(new_mount_opt & UFS_MOUNT_UFSTYPE)) { + new_mount_opt |= ufstype; + } + else if ((new_mount_opt & UFS_MOUNT_UFSTYPE) != ufstype) { + printk("ufstype can't be changed during remount\n"); + return -EINVAL; + } + sb->u.ufs_sb.s_mount_opt = new_mount_opt; + + if ((*mount_flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) + return 0; + if (*mount_flags & MS_RDONLY) { + ufs_put_cylinder_structures(sb); + usb1->fs_time = SWAB32(CURRENT_TIME); + if (usb1->fs_clean == UFS_FSCLEAN && (flags&UFS_ST_MASK) == UFS_ST_SUN) + ufs_set_fs_state(usb3, UFS_FSOK - SWAB32(usb1->fs_time)); + ubh_mark_buffer_dirty (USPI_UBH, 1); + sb->s_dirt = 0; sb->s_flags |= MS_RDONLY; } - va_start (args, fmt); - vsprintf (error_buf, fmt, args); - va_end (args); - printk (KERN_CRIT "UFS-fs error (device %s): %s: %s\n", - kdevname(sb->s_dev), function, error_buf); + else { + if (ufstype != UFS_MOUNT_UFSTYPE_SUN && + ufstype != UFS_MOUNT_UFSTYPE_44BSD) { + printk("this ufstype is read-only supported\n"); + return 0; + } + if (!ufs_read_cylinder_structures (sb)) { + printk("failed during remounting\n"); + return 0; + } + sb->s_flags &= ~MS_RDONLY; + } + return 0; } -void ufs_panic (struct super_block * sb, const char * function, - const char * fmt, ...) +int ufs_statfs (struct super_block * sb, struct statfs * buf, int bufsiz) { struct ufs_sb_private_info * uspi; struct ufs_super_block_first * usb1; - va_list args; - + struct statfs tmp; + unsigned swab; + + swab = sb->u.ufs_sb.s_swab; uspi = sb->u.ufs_sb.s_uspi; - usb1 = ubh_get_usb_first(USPI_UBH); + usb1 = ubh_get_usb_first (USPI_UBH); - if (!(sb->s_flags & MS_RDONLY)) { - usb1->fs_clean = UFS_FSBAD; - ubh_mark_buffer_dirty(USPI_UBH, 1); - sb->s_dirt = 1; - } - va_start (args, fmt); - vsprintf (error_buf, fmt, args); - va_end (args); - /* this is to prevent panic from syncing this filesystem */ - if (sb->s_lock) - sb->s_lock = 0; - sb->s_flags |= MS_RDONLY; - printk (KERN_CRIT "UFS-fs panic (device %s): %s: %s\n", - kdevname(sb->s_dev), function, error_buf); -/* panic ("UFS-fs panic (device %s): %s: %s\n", - kdevname(sb->s_dev), function, error_buf); -*/ + tmp.f_type = UFS_MAGIC; + tmp.f_bsize = sb->s_blocksize; + tmp.f_blocks = uspi->s_dsize; + tmp.f_bfree = ufs_blkstofrags(SWAB32(usb1->fs_cstotal.cs_nbfree)) + + SWAB32(usb1->fs_cstotal.cs_nffree); + tmp.f_bavail = (tmp.f_bfree > ((tmp.f_blocks / 100) * uspi->s_minfree)) + ? (tmp.f_bfree - ((tmp.f_blocks / 100) * uspi->s_minfree)) : 0; + tmp.f_files = uspi->s_ncg * uspi->s_ipg; + tmp.f_ffree = SWAB32(usb1->fs_cstotal.cs_nifree); + tmp.f_namelen = UFS_MAXNAMLEN; + return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0; } - static struct super_operations ufs_super_ops = { ufs_read_inode, ufs_write_inode, @@ -687,20 +879,19 @@ static struct super_operations ufs_super_ops = { ufs_put_super, ufs_write_super, ufs_statfs, - NULL, /* XXX - ufs_remount() */ + ufs_remount }; static struct file_system_type ufs_fs_type = { - "ufs", + "ufs", FS_REQUIRES_DEV, ufs_read_super, NULL }; - __initfunc(int init_ufs_fs(void)) { - return(register_filesystem(&ufs_fs_type)); + return register_filesystem(&ufs_fs_type); } #ifdef MODULE @@ -715,5 +906,5 @@ void cleanup_module(void) { unregister_filesystem(&ufs_fs_type); } -#endif +#endif |