📄 super.c
字号:
/* * linux/fs/hpfs/super.c * * Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999 * * mounting, unmounting, error handling */#include <linux/string.h>#include "hpfs_fn.h"#include <linux/module.h>#include <linux/init.h>/* Mark the filesystem dirty, so that chkdsk checks it when os/2 booted */static void mark_dirty(struct super_block *s){ if (s->s_hpfs_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 = s->s_hpfs_chkdsk > 1 - s->s_hpfs_was_error; sb->old_wrote = s->s_hpfs_chkdsk >= 2 && !s->s_hpfs_was_error; mark_buffer_dirty(bh); brelse(bh); }}/* Filesystem error... */#define ERR_BUF_SIZE 1024void hpfs_error(struct super_block *s, char *m,...){ char *buf; va_list l; va_start(l, m); if (!(buf = kmalloc(ERR_BUF_SIZE, GFP_KERNEL))) printk("HPFS: No memory for error message '%s'\n",m); else if (vsprintf(buf, m, l) >= ERR_BUF_SIZE) printk("HPFS: Grrrr... Kernel memory corrupted ... going on, but it'll crash very soon :-(\n"); printk("HPFS: filesystem error: "); if (buf) printk("%s", buf); else printk("%s\n",m); if (!s->s_hpfs_was_error) { if (s->s_hpfs_err == 2) { printk("; crashing the system because you wanted it\n"); mark_dirty(s); panic("HPFS panic"); } else if (s->s_hpfs_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"); if (buf) kfree(buf); s->s_hpfs_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;}void hpfs_put_super(struct super_block *s){ if (s->s_hpfs_cp_table) kfree(s->s_hpfs_cp_table); if (s->s_hpfs_bmp_dir) kfree(s->s_hpfs_bmp_dir); unmark_dirty(s);}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 = (s->s_hpfs_fs_size + 0x3fff) >> 14; count = 0; for (n = 0; n < n_bands; n++) count += hpfs_count_one_bitmap(s, s->s_hpfs_bmp_dir[n]); return count;}int hpfs_statfs(struct super_block *s, struct statfs *buf){ /*if (s->s_hpfs_n_free == -1) {*/ s->s_hpfs_n_free = count_bitmaps(s); s->s_hpfs_n_free_dnodes = hpfs_count_one_bitmap(s, s->s_hpfs_dmap); /*}*/ buf->f_type = s->s_magic; buf->f_bsize = 512; buf->f_blocks = s->s_hpfs_fs_size; buf->f_bfree = s->s_hpfs_n_free; buf->f_bavail = s->s_hpfs_n_free; buf->f_files = s->s_hpfs_dirband_size / 4; buf->f_ffree = s->s_hpfs_n_free_dnodes; buf->f_namelen = 254; return 0;}/* Super operations */static struct super_operations hpfs_sops ={ read_inode: hpfs_read_inode, delete_inode: hpfs_delete_inode, put_super: hpfs_put_super, statfs: hpfs_statfs, remount_fs: hpfs_remount_fs,};/* * A tiny parser for option strings, stolen from dosfs. * * Stolen again from read-only hpfs. */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, *rhs; if (!opts) return 1; /*printk("Parsing opts: '%s'\n",opts);*/ for (p = strtok(opts, ","); p != 0; p = strtok(0, ",")) { if ((rhs = strchr(p, '=')) != 0) *rhs++ = '\0'; if (!strcmp(p, "help")) return 2; if (!strcmp(p, "uid")) { if (!rhs || !*rhs) return 0; *uid = simple_strtoul(rhs, &rhs, 0); if (*rhs) return 0; } else if (!strcmp(p, "gid")) { if (!rhs || !*rhs) return 0; *gid = simple_strtoul(rhs, &rhs, 0); if (*rhs) return 0; } else if (!strcmp(p, "umask")) { if (!rhs || !*rhs) return 0; *umask = simple_strtoul(rhs, &rhs, 8); if (*rhs) return 0; } else if (!strcmp(p, "timeshift")) { int m = 1; if (!rhs || !*rhs) return 0; if (*rhs == '-') m = -1; if (*rhs == '+' || *rhs == '-') rhs++; *timeshift = simple_strtoul(rhs, &rhs, 0) * m; if (*rhs) return 0; } else if (!strcmp(p, "case")) { if (!rhs || !*rhs) return 0; if (!strcmp(rhs, "lower")) *lowercase = 1; else if (!strcmp(rhs, "asis")) *lowercase = 0; else return 0; } else if (!strcmp(p, "conv")) { if (!rhs || !*rhs) return 0; if (!strcmp(rhs, "binary")) *conv = CONV_BINARY; else if (!strcmp(rhs, "text")) *conv = CONV_TEXT; else if (!strcmp(rhs, "auto")) *conv = CONV_AUTO; else return 0; } else if (!strcmp(p, "check")) { if (!rhs || !*rhs) return 0; if (!strcmp(rhs, "none")) *chk = 0; else if (!strcmp(rhs, "normal")) *chk = 1; else if (!strcmp(rhs, "strict")) *chk = 2; else return 0; } else if (!strcmp(p, "errors")) { if (!rhs || !*rhs) return 0; if (!strcmp(rhs, "continue")) *errs = 0; else if (!strcmp(rhs, "remount-ro")) *errs = 1; else if (!strcmp(rhs, "panic")) *errs = 2; else return 0; } else if (!strcmp(p, "eas")) { if (!rhs || !*rhs) return 0; if (!strcmp(rhs, "no")) *eas = 0; else if (!strcmp(rhs, "ro")) *eas = 1; else if (!strcmp(rhs, "rw")) *eas = 2; else return 0; } else if (!strcmp(p, "chkdsk")) { if (!rhs || !*rhs) return 0; if (!strcmp(rhs, "no")) *chkdsk = 0; else if (!strcmp(rhs, "errors")) *chkdsk = 1; else if (!strcmp(rhs, "always")) *chkdsk = 2; else return 0; } else return 0; } return 1;}static inline void hpfs_help(void){ printk("\n\HPFS filesystem options:\n\ help do not mount and display this text\n\
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -