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

📄 super.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *  linux/fs/ext4/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/time.h>#include <linux/jbd2.h>#include <linux/ext4_fs.h>#include <linux/ext4_jbd2.h>#include <linux/slab.h>#include <linux/init.h>#include <linux/blkdev.h>#include <linux/parser.h>#include <linux/smp_lock.h>#include <linux/buffer_head.h>#include <linux/exportfs.h>#include <linux/vfs.h>#include <linux/random.h>#include <linux/mount.h>#include <linux/namei.h>#include <linux/quotaops.h>#include <linux/seq_file.h>#include <linux/log2.h>#include <linux/crc16.h>#include <asm/uaccess.h>#include "xattr.h"#include "acl.h"#include "namei.h"#include "group.h"static int ext4_load_journal(struct super_block *, struct ext4_super_block *,			     unsigned long journal_devnum);static int ext4_create_journal(struct super_block *, struct ext4_super_block *,			       unsigned int);static void ext4_commit_super (struct super_block * sb,			       struct ext4_super_block * es,			       int sync);static void ext4_mark_recovery_complete(struct super_block * sb,					struct ext4_super_block * es);static void ext4_clear_journal_err(struct super_block * sb,				   struct ext4_super_block * es);static int ext4_sync_fs(struct super_block *sb, int wait);static const char *ext4_decode_error(struct super_block * sb, int errno,				     char nbuf[16]);static int ext4_remount (struct super_block * sb, int * flags, char * data);static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf);static void ext4_unlockfs(struct super_block *sb);static void ext4_write_super (struct super_block * sb);static void ext4_write_super_lockfs(struct super_block *sb);ext4_fsblk_t ext4_block_bitmap(struct super_block *sb,			       struct ext4_group_desc *bg){	return le32_to_cpu(bg->bg_block_bitmap_lo) |		(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?		(ext4_fsblk_t)le32_to_cpu(bg->bg_block_bitmap_hi) << 32 : 0);}ext4_fsblk_t ext4_inode_bitmap(struct super_block *sb,			       struct ext4_group_desc *bg){	return le32_to_cpu(bg->bg_inode_bitmap_lo) |		(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?		(ext4_fsblk_t)le32_to_cpu(bg->bg_inode_bitmap_hi) << 32 : 0);}ext4_fsblk_t ext4_inode_table(struct super_block *sb,			      struct ext4_group_desc *bg){	return le32_to_cpu(bg->bg_inode_table_lo) |		(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?		(ext4_fsblk_t)le32_to_cpu(bg->bg_inode_table_hi) << 32 : 0);}void ext4_block_bitmap_set(struct super_block *sb,			   struct ext4_group_desc *bg, ext4_fsblk_t blk){	bg->bg_block_bitmap_lo = cpu_to_le32((u32)blk);	if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)		bg->bg_block_bitmap_hi = cpu_to_le32(blk >> 32);}void ext4_inode_bitmap_set(struct super_block *sb,			   struct ext4_group_desc *bg, ext4_fsblk_t blk){	bg->bg_inode_bitmap_lo  = cpu_to_le32((u32)blk);	if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)		bg->bg_inode_bitmap_hi = cpu_to_le32(blk >> 32);}void ext4_inode_table_set(struct super_block *sb,			  struct ext4_group_desc *bg, ext4_fsblk_t blk){	bg->bg_inode_table_lo = cpu_to_le32((u32)blk);	if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)		bg->bg_inode_table_hi = cpu_to_le32(blk >> 32);}/* * Wrappers for jbd2_journal_start/end. * * The only special thing we need to do here is to make sure that all * journal_end calls result in the superblock being marked dirty, so * that sync() will call the filesystem's write_super callback if * appropriate. */handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks){	journal_t *journal;	if (sb->s_flags & MS_RDONLY)		return ERR_PTR(-EROFS);	/* Special case here: if the journal has aborted behind our	 * backs (eg. EIO in the commit thread), then we still need to	 * take the FS itself readonly cleanly. */	journal = EXT4_SB(sb)->s_journal;	if (is_journal_aborted(journal)) {		ext4_abort(sb, __FUNCTION__,			   "Detected aborted journal");		return ERR_PTR(-EROFS);	}	return jbd2_journal_start(journal, nblocks);}/* * The only special thing we need to do here is to make sure that all * jbd2_journal_stop calls result in the superblock being marked dirty, so * that sync() will call the filesystem's write_super callback if * appropriate. */int __ext4_journal_stop(const char *where, handle_t *handle){	struct super_block *sb;	int err;	int rc;	sb = handle->h_transaction->t_journal->j_private;	err = handle->h_err;	rc = jbd2_journal_stop(handle);	if (!err)		err = rc;	if (err)		__ext4_std_error(sb, where, err);	return err;}void ext4_journal_abort_handle(const char *caller, const char *err_fn,		struct buffer_head *bh, handle_t *handle, int err){	char nbuf[16];	const char *errstr = ext4_decode_error(NULL, err, nbuf);	if (bh)		BUFFER_TRACE(bh, "abort");	if (!handle->h_err)		handle->h_err = err;	if (is_handle_aborted(handle))		return;	printk(KERN_ERR "%s: aborting transaction: %s in %s\n",	       caller, errstr, err_fn);	jbd2_journal_abort_handle(handle);}/* Deal with the reporting of failure conditions on a filesystem such as * inconsistencies detected or read IO failures. * * On ext2, we can store the error state of the filesystem in the * superblock.  That is not possible on ext4, because we may have other * write ordering constraints on the superblock which prevent us from * writing it out straight away; and given that the journal is about to * be aborted, we can't rely on the current, or future, transactions to * write out the superblock safely. * * We'll just use the jbd2_journal_abort() error code to record an error in * the journal instead.  On recovery, the journal will compain about * that error until we've noted it down and cleared it. */static void ext4_handle_error(struct super_block *sb){	struct ext4_super_block *es = EXT4_SB(sb)->s_es;	EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;	es->s_state |= cpu_to_le16(EXT4_ERROR_FS);	if (sb->s_flags & MS_RDONLY)		return;	if (!test_opt (sb, ERRORS_CONT)) {		journal_t *journal = EXT4_SB(sb)->s_journal;		EXT4_SB(sb)->s_mount_opt |= EXT4_MOUNT_ABORT;		if (journal)			jbd2_journal_abort(journal, -EIO);	}	if (test_opt (sb, ERRORS_RO)) {		printk (KERN_CRIT "Remounting filesystem read-only\n");		sb->s_flags |= MS_RDONLY;	}	ext4_commit_super(sb, es, 1);	if (test_opt(sb, ERRORS_PANIC))		panic("EXT4-fs (device %s): panic forced after error\n",			sb->s_id);}void ext4_error (struct super_block * sb, const char * function,		 const char * fmt, ...){	va_list args;	va_start(args, fmt);	printk(KERN_CRIT "EXT4-fs error (device %s): %s: ",sb->s_id, function);	vprintk(fmt, args);	printk("\n");	va_end(args);	ext4_handle_error(sb);}static const char *ext4_decode_error(struct super_block * sb, int errno,				     char nbuf[16]){	char *errstr = NULL;	switch (errno) {	case -EIO:		errstr = "IO failure";		break;	case -ENOMEM:		errstr = "Out of memory";		break;	case -EROFS:		if (!sb || EXT4_SB(sb)->s_journal->j_flags & JBD2_ABORT)			errstr = "Journal has aborted";		else			errstr = "Readonly filesystem";		break;	default:		/* If the caller passed in an extra buffer for unknown		 * errors, textualise them now.  Else we just return		 * NULL. */		if (nbuf) {			/* Check for truncated error codes... */			if (snprintf(nbuf, 16, "error %d", -errno) >= 0)				errstr = nbuf;		}		break;	}	return errstr;}/* __ext4_std_error decodes expected errors from journaling functions * automatically and invokes the appropriate error response.  */void __ext4_std_error (struct super_block * sb, const char * function,		       int errno){	char nbuf[16];	const char *errstr;	/* Special case: if the error is EROFS, and we're not already	 * inside a transaction, then there's really no point in logging	 * an error. */	if (errno == -EROFS && journal_current_handle() == NULL &&	    (sb->s_flags & MS_RDONLY))		return;	errstr = ext4_decode_error(sb, errno, nbuf);	printk (KERN_CRIT "EXT4-fs error (device %s) in %s: %s\n",		sb->s_id, function, errstr);	ext4_handle_error(sb);}/* * ext4_abort is a much stronger failure handler than ext4_error.  The * abort function may be used to deal with unrecoverable failures such * as journal IO errors or ENOMEM at a critical moment in log management. * * We unconditionally force the filesystem into an ABORT|READONLY state, * unless the error response on the fs has been set to panic in which * case we take the easy way out and panic immediately. */void ext4_abort (struct super_block * sb, const char * function,		 const char * fmt, ...){	va_list args;	printk (KERN_CRIT "ext4_abort called.\n");	va_start(args, fmt);	printk(KERN_CRIT "EXT4-fs error (device %s): %s: ",sb->s_id, function);	vprintk(fmt, args);	printk("\n");	va_end(args);	if (test_opt(sb, ERRORS_PANIC))		panic("EXT4-fs panic from previous error\n");	if (sb->s_flags & MS_RDONLY)		return;	printk(KERN_CRIT "Remounting filesystem read-only\n");	EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;	sb->s_flags |= MS_RDONLY;	EXT4_SB(sb)->s_mount_opt |= EXT4_MOUNT_ABORT;	jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO);}void ext4_warning (struct super_block * sb, const char * function,		   const char * fmt, ...){	va_list args;	va_start(args, fmt);	printk(KERN_WARNING "EXT4-fs warning (device %s): %s: ",	       sb->s_id, function);	vprintk(fmt, args);	printk("\n");	va_end(args);}void ext4_update_dynamic_rev(struct super_block *sb){	struct ext4_super_block *es = EXT4_SB(sb)->s_es;	if (le32_to_cpu(es->s_rev_level) > EXT4_GOOD_OLD_REV)		return;	ext4_warning(sb, __FUNCTION__,		     "updating to rev %d because of new feature flag, "		     "running e2fsck is recommended",		     EXT4_DYNAMIC_REV);	es->s_first_ino = cpu_to_le32(EXT4_GOOD_OLD_FIRST_INO);	es->s_inode_size = cpu_to_le16(EXT4_GOOD_OLD_INODE_SIZE);	es->s_rev_level = cpu_to_le32(EXT4_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.	 */}/* * Open the external journal device */static struct block_device *ext4_blkdev_get(dev_t dev){	struct block_device *bdev;	char b[BDEVNAME_SIZE];	bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE);	if (IS_ERR(bdev))		goto fail;	return bdev;fail:	printk(KERN_ERR "EXT4: failed to open journal device %s: %ld\n",			__bdevname(dev, b), PTR_ERR(bdev));	return NULL;}/* * Release the journal device */static int ext4_blkdev_put(struct block_device *bdev){	bd_release(bdev);	return blkdev_put(bdev);}static int ext4_blkdev_remove(struct ext4_sb_info *sbi){	struct block_device *bdev;	int ret = -ENODEV;	bdev = sbi->journal_bdev;	if (bdev) {		ret = ext4_blkdev_put(bdev);		sbi->journal_bdev = NULL;	}	return ret;}static inline struct inode *orphan_list_entry(struct list_head *l){	return &list_entry(l, struct ext4_inode_info, i_orphan)->vfs_inode;}static void dump_orphan_list(struct super_block *sb, struct ext4_sb_info *sbi){	struct list_head *l;	printk(KERN_ERR "sb orphan head is %d\n",	       le32_to_cpu(sbi->s_es->s_last_orphan));	printk(KERN_ERR "sb_info orphan list:\n");	list_for_each(l, &sbi->s_orphan) {		struct inode *inode = orphan_list_entry(l);		printk(KERN_ERR "  "		       "inode %s:%lu at %p: mode %o, nlink %d, next %d\n",		       inode->i_sb->s_id, inode->i_ino, inode,		       inode->i_mode, inode->i_nlink,		       NEXT_ORPHAN(inode));	}}static void ext4_put_super (struct super_block * sb){	struct ext4_sb_info *sbi = EXT4_SB(sb);	struct ext4_super_block *es = sbi->s_es;	int i;	ext4_ext_release(sb);	ext4_xattr_put_super(sb);	jbd2_journal_destroy(sbi->s_journal);	if (!(sb->s_flags & MS_RDONLY)) {		EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);		es->s_state = cpu_to_le16(sbi->s_mount_state);

⌨️ 快捷键说明

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