⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 super.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  linux/fs/hpfs/super.c * *  Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999 * *  mounting, unmounting, error handling */#include "hpfs_fn.h"#include <linux/module.h>#include <linux/parser.h>#include <linux/init.h>#include <linux/statfs.h>#include <linux/magic.h>#include <linux/sched.h>/* Mark the filesystem dirty, so that chkdsk checks it when os/2 booted */static void mark_dirty(struct super_block *s){	if (hpfs_sb(s)->sb_chkdsk && !(s->s_flags & MS_RDONLY)) {		struct buffer_head *bh;		struct hpfs_spare_block *sb;		if ((sb = hpfs_map_sector(s, 17, &bh, 0))) {			sb->dirty = 1;			sb->old_wrote = 0;			mark_buffer_dirty(bh);			brelse(bh);		}	}}/* Mark the filesystem clean (mark it dirty for chkdsk if chkdsk==2 or if there   were errors) */static void unmark_dirty(struct super_block *s){	struct buffer_head *bh;	struct hpfs_spare_block *sb;	if (s->s_flags & MS_RDONLY) return;	if ((sb = hpfs_map_sector(s, 17, &bh, 0))) {		sb->dirty = hpfs_sb(s)->sb_chkdsk > 1 - hpfs_sb(s)->sb_was_error;		sb->old_wrote = hpfs_sb(s)->sb_chkdsk >= 2 && !hpfs_sb(s)->sb_was_error;		mark_buffer_dirty(bh);		brelse(bh);	}}/* Filesystem error... */static char err_buf[1024];void hpfs_error(struct super_block *s, const char *fmt, ...){	va_list args;	va_start(args, fmt);	vsnprintf(err_buf, sizeof(err_buf), fmt, args);	va_end(args);	printk("HPFS: filesystem error: %s", err_buf);	if (!hpfs_sb(s)->sb_was_error) {		if (hpfs_sb(s)->sb_err == 2) {			printk("; crashing the system because you wanted it\n");			mark_dirty(s);			panic("HPFS panic");		} else if (hpfs_sb(s)->sb_err == 1) {			if (s->s_flags & MS_RDONLY) printk("; already mounted read-only\n");			else {				printk("; remounting read-only\n");				mark_dirty(s);				s->s_flags |= MS_RDONLY;			}		} else if (s->s_flags & MS_RDONLY) printk("; going on - but anything won't be destroyed because it's read-only\n");		else printk("; corrupted filesystem mounted read/write - your computer will explode within 20 seconds ... but you wanted it so!\n");	} else printk("\n");	hpfs_sb(s)->sb_was_error = 1;}/*  * A little trick to detect cycles in many hpfs structures and don't let the * kernel crash on corrupted filesystem. When first called, set c2 to 0. * * BTW. chkdsk doesn't detect cycles correctly. When I had 2 lost directories * nested each in other, chkdsk locked up happilly. */int hpfs_stop_cycles(struct super_block *s, int key, int *c1, int *c2,		char *msg){	if (*c2 && *c1 == key) {		hpfs_error(s, "cycle detected on key %08x in %s", key, msg);		return 1;	}	(*c2)++;	if (!((*c2 - 1) & *c2)) *c1 = key;	return 0;}static void hpfs_put_super(struct super_block *s){	struct hpfs_sb_info *sbi = hpfs_sb(s);	kfree(sbi->sb_cp_table);	kfree(sbi->sb_bmp_dir);	unmark_dirty(s);	s->s_fs_info = NULL;	kfree(sbi);}unsigned hpfs_count_one_bitmap(struct super_block *s, secno secno){	struct quad_buffer_head qbh;	unsigned *bits;	unsigned i, count;	if (!(bits = hpfs_map_4sectors(s, secno, &qbh, 4))) return 0;	count = 0;	for (i = 0; i < 2048 / sizeof(unsigned); i++) {		unsigned b; 		if (!bits[i]) continue;		for (b = bits[i]; b; b>>=1) count += b & 1;	}	hpfs_brelse4(&qbh);	return count;}static unsigned count_bitmaps(struct super_block *s){	unsigned n, count, n_bands;	n_bands = (hpfs_sb(s)->sb_fs_size + 0x3fff) >> 14;	count = 0;	for (n = 0; n < n_bands; n++)		count += hpfs_count_one_bitmap(s, hpfs_sb(s)->sb_bmp_dir[n]);	return count;}static int hpfs_statfs(struct dentry *dentry, struct kstatfs *buf){	struct super_block *s = dentry->d_sb;	struct hpfs_sb_info *sbi = hpfs_sb(s);	lock_kernel();	/*if (sbi->sb_n_free == -1) {*/		sbi->sb_n_free = count_bitmaps(s);		sbi->sb_n_free_dnodes = hpfs_count_one_bitmap(s, sbi->sb_dmap);	/*}*/	buf->f_type = s->s_magic;	buf->f_bsize = 512;	buf->f_blocks = sbi->sb_fs_size;	buf->f_bfree = sbi->sb_n_free;	buf->f_bavail = sbi->sb_n_free;	buf->f_files = sbi->sb_dirband_size / 4;	buf->f_ffree = sbi->sb_n_free_dnodes;	buf->f_namelen = 254;	unlock_kernel();	return 0;}static struct kmem_cache * hpfs_inode_cachep;static struct inode *hpfs_alloc_inode(struct super_block *sb){	struct hpfs_inode_info *ei;	ei = (struct hpfs_inode_info *)kmem_cache_alloc(hpfs_inode_cachep, GFP_NOFS);	if (!ei)		return NULL;	ei->vfs_inode.i_version = 1;	return &ei->vfs_inode;}static void hpfs_destroy_inode(struct inode *inode){	kmem_cache_free(hpfs_inode_cachep, hpfs_i(inode));}static void init_once(struct kmem_cache *cachep, void *foo){	struct hpfs_inode_info *ei = (struct hpfs_inode_info *) foo;	mutex_init(&ei->i_mutex);	mutex_init(&ei->i_parent_mutex);	inode_init_once(&ei->vfs_inode);}static int init_inodecache(void){	hpfs_inode_cachep = kmem_cache_create("hpfs_inode_cache",					     sizeof(struct hpfs_inode_info),					     0, (SLAB_RECLAIM_ACCOUNT|						SLAB_MEM_SPREAD),					     init_once);	if (hpfs_inode_cachep == NULL)		return -ENOMEM;	return 0;}static void destroy_inodecache(void){	kmem_cache_destroy(hpfs_inode_cachep);}/* * A tiny parser for option strings, stolen from dosfs. * Stolen again from read-only hpfs. * And updated for table-driven option parsing. */enum {	Opt_help, Opt_uid, Opt_gid, Opt_umask, Opt_case_lower, Opt_case_asis,	Opt_conv_binary, Opt_conv_text, Opt_conv_auto,	Opt_check_none, Opt_check_normal, Opt_check_strict,	Opt_err_cont, Opt_err_ro, Opt_err_panic,	Opt_eas_no, Opt_eas_ro, Opt_eas_rw,	Opt_chkdsk_no, Opt_chkdsk_errors, Opt_chkdsk_always,	Opt_timeshift, Opt_err,};static match_table_t tokens = {	{Opt_help, "help"},	{Opt_uid, "uid=%u"},	{Opt_gid, "gid=%u"},	{Opt_umask, "umask=%o"},	{Opt_case_lower, "case=lower"},	{Opt_case_asis, "case=asis"},	{Opt_conv_binary, "conv=binary"},	{Opt_conv_text, "conv=text"},	{Opt_conv_auto, "conv=auto"},	{Opt_check_none, "check=none"},	{Opt_check_normal, "check=normal"},	{Opt_check_strict, "check=strict"},	{Opt_err_cont, "errors=continue"},	{Opt_err_ro, "errors=remount-ro"},	{Opt_err_panic, "errors=panic"},	{Opt_eas_no, "eas=no"},	{Opt_eas_ro, "eas=ro"},	{Opt_eas_rw, "eas=rw"},	{Opt_chkdsk_no, "chkdsk=no"},	{Opt_chkdsk_errors, "chkdsk=errors"},	{Opt_chkdsk_always, "chkdsk=always"},	{Opt_timeshift, "timeshift=%d"},	{Opt_err, NULL},};static int parse_opts(char *opts, uid_t *uid, gid_t *gid, umode_t *umask,		      int *lowercase, int *conv, int *eas, int *chk, int *errs,		      int *chkdsk, int *timeshift){	char *p;	int option;	if (!opts)		return 1;	/*printk("Parsing opts: '%s'\n",opts);*/	while ((p = strsep(&opts, ",")) != NULL) {		substring_t args[MAX_OPT_ARGS];		int token;		if (!*p)			continue;		token = match_token(p, tokens, args);		switch (token) {		case Opt_help:			return 2;		case Opt_uid:			if (match_int(args, &option))				return 0;			*uid = option;			break;		case Opt_gid:			if (match_int(args, &option))				return 0;			*gid = option;			break;		case Opt_umask:			if (match_octal(args, &option))				return 0;			*umask = option;			break;		case Opt_case_lower:			*lowercase = 1;			break;		case Opt_case_asis:			*lowercase = 0;			break;		case Opt_conv_binary:			*conv = CONV_BINARY;			break;		case Opt_conv_text:			*conv = CONV_TEXT;			break;		case Opt_conv_auto:			*conv = CONV_AUTO;			break;		case Opt_check_none:			*chk = 0;			break;		case Opt_check_normal:			*chk = 1;			break;		case Opt_check_strict:			*chk = 2;			break;		case Opt_err_cont:			*errs = 0;			break;		case Opt_err_ro:			*errs = 1;			break;		case Opt_err_panic:			*errs = 2;			break;		case Opt_eas_no:			*eas = 0;			break;		case Opt_eas_ro:			*eas = 1;			break;		case Opt_eas_rw:			*eas = 2;			break;		case Opt_chkdsk_no:			*chkdsk = 0;			break;		case Opt_chkdsk_errors:			*chkdsk = 1;			break;		case Opt_chkdsk_always:			*chkdsk = 2;			break;		case Opt_timeshift:		{			int m = 1;			char *rhs = args[0].from;			if (!rhs || !*rhs)				return 0;			if (*rhs == '-') m = -1;			if (*rhs == '+' || *rhs == '-') rhs++;			*timeshift = simple_strtoul(rhs, &rhs, 0) * m;			if (*rhs)				return 0;			break;		}		default:			return 0;		}	}	return 1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -