📄 super.c
字号:
static void reiserfs_kill_sb(struct super_block *s){ if (REISERFS_SB(s)) {#ifdef CONFIG_REISERFS_FS_XATTR if (REISERFS_SB(s)->xattr_root) { d_invalidate(REISERFS_SB(s)->xattr_root); dput(REISERFS_SB(s)->xattr_root); REISERFS_SB(s)->xattr_root = NULL; }#endif if (REISERFS_SB(s)->priv_root) { d_invalidate(REISERFS_SB(s)->priv_root); dput(REISERFS_SB(s)->priv_root); REISERFS_SB(s)->priv_root = NULL; } } kill_block_super(s);}static void reiserfs_put_super(struct super_block *s){ struct reiserfs_transaction_handle th; th.t_trans_id = 0; /* change file system state to current state if it was mounted with read-write permissions */ if (!(s->s_flags & MS_RDONLY)) { if (!journal_begin(&th, s, 10)) { reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); set_sb_umount_state(SB_DISK_SUPER_BLOCK(s), REISERFS_SB(s)->s_mount_state); journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s)); } } /* note, journal_release checks for readonly mount, and can decide not ** to do a journal_end */ journal_release(&th, s); reiserfs_free_bitmap_cache(s); brelse(SB_BUFFER_WITH_SB(s)); print_statistics(s); if (REISERFS_SB(s)->reserved_blocks != 0) { reiserfs_warning(s, "green-2005: reiserfs_put_super: reserved blocks left %d", REISERFS_SB(s)->reserved_blocks); } reiserfs_proc_info_done(s); kfree(s->s_fs_info); s->s_fs_info = NULL; return;}static struct kmem_cache *reiserfs_inode_cachep;static struct inode *reiserfs_alloc_inode(struct super_block *sb){ struct reiserfs_inode_info *ei; ei = (struct reiserfs_inode_info *) kmem_cache_alloc(reiserfs_inode_cachep, GFP_KERNEL); if (!ei) return NULL; return &ei->vfs_inode;}static void reiserfs_destroy_inode(struct inode *inode){ kmem_cache_free(reiserfs_inode_cachep, REISERFS_I(inode));}static void init_once(struct kmem_cache * cachep, void *foo){ struct reiserfs_inode_info *ei = (struct reiserfs_inode_info *)foo; INIT_LIST_HEAD(&ei->i_prealloc_list); inode_init_once(&ei->vfs_inode);#ifdef CONFIG_REISERFS_FS_POSIX_ACL ei->i_acl_access = NULL; ei->i_acl_default = NULL;#endif}static int init_inodecache(void){ reiserfs_inode_cachep = kmem_cache_create("reiser_inode_cache", sizeof(struct reiserfs_inode_info), 0, (SLAB_RECLAIM_ACCOUNT| SLAB_MEM_SPREAD), init_once); if (reiserfs_inode_cachep == NULL) return -ENOMEM; return 0;}static void destroy_inodecache(void){ kmem_cache_destroy(reiserfs_inode_cachep);}/* we don't mark inodes dirty, we just log them */static void reiserfs_dirty_inode(struct inode *inode){ struct reiserfs_transaction_handle th; int err = 0; if (inode->i_sb->s_flags & MS_RDONLY) { reiserfs_warning(inode->i_sb, "clm-6006: writing inode %lu on readonly FS", inode->i_ino); return; } reiserfs_write_lock(inode->i_sb); /* this is really only used for atime updates, so they don't have ** to be included in O_SYNC or fsync */ err = journal_begin(&th, inode->i_sb, 1); if (err) { reiserfs_write_unlock(inode->i_sb); return; } reiserfs_update_sd(&th, inode); journal_end(&th, inode->i_sb, 1); reiserfs_write_unlock(inode->i_sb);}#ifdef CONFIG_REISERFS_FS_POSIX_ACLstatic void reiserfs_clear_inode(struct inode *inode){ struct posix_acl *acl; acl = REISERFS_I(inode)->i_acl_access; if (acl && !IS_ERR(acl)) posix_acl_release(acl); REISERFS_I(inode)->i_acl_access = NULL; acl = REISERFS_I(inode)->i_acl_default; if (acl && !IS_ERR(acl)) posix_acl_release(acl); REISERFS_I(inode)->i_acl_default = NULL;}#else#define reiserfs_clear_inode NULL#endif#ifdef CONFIG_QUOTAstatic ssize_t reiserfs_quota_write(struct super_block *, int, const char *, size_t, loff_t);static ssize_t reiserfs_quota_read(struct super_block *, int, char *, size_t, loff_t);#endifstatic const struct super_operations reiserfs_sops = { .alloc_inode = reiserfs_alloc_inode, .destroy_inode = reiserfs_destroy_inode, .write_inode = reiserfs_write_inode, .dirty_inode = reiserfs_dirty_inode, .delete_inode = reiserfs_delete_inode, .clear_inode = reiserfs_clear_inode, .put_super = reiserfs_put_super, .write_super = reiserfs_write_super, .sync_fs = reiserfs_sync_fs, .write_super_lockfs = reiserfs_write_super_lockfs, .unlockfs = reiserfs_unlockfs, .statfs = reiserfs_statfs, .remount_fs = reiserfs_remount,#ifdef CONFIG_QUOTA .quota_read = reiserfs_quota_read, .quota_write = reiserfs_quota_write,#endif};#ifdef CONFIG_QUOTA#define QTYPE2NAME(t) ((t)==USRQUOTA?"user":"group")static int reiserfs_dquot_initialize(struct inode *, int);static int reiserfs_dquot_drop(struct inode *);static int reiserfs_write_dquot(struct dquot *);static int reiserfs_acquire_dquot(struct dquot *);static int reiserfs_release_dquot(struct dquot *);static int reiserfs_mark_dquot_dirty(struct dquot *);static int reiserfs_write_info(struct super_block *, int);static int reiserfs_quota_on(struct super_block *, int, int, char *);static struct dquot_operations reiserfs_quota_operations = { .initialize = reiserfs_dquot_initialize, .drop = reiserfs_dquot_drop, .alloc_space = dquot_alloc_space, .alloc_inode = dquot_alloc_inode, .free_space = dquot_free_space, .free_inode = dquot_free_inode, .transfer = dquot_transfer, .write_dquot = reiserfs_write_dquot, .acquire_dquot = reiserfs_acquire_dquot, .release_dquot = reiserfs_release_dquot, .mark_dirty = reiserfs_mark_dquot_dirty, .write_info = reiserfs_write_info,};static struct quotactl_ops reiserfs_qctl_operations = { .quota_on = reiserfs_quota_on, .quota_off = vfs_quota_off, .quota_sync = vfs_quota_sync, .get_info = vfs_get_dqinfo, .set_info = vfs_set_dqinfo, .get_dqblk = vfs_get_dqblk, .set_dqblk = vfs_set_dqblk,};#endifstatic const struct export_operations reiserfs_export_ops = { .encode_fh = reiserfs_encode_fh, .fh_to_dentry = reiserfs_fh_to_dentry, .fh_to_parent = reiserfs_fh_to_parent, .get_parent = reiserfs_get_parent,};/* this struct is used in reiserfs_getopt () for containing the value for those mount options that have values rather than being toggles. */typedef struct { char *value; int setmask; /* bitmask which is to set on mount_options bitmask when this value is found, 0 is no bits are to be changed. */ int clrmask; /* bitmask which is to clear on mount_options bitmask when this value is found, 0 is no bits are to be changed. This is applied BEFORE setmask */} arg_desc_t;/* Set this bit in arg_required to allow empty arguments */#define REISERFS_OPT_ALLOWEMPTY 31/* this struct is used in reiserfs_getopt() for describing the set of reiserfs mount options */typedef struct { char *option_name; int arg_required; /* 0 if argument is not required, not 0 otherwise */ const arg_desc_t *values; /* list of values accepted by an option */ int setmask; /* bitmask which is to set on mount_options bitmask when this value is found, 0 is no bits are to be changed. */ int clrmask; /* bitmask which is to clear on mount_options bitmask when this value is found, 0 is no bits are to be changed. This is applied BEFORE setmask */} opt_desc_t;/* possible values for -o data= */static const arg_desc_t logging_mode[] = { {"ordered", 1 << REISERFS_DATA_ORDERED, (1 << REISERFS_DATA_LOG | 1 << REISERFS_DATA_WRITEBACK)}, {"journal", 1 << REISERFS_DATA_LOG, (1 << REISERFS_DATA_ORDERED | 1 << REISERFS_DATA_WRITEBACK)}, {"writeback", 1 << REISERFS_DATA_WRITEBACK, (1 << REISERFS_DATA_ORDERED | 1 << REISERFS_DATA_LOG)}, {.value = NULL}};/* possible values for -o barrier= */static const arg_desc_t barrier_mode[] = { {"none", 1 << REISERFS_BARRIER_NONE, 1 << REISERFS_BARRIER_FLUSH}, {"flush", 1 << REISERFS_BARRIER_FLUSH, 1 << REISERFS_BARRIER_NONE}, {.value = NULL}};/* possible values for "-o block-allocator=" and bits which are to be set in s_mount_opt of reiserfs specific part of in-core super block */static const arg_desc_t balloc[] = { {"noborder", 1 << REISERFS_NO_BORDER, 0}, {"border", 0, 1 << REISERFS_NO_BORDER}, {"no_unhashed_relocation", 1 << REISERFS_NO_UNHASHED_RELOCATION, 0}, {"hashed_relocation", 1 << REISERFS_HASHED_RELOCATION, 0}, {"test4", 1 << REISERFS_TEST4, 0}, {"notest4", 0, 1 << REISERFS_TEST4}, {NULL, 0, 0}};static const arg_desc_t tails[] = { {"on", 1 << REISERFS_LARGETAIL, 1 << REISERFS_SMALLTAIL}, {"off", 0, (1 << REISERFS_LARGETAIL) | (1 << REISERFS_SMALLTAIL)}, {"small", 1 << REISERFS_SMALLTAIL, 1 << REISERFS_LARGETAIL}, {NULL, 0, 0}};static const arg_desc_t error_actions[] = { {"panic", 1 << REISERFS_ERROR_PANIC, (1 << REISERFS_ERROR_RO | 1 << REISERFS_ERROR_CONTINUE)}, {"ro-remount", 1 << REISERFS_ERROR_RO, (1 << REISERFS_ERROR_PANIC | 1 << REISERFS_ERROR_CONTINUE)},#ifdef REISERFS_JOURNAL_ERROR_ALLOWS_NO_LOG {"continue", 1 << REISERFS_ERROR_CONTINUE, (1 << REISERFS_ERROR_PANIC | 1 << REISERFS_ERROR_RO)},#endif {NULL, 0, 0},};/* proceed only one option from a list *cur - string containing of mount options opts - array of options which are accepted opt_arg - if option is found and requires an argument and if it is specifed in the input - pointer to the argument is stored here bit_flags - if option requires to set a certain bit - it is set here return -1 if unknown option is found, opt->arg_required otherwise */static int reiserfs_getopt(struct super_block *s, char **cur, opt_desc_t * opts, char **opt_arg, unsigned long *bit_flags){ char *p; /* foo=bar, ^ ^ ^ | | +-- option_end | +-- arg_start +-- option_start */ const opt_desc_t *opt; const arg_desc_t *arg; p = *cur; /* assume argument cannot contain commas */ *cur = strchr(p, ','); if (*cur) { *(*cur) = '\0'; (*cur)++; } if (!strncmp(p, "alloc=", 6)) { /* Ugly special case, probably we should redo options parser so that it can understand several arguments for some options, also so that it can fill several bitfields with option values. */ if (reiserfs_parse_alloc_options(s, p + 6)) { return -1; } else { return 0; } } /* for every option in the list */ for (opt = opts; opt->option_name; opt++) { if (!strncmp(p, opt->option_name, strlen(opt->option_name))) { if (bit_flags) { if (opt->clrmask == (1 << REISERFS_UNSUPPORTED_OPT)) reiserfs_warning(s, "%s not supported.", p); else *bit_flags &= ~opt->clrmask; if (opt->setmask == (1 << REISERFS_UNSUPPORTED_OPT)) reiserfs_warning(s, "%s not supported.", p); else *bit_flags |= opt->setmask; } break; } } if (!opt->option_name) { reiserfs_warning(s, "unknown mount option \"%s\"", p); return -1; } p += strlen(opt->option_name); switch (*p) { case '=': if (!opt->arg_required) { reiserfs_warning(s, "the option \"%s\" does not require an argument", opt->option_name); return -1; } break; case 0: if (opt->arg_required) { reiserfs_warning(s, "the option \"%s\" requires an argument", opt->option_name); return -1; } break; default: reiserfs_warning(s, "head of option \"%s\" is only correct", opt->option_name); return -1; } /* move to the argument, or to next option if argument is not required */ p++; if (opt->arg_required && !(opt->arg_required & (1 << REISERFS_OPT_ALLOWEMPTY)) && !strlen(p)) { /* this catches "option=," if not allowed */ reiserfs_warning(s, "empty argument for \"%s\"", opt->option_name); return -1; } if (!opt->values) { /* *=NULLopt_arg contains pointer to argument */ *opt_arg = p; return opt->arg_required & ~(1 << REISERFS_OPT_ALLOWEMPTY); } /* values possible for this option are listed in opt->values */ for (arg = opt->values; arg->value; arg++) { if (!strcmp(p, arg->value)) { if (bit_flags) { *bit_flags &= ~arg->clrmask; *bit_flags |= arg->setmask; } return opt->arg_required; } } reiserfs_warning(s, "bad value \"%s\" for option \"%s\"", p, opt->option_name); return -1;}/* returns 0 if something is wrong in option string, 1 - otherwise */static int reiserfs_parse_options(struct super_block *s, char *options, /* string given via mount's -o */ unsigned long *mount_options, /* after the parsing phase, contains the collection of bitflags defining what mount options were selected. */ unsigned long *blocks, /* strtol-ed from NNN of resize=NNN */ char **jdev_name, unsigned int *commit_max_age){ int c; char *arg = NULL; char *pos; opt_desc_t opts[] = { /* Compatibility stuff, so that -o notail for old setups still work */ {"tails",.arg_required = 't',.values = tails}, {"notail",.clrmask =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -