📄 super.c
字号:
goto out_bdev; } len = le32_to_cpu(es->s_blocks_count); start = sb_block + 1; brelse(bh); /* we're done with the superblock */ journal = journal_init_dev(journal_dev, sb->s_dev, start, len, blocksize); if (!journal) { printk(KERN_ERR "EXT3-fs: failed to create device journal\n"); goto out_bdev; } ll_rw_block(READ, 1, &journal->j_sb_buffer); wait_on_buffer(journal->j_sb_buffer); if (!buffer_uptodate(journal->j_sb_buffer)) { printk(KERN_ERR "EXT3-fs: I/O error on journal device\n"); goto out_journal; } if (ntohl(journal->j_superblock->s_nr_users) != 1) { printk(KERN_ERR "EXT3-fs: External journal has more than one " "user (unsupported) - %d\n", ntohl(journal->j_superblock->s_nr_users)); goto out_journal; } EXT3_SB(sb)->journal_bdev = bdev; return journal;out_journal: journal_destroy(journal);out_bdev: ext3_blkdev_put(bdev); return NULL;}static int ext3_load_journal(struct super_block * sb, struct ext3_super_block * es){ journal_t *journal; int journal_inum = le32_to_cpu(es->s_journal_inum); int journal_dev = le32_to_cpu(es->s_journal_dev); int err = 0; int really_read_only; really_read_only = is_read_only(sb->s_dev); /* * Are we loading a blank journal or performing recovery after a * crash? For recovery, we need to check in advance whether we * can get read-write access to the device. */ if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER)) { if (sb->s_flags & MS_RDONLY) { printk(KERN_INFO "EXT3-fs: INFO: recovery " "required on readonly filesystem.\n"); if (really_read_only) { printk(KERN_ERR "EXT3-fs: write access " "unavailable, cannot proceed.\n"); return -EROFS; } printk (KERN_INFO "EXT3-fs: write access will " "be enabled during recovery.\n"); } } if (journal_inum && journal_dev) { printk(KERN_ERR "EXT3-fs: filesystem has both journal " "and inode journals!\n"); return -EINVAL; } if (journal_inum) { if (!(journal = ext3_get_journal(sb, journal_inum))) return -EINVAL; } else { if (!(journal = ext3_get_dev_journal(sb, journal_dev))) return -EINVAL; } if (!really_read_only && test_opt(sb, UPDATE_JOURNAL)) { err = journal_update_format(journal); if (err) { printk(KERN_ERR "EXT3-fs: error updating journal.\n"); journal_destroy(journal); return err; } } if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER)) err = journal_wipe(journal, !really_read_only); if (!err) err = journal_load(journal); if (err) { printk(KERN_ERR "EXT3-fs: error loading journal.\n"); journal_destroy(journal); return err; } EXT3_SB(sb)->s_journal = journal; ext3_clear_journal_err(sb, es); return 0;}static int ext3_create_journal(struct super_block * sb, struct ext3_super_block * es, int journal_inum){ journal_t *journal; if (sb->s_flags & MS_RDONLY) { printk(KERN_ERR "EXT3-fs: readonly filesystem when trying to " "create journal.\n"); return -EROFS; } if (!(journal = ext3_get_journal(sb, journal_inum))) return -EINVAL; printk(KERN_INFO "EXT3-fs: creating new journal on inode %d\n", journal_inum); if (journal_create(journal)) { printk(KERN_ERR "EXT3-fs: error creating journal.\n"); journal_destroy(journal); return -EIO; } EXT3_SB(sb)->s_journal = journal; ext3_update_dynamic_rev(sb); EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER); EXT3_SET_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL); es->s_journal_inum = cpu_to_le32(journal_inum); sb->s_dirt = 1; /* Make sure we flush the recovery flag to disk. */ ext3_commit_super(sb, es, 1); return 0;}static void ext3_commit_super (struct super_block * sb, struct ext3_super_block * es, int sync){ es->s_wtime = cpu_to_le32(CURRENT_TIME); BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "marking dirty"); mark_buffer_dirty(sb->u.ext3_sb.s_sbh); if (sync) { ll_rw_block(WRITE, 1, &sb->u.ext3_sb.s_sbh); wait_on_buffer(sb->u.ext3_sb.s_sbh); }}/* * Have we just finished recovery? If so, and if we are mounting (or * remounting) the filesystem readonly, then we will end up with a * consistent fs on disk. Record that fact. */static void ext3_mark_recovery_complete(struct super_block * sb, struct ext3_super_block * es){ journal_flush(EXT3_SB(sb)->s_journal); if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER) && sb->s_flags & MS_RDONLY) { EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER); sb->s_dirt = 0; ext3_commit_super(sb, es, 1); }}/* * If we are mounting (or read-write remounting) a filesystem whose journal * has recorded an error from a previous lifetime, move that error to the * main filesystem now. */static void ext3_clear_journal_err(struct super_block * sb, struct ext3_super_block * es){ journal_t *journal; int j_errno; const char *errstr; journal = EXT3_SB(sb)->s_journal; /* * Now check for any error status which may have been recorded in the * journal by a prior ext3_error() or ext3_abort() */ j_errno = journal_errno(journal); if (j_errno) { char nbuf[16]; errstr = ext3_decode_error(sb, j_errno, nbuf); ext3_warning(sb, __FUNCTION__, "Filesystem error recorded " "from previous mount: %s", errstr); ext3_warning(sb, __FUNCTION__, "Marking fs in need of " "filesystem check."); sb->u.ext3_sb.s_mount_state |= EXT3_ERROR_FS; es->s_state |= cpu_to_le16(EXT3_ERROR_FS); ext3_commit_super (sb, es, 1); journal_clear_err(journal); }}/* * Force the running and committing transactions to commit, * and wait on the commit. */int ext3_force_commit(struct super_block *sb){ journal_t *journal; int ret; if (sb->s_flags & MS_RDONLY) return 0; journal = EXT3_SB(sb)->s_journal; sb->s_dirt = 0; lock_kernel(); /* important: lock down j_running_transaction */ ret = ext3_journal_force_commit(journal); unlock_kernel(); return ret;}/* * Ext3 always journals updates to the superblock itself, so we don't * have to propagate any other updates to the superblock on disk at this * point. Just start an async writeback to get the buffers on their way * to the disk. * * This implicitly triggers the writebehind on sync(). */static int do_sync_supers = 0;MODULE_PARM(do_sync_supers, "i");MODULE_PARM_DESC(do_sync_supers, "Write superblocks synchronously");void ext3_write_super (struct super_block * sb){ tid_t target; if (down_trylock(&sb->s_lock) == 0) BUG(); /* aviro detector */ sb->s_dirt = 0; target = log_start_commit(EXT3_SB(sb)->s_journal, NULL); if (do_sync_supers) { unlock_super(sb); log_wait_commit(EXT3_SB(sb)->s_journal, target); lock_super(sb); }}/* * LVM calls this function before a (read-only) snapshot is created. This * gives us a chance to flush the journal completely and mark the fs clean. */void ext3_write_super_lockfs(struct super_block *sb){ sb->s_dirt = 0; lock_kernel(); /* 2.4.5 forgot to do this for us */ if (!(sb->s_flags & MS_RDONLY)) { journal_t *journal = EXT3_SB(sb)->s_journal; /* Now we set up the journal barrier. */ journal_lock_updates(journal); journal_flush(journal); /* Journal blocked and flushed, clear needs_recovery flag. */ EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER); ext3_commit_super(sb, EXT3_SB(sb)->s_es, 1); } unlock_kernel();}/* * Called by LVM after the snapshot is done. We need to reset the RECOVER * flag here, even though the filesystem is not technically dirty yet. */void ext3_unlockfs(struct super_block *sb){ if (!(sb->s_flags & MS_RDONLY)) { lock_kernel(); lock_super(sb); /* Reser the needs_recovery flag before the fs is unlocked. */ EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER); ext3_commit_super(sb, EXT3_SB(sb)->s_es, 1); unlock_super(sb); journal_unlock_updates(EXT3_SB(sb)->s_journal); unlock_kernel(); }}int ext3_remount (struct super_block * sb, int * flags, char * data){ struct ext3_super_block * es; struct ext3_sb_info *sbi = EXT3_SB(sb); unsigned long tmp; clear_ro_after(sb); /* * Allow the "check" option to be passed as a remount option. */ if (!parse_options(data, &tmp, sbi, &tmp, 1)) return -EINVAL; if (sbi->s_mount_opt & EXT3_MOUNT_ABORT) ext3_abort(sb, __FUNCTION__, "Abort forced by user"); es = sbi->s_es; if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY)) { if (sbi->s_mount_opt & EXT3_MOUNT_ABORT) return -EROFS; if (*flags & MS_RDONLY) { /* * First of all, the unconditional stuff we have to do * to disable replay of the journal when we next remount */ sb->s_flags |= MS_RDONLY; /* * OK, test if we are remounting a valid rw partition * readonly, and if so set the rdonly flag and then * mark the partition as valid again. */ if (!(es->s_state & cpu_to_le16(EXT3_VALID_FS)) && (sbi->s_mount_state & EXT3_VALID_FS)) es->s_state = cpu_to_le16(sbi->s_mount_state); ext3_mark_recovery_complete(sb, es); } else { int ret; if ((ret = EXT3_HAS_RO_COMPAT_FEATURE(sb, ~EXT3_FEATURE_RO_COMPAT_SUPP))) { printk(KERN_WARNING "EXT3-fs: %s: couldn't " "remount RDWR because of unsupported " "optional features (%x).\n", bdevname(sb->s_dev), 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.) */ ext3_clear_journal_err(sb, es); sbi->s_mount_state = le16_to_cpu(es->s_state); if (!ext3_setup_super (sb, es, 0)) sb->s_flags &= ~MS_RDONLY; } } setup_ro_after(sb); return 0;}int ext3_statfs (struct super_block * sb, struct statfs * buf){ struct ext3_super_block *es = EXT3_SB(sb)->s_es; unsigned long overhead; int i; if (test_opt (sb, MINIX_DF)) overhead = 0; else { /* * Compute the overhead (FS structures) */ /* * 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 < EXT3_SB(sb)->s_groups_count; i++) overhead += ext3_bg_has_super(sb, i) + ext3_bg_num_gdb(sb, i); /* * Every block group has an inode bitmap, a block * bitmap, and an inode table. */ overhead += (EXT3_SB(sb)->s_groups_count * (2 + EXT3_SB(sb)->s_itb_per_group)); } buf->f_type = EXT3_SUPER_MAGIC; buf->f_bsize = sb->s_blocksize; buf->f_blocks = le32_to_cpu(es->s_blocks_count) - overhead; buf->f_bfree = ext3_count_free_blocks (sb); 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 = ext3_count_free_inodes (sb); buf->f_namelen = EXT3_NAME_LEN; return 0;}static DECLARE_FSTYPE_DEV(ext3_fs_type, "ext3", ext3_read_super);static int __init init_ext3_fs(void){ return register_filesystem(&ext3_fs_type);}static void __exit exit_ext3_fs(void){ unregister_filesystem(&ext3_fs_type);}EXPORT_NO_SYMBOLS;MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");MODULE_LICENSE("GPL");module_init(init_ext3_fs)module_exit(exit_ext3_fs)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -