📄 super.c
字号:
/* * linux/fs/ufs/super.c * * Copyright (C) 1998 * Daniel Pirkl <daniel.pirkl@email.cz> * Charles University, Faculty of Mathematics and Physics *//* Derived 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 */ /* * Inspired by * * linux/fs/ufs/super.c * * Copyright (C) 1996 * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu) * Laboratory for Computer Science Research Computing Facility * Rutgers, The State University of New Jersey * * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) * * Kernel module support added on 96/04/26 by * Stefan Reinauer <stepan@home.culture.mipt.ru> * * Module usage counts added on 96/04/29 by * Gertjan van Wingerde <gertjan@cs.vu.nl> * * Clean swab support on 19970406 by * Francois-Rene Rideau <fare@tunes.org> * * 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>. * * write support Daniel Pirkl <daniel.pirkl@email.cz> 1998 * * HP/UX hfs filesystem support added by * Martin K. Petersen <mkp@mkp.net>, August 1999 * */#include <linux/config.h>#include <linux/module.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/slab.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#ifdef UFS_SUPER_DEBUG#define UFSD(x) printk("(%s, %d), %s: ", __FILE__, __LINE__, __FUNCTION__); printk x;#else#define UFSD(x)#endif#ifdef UFS_SUPER_DEBUG_MORE/* * Print contents of ufs_super_block, useful for debugging */void ufs_print_super_stuff(struct super_block *sb, struct ufs_super_block_first * usb1, struct ufs_super_block_second * usb2, struct ufs_super_block_third * usb3){ printk("ufs_print_super_stuff\n"); printk("size of usb: %u\n", sizeof(struct ufs_super_block)); printk(" magic: 0x%x\n", fs32_to_cpu(sb, usb3->fs_magic)); printk(" sblkno: %u\n", fs32_to_cpu(sb, usb1->fs_sblkno)); printk(" cblkno: %u\n", fs32_to_cpu(sb, usb1->fs_cblkno)); printk(" iblkno: %u\n", fs32_to_cpu(sb, usb1->fs_iblkno)); printk(" dblkno: %u\n", fs32_to_cpu(sb, usb1->fs_dblkno)); printk(" cgoffset: %u\n", fs32_to_cpu(sb, usb1->fs_cgoffset)); printk(" ~cgmask: 0x%x\n", ~fs32_to_cpu(sb, usb1->fs_cgmask)); printk(" size: %u\n", fs32_to_cpu(sb, usb1->fs_size)); printk(" dsize: %u\n", fs32_to_cpu(sb, usb1->fs_dsize)); printk(" ncg: %u\n", fs32_to_cpu(sb, usb1->fs_ncg)); printk(" bsize: %u\n", fs32_to_cpu(sb, usb1->fs_bsize)); printk(" fsize: %u\n", fs32_to_cpu(sb, usb1->fs_fsize)); printk(" frag: %u\n", fs32_to_cpu(sb, usb1->fs_frag)); printk(" fragshift: %u\n", fs32_to_cpu(sb, usb1->fs_fragshift)); printk(" ~fmask: %u\n", ~fs32_to_cpu(sb, usb1->fs_fmask)); printk(" fshift: %u\n", fs32_to_cpu(sb, usb1->fs_fshift)); printk(" sbsize: %u\n", fs32_to_cpu(sb, usb1->fs_sbsize)); printk(" spc: %u\n", fs32_to_cpu(sb, usb1->fs_spc)); printk(" cpg: %u\n", fs32_to_cpu(sb, usb1->fs_cpg)); printk(" ipg: %u\n", fs32_to_cpu(sb, usb1->fs_ipg)); printk(" fpg: %u\n", fs32_to_cpu(sb, usb1->fs_fpg)); printk(" csaddr: %u\n", fs32_to_cpu(sb, usb1->fs_csaddr)); printk(" cssize: %u\n", fs32_to_cpu(sb, usb1->fs_cssize)); printk(" cgsize: %u\n", fs32_to_cpu(sb, usb1->fs_cgsize)); printk(" fstodb: %u\n", fs32_to_cpu(sb, usb1->fs_fsbtodb)); printk(" contigsumsize: %d\n", fs32_to_cpu(sb, usb3->fs_u2.fs_44.fs_contigsumsize)); printk(" postblformat: %u\n", fs32_to_cpu(sb, usb3->fs_postblformat)); printk(" nrpos: %u\n", fs32_to_cpu(sb, usb3->fs_nrpos)); printk(" ndir %u\n", fs32_to_cpu(sb, usb1->fs_cstotal.cs_ndir)); printk(" nifree %u\n", fs32_to_cpu(sb, usb1->fs_cstotal.cs_nifree)); printk(" nbfree %u\n", fs32_to_cpu(sb, usb1->fs_cstotal.cs_nbfree)); printk(" nffree %u\n", fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree)); printk("\n");}/* * Print contents of ufs_cylinder_group, useful for debugging */void ufs_print_cylinder_stuff(struct super_block *sb, struct ufs_cylinder_group *cg){ printk("\nufs_print_cylinder_stuff\n"); printk("size of ucg: %u\n", sizeof(struct ufs_cylinder_group)); printk(" magic: %x\n", fs32_to_cpu(sb, cg->cg_magic)); printk(" time: %u\n", fs32_to_cpu(sb, cg->cg_time)); printk(" cgx: %u\n", fs32_to_cpu(sb, cg->cg_cgx)); printk(" ncyl: %u\n", fs16_to_cpu(sb, cg->cg_ncyl)); printk(" niblk: %u\n", fs16_to_cpu(sb, cg->cg_niblk)); printk(" ndblk: %u\n", fs32_to_cpu(sb, cg->cg_ndblk)); printk(" cs_ndir: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_ndir)); printk(" cs_nbfree: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_nbfree)); printk(" cs_nifree: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_nifree)); printk(" cs_nffree: %u\n", fs32_to_cpu(sb, cg->cg_cs.cs_nffree)); printk(" rotor: %u\n", fs32_to_cpu(sb, cg->cg_rotor)); printk(" frotor: %u\n", fs32_to_cpu(sb, cg->cg_frotor)); printk(" irotor: %u\n", fs32_to_cpu(sb, cg->cg_irotor)); printk(" frsum: %u, %u, %u, %u, %u, %u, %u, %u\n", fs32_to_cpu(sb, cg->cg_frsum[0]), fs32_to_cpu(sb, cg->cg_frsum[1]), fs32_to_cpu(sb, cg->cg_frsum[2]), fs32_to_cpu(sb, cg->cg_frsum[3]), fs32_to_cpu(sb, cg->cg_frsum[4]), fs32_to_cpu(sb, cg->cg_frsum[5]), fs32_to_cpu(sb, cg->cg_frsum[6]), fs32_to_cpu(sb, cg->cg_frsum[7])); printk(" btotoff: %u\n", fs32_to_cpu(sb, cg->cg_btotoff)); printk(" boff: %u\n", fs32_to_cpu(sb, cg->cg_boff)); printk(" iuseoff: %u\n", fs32_to_cpu(sb, cg->cg_iusedoff)); printk(" freeoff: %u\n", fs32_to_cpu(sb, cg->cg_freeoff)); printk(" nextfreeoff: %u\n", fs32_to_cpu(sb, cg->cg_nextfreeoff)); printk(" clustersumoff %u\n", fs32_to_cpu(sb, cg->cg_u.cg_44.cg_clustersumoff)); printk(" clusteroff %u\n", fs32_to_cpu(sb, cg->cg_u.cg_44.cg_clusteroff)); printk(" nclusterblks %u\n", fs32_to_cpu(sb, cg->cg_u.cg_44.cg_nclusterblks)); printk("\n");}#endif /* UFS_SUPER_DEBUG_MORE */static struct super_operations ufs_super_ops;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); 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); sb->s_dirt = 1; } va_start (args, fmt); vsprintf (error_buf, fmt, args); va_end (args); sb->s_flags |= MS_RDONLY; printk (KERN_CRIT "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, "nextstep")) ufs_set_opt (*mount_options, UFSTYPE_NEXTSTEP); else if (!strcmp (value, "nextstep-cd")) ufs_set_opt (*mount_options, UFSTYPE_NEXTSTEP_CD); else if (!strcmp (value, "openstep")) ufs_set_opt (*mount_options, UFSTYPE_OPENSTEP); else if (!strcmp (value, "sunx86")) ufs_set_opt (*mount_options, UFSTYPE_SUNx86); else if (!strcmp (value, "hp")) ufs_set_opt (*mount_options, UFSTYPE_HP); 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 associated 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; UFSD(("ENTER\n")) uspi = sb->u.ufs_sb.s_uspi; /* * Read cs structures from (usually) first data block * on the device. */ size = uspi->s_cssize; blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift; 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, 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] = sb_bread(sb, ufs_cgcmin(i)))) goto failed; if (!ufs_cg_chkmagic (sb, (struct ufs_cylinder_group *) sb->u.ufs_sb.s_ucg[i]->b_data)) goto failed;#ifdef UFS_SUPER_DEBUG_MORE ufs_print_cylinder_stuff(sb, (struct ufs_cylinder_group *) sb->u.ufs_sb.s_ucg[i]->b_data);#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;}/* * Put on-disk structures associated with cylinder groups and * write them back to disk */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 = (size + uspi->s_fsize - 1) >> uspi->s_fshift; 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, uspi->s_csaddr + i, size); ubh_memcpyubh (ubh, space, size); space += size; ubh_mark_buffer_uptodate (ubh, 1); ubh_mark_buffer_dirty (ubh); 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; struct inode *inode; unsigned block_size, super_block_size; unsigned flags; uspi = NULL; ubh = NULL; flags = 0; UFSD(("ENTER\n")) UFSD(("flag %u\n", (int)(sb->s_flags & MS_RDONLY))) #ifndef CONFIG_UFS_FS_WRITE if (!(sb->s_flags & MS_RDONLY)) { printk("ufs was compiled with read-only support, " "can't be mounted as read-write\n"); goto failed; }#endif /* * 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 the type of your ufs filesystem\n\n" "mount -t ufs -o ufstype=" "sun|sunx86|44bsd|old|hp|nextstep|netxstep-cd|openstep ...\n\n" ">>>WARNING<<< Wrong ufstype may corrupt your filesystem, " "default 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; /* Keep 2Gig file limit. Some UFS variants need to override this but as I don't know which I'll let those in the know loosen the rules */ switch (sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE) { case UFS_MOUNT_UFSTYPE_44BSD:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -