📄 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 <gwingerde@gmail.com> * * 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 * * UFS2 (of FreeBSD 5.x) support added by * Niraj Kumar <niraj17@iitbombay.org>, Jan 2004 * * UFS2 write support added by * Evgeniy Dushistov <dushistov@mail.ru>, 2007 */#include <linux/module.h>#include <linux/bitops.h>#include <stdarg.h>#include <asm/uaccess.h>#include <asm/system.h>#include <linux/errno.h>#include <linux/fs.h>#include <linux/quotaops.h>#include <linux/slab.h>#include <linux/time.h>#include <linux/stat.h>#include <linux/string.h>#include <linux/blkdev.h>#include <linux/init.h>#include <linux/parser.h>#include <linux/smp_lock.h>#include <linux/buffer_head.h>#include <linux/vfs.h>#include <linux/log2.h>#include <linux/mount.h>#include <linux/seq_file.h>#include "ufs_fs.h"#include "ufs.h"#include "swab.h"#include "util.h"#ifdef CONFIG_UFS_DEBUG/* * Print contents of ufs_super_block, useful for debugging */static 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){ u32 magic = fs32_to_cpu(sb, usb3->fs_magic); printk("ufs_print_super_stuff\n"); printk(" magic: 0x%x\n", magic); if (fs32_to_cpu(sb, usb3->fs_magic) == UFS2_MAGIC) { printk(" fs_size: %llu\n", (unsigned long long) fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_size)); printk(" fs_dsize: %llu\n", (unsigned long long) fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_dsize)); printk(" bsize: %u\n", fs32_to_cpu(sb, usb1->fs_bsize)); printk(" fsize: %u\n", fs32_to_cpu(sb, usb1->fs_fsize)); printk(" fs_volname: %s\n", usb2->fs_un.fs_u2.fs_volname); printk(" fs_sblockloc: %llu\n", (unsigned long long) fs64_to_cpu(sb, usb2->fs_un.fs_u2.fs_sblockloc)); printk(" cs_ndir(No of dirs): %llu\n", (unsigned long long) fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_ndir)); printk(" cs_nbfree(No of free blocks): %llu\n", (unsigned long long) fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_nbfree)); printk(KERN_INFO" cs_nifree(Num of free inodes): %llu\n", (unsigned long long) fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nifree)); printk(KERN_INFO" cs_nffree(Num of free frags): %llu\n", (unsigned long long) fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nffree)); printk(KERN_INFO" fs_maxsymlinklen: %u\n", fs32_to_cpu(sb, usb3->fs_un2.fs_44.fs_maxsymlinklen)); } else { 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(" 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 */static void ufs_print_cylinder_stuff(struct super_block *sb, struct ufs_cylinder_group *cg){ printk("\nufs_print_cylinder_stuff\n"); printk("size of ucg: %zu\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");}#else# define ufs_print_super_stuff(sb, usb1, usb2, usb3) /**/# define ufs_print_cylinder_stuff(sb, cg) /**/#endif /* CONFIG_UFS_DEBUG */static const 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 = UFS_SB(sb)->s_uspi; usb1 = ubh_get_usb_first(uspi); if (!(sb->s_flags & MS_RDONLY)) { usb1->fs_clean = UFS_FSBAD; ubh_mark_buffer_dirty(USPI_UBH(uspi)); sb->s_dirt = 1; sb->s_flags |= MS_RDONLY; } va_start (args, fmt); vsnprintf (error_buf, sizeof(error_buf), fmt, args); va_end (args); switch (UFS_SB(sb)->s_mount_opt & UFS_MOUNT_ONERROR) { case UFS_MOUNT_ONERROR_PANIC: panic ("UFS-fs panic (device %s): %s: %s\n", sb->s_id, 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", sb->s_id, 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 = UFS_SB(sb)->s_uspi; usb1 = ubh_get_usb_first(uspi); if (!(sb->s_flags & MS_RDONLY)) { usb1->fs_clean = UFS_FSBAD; ubh_mark_buffer_dirty(USPI_UBH(uspi)); sb->s_dirt = 1; } va_start (args, fmt); vsnprintf (error_buf, sizeof(error_buf), fmt, args); va_end (args); sb->s_flags |= MS_RDONLY; printk (KERN_CRIT "UFS-fs panic (device %s): %s: %s\n", sb->s_id, function, error_buf);}void ufs_warning (struct super_block * sb, const char * function, const char * fmt, ...){ va_list args; va_start (args, fmt); vsnprintf (error_buf, sizeof(error_buf), fmt, args); va_end (args); printk (KERN_WARNING "UFS-fs warning (device %s): %s: %s\n", sb->s_id, function, error_buf);}enum { Opt_type_old = UFS_MOUNT_UFSTYPE_OLD, Opt_type_sunx86 = UFS_MOUNT_UFSTYPE_SUNx86, Opt_type_sun = UFS_MOUNT_UFSTYPE_SUN, Opt_type_sunos = UFS_MOUNT_UFSTYPE_SUNOS, Opt_type_44bsd = UFS_MOUNT_UFSTYPE_44BSD, Opt_type_ufs2 = UFS_MOUNT_UFSTYPE_UFS2, Opt_type_hp = UFS_MOUNT_UFSTYPE_HP, Opt_type_nextstepcd = UFS_MOUNT_UFSTYPE_NEXTSTEP_CD, Opt_type_nextstep = UFS_MOUNT_UFSTYPE_NEXTSTEP, Opt_type_openstep = UFS_MOUNT_UFSTYPE_OPENSTEP, Opt_onerror_panic = UFS_MOUNT_ONERROR_PANIC, Opt_onerror_lock = UFS_MOUNT_ONERROR_LOCK, Opt_onerror_umount = UFS_MOUNT_ONERROR_UMOUNT, Opt_onerror_repair = UFS_MOUNT_ONERROR_REPAIR, Opt_err};static const match_table_t tokens = { {Opt_type_old, "ufstype=old"}, {Opt_type_sunx86, "ufstype=sunx86"}, {Opt_type_sun, "ufstype=sun"}, {Opt_type_sunos, "ufstype=sunos"}, {Opt_type_44bsd, "ufstype=44bsd"}, {Opt_type_ufs2, "ufstype=ufs2"}, {Opt_type_ufs2, "ufstype=5xbsd"}, {Opt_type_hp, "ufstype=hp"}, {Opt_type_nextstepcd, "ufstype=nextstep-cd"}, {Opt_type_nextstep, "ufstype=nextstep"}, {Opt_type_openstep, "ufstype=openstep"},/*end of possible ufs types */ {Opt_onerror_panic, "onerror=panic"}, {Opt_onerror_lock, "onerror=lock"}, {Opt_onerror_umount, "onerror=umount"}, {Opt_onerror_repair, "onerror=repair"}, {Opt_err, NULL}};static int ufs_parse_options (char * options, unsigned * mount_options){ char * p; UFSD("ENTER\n"); if (!options) return 1; while ((p = strsep(&options, ",")) != NULL) { substring_t args[MAX_OPT_ARGS]; int token; if (!*p) continue; token = match_token(p, tokens, args); switch (token) { case Opt_type_old: ufs_clear_opt (*mount_options, UFSTYPE); ufs_set_opt (*mount_options, UFSTYPE_OLD); break; case Opt_type_sunx86: ufs_clear_opt (*mount_options, UFSTYPE); ufs_set_opt (*mount_options, UFSTYPE_SUNx86); break; case Opt_type_sun: ufs_clear_opt (*mount_options, UFSTYPE); ufs_set_opt (*mount_options, UFSTYPE_SUN); break; case Opt_type_sunos: ufs_clear_opt(*mount_options, UFSTYPE); ufs_set_opt(*mount_options, UFSTYPE_SUNOS); break; case Opt_type_44bsd: ufs_clear_opt (*mount_options, UFSTYPE); ufs_set_opt (*mount_options, UFSTYPE_44BSD); break; case Opt_type_ufs2: ufs_clear_opt(*mount_options, UFSTYPE); ufs_set_opt(*mount_options, UFSTYPE_UFS2); break; case Opt_type_hp: ufs_clear_opt (*mount_options, UFSTYPE); ufs_set_opt (*mount_options, UFSTYPE_HP); break; case Opt_type_nextstepcd: ufs_clear_opt (*mount_options, UFSTYPE); ufs_set_opt (*mount_options, UFSTYPE_NEXTSTEP_CD); break; case Opt_type_nextstep: ufs_clear_opt (*mount_options, UFSTYPE); ufs_set_opt (*mount_options, UFSTYPE_NEXTSTEP); break; case Opt_type_openstep: ufs_clear_opt (*mount_options, UFSTYPE); ufs_set_opt (*mount_options, UFSTYPE_OPENSTEP); break; case Opt_onerror_panic: ufs_clear_opt (*mount_options, ONERROR); ufs_set_opt (*mount_options, ONERROR_PANIC); break; case Opt_onerror_lock: ufs_clear_opt (*mount_options, ONERROR); ufs_set_opt (*mount_options, ONERROR_LOCK); break; case Opt_onerror_umount: ufs_clear_opt (*mount_options, ONERROR); ufs_set_opt (*mount_options, ONERROR_UMOUNT); break; case Opt_onerror_repair: printk("UFS-fs: Unable to do repair on error, " "will lock lock instead\n"); ufs_clear_opt (*mount_options, ONERROR); ufs_set_opt (*mount_options, ONERROR_REPAIR); break; default: printk("UFS-fs: Invalid option: \"%s\" " "or missing value\n", p); return 0; } } return 1;}/* * Diffrent types of UFS hold fs_cstotal in different * places, and use diffrent data structure for it. * To make things simplier we just copy fs_cstotal to ufs_sb_private_info */static void ufs_setup_cstotal(struct super_block *sb){ struct ufs_sb_info *sbi = UFS_SB(sb); struct ufs_sb_private_info *uspi = sbi->s_uspi; struct ufs_super_block_first *usb1; struct ufs_super_block_second *usb2; struct ufs_super_block_third *usb3; unsigned mtype = sbi->s_mount_opt & UFS_MOUNT_UFSTYPE; UFSD("ENTER, mtype=%u\n", mtype); usb1 = ubh_get_usb_first(uspi); usb2 = ubh_get_usb_second(uspi); usb3 = ubh_get_usb_third(uspi); if ((mtype == UFS_MOUNT_UFSTYPE_44BSD && (usb1->fs_flags & UFS_FLAGS_UPDATED)) || mtype == UFS_MOUNT_UFSTYPE_UFS2) { /*we have statistic in different place, then usual*/ uspi->cs_total.cs_ndir = fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_ndir); uspi->cs_total.cs_nbfree = fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_nbfree); uspi->cs_total.cs_nifree = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nifree); uspi->cs_total.cs_nffree = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nffree); } else { uspi->cs_total.cs_ndir = fs32_to_cpu(sb, usb1->fs_cstotal.cs_ndir); uspi->cs_total.cs_nbfree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nbfree); uspi->cs_total.cs_nifree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nifree); uspi->cs_total.cs_nffree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree); } UFSD("EXIT\n");}/* * Read on-disk structures associated with cylinder groups */static int ufs_read_cylinder_structures(struct super_block *sb){ struct ufs_sb_info *sbi = UFS_SB(sb); struct ufs_sb_private_info *uspi = sbi->s_uspi; struct ufs_buffer_head * ubh; unsigned char * base, * space; unsigned size, blks, i; struct ufs_super_block_third *usb3; UFSD("ENTER\n"); usb3 = ubh_get_usb_third(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; sbi->s_csp = (struct ufs_csum *)space; 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); space += size; ubh_brelse (ubh); ubh = NULL; } /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -