cregit-Linux how code gets into the kernel

Release 4.17 fs/ext2/super.c

Directory: fs/ext2
/*
 *  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
 */

#include <linux/module.h>
#include <linux/string.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/blkdev.h>
#include <linux/parser.h>
#include <linux/random.h>
#include <linux/buffer_head.h>
#include <linux/exportfs.h>
#include <linux/vfs.h>
#include <linux/seq_file.h>
#include <linux/mount.h>
#include <linux/log2.h>
#include <linux/quotaops.h>
#include <linux/uaccess.h>
#include <linux/dax.h>
#include <linux/iversion.h>
#include "ext2.h"
#include "xattr.h"
#include "acl.h"

static void ext2_write_super(struct super_block *sb);
static int ext2_remount (struct super_block * sb, int * flags, char * data);
static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf);
static int ext2_sync_fs(struct super_block *sb, int wait);
static int ext2_freeze(struct super_block *sb);
static int ext2_unfreeze(struct super_block *sb);


void ext2_error(struct super_block *sb, const char *function, const char *fmt, ...) { struct va_format vaf; va_list args; struct ext2_sb_info *sbi = EXT2_SB(sb); struct ext2_super_block *es = sbi->s_es; if (!sb_rdonly(sb)) { spin_lock(&sbi->s_lock); sbi->s_mount_state |= EXT2_ERROR_FS; es->s_state |= cpu_to_le16(EXT2_ERROR_FS); spin_unlock(&sbi->s_lock); ext2_sync_super(sb, es, 1); } va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; printk(KERN_CRIT "EXT2-fs (%s): error: %s: %pV\n", sb->s_id, function, &vaf); va_end(args); if (test_opt(sb, ERRORS_PANIC)) panic("EXT2-fs: panic from previous error\n"); if (test_opt(sb, ERRORS_RO)) { ext2_msg(sb, KERN_CRIT, "error: remounting filesystem read-only"); sb->s_flags |= SB_RDONLY; } }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)9553.37%428.57%
Joe Perches2011.24%17.14%
Jan Blunck1810.11%214.29%
Linus Torvalds158.43%214.29%
Brian Gerst105.62%17.14%
Matt Mackall95.06%17.14%
Alexey Fisher73.93%17.14%
David Howells31.69%17.14%
Marcin Ślusarz10.56%17.14%
Total178100.00%14100.00%


void ext2_msg(struct super_block *sb, const char *prefix, const char *fmt, ...) { struct va_format vaf; va_list args; va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; printk("%sEXT2-fs (%s): %pV\n", prefix, sb->s_id, &vaf); va_end(args); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)3450.00%125.00%
Joe Perches2029.41%125.00%
Matt Mackall1014.71%125.00%
Alexey Fisher45.88%125.00%
Total68100.00%4100.00%

/* * This must be called with sbi->s_lock held. */
void ext2_update_dynamic_rev(struct super_block *sb) { struct ext2_super_block *es = EXT2_SB(sb)->s_es; if (le32_to_cpu(es->s_rev_level) > EXT2_GOOD_OLD_REV) return; ext2_msg(sb, KERN_WARNING, "warning: updating to rev %d because of " "new feature flag, running e2fsck is recommended", EXT2_DYNAMIC_REV); es->s_first_ino = cpu_to_le32(EXT2_GOOD_OLD_FIRST_INO); es->s_inode_size = cpu_to_le16(EXT2_GOOD_OLD_INODE_SIZE); es->s_rev_level = cpu_to_le32(EXT2_DYNAMIC_REV); /* leave es->s_feature_*compat flags alone */ /* es->s_uuid will be set by e2fsck if empty */ /* * The rest of the superblock fields should be zero, and if not it * means they are likely already in use, so leave them alone. We * can leave it up to e2fsck to clean up any inconsistencies there. */ }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)7294.74%150.00%
Alexey Fisher45.26%150.00%
Total76100.00%2100.00%

#ifdef CONFIG_QUOTA static int ext2_quota_off(struct super_block *sb, int type);
static void ext2_quota_off_umount(struct super_block *sb) { int type; for (type = 0; type < MAXQUOTAS; type++) ext2_quota_off(sb, type); }

Contributors

PersonTokensPropCommitsCommitProp
Jan Kara34100.00%1100.00%
Total34100.00%1100.00%

#else
static inline void ext2_quota_off_umount(struct super_block *sb) { }

Contributors

PersonTokensPropCommitsCommitProp
Jan Kara11100.00%1100.00%
Total11100.00%1100.00%

#endif
static void ext2_put_super (struct super_block * sb) { int db_count; int i; struct ext2_sb_info *sbi = EXT2_SB(sb); ext2_quota_off_umount(sb); if (sbi->s_ea_block_cache) { ext2_xattr_destroy_cache(sbi->s_ea_block_cache); sbi->s_ea_block_cache = NULL; } if (!sb_rdonly(sb)) { struct ext2_super_block *es = sbi->s_es; spin_lock(&sbi->s_lock); es->s_state = cpu_to_le16(sbi->s_mount_state); spin_unlock(&sbi->s_lock); ext2_sync_super(sb, es, 1); } db_count = sbi->s_gdb_count; for (i = 0; i < db_count; i++) if (sbi->s_group_desc[i]) brelse (sbi->s_group_desc[i]); kfree(sbi->s_group_desc); kfree(sbi->s_debts); percpu_counter_destroy(&sbi->s_freeblocks_counter); percpu_counter_destroy(&sbi->s_freeinodes_counter); percpu_counter_destroy(&sbi->s_dirs_counter); brelse (sbi->s_sbh); sb->s_fs_info = NULL; kfree(sbi->s_blockgroup_lock); fs_put_dax(sbi->s_daxdev); kfree(sbi); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)8438.89%625.00%
Brian Gerst2812.96%312.50%
Heiko Carstens2411.11%14.17%
Jan Blunck188.33%28.33%
Jan Kara167.41%28.33%
Linus Torvalds104.63%14.17%
Theodore Y. Ts'o104.63%28.33%
Dan J Williams73.24%14.17%
Pekka J Enberg73.24%14.17%
Christoph Hellwig41.85%14.17%
Tahsin Erdogan31.39%14.17%
David Howells31.39%14.17%
Al Viro10.46%14.17%
Stephen Rothwell10.46%14.17%
Total216100.00%24100.00%

static struct kmem_cache * ext2_inode_cachep;
static struct inode *ext2_alloc_inode(struct super_block *sb) { struct ext2_inode_info *ei; ei = kmem_cache_alloc(ext2_inode_cachep, GFP_KERNEL); if (!ei) return NULL; ei->i_block_alloc_info = NULL; inode_set_iversion(&ei->vfs_inode, 1); #ifdef CONFIG_QUOTA memset(&ei->i_dquot, 0, sizeof(ei->i_dquot)); #endif return &ei->vfs_inode; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds4050.63%116.67%
Jan Kara2227.85%116.67%
Martin J. Bligh67.59%116.67%
Andrew Morton56.33%116.67%
Jeff Layton56.33%116.67%
Christoph Lameter11.27%116.67%
Total79100.00%6100.00%


static void ext2_i_callback(struct rcu_head *head) { struct inode *inode = container_of(head, struct inode, i_rcu); kmem_cache_free(ext2_inode_cachep, EXT2_I(inode)); }

Contributors

PersonTokensPropCommitsCommitProp
Nicholas Piggin1850.00%150.00%
Linus Torvalds1850.00%150.00%
Total36100.00%2100.00%


static void ext2_destroy_inode(struct inode *inode) { call_rcu(&inode->i_rcu, ext2_i_callback); }

Contributors

PersonTokensPropCommitsCommitProp
Nicholas Piggin21100.00%1100.00%
Total21100.00%1100.00%


static void init_once(void *foo) { struct ext2_inode_info *ei = (struct ext2_inode_info *) foo; rwlock_init(&ei->i_meta_lock); #ifdef CONFIG_EXT2_FS_XATTR init_rwsem(&ei->xattr_sem); #endif mutex_init(&ei->truncate_mutex); #ifdef CONFIG_FS_DAX init_rwsem(&ei->dax_sem); #endif inode_init_once(&ei->vfs_inode); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds2737.50%116.67%
Ross Zwisler1318.06%116.67%
Andrew Morton1318.06%116.67%
Al Viro811.11%116.67%
Martin J. Bligh811.11%116.67%
Christoph Lameter34.17%116.67%
Total72100.00%6100.00%


static int __init init_inodecache(void) { ext2_inode_cachep = kmem_cache_create_usercopy("ext2_inode_cache", sizeof(struct ext2_inode_info), 0, (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD| SLAB_ACCOUNT), offsetof(struct ext2_inode_info, i_data), sizeof_field(struct ext2_inode_info, i_data), init_once); if (ext2_inode_cachep == NULL) return -ENOMEM; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds3860.32%114.29%
David Windsor1726.98%114.29%
Paul Jackson46.35%228.57%
Vladimir Davydov23.17%114.29%
Fabian Frederick11.59%114.29%
Andrew Morton11.59%114.29%
Total63100.00%7100.00%


static void destroy_inodecache(void) { /* * Make sure all delayed rcu free inodes are flushed before we * destroy cache. */ rcu_barrier(); kmem_cache_destroy(ext2_inode_cachep); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds1376.47%150.00%
Kirill A. Shutemov423.53%150.00%
Total17100.00%2100.00%


static int ext2_show_options(struct seq_file *seq, struct dentry *root) { struct super_block *sb = root->d_sb; struct ext2_sb_info *sbi = EXT2_SB(sb); struct ext2_super_block *es = sbi->s_es; unsigned long def_mount_opts; spin_lock(&sbi->s_lock); def_mount_opts = le32_to_cpu(es->s_default_mount_opts); if (sbi->s_sb_block != 1) seq_printf(seq, ",sb=%lu", sbi->s_sb_block); if (test_opt(sb, MINIX_DF)) seq_puts(seq, ",minixdf"); if (test_opt(sb, GRPID)) seq_puts(seq, ",grpid"); if (!test_opt(sb, GRPID) && (def_mount_opts & EXT2_DEFM_BSDGROUPS)) seq_puts(seq, ",nogrpid"); if (!uid_eq(sbi->s_resuid, make_kuid(&init_user_ns, EXT2_DEF_RESUID)) || le16_to_cpu(es->s_def_resuid) != EXT2_DEF_RESUID) { seq_printf(seq, ",resuid=%u", from_kuid_munged(&init_user_ns, sbi->s_resuid)); } if (!gid_eq(sbi->s_resgid, make_kgid(&init_user_ns, EXT2_DEF_RESGID)) || le16_to_cpu(es->s_def_resgid) != EXT2_DEF_RESGID) { seq_printf(seq, ",resgid=%u", from_kgid_munged(&init_user_ns, sbi->s_resgid)); } if (test_opt(sb, ERRORS_RO)) { int def_errors = le16_to_cpu(es->s_errors); if (def_errors == EXT2_ERRORS_PANIC || def_errors == EXT2_ERRORS_CONTINUE) { seq_puts(seq, ",errors=remount-ro"); } } if (test_opt(sb, ERRORS_CONT)) seq_puts(seq, ",errors=continue"); if (test_opt(sb, ERRORS_PANIC)) seq_puts(seq, ",errors=panic"); if (test_opt(sb, NO_UID32)) seq_puts(seq, ",nouid32"); if (test_opt(sb, DEBUG)) seq_puts(seq, ",debug"); if (test_opt(sb, OLDALLOC)) seq_puts(seq, ",oldalloc"); #ifdef CONFIG_EXT2_FS_XATTR if (test_opt(sb, XATTR_USER)) seq_puts(seq, ",user_xattr"); if (!test_opt(sb, XATTR_USER) && (def_mount_opts & EXT2_DEFM_XATTR_USER)) { seq_puts(seq, ",nouser_xattr"); } #endif #ifdef CONFIG_EXT2_FS_POSIX_ACL if (test_opt(sb, POSIX_ACL)) seq_puts(seq, ",acl"); if (!test_opt(sb, POSIX_ACL) && (def_mount_opts & EXT2_DEFM_ACL)) seq_puts(seq, ",noacl"); #endif if (test_opt(sb, NOBH)) seq_puts(seq, ",nobh"); #if defined(CONFIG_QUOTA) if (sbi->s_mount_opt & EXT2_MOUNT_USRQUOTA) seq_puts(seq, ",usrquota"); if (sbi->s_mount_opt & EXT2_MOUNT_GRPQUOTA) seq_puts(seq, ",grpquota"); #endif #ifdef CONFIG_FS_DAX if (sbi->s_mount_opt & EXT2_MOUNT_XIP) seq_puts(seq, ",xip"); if (sbi->s_mount_opt & EXT2_MOUNT_DAX) seq_puts(seq, ",dax"); #endif if (!test_opt(sb, RESERVATION)) seq_puts(seq, ",noreservation"); spin_unlock(&sbi->s_lock); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Miklos Szeredi38869.53%220.00%
Mark Bellon7613.62%110.00%
Eric W. Biedermann346.09%110.00%
Matthew Wilcox183.23%220.00%
Carsten Otte173.05%110.00%
Jan Blunck162.87%110.00%
Aneesh Kumar K.V50.90%110.00%
Al Viro40.72%110.00%
Total558100.00%10100.00%

#ifdef CONFIG_QUOTA static ssize_t ext2_quota_read(struct super_block *sb, int type, char *data, size_t len, loff_t off); static ssize_t ext2_quota_write(struct super_block *sb, int type, const char *data, size_t len, loff_t off); static int ext2_quota_on(struct super_block *sb, int type, int format_id, const struct path *path);
static struct dquot **ext2_get_dquots(struct inode *inode) { return EXT2_I(inode)->i_dquot; }

Contributors

PersonTokensPropCommitsCommitProp
Jan Kara22100.00%1100.00%
Total22100.00%1100.00%

static const struct quotactl_ops ext2_quotactl_ops = { .quota_on = ext2_quota_on, .quota_off = ext2_quota_off, .quota_sync = dquot_quota_sync, .get_state = dquot_get_state, .set_info = dquot_set_dqinfo, .get_dqblk = dquot_get_dqblk, .set_dqblk = dquot_set_dqblk, .get_nextdqblk = dquot_get_next_dqblk, }; #endif static const struct super_operations ext2_sops = { .alloc_inode = ext2_alloc_inode, .destroy_inode = ext2_destroy_inode, .write_inode = ext2_write_inode, .evict_inode = ext2_evict_inode, .put_super = ext2_put_super, .sync_fs = ext2_sync_fs, .freeze_fs = ext2_freeze, .unfreeze_fs = ext2_unfreeze, .statfs = ext2_statfs, .remount_fs = ext2_remount, .show_options = ext2_show_options, #ifdef CONFIG_QUOTA .quota_read = ext2_quota_read, .quota_write = ext2_quota_write, .get_dquots = ext2_get_dquots, #endif };
static struct inode *ext2_nfs_get_inode(struct super_block *sb, u64 ino, u32 generation) { struct inode *inode; if (ino < EXT2_FIRST_INO(sb) && ino != EXT2_ROOT_INO) return ERR_PTR(-ESTALE); if (ino > le32_to_cpu(EXT2_SB(sb)->s_es->s_inodes_count)) return ERR_PTR(-ESTALE); /* * ext2_iget isn't quite right if the inode is currently unallocated! * However ext2_iget currently does appropriate checks to handle stale * inodes so everything is OK. */ inode = ext2_iget(sb, ino); if (IS_ERR(inode)) return ERR_CAST(inode); if (generation && inode->i_generation != generation) { /* we didn't find the right inode.. */ iput(inode); return ERR_PTR(-ESTALE); } return inode; }

Contributors

PersonTokensPropCommitsCommitProp
Neil Brown10185.59%125.00%
Christoph Hellwig108.47%125.00%
David Howells65.08%125.00%
Li Haifeng10.85%125.00%
Total118100.00%4100.00%


static struct dentry *ext2_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len, int fh_type) { return generic_fh_to_dentry(sb, fid, fh_len, fh_type, ext2_nfs_get_inode); }

Contributors

PersonTokensPropCommitsCommitProp
Christoph Hellwig3284.21%150.00%
Neil Brown615.79%150.00%
Total38100.00%2100.00%


static struct dentry *ext2_fh_to_parent(struct super_block *sb, struct fid *fid, int fh_len, int fh_type) { return generic_fh_to_parent(sb, fid, fh_len, fh_type, ext2_nfs_get_inode); }

Contributors

PersonTokensPropCommitsCommitProp
Christoph Hellwig3592.11%150.00%
Neil Brown37.89%150.00%
Total38100.00%2100.00%

static const struct export_operations ext2_export_ops = { .fh_to_dentry = ext2_fh_to_dentry, .fh_to_parent = ext2_fh_to_parent, .get_parent = ext2_get_parent, };
static unsigned long get_sb_block(void **data) { unsigned long sb_block; char *options = (char *) *data; if (!options || strncmp(options, "sb=", 3) != 0) return 1; /* Default location */ options += 3; sb_block = simple_strtoul(options, &options, 0); if (*options && *options != ',') { printk("EXT2-fs: Invalid sb specification: %s\n", (char *) *data); return 1; } if (*options == ',') options++; *data = (void *) options; return sb_block; }

Contributors

PersonTokensPropCommitsCommitProp
Theodore Y. Ts'o112100.00%1100.00%
Total112100.00%1100.00%

enum { Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid, Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro, Opt_nouid32, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov, Opt_nobh, Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, Opt_xip, Opt_dax, Opt_ignore, Opt_err, Opt_quota, Opt_usrquota, Opt_grpquota, Opt_reservation, Opt_noreservation }; static const match_table_t tokens = { {Opt_bsd_df, "bsddf"}, {Opt_minix_df, "minixdf"}, {Opt_grpid, "grpid"}, {Opt_grpid, "bsdgroups"}, {Opt_nogrpid, "nogrpid"}, {Opt_nogrpid, "sysvgroups"}, {Opt_resgid, "resgid=%u"}, {Opt_resuid, "resuid=%u"}, {Opt_sb, "sb=%u"}, {Opt_err_cont, "errors=continue"}, {Opt_err_panic, "errors=panic"}, {Opt_err_ro, "errors=remount-ro"}, {Opt_nouid32, "nouid32"}, {Opt_nocheck, "check=none"}, {Opt_nocheck, "nocheck"}, {Opt_debug, "debug"}, {Opt_oldalloc, "oldalloc"}, {Opt_orlov, "orlov"}, {Opt_nobh, "nobh"}, {Opt_user_xattr, "user_xattr"}, {Opt_nouser_xattr, "nouser_xattr"}, {Opt_acl, "acl"}, {Opt_noacl, "noacl"}, {Opt_xip, "xip"}, {Opt_dax, "dax"}, {Opt_grpquota, "grpquota"}, {Opt_ignore, "noquota"}, {Opt_quota, "quota"}, {Opt_usrquota, "usrquota"}, {Opt_reservation, "reservation"}, {Opt_noreservation, "noreservation"}, {Opt_err, NULL} };
static int parse_options(char *options, struct super_block *sb, struct ext2_mount_options *opts) { char *p; substring_t args[MAX_OPT_ARGS]; int option; kuid_t uid; kgid_t gid; if (!options) return 1; while ((p = strsep (&options, ",")) != NULL) { int token; if (!*p) continue; token = match_token(p, tokens, args); switch (token) { case Opt_bsd_df: clear_opt (opts->s_mount_opt, MINIX_DF); break; case Opt_minix_df: set_opt (opts->s_mount_opt, MINIX_DF); break; case Opt_grpid: set_opt (opts->s_mount_opt, GRPID); break; case Opt_nogrpid: clear_opt (opts->s_mount_opt, GRPID); break; case Opt_resuid: if (match_int(&args[0], &option)) return 0; uid = make_kuid(current_user_ns(), option); if (!uid_valid(uid)) { ext2_msg(sb, KERN_ERR, "Invalid uid value %d", option); return 0; } opts->s_resuid = uid; break; case Opt_resgid: if (match_int(&args[0], &option)) return 0; gid = make_kgid(current_user_ns(), option); if (!gid_valid(gid)) { ext2_msg(sb, KERN_ERR, "Invalid gid value %d", option); return 0; } opts->s_resgid = gid; break; case Opt_sb: /* handled by get_sb_block() instead of here */ /* *sb_block = match_int(&args[0]); */ break; case Opt_err_panic: clear_opt (opts->s_mount_opt, ERRORS_CONT); clear_opt (opts->s_mount_opt, ERRORS_RO); set_opt (opts->s_mount_opt, ERRORS_PANIC); break; case Opt_err_ro: clear_opt (opts->s_mount_opt, ERRORS_CONT); clear_opt (opts->s_mount_opt, ERRORS_PANIC); set_opt (opts->s_mount_opt, ERRORS_RO); break; case Opt_err_cont: clear_opt (opts->s_mount_opt, ERRORS_RO); clear_opt (opts->s_mount_opt, ERRORS_PANIC); set_opt (opts->s_mount_opt, ERRORS_CONT); break; case Opt_nouid32: set_opt (opts->s_mount_opt, NO_UID32); break; case Opt_nocheck: clear_opt (opts->s_mount_opt, CHECK); break; case Opt_debug: set_opt (opts->s_mount_opt, DEBUG); break; case Opt_oldalloc: set_opt (opts->s_mount_opt, OLDALLOC); break; case Opt_orlov: clear_opt (opts->s_mount_opt, OLDALLOC); break; case Opt_nobh: set_opt (opts->s_mount_opt, NOBH); break; #ifdef CONFIG_EXT2_FS_XATTR case Opt_user_xattr: set_opt (opts->s_mount_opt, XATTR_USER); break; case Opt_nouser_xattr: clear_opt (opts->s_mount_opt, XATTR_USER); break; #else case Opt_user_xattr: case Opt_nouser_xattr: ext2_msg(sb, KERN_INFO, "(no)user_xattr options" "not supported"); break; #endif #ifdef CONFIG_EXT2_FS_POSIX_ACL case Opt_acl: set_opt(opts->s_mount_opt, POSIX_ACL); break; case Opt_noacl: clear_opt(opts->s_mount_opt, POSIX_ACL); break; #else case Opt_acl: case Opt_noacl: ext2_msg(sb, KERN_INFO, "(no)acl options not supported"); break; #endif case Opt_xip: ext2_msg(sb, KERN_INFO, "use dax instead of xip"); set_opt(opts->s_mount_opt, XIP); /* Fall through */ case Opt_dax: #ifdef CONFIG_FS_DAX ext2_msg(sb, KERN_WARNING, "DAX enabled. Warning: EXPERIMENTAL, use at your own risk"); set_opt(opts->s_mount_opt, DAX); #else ext2_msg(sb, KERN_INFO, "dax option not supported"); #endif break; #if defined(CONFIG_QUOTA) case Opt_quota: case Opt_usrquota: set_opt(opts->s_mount_opt, USRQUOTA); break; case Opt_grpquota: set_opt(opts->s_mount_opt, GRPQUOTA); break; #else case Opt_quota: case Opt_usrquota: case Opt_grpquota: ext2_msg(sb, KERN_INFO, "quota operations not supported"); break; #endif case Opt_reservation: set_opt(opts->s_mount_opt, RESERVATION); ext2_msg(sb, KERN_INFO, "reservations ON"); break; case Opt_noreservation: clear_opt(opts->s_mount_opt, RESERVATION); ext2_msg(sb, KERN_INFO, "reservations OFF"); break; case Opt_ignore: break; default: return 0; } } return 1; }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton23833.29%210.00%
Eric W. Biedermann7410.35%15.00%
Linus Torvalds (pre-git)719.93%525.00%
Vasily Averin699.65%15.00%
Theodore Y. Ts'o547.55%210.00%
Mark Bellon506.99%15.00%
Alexey Fisher385.31%15.00%
Jan Kara365.03%15.00%
Martin J. Bligh304.20%15.00%
Matthew Wilcox243.36%210.00%
Carsten Otte202.80%15.00%
Dan J Williams91.26%15.00%
Zhao Hongjiang20.28%15.00%
Total715100.00%20100.00%


static int ext2_setup_super (struct super_block * sb, struct ext2_super_block * es, int read_only) { int res = 0; struct ext2_sb_info *sbi = EXT2_SB(sb); if (le32_to_cpu(es->s_rev_level) > EXT2_MAX_SUPP_REV) { ext2_msg(sb, KERN_ERR, "error: revision level too high, " "forcing read-only mode"); res = SB_RDONLY; } if (read_only) return res; if (!(sbi->s_mount_state & EXT2_VALID_FS)) ext2_msg(sb, KERN_WARNING, "warning: mounting unchecked fs, " "running e2fsck is recommended"); else if ((sbi->s_mount_state & EXT2_ERROR_FS)) ext2_msg(sb, KERN_WARNING, "warning: mounting fs with errors, " "running e2fsck is recommended"); else if ((__s16) le16_to_cpu(es->s_max_mnt_count) >= 0 && le16_to_cpu(es->s_mnt_count) >= (unsigned short) (__s16) le16_to_cpu(es->s_max_mnt_count)) ext2_msg(sb, KERN_WARNING, "warning: maximal mount count reached, " "running e2fsck is recommended"); else if (le32_to_cpu(es->s_checkinterval) && (le32_to_cpu(es->s_lastcheck) + le32_to_cpu(es->s_checkinterval) <= get_seconds())) ext2_msg(sb, KERN_WARNING, "warning: checktime reached, " "running e2fsck is recommended"); if (!le16_to_cpu(es->s_max_mnt_count)) es->s_max_mnt_count = cpu_to_le16(EXT2_DFL_MAX_MNT_COUNT); le16_add_cpu(&es->s_mnt_count, 1); if (test_opt (sb, DEBUG)) ext2_msg(sb, KERN_INFO, "%s, %s, bs=%lu, fs=%lu, gc=%lu, " "bpg=%lu, ipg=%lu, mo=%04lx]", EXT2FS_VERSION, EXT2FS_DATE, sb->s_blocksize, sbi->s_frag_size, sbi->s_groups_count, EXT2_BLOCKS_PER_GROUP(sb), EXT2_INODES_PER_GROUP(sb), sbi->s_mount_opt); return res; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)21377.17%964.29%
Alexey Fisher4215.22%17.14%
Brian Gerst155.43%17.14%
Marcin Ślusarz31.09%17.14%
Andi Kleen20.72%17.14%
Linus Torvalds10.36%17.14%
Total276100.00%14100.00%


static int ext2_check_descriptors(struct super_block *sb) { int i; struct ext2_sb_info *sbi = EXT2_SB(sb); ext2_debug ("Checking group descriptors"); for (i = 0; i < sbi->s_groups_count; i++) { struct ext2_group_desc *gdp = ext2_get_group_desc(sb, i, NULL); ext2_fsblk_t first_block = ext2_group_first_block_no(sb, i); ext2_fsblk_t last_block; if (i == sbi->s_groups_count - 1) last_block = le32_to_cpu(sbi->s_es->s_blocks_count) - 1; else last_block = first_block + (EXT2_BLOCKS_PER_GROUP(sb) - 1); if (le32_to_cpu(gdp->bg_block_bitmap) < first_block || le32_to_cpu(gdp->bg_block_bitmap) > last_block) { ext2_error (sb, "ext2_check_descriptors", "Block bitmap for group %d" " not in group (block %lu)!", i, (unsigned long) le32_to_cpu(gdp->bg_block_bitmap)); return 0; } if (le32_to_cpu(gdp->bg_inode_bitmap) < first_block || le32_to_cpu(gdp->bg_inode_bitmap) > last_block) { ext2_error (sb, "ext2_check_descriptors", "Inode bitmap for group %d" " not in group (block %lu)!", i, (unsigned long) le32_to_cpu(gdp->bg_inode_bitmap)); return 0; } if (le32_to_cpu(gdp->bg_inode_table) < first_block || le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group - 1 > last_block) { ext2_error (sb, "ext2_check_descriptors", "Inode table for group %d" " not in group (block %lu)!", i, (unsigned long) le32_to_cpu(gdp->bg_inode_table)); return 0; } } return 1; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)17666.92%550.00%
Eric Sandeen4818.25%220.00%
Akinobu Mita2710.27%220.00%
Brian Gerst124.56%110.00%
Total263100.00%10100.00%

/* * Maximal file size. There is a direct, and {,double-,triple-}indirect * block limit, and also a limit of (2^32 - 1) 512-byte sectors in i_blocks. * We need to be 1 filesystem block less than the 2^32 sector limit. */
static loff_t ext2_max_size(int bits) { loff_t res = EXT2_NDIR_BLOCKS; int meta_blocks; loff_t upper_limit; /* This is calculated to be the largest file size for a * dense, file such that the total number of * sectors in the file, including data and all indirect blocks, * does not exceed 2^32 -1 * __u32 i_blocks representing the total number of * 512 bytes blocks of the file */ upper_limit = (1LL << 32) - 1; /* total blocks in file system block size */ upper_limit >>= (bits - 9); /* indirect blocks */ meta_blocks = 1; /* double indirect blocks */ meta_blocks += 1 + (1LL << (bits-2)); /* tripple indirect blocks */ meta_blocks += 1 + (1LL << (bits-2)) + (1LL << (2*(bits-2))); upper_limit -= meta_blocks; upper_limit <<= bits; res += 1LL << (bits-2); res += 1LL << (2*(bits-2)); res += 1LL << (3*(bits-2)); res <<= bits; if (res > upper_limit) res = upper_limit; if (res > MAX_LFS_FILESIZE) res = MAX_LFS_FILESIZE; return res; }

Contributors

PersonTokensPropCommitsCommitProp
Aneesh Kumar K.V9055.56%133.33%
Linus Torvalds6741.36%133.33%
Stephen C. Tweedie53.09%133.33%
Total162100.00%3100.00%


static unsigned long descriptor_loc(struct super_block *sb, unsigned long logic_sb_block, int nr) { struct ext2_sb_info *sbi = EXT2_SB(sb); unsigned long bg, first_meta_bg; int has_super = 0; first_meta_bg = le32_to_cpu(sbi->s_es->s_first_meta_bg); if (!EXT2_HAS_INCOMPAT_FEATURE(sb, EXT2_FEATURE_INCOMPAT_META_BG) || nr < first_meta_bg) return (logic_sb_block + nr + 1); bg = sbi->s_desc_per_block * nr; if (ext2_bg_has_super(sb, bg)) has_super = 1; return ext2_group_first_block_no(sb, bg) + has_super; }

Contributors

PersonTokensPropCommitsCommitProp
Theodore Y. Ts'o9994.29%266.67%
Akinobu Mita65.71%133.33%
Total105100.00%3100.00%


static int ext2_fill_super(struct super_block *sb, void *data, int silent) { struct dax_device *dax_dev = fs_dax_get_by_bdev(sb->s_bdev); struct buffer_head * bh; struct ext2_sb_info * sbi; struct ext2_super_block * es; struct inode *root; unsigned long block; unsigned long sb_block = get_sb_block(&data); unsigned long logic_sb_block; unsigned long offset = 0; unsigned long def_mount_opts; long ret = -ENOMEM; int blocksize = BLOCK_SIZE; int db_count; int i, j; __le32 features; int err; struct ext2_mount_options opts; sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); if (!sbi) goto failed; sbi->s_blockgroup_lock = kzalloc(sizeof(struct blockgroup_lock), GFP_KERNEL); if (!sbi->s_blockgroup_lock) { kfree(sbi); goto failed; } sb->s_fs_info = sbi; sbi->s_sb_block = sb_block; sbi->s_daxdev = dax_dev; spin_lock_init(&sbi->s_lock); ret = -EINVAL; /* * See what the current blocksize for the device is, and * use that as the blocksize. Otherwise (or if the blocksize * is smaller than the default) use the default. * This is important for devices that have a hardware * sectorsize that is larger than the default. */ blocksize = sb_min_blocksize(sb, BLOCK_SIZE); if (!blocksize) { ext2_msg(sb, KERN_ERR, "error: unable to set blocksize"); goto failed_sbi; } /* * If the superblock doesn't start on a hardware sector boundary, * calculate the offset. */ if (blocksize != BLOCK_SIZE) { logic_sb_block = (sb_block*BLOCK_SIZE) / blocksize; offset = (sb_block*BLOCK_SIZE) % blocksize; } else { logic_sb_block = sb_block; } if (!(bh = sb_bread(sb, logic_sb_block))) { ext2_msg(sb, KERN_ERR, "error: unable to read superblock"); goto failed_sbi; } /* * Note: s_es must be initialized as soon as possible because * some ext2 macro-instructions depend on its value */ es = (struct ext2_super_block *) (((char *)bh->b_data) + offset); sbi->s_es = es; sb->s_magic = le16_to_cpu(es->s_magic); if (sb->s_magic != EXT2_SUPER_MAGIC) goto cantfind_ext2; /* Set defaults before we parse the mount options */ def_mount_opts = le32_to_cpu(es->s_default_mount_opts); if (def_mount_opts & EXT2_DEFM_DEBUG) set_opt(opts.s_mount_opt, DEBUG); if (def_mount_opts & EXT2_DEFM_BSDGROUPS) set_opt(opts.s_mount_opt, GRPID); if (def_mount_opts & EXT2_DEFM_UID16) set_opt(opts.s_mount_opt, NO_UID32); #ifdef CONFIG_EXT2_FS_XATTR if (def_mount_opts & EXT2_DEFM_XATTR_USER) set_opt(opts.s_mount_opt, XATTR_USER); #endif #ifdef CONFIG_EXT2_FS_POSIX_ACL if (def_mount_opts & EXT2_DEFM_ACL) set_opt(opts.s_mount_opt, POSIX_ACL); #endif if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_PANIC) set_opt(opts.s_mount_opt, ERRORS_PANIC); else if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_CONTINUE) set_opt(opts.s_mount_opt, ERRORS_CONT); else set_opt(opts.s_mount_opt, ERRORS_RO); opts.s_resuid = make_kuid(&init_user_ns, le16_to_cpu(es->s_def_resuid)); opts.s_resgid = make_kgid(&init_user_ns, le16_to_cpu(es->s_def_resgid)); set_opt(opts.s_mount_opt, RESERVATION); if (!parse_options((char *) data, sb, &opts)) goto failed_mount; sbi->s_mount_opt = opts.s_mount_opt; sbi->s_resuid = opts.s_resuid; sbi->s_resgid = opts.s_resgid; sb->s_flags = (sb->s_flags & ~SB_POSIXACL) | ((EXT2_SB(sb)->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ? SB_POSIXACL : 0); sb->s_iflags |= SB_I_CGROUPWB; if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV && (EXT2_HAS_COMPAT_FEATURE(sb, ~0U) || EXT2_HAS_RO_COMPAT_FEATURE(sb, ~0U) || EXT2_HAS_INCOMPAT_FEATURE(sb, ~0U))) ext2_msg(sb, KERN_WARNING, "warning: feature flags set on rev 0 fs, " "running e2fsck is recommended"); /* * Check feature flags regardless of the revision level, since we * previously didn't change the revision level when setting the flags, * so there is a chance incompat flags are set on a rev 0 filesystem. */ features = EXT2_HAS_INCOMPAT_FEATURE(sb, ~EXT2_FEATURE_INCOMPAT_SUPP); if (features) { ext2_msg(sb, KERN_ERR, "error: couldn't mount because of " "unsupported optional features (%x)", le32_to_cpu(features)); goto failed_mount; } if (!sb_rdonly(sb) && (features = EXT2_HAS_RO_COMPAT_FEATURE(sb, ~EXT2_FEATURE_RO_COMPAT_SUPP))){ ext2_msg(sb, KERN_ERR, "error: couldn't mount RDWR because of " "unsupported optional features (%x)", le32_to_cpu(features)); goto failed_mount; } blocksize = BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size); if (sbi->s_mount_opt & EXT2_MOUNT_DAX) { err = bdev_dax_supported(sb, blocksize); if (err) { ext2_msg(sb, KERN_ERR, "DAX unsupported by block device. Turning off DAX."); sbi->s_mount_opt &= ~EXT2_MOUNT_DAX; } } /* If the blocksize doesn't match, re-read the thing.. */ if (sb->s_blocksize != blocksize) { brelse(bh); if (!sb_set_blocksize(sb, blocksize)) { ext2_msg(sb, KERN_ERR, "error: bad blocksize %d", blocksize); goto failed_sbi; } logic_sb_block = (sb_block*BLOCK_SIZE) / blocksize; offset = (sb_block*BLOCK_SIZE) % blocksize; bh = sb_bread(sb, logic_sb_block); if(!bh) { ext2_msg(sb, KERN_ERR, "error: couldn't read" "superblock on 2nd try"); goto failed_sbi; } es = (struct ext2_super_block *) (((char *)bh->b_data) + offset); sbi->s_es = es; if (es->s_magic != cpu_to_le16(EXT2_SUPER_MAGIC)) { ext2_msg(sb, KERN_ERR, "error: magic mismatch"); goto failed_mount; } } sb->s_maxbytes = ext2_max_size(sb->s_blocksize_bits); sb->s_max_links = EXT2_LINK_MAX; if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV) { sbi->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE; sbi->s_first_ino = EXT2_GOOD_OLD_FIRST_INO; } else { sbi->s_inode_size = le16_to_cpu(es->s_inode_size); sbi->s_first_ino = le32_to_cpu(es->s_first_ino); if ((sbi->s_inode_size < EXT2_GOOD_OLD_INODE_SIZE) || !is_power_of_2(sbi->s_inode_size) || (sbi->s_inode_size > blocksize)) { ext2_msg(sb, KERN_ERR, "error: unsupported inode size: %d", sbi->s_inode_size); goto failed_mount; } } sbi->s_frag_size = EXT2_MIN_FRAG_SIZE << le32_to_cpu(es->s_log_frag_size); if (sbi->s_frag_size == 0) goto cantfind_ext2; sbi->s_frags_per_block = sb->s_blocksize / sbi->s_frag_size; sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group); sbi->s_frags_per_group = le32_to_cpu(es->s_frags_per_group); sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group); if (EXT2_INODE_SIZE(sb) == 0) goto cantfind_ext2; sbi->s_inodes_per_block = sb->s_blocksize / EXT2_INODE_SIZE(sb); if (sbi->s_inodes_per_block == 0 || sbi->s_inodes_per_group == 0) goto cantfind_ext2; sbi->s_itb_per_group = sbi->s_inodes_per_group / sbi->s_inodes_per_block; sbi->s_desc_per_block = sb->s_blocksize / sizeof (struct ext2_group_desc); sbi->s_sbh = bh; sbi->s_mount_state = le16_to_cpu(es->s_state); sbi->s_addr_per_block_bits = ilog2 (EXT2_ADDR_PER_BLOCK(sb)); sbi->s_desc_per_block_bits = ilog2 (EXT2_DESC_PER_BLOCK(sb)); if (sb->s_magic != EXT2_SUPER_MAGIC) goto cantfind_ext2; if (sb->s_blocksize != bh->b_size) { if (!silent) ext2_msg(sb, KERN_ERR, "error: unsupported blocksize"); goto failed_mount; } if (sb->s_blocksize != sbi->s_frag_size) { ext2_msg(sb, KERN_ERR, "error: fragsize %lu != blocksize %lu" "(not supported yet)", sbi->s_frag_size, sb->s_blocksize); goto failed_mount; } if (sbi->s_blocks_per_group > sb->s_blocksize * 8) { ext2_msg(sb, KERN_ERR, "error: #blocks per group too big: %lu", sbi->s_blocks_per_group); goto failed_mount; } if (sbi->s_frags_per_group > sb->s_blocksize * 8) { ext2_msg(sb, KERN_ERR, "error: #fragments per group too big: %lu", sbi->s_frags_per_group); goto failed_mount; } if (sbi->s_inodes_per_group > sb->s_blocksize * 8) { ext2_msg(sb, KERN_ERR, "error: #inodes per group too big: %lu", sbi->s_inodes_per_group); goto failed_mount; } if (EXT2_BLOCKS_PER_GROUP(sb) == 0) goto cantfind_ext2; sbi->s_groups_count = ((le32_to_cpu(es->s_blocks_count) - le32_to_cpu(es->s_first_data_block) - 1) / EXT2_BLOCKS_PER_GROUP(sb)) + 1; db_count = (sbi->s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) / EXT2_DESC_PER_BLOCK(sb); sbi->s_group_desc = kmalloc (db_count * sizeof (struct buffer_head *), GFP_KERNEL); if (sbi->s_group_desc == NULL) { ext2_msg(sb, KERN_ERR, "error: not enough memory"); goto failed_mount; } bgl_lock_init(sbi->s_blockgroup_lock); sbi->s_debts = kcalloc(sbi->s_groups_count, sizeof(*sbi->s_debts), GFP_KERNEL); if (!sbi->s_debts) { ext2_msg(sb, KERN_ERR, "error: not enough memory"); goto failed_mount_group_desc; } for (i = 0; i < db_count; i++) { block = descriptor_loc(sb, logic_sb_block, i); sbi->s_group_desc[i] = sb_bread(sb, block); if (!sbi->s_group_desc[i]) { for (j = 0; j < i; j++) brelse (sbi->s_group_desc[j]); ext2_msg(sb, KERN_ERR, "error: unable to read group descriptors"); goto failed_mount_group_desc; } } if (!ext2_check_descriptors (sb)) { ext2_msg(sb, KERN_ERR, "group descriptors corrupted"); goto failed_mount2; } sbi->s_gdb_count = db_count; get_random_bytes(&sbi->s_next_generation, sizeof(u32)); spin_lock_init(&sbi->s_next_gen_lock); /* per fileystem reservation list head & lock */ spin_lock_init(&sbi->s_rsv_window_lock); sbi->s_rsv_window_root = RB_ROOT; /* * Add a single, static dummy reservation to the start of the * reservation window list --- it gives us a placeholder for * append-at-start-of-list which makes the allocation logic * _much_ simpler. */ sbi->s_rsv_window_head.rsv_start = EXT2_RESERVE_WINDOW_NOT_ALLOCATED; sbi->s_rsv_window_head.rsv_end = EXT2_RESERVE_WINDOW_NOT_ALLOCATED; sbi->s_rsv_window_head.rsv_alloc_hit = 0; sbi->s_rsv_window_head.rsv_goal_size = 0; ext2_rsv_window_add(sb, &sbi->s_rsv_window_head); err = percpu_counter_init(&sbi->s_freeblocks_counter, ext2_count_free_blocks(sb), GFP_KERNEL); if (!err) { err = percpu_counter_init(&sbi->s_freeinodes_counter, ext2_count_free_inodes(sb), GFP_KERNEL); } if (!err) { err = percpu_counter_init(&sbi->s_dirs_counter, ext2_count_dirs(sb), GFP_KERNEL); } if (err) { ext2_msg(sb, KERN_ERR, "error: insufficient memory"); goto failed_mount3; } #ifdef CONFIG_EXT2_FS_XATTR sbi->s_ea_block_cache = ext2_xattr_create_cache(); if (!sbi->s_ea_block_cache) { ext2_msg(sb, KERN_ERR, "Failed to create ea_block_cache"); goto failed_mount3; } #endif /* * set up enough so that it can read an inode */ sb->s_op = &ext2_sops; sb->s_export_op = &ext2_export_ops; sb->s_xattr = ext2_xattr_handlers; #ifdef CONFIG_QUOTA sb->dq_op = &dquot_operations; sb->s_qcop = &ext2_quotactl_ops; sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP; #endif root = ext2_iget(sb, EXT2_ROOT_INO); if (IS_ERR(root)) { ret = PTR_ERR(root); goto failed_mount3; } if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) { iput(root); ext2_msg(sb, KERN_ERR, "error: corrupt root inode, run e2fsck"); goto failed_mount3; } sb->s_root = d_make_root(root); if (!sb->s_root) { ext2_msg(sb, KERN_ERR, "error: get root inode failed"); ret = -ENOMEM; goto failed_mount3; } if (EXT2_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) ext2_msg(sb, KERN_WARNING, "warning: mounting ext3 filesystem as ext2"); if (ext2_setup_super (sb, es, sb_rdonly(sb))) sb->s_flags |= SB_RDONLY; ext2_write_super(sb); return 0; cantfind_ext2: if (!silent) ext2_msg(sb, KERN_ERR, "error: can't find an ext2 filesystem on dev %s.", sb->s_id); goto failed_mount; failed_mount3: if (sbi->s_ea_block_cache) ext2_xattr_destroy_cache(sbi->s_ea_block_cache); percpu_counter_destroy(&sbi->s_freeblocks_counter); percpu_counter_destroy(&sbi->s_freeinodes_counter); percpu_counter_destroy(&sbi->s_dirs_counter); failed_mount2: for (i = 0; i < db_count; i++) brelse(sbi->s_group_desc[i]); failed_mount_group_desc: kfree(sbi->s_group_desc); kfree(sbi->s_debts); failed_mount: brelse(bh); failed_sbi: sb->s_fs_info = NULL; kfree(sbi->s_blockgroup_lock); kfree(sbi); failed: fs_put_dax(dax_dev); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)86039.52%1617.98%
Theodore Y. Ts'o22510.34%66.74%
Alexey Fisher1336.11%11.12%
Linus Torvalds1215.56%910.11%
Jan Kara1034.73%44.49%
Brian Gerst934.27%33.37%
Andrew Morton773.54%66.74%
Mingming Cao673.08%11.12%
Martin J. Bligh652.99%11.12%
Andries E. Brouwer652.99%22.25%
Al Viro522.39%66.74%
David Howells462.11%33.37%
Dan J Williams411.88%22.25%
Peter Zijlstra361.65%11.12%
Pekka J Enberg291.33%11.12%
Jan Blunck251.15%33.37%
Christoph Hellwig180.83%11.12%
Matthew Wilcox120.55%22.25%
Eric W. Biedermann120.55%11.12%
Tejun Heo120.55%22.25%
Hugh Dickins100.46%11.12%
Vasily Averin70.32%11.12%
Manish Katiyar70.32%11.12%
Carsten Otte60.28%11.12%
Chengguang Xu60.28%11.12%
Miklos Szeredi60.28%11.12%
James Morris60.28%11.12%
Tahsin Erdogan50.23%11.12%
Neil Brown50.23%11.12%
Toshi Kani50.23%11.12%
Vignesh Babu40.18%11.12%
Eric Sandeen40.18%11.12%
Robin Dong30.14%11.12%
Wanlong Gao30.14%11.12%
Aneesh Kumar K.V30.14%11.12%
Yoann Padioleau20.09%11.12%
Panagiotis Issaris10.05%11.12%
Mikulas Patocka10.05%11.12%
Total2176100.00%89100.00%


static void ext2_clear_super_error(struct super_block *sb) { struct buffer_head *sbh = EXT2_SB(sb)->s_sbh; if (buffer_write_io_error(sbh)) { /* * Oh, dear. A previous attempt to write the * superblock failed. This could happen because the * USB device was yanked out. Or it could happen to * be a transient write error and maybe the block will * be remapped. Nothing we can do but to retry the * write and hope for the best. */ ext2_msg(sb, KERN_ERR, "previous I/O error to superblock detected"); clear_buffer_write_io_error(sbh); set_buffer_uptodate(sbh); } }

Contributors

PersonTokensPropCommitsCommitProp
Theodore Y. Ts'o4892.31%133.33%
Jan Blunck35.77%133.33%
Julia Lawall11.92%133.33%
Total52100.00%3100.00%


void ext2_sync_super(struct super_block *sb, struct ext2_super_block *es, int wait) { ext2_clear_super_error(sb); spin_lock(&EXT2_SB(sb)->s_lock); es->s_free_blocks_count = cpu_to_le32(ext2_count_free_blocks(sb)); es->s_free_inodes_count = cpu_to_le32(ext2_count_free_inodes(sb)); es->s_wtime = cpu_to_le32(get_seconds()); /* unlock before we do IO */ spin_unlock(&EXT2_SB(sb)->s_lock); mark_buffer_dirty(EXT2_SB(sb)->s_sbh); if (wait) sync_dirty_buffer(EXT2_SB(sb)->s_sbh); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds4240.38%112.50%
Jan Blunck3028.85%225.00%
Andrew Morton2524.04%337.50%
Theodore Y. Ts'o54.81%112.50%
Andi Kleen21.92%112.50%
Total104100.00%8100.00%

/* * In the second extended file system, it is not necessary to * write the super block since we use a mapping of the * disk super block in a buffer. * * However, this function is still used to set the fs valid * flags to 0. We need to set this flag to 0 since the fs * may have been checked while mounted and e2fsck may have * set s_state to EXT2_VALID_FS after some corrections. */
static int ext2_sync_fs(struct super_block *sb, int wait) { struct ext2_sb_info *sbi = EXT2_SB(sb); struct ext2_super_block *es = EXT2_SB(sb)->s_es; /* * Write quota structures to quota file, sync_blockdev() will write * them to disk later */ dquot_writeback_dquots(sb, -1); spin_lock(&sbi->s_lock); if (es->s_state & cpu_to_le16(EXT2_VALID_FS)) { ext2_debug("setting valid to 0\n"); es->s_state &= cpu_to_le16(~EXT2_VALID_FS); } spin_unlock(&sbi->s_lock); ext2_sync_super(sb, es, wait); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)3332.67%220.00%
Jan Blunck2827.72%220.00%
Christoph Hellwig1211.88%110.00%
Linus Torvalds109.90%110.00%
Jan Kara98.91%110.00%
Marcin Ślusarz43.96%110.00%
Brian Gerst32.97%110.00%
Stephen Hemminger21.98%110.00%
Total101100.00%10100.00%


static int ext2_freeze(struct super_block *sb) { struct ext2_sb_info *sbi = EXT2_SB(sb); /* * Open but unlinked files present? Keep EXT2_VALID_FS flag cleared * because we have unattached inodes and thus filesystem is not fully * consistent. */ if (atomic_long_read(&sb->s_remove_count)) { ext2_sync_fs(sb, 1); return 0; } /* Set EXT2_FS_VALID flag */ spin_lock(&sbi->s_lock); sbi->s_es->s_state = cpu_to_le16(sbi->s_mount_state); spin_unlock(&sbi->s_lock); ext2_sync_super(sb, sbi->s_es, 1); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Jan Kara88100.00%1100.00%
Total88100.00%1100.00%


static int ext2_unfreeze(struct super_block *sb) { /* Just write sb to clear EXT2_VALID_FS flag */ ext2_write_super(sb); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Jan Kara20100.00%1100.00%
Total20100.00%1100.00%


static void ext2_write_super(struct super_block *sb) { if (!sb_rdonly(sb)) ext2_sync_fs(sb, 1); }

Contributors

PersonTokensPropCommitsCommitProp
Christoph Hellwig2180.77%125.00%
David Howells311.54%125.00%
Jan Kara13.85%125.00%
Linus Torvalds (pre-git)13.85%125.00%
Total26100.00%4100.00%


static int ext2_remount (struct super_block * sb, int * flags, char * data) { struct ext2_sb_info * sbi = EXT2_SB(sb); struct ext2_super_block * es; struct ext2_mount_options new_opts; int err; sync_filesystem(sb); spin_lock(&sbi->s_lock); new_opts.s_mount_opt = sbi->s_mount_opt; new_opts.s_resuid = sbi->s_resuid; new_opts.s_resgid = sbi->s_resgid; spin_unlock(&sbi->s_lock); /* * Allow the "check" option to be passed as a remount option. */ if (!parse_options(data, sb, &new_opts)) return -EINVAL; spin_lock(&sbi->s_lock); es = sbi->s_es; if ((sbi->s_mount_opt ^ new_opts.s_mount_opt) & EXT2_MOUNT_DAX) { ext2_msg(sb, KERN_WARNING, "warning: refusing change of " "dax flag with busy inodes while remounting"); new_opts.s_mount_opt ^= EXT2_MOUNT_DAX; } if ((bool)(*flags & SB_RDONLY) == sb_rdonly(sb)) goto out_set; if (*flags & SB_RDONLY) { if (le16_to_cpu(es->s_state) & EXT2_VALID_FS || !(sbi->s_mount_state & EXT2_VALID_FS)) goto out_set; /* * OK, we are remounting a valid rw partition rdonly, so set * the rdonly flag and then mark the partition as valid again. */ es->s_state = cpu_to_le16(sbi->s_mount_state); es->s_mtime = cpu_to_le32(get_seconds()); spin_unlock(&sbi->s_lock); err = dquot_suspend(sb, -1); if (err < 0) return err; ext2_sync_super(sb, es, 1); } else { __le32 ret = EXT2_HAS_RO_COMPAT_FEATURE(sb, ~EXT2_FEATURE_RO_COMPAT_SUPP); if (ret) { spin_unlock(&sbi->s_lock); ext2_msg(sb, KERN_WARNING, "warning: couldn't remount RDWR because of " "unsupported optional features (%x).", le32_to_cpu(ret)); return -EROFS; } /* * Mounting a RDONLY partition read-write, so reread and * store the current valid flag. (It may have been changed * by e2fsck since we originally mounted the partition.) */ sbi->s_mount_state = le16_to_cpu(es->s_state); if (!ext2_setup_super (sb, es, 0)) sb->s_flags &= ~SB_RDONLY; spin_unlock(&sbi->s_lock); ext2_write_super(sb); dquot_resume(sb, -1); } spin_lock(&sbi->s_lock); out_set: sbi->s_mount_opt = new_opts.s_mount_opt; sbi->s_resuid = new_opts.s_resuid; sbi->s_resgid = new_opts.s_resgid; sb->s_flags = (sb->s_flags & ~SB_POSIXACL) | ((sbi->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ? SB_POSIXACL : 0); spin_unlock(&sbi->s_lock); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)14333.18%723.33%
Jan Kara13431.09%310.00%
Jan Blunck439.98%26.67%
Christoph Hellwig245.57%26.67%
Carsten Otte173.94%26.67%
Brian Gerst143.25%13.33%
Al Viro112.55%310.00%
Alexey Fisher102.32%13.33%
Theodore Y. Ts'o92.09%26.67%
Linus Torvalds92.09%26.67%
David Howells81.86%13.33%
Matthew Wilcox61.39%26.67%
Andi Kleen20.46%13.33%
Stephen Rothwell10.23%13.33%
Total431100.00%30100.00%


static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf) { struct super_block *sb = dentry->d_sb; struct ext2_sb_info *sbi = EXT2_SB(sb); struct ext2_super_block *es = sbi->s_es; u64 fsid; spin_lock(&sbi->s_lock); if (test_opt (sb, MINIX_DF)) sbi->s_overhead_last = 0; else if (sbi->s_blocks_last != le32_to_cpu(es->s_blocks_count)) { unsigned long i, overhead = 0; smp_rmb(); /* * Compute the overhead (FS structures). This is constant * for a given filesystem unless the number of block groups * changes so we cache the previous value until it does. */ /* * All of the blocks before first_data_block are * overhead */ overhead = le32_to_cpu(es->s_first_data_block); /* * Add the overhead attributed to the superblock and * block group descriptors. If the sparse superblocks * feature is turned on, then not all groups have this. */ for (i = 0; i < sbi->s_groups_count; i++) overhead += ext2_bg_has_super(sb, i) + ext2_bg_num_gdb(sb, i); /* * Every block group has an inode bitmap, a block * bitmap, and an inode table. */ overhead += (sbi->s_groups_count * (2 + sbi->s_itb_per_group)); sbi->s_overhead_last = overhead; smp_wmb(); sbi->s_blocks_last = le32_to_cpu(es->s_blocks_count); } buf->f_type = EXT2_SUPER_MAGIC; buf->f_bsize = sb->s_blocksize; buf->f_blocks = le32_to_cpu(es->s_blocks_count) - sbi->s_overhead_last; buf->f_bfree = ext2_count_free_blocks(sb); es->s_free_blocks_count = cpu_to_le32(buf->f_bfree); buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count); if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count)) buf->f_bavail = 0; buf->f_files = le32_to_cpu(es->s_inodes_count); buf->f_ffree = ext2_count_free_inodes(sb); es->s_free_inodes_count = cpu_to_le32(buf->f_ffree); buf->f_namelen = EXT2_NAME_LEN; fsid = le64_to_cpup((void *)es->s_uuid) ^ le64_to_cpup((void *)es->s_uuid + sizeof(u64)); buf->f_fsid.val[0] = fsid & 0xFFFFFFFFUL; buf->f_fsid.val[1] = (fsid >> 32) & 0xFFFFFFFFUL; spin_unlock(&sbi->s_lock); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)17547.68%853.33%
Pekka J Enberg7620.71%16.67%
Badari Pulavarty7420.16%16.67%
Jan Blunck164.36%16.67%
Brian Gerst133.54%16.67%
David Howells113.00%16.67%
Stephen Rothwell10.27%16.67%
Andrew Morton10.27%16.67%
Total367100.00%15100.00%


static struct dentry *ext2_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { return mount_bdev(fs_type, flags, dev_name, data, ext2_fill_super); }

Contributors

PersonTokensPropCommitsCommitProp
Al Viro3384.62%240.00%
Linus Torvalds (pre-git)512.82%240.00%
Andries E. Brouwer12.56%120.00%
Total39100.00%5100.00%

#ifdef CONFIG_QUOTA /* Read data from quotafile - avoid pagecache and such because we cannot afford * acquiring the locks... As quota files are never truncated and quota code * itself serializes the operations (and no one else should touch the files) * we don't have to be afraid of races */
static ssize_t ext2_quota_read(struct super_block *sb, int type, char *data, size_t len, loff_t off) { struct inode *inode = sb_dqopt(sb)->files[type]; sector_t blk = off >> EXT2_BLOCK_SIZE_BITS(sb); int err = 0; int offset = off & (sb->s_blocksize - 1); int tocopy; size_t toread; struct buffer_head tmp_bh; struct buffer_head *bh; loff_t i_size = i_size_read(inode); if (off > i_size) return 0; if (off+len > i_size) len = i_size-off; toread = len; while (toread > 0) { tocopy = sb->s_blocksize - offset < toread ? sb->s_blocksize - offset : toread; tmp_bh.b_state = 0; tmp_bh.b_size = sb->s_blocksize; err = ext2_get_block(inode, blk, &tmp_bh, 0); if (err < 0) return err; if (!buffer_mapped(&tmp_bh)) /* A hole? */ memset(data, 0, tocopy); else { bh = sb_bread(sb, tmp_bh.b_blocknr); if (!bh) return -EIO; memcpy(data, bh->b_data+offset, tocopy); brelse(bh); } offset = 0; toread -= tocopy; data += tocopy; blk++; } return len; }

Contributors

PersonTokensPropCommitsCommitProp
Jan Kara24896.12%133.33%
Manish Katiyar83.10%133.33%
Martin J. Bligh20.78%133.33%
Total258100.00%3100.00%

/* Write to quotafile */
static ssize_t ext2_quota_write(struct super_block *sb, int type, const char *data, size_t len, loff_t off) { struct inode *inode = sb_dqopt(sb)->files[type]; sector_t blk = off >> EXT2_BLOCK_SIZE_BITS(sb); int err = 0; int offset = off & (sb->s_blocksize - 1); int tocopy; size_t towrite = len; struct buffer_head tmp_bh; struct buffer_head *bh; while (towrite > 0) { tocopy = sb->s_blocksize - offset < towrite ? sb->s_blocksize - offset : towrite; tmp_bh.b_state = 0; tmp_bh.b_size = sb->s_blocksize; err = ext2_get_block(inode, blk, &tmp_bh, 1); if (err < 0) goto out; if (offset || tocopy != EXT2_BLOCK_SIZE(sb)) bh = sb_bread(sb, tmp_bh.b_blocknr); else bh = sb_getblk(sb, tmp_bh.b_blocknr); if (unlikely(!bh)) { err = -EIO; goto out; } lock_buffer(bh); memcpy(bh->b_data+offset, data, tocopy); flush_dcache_page(bh->b_page); set_buffer_uptodate(bh); mark_buffer_dirty(bh); unlock_buffer(bh); brelse(bh); offset = 0; towrite -= tocopy; data += tocopy; blk++; } out: if (len == towrite) return err; if (inode->i_size < off+len-towrite) i_size_write(inode, off+len-towrite); inode_inc_iversion(inode); inode->i_mtime = inode->i_ctime = current_time(inode); mark_inode_dirty(inode); return len - towrite; }

Contributors

PersonTokensPropCommitsCommitProp
Jan Kara31096.27%233.33%
Deepa Dinamani41.24%116.67%
Shilong Wang30.93%116.67%
Jeff Layton30.93%116.67%
Martin J. Bligh20.62%116.67%
Total322100.00%6100.00%


static int ext2_quota_on(struct super_block *sb, int type, int format_id, const struct path *path) { int err; struct inode *inode; err = dquot_quota_on(sb, type, format_id, path); if (err) return err; inode = d_inode(path->dentry); inode_lock(inode); EXT2_I(inode)->i_flags |= EXT2_NOATIME_FL | EXT2_IMMUTABLE_FL; inode_set_flags(inode, S_NOATIME | S_IMMUTABLE, S_NOATIME | S_IMMUTABLE); inode_unlock(inode); mark_inode_dirty(inode); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Jan Kara102100.00%1100.00%
Total102100.00%1100.00%


static int ext2_quota_off(struct super_block *sb, int type) { struct inode *inode = sb_dqopt(sb)->files[type]; int err; if (!inode || !igrab(inode)) goto out; err = dquot_quota_off(sb, type); if (err) goto out_put; inode_lock(inode); EXT2_I(inode)->i_flags &= ~(EXT2_NOATIME_FL | EXT2_IMMUTABLE_FL); inode_set_flags(inode, 0, S_NOATIME | S_IMMUTABLE); inode_unlock(inode); mark_inode_dirty(inode); out_put: iput(inode); return err; out: return dquot_quota_off(sb, type); }

Contributors

PersonTokensPropCommitsCommitProp
Jan Kara122100.00%1100.00%
Total122100.00%1100.00%

#endif static struct file_system_type ext2_fs_type = { .owner = THIS_MODULE, .name = "ext2", .mount = ext2_mount, .kill_sb = kill_block_super, .fs_flags = FS_REQUIRES_DEV, }; MODULE_ALIAS_FS("ext2");
static int __init init_ext2_fs(void) { int err; err = init_inodecache(); if (err) return err; err = register_filesystem(&ext2_fs_type); if (err) goto out; return 0; out: destroy_inodecache(); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds2346.00%125.00%
Linus Torvalds (pre-git)1530.00%125.00%
Theodore Y. Ts'o918.00%125.00%
Jan Kara36.00%125.00%
Total50100.00%4100.00%


static void __exit exit_ext2_fs(void) { unregister_filesystem(&ext2_fs_type); destroy_inodecache(); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)1583.33%266.67%
Linus Torvalds316.67%133.33%
Total18100.00%3100.00%

MODULE_AUTHOR("Remy Card and others"); MODULE_DESCRIPTION("Second Extended Filesystem"); MODULE_LICENSE("GPL"); module_init(init_ext2_fs) module_exit(exit_ext2_fs)

Overall Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)203524.58%3718.59%
Jan Kara148417.92%126.03%
Andrew Morton6027.27%157.54%
Theodore Y. Ts'o5827.03%94.52%
Linus Torvalds4645.60%126.03%
Miklos Szeredi3944.76%21.01%
Alexey Fisher2382.87%10.50%
Jan Blunck1982.39%52.51%
Christoph Hellwig1932.33%105.03%
Brian Gerst1882.27%31.51%
Mark Bellon1511.82%10.50%
Al Viro1331.61%126.03%
Martin J. Bligh1291.56%10.50%
Neil Brown1261.52%21.01%
Eric W. Biedermann1251.51%21.01%
Pekka J Enberg1121.35%21.01%
Aneesh Kumar K.V981.18%21.01%
David Howells820.99%42.01%
Vasily Averin760.92%10.50%
Badari Pulavarty740.89%10.50%
Matthew Wilcox680.82%31.51%
Carsten Otte680.82%31.51%
Mingming Cao670.81%10.50%
Andries E. Brouwer660.80%31.51%
Dan J Williams600.72%42.01%
Eric Sandeen520.63%21.01%
Joe Perches400.48%10.50%
Nicholas Piggin390.47%10.50%
Peter Zijlstra360.43%10.50%
Stephen Rothwell330.40%10.50%
Akinobu Mita330.40%21.01%
Heiko Carstens240.29%10.50%
Matt Mackall190.23%10.50%
David Windsor170.21%10.50%
Paul Gortmaker150.18%10.50%
Manish Katiyar150.18%21.01%
Ross Zwisler130.16%10.50%
Tejun Heo120.14%21.01%
Jeff Layton110.13%10.50%
Hugh Dickins100.12%10.50%
Marcin Ślusarz80.10%21.01%
Tahsin Erdogan80.10%10.50%
Vignesh Babu70.08%10.50%
James Morris60.07%10.50%
Chengguang Xu60.07%10.50%
Andi Kleen60.07%10.50%
Christoph Lameter60.07%31.51%
Toshi Kani50.06%10.50%
Stephen C. Tweedie50.06%10.50%
Kirill A. Shutemov40.05%10.50%
Deepa Dinamani40.05%10.50%
Paul Jackson40.05%21.01%
Hirofumi Ogawa30.04%10.50%
Shilong Wang30.04%10.50%
Wanlong Gao30.04%10.50%
Robin Dong30.04%10.50%
Zhao Hongjiang20.02%10.50%
Vladimir Davydov20.02%10.50%
Yoann Padioleau20.02%10.50%
Stephen Hemminger20.02%10.50%
Steven Whitehouse10.01%10.50%
Mikulas Patocka10.01%10.50%
Fabian Frederick10.01%10.50%
Panagiotis Issaris10.01%10.50%
Lucas De Marchi10.01%10.50%
Julia Lawall10.01%10.50%
Li Haifeng10.01%10.50%
Josef 'Jeff' Sipek10.01%10.50%
Alexey Dobriyan0.00%00.00%
Total8279100.00%199100.00%
Directory: fs/ext2
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.