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

📄 xfs_mount.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */#include "xfs.h"#include "xfs_fs.h"#include "xfs_types.h"#include "xfs_bit.h"#include "xfs_log.h"#include "xfs_inum.h"#include "xfs_trans.h"#include "xfs_sb.h"#include "xfs_ag.h"#include "xfs_dir2.h"#include "xfs_dmapi.h"#include "xfs_mount.h"#include "xfs_bmap_btree.h"#include "xfs_alloc_btree.h"#include "xfs_ialloc_btree.h"#include "xfs_dir2_sf.h"#include "xfs_attr_sf.h"#include "xfs_dinode.h"#include "xfs_inode.h"#include "xfs_btree.h"#include "xfs_ialloc.h"#include "xfs_alloc.h"#include "xfs_rtalloc.h"#include "xfs_bmap.h"#include "xfs_error.h"#include "xfs_rw.h"#include "xfs_quota.h"#include "xfs_fsops.h"STATIC void	xfs_mount_log_sbunit(xfs_mount_t *, __int64_t);STATIC int	xfs_uuid_mount(xfs_mount_t *);STATIC void	xfs_uuid_unmount(xfs_mount_t *mp);STATIC void	xfs_unmountfs_wait(xfs_mount_t *);#ifdef HAVE_PERCPU_SBSTATIC void	xfs_icsb_destroy_counters(xfs_mount_t *);STATIC void	xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t,						int, int);STATIC void	xfs_icsb_sync_counters(xfs_mount_t *);STATIC int	xfs_icsb_modify_counters(xfs_mount_t *, xfs_sb_field_t,						int64_t, int);STATIC int	xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t);#else#define xfs_icsb_destroy_counters(mp)			do { } while (0)#define xfs_icsb_balance_counter(mp, a, b, c)		do { } while (0)#define xfs_icsb_sync_counters(mp)			do { } while (0)#define xfs_icsb_modify_counters(mp, a, b, c)		do { } while (0)#endifstatic const struct {	short offset;	short type;	/* 0 = integer			 * 1 = binary / string (no translation)			 */} xfs_sb_info[] = {    { offsetof(xfs_sb_t, sb_magicnum),   0 },    { offsetof(xfs_sb_t, sb_blocksize),  0 },    { offsetof(xfs_sb_t, sb_dblocks),    0 },    { offsetof(xfs_sb_t, sb_rblocks),    0 },    { offsetof(xfs_sb_t, sb_rextents),   0 },    { offsetof(xfs_sb_t, sb_uuid),       1 },    { offsetof(xfs_sb_t, sb_logstart),   0 },    { offsetof(xfs_sb_t, sb_rootino),    0 },    { offsetof(xfs_sb_t, sb_rbmino),     0 },    { offsetof(xfs_sb_t, sb_rsumino),    0 },    { offsetof(xfs_sb_t, sb_rextsize),   0 },    { offsetof(xfs_sb_t, sb_agblocks),   0 },    { offsetof(xfs_sb_t, sb_agcount),    0 },    { offsetof(xfs_sb_t, sb_rbmblocks),  0 },    { offsetof(xfs_sb_t, sb_logblocks),  0 },    { offsetof(xfs_sb_t, sb_versionnum), 0 },    { offsetof(xfs_sb_t, sb_sectsize),   0 },    { offsetof(xfs_sb_t, sb_inodesize),  0 },    { offsetof(xfs_sb_t, sb_inopblock),  0 },    { offsetof(xfs_sb_t, sb_fname[0]),   1 },    { offsetof(xfs_sb_t, sb_blocklog),   0 },    { offsetof(xfs_sb_t, sb_sectlog),    0 },    { offsetof(xfs_sb_t, sb_inodelog),   0 },    { offsetof(xfs_sb_t, sb_inopblog),   0 },    { offsetof(xfs_sb_t, sb_agblklog),   0 },    { offsetof(xfs_sb_t, sb_rextslog),   0 },    { offsetof(xfs_sb_t, sb_inprogress), 0 },    { offsetof(xfs_sb_t, sb_imax_pct),   0 },    { offsetof(xfs_sb_t, sb_icount),     0 },    { offsetof(xfs_sb_t, sb_ifree),      0 },    { offsetof(xfs_sb_t, sb_fdblocks),   0 },    { offsetof(xfs_sb_t, sb_frextents),  0 },    { offsetof(xfs_sb_t, sb_uquotino),   0 },    { offsetof(xfs_sb_t, sb_gquotino),   0 },    { offsetof(xfs_sb_t, sb_qflags),     0 },    { offsetof(xfs_sb_t, sb_flags),      0 },    { offsetof(xfs_sb_t, sb_shared_vn),  0 },    { offsetof(xfs_sb_t, sb_inoalignmt), 0 },    { offsetof(xfs_sb_t, sb_unit),	 0 },    { offsetof(xfs_sb_t, sb_width),	 0 },    { offsetof(xfs_sb_t, sb_dirblklog),	 0 },    { offsetof(xfs_sb_t, sb_logsectlog), 0 },    { offsetof(xfs_sb_t, sb_logsectsize),0 },    { offsetof(xfs_sb_t, sb_logsunit),	 0 },    { offsetof(xfs_sb_t, sb_features2),	 0 },    { sizeof(xfs_sb_t),			 0 }};/* * Return a pointer to an initialized xfs_mount structure. */xfs_mount_t *xfs_mount_init(void){	xfs_mount_t *mp;	mp = kmem_zalloc(sizeof(xfs_mount_t), KM_SLEEP);	if (xfs_icsb_init_counters(mp)) {		mp->m_flags |= XFS_MOUNT_NO_PERCPU_SB;	}	AIL_LOCKINIT(&mp->m_ail_lock, "xfs_ail");	spinlock_init(&mp->m_sb_lock, "xfs_sb");	mutex_init(&mp->m_ilock);	mutex_init(&mp->m_growlock);	/*	 * Initialize the AIL.	 */	xfs_trans_ail_init(mp);	atomic_set(&mp->m_active_trans, 0);	return mp;}/* * Free up the resources associated with a mount structure.  Assume that * the structure was initially zeroed, so we can tell which fields got * initialized. */voidxfs_mount_free(	xfs_mount_t	*mp){	if (mp->m_perag) {		int	agno;		for (agno = 0; agno < mp->m_maxagi; agno++)			if (mp->m_perag[agno].pagb_list)				kmem_free(mp->m_perag[agno].pagb_list,						sizeof(xfs_perag_busy_t) *							XFS_PAGB_NUM_SLOTS);		kmem_free(mp->m_perag,			  sizeof(xfs_perag_t) * mp->m_sb.sb_agcount);	}	AIL_LOCK_DESTROY(&mp->m_ail_lock);	spinlock_destroy(&mp->m_sb_lock);	mutex_destroy(&mp->m_ilock);	mutex_destroy(&mp->m_growlock);	if (mp->m_quotainfo)		XFS_QM_DONE(mp);	if (mp->m_fsname != NULL)		kmem_free(mp->m_fsname, mp->m_fsname_len);	if (mp->m_rtname != NULL)		kmem_free(mp->m_rtname, strlen(mp->m_rtname) + 1);	if (mp->m_logname != NULL)		kmem_free(mp->m_logname, strlen(mp->m_logname) + 1);	xfs_icsb_destroy_counters(mp);}/* * Check size of device based on the (data/realtime) block count. * Note: this check is used by the growfs code as well as mount. */intxfs_sb_validate_fsb_count(	xfs_sb_t	*sbp,	__uint64_t	nblocks){	ASSERT(PAGE_SHIFT >= sbp->sb_blocklog);	ASSERT(sbp->sb_blocklog >= BBSHIFT);#if XFS_BIG_BLKNOS     /* Limited by ULONG_MAX of page cache index */	if (nblocks >> (PAGE_CACHE_SHIFT - sbp->sb_blocklog) > ULONG_MAX)		return E2BIG;#else                  /* Limited by UINT_MAX of sectors */	if (nblocks << (sbp->sb_blocklog - BBSHIFT) > UINT_MAX)		return E2BIG;#endif	return 0;}/* * Check the validity of the SB found. */STATIC intxfs_mount_validate_sb(	xfs_mount_t	*mp,	xfs_sb_t	*sbp,	int		flags){	/*	 * If the log device and data device have the	 * same device number, the log is internal.	 * Consequently, the sb_logstart should be non-zero.  If	 * we have a zero sb_logstart in this case, we may be trying to mount	 * a volume filesystem in a non-volume manner.	 */	if (sbp->sb_magicnum != XFS_SB_MAGIC) {		xfs_fs_mount_cmn_err(flags, "bad magic number");		return XFS_ERROR(EWRONGFS);	}	if (!XFS_SB_GOOD_VERSION(sbp)) {		xfs_fs_mount_cmn_err(flags, "bad version");		return XFS_ERROR(EWRONGFS);	}	if (unlikely(	    sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) {		xfs_fs_mount_cmn_err(flags,			"filesystem is marked as having an external log; "			"specify logdev on the\nmount command line.");		return XFS_ERROR(EINVAL);	}	if (unlikely(	    sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) {		xfs_fs_mount_cmn_err(flags,			"filesystem is marked as having an internal log; "			"do not specify logdev on\nthe mount command line.");		return XFS_ERROR(EINVAL);	}	/*	 * More sanity checking. These were stolen directly from	 * xfs_repair.	 */	if (unlikely(	    sbp->sb_agcount <= 0					||	    sbp->sb_sectsize < XFS_MIN_SECTORSIZE			||	    sbp->sb_sectsize > XFS_MAX_SECTORSIZE			||	    sbp->sb_sectlog < XFS_MIN_SECTORSIZE_LOG			||	    sbp->sb_sectlog > XFS_MAX_SECTORSIZE_LOG			||	    sbp->sb_blocksize < XFS_MIN_BLOCKSIZE			||	    sbp->sb_blocksize > XFS_MAX_BLOCKSIZE			||	    sbp->sb_blocklog < XFS_MIN_BLOCKSIZE_LOG			||	    sbp->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG			||	    sbp->sb_inodesize < XFS_DINODE_MIN_SIZE			||	    sbp->sb_inodesize > XFS_DINODE_MAX_SIZE			||	    sbp->sb_inodelog < XFS_DINODE_MIN_LOG			||	    sbp->sb_inodelog > XFS_DINODE_MAX_LOG			||	    (sbp->sb_blocklog - sbp->sb_inodelog != sbp->sb_inopblog)	||	    (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE)	||	    (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE)	||	    (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */))) {		xfs_fs_mount_cmn_err(flags, "SB sanity check 1 failed");		return XFS_ERROR(EFSCORRUPTED);	}	/*	 * Sanity check AG count, size fields against data size field	 */	if (unlikely(	    sbp->sb_dblocks == 0 ||	    sbp->sb_dblocks >	     (xfs_drfsbno_t)sbp->sb_agcount * sbp->sb_agblocks ||	    sbp->sb_dblocks < (xfs_drfsbno_t)(sbp->sb_agcount - 1) *			      sbp->sb_agblocks + XFS_MIN_AG_BLOCKS)) {		xfs_fs_mount_cmn_err(flags, "SB sanity check 2 failed");		return XFS_ERROR(EFSCORRUPTED);	}	if (xfs_sb_validate_fsb_count(sbp, sbp->sb_dblocks) ||	    xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) {		xfs_fs_mount_cmn_err(flags,			"file system too large to be mounted on this system.");		return XFS_ERROR(E2BIG);	}	if (unlikely(sbp->sb_inprogress)) {		xfs_fs_mount_cmn_err(flags, "file system busy");		return XFS_ERROR(EFSCORRUPTED);	}	/*	 * Version 1 directory format has never worked on Linux.	 */	if (unlikely(!XFS_SB_VERSION_HASDIRV2(sbp))) {		xfs_fs_mount_cmn_err(flags,			"file system using version 1 directory format");		return XFS_ERROR(ENOSYS);	}	/*	 * Until this is fixed only page-sized or smaller data blocks work.	 */	if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) {		xfs_fs_mount_cmn_err(flags,			"file system with blocksize %d bytes",			sbp->sb_blocksize);		xfs_fs_mount_cmn_err(flags,			"only pagesize (%ld) or less will currently work.",			PAGE_SIZE);		return XFS_ERROR(ENOSYS);	}	return 0;}STATIC voidxfs_initialize_perag_icache(	xfs_perag_t	*pag){	if (!pag->pag_ici_init) {		rwlock_init(&pag->pag_ici_lock);		INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC);		pag->pag_ici_init = 1;	}}xfs_agnumber_txfs_initialize_perag(	xfs_mount_t	*mp,	xfs_agnumber_t	agcount){	xfs_agnumber_t	index, max_metadata;	xfs_perag_t	*pag;	xfs_agino_t	agino;	xfs_ino_t	ino;	xfs_sb_t	*sbp = &mp->m_sb;	xfs_ino_t	max_inum = XFS_MAXINUMBER_32;	/* Check to see if the filesystem can overflow 32 bit inodes */	agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks - 1, 0);	ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino);	/* Clear the mount flag if no inode can overflow 32 bits	 * on this filesystem, or if specifically requested..	 */	if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) && ino > max_inum) {		mp->m_flags |= XFS_MOUNT_32BITINODES;	} else {		mp->m_flags &= ~XFS_MOUNT_32BITINODES;	}	/* If we can overflow then setup the ag headers accordingly */	if (mp->m_flags & XFS_MOUNT_32BITINODES) {		/* Calculate how much should be reserved for inodes to		 * meet the max inode percentage.		 */		if (mp->m_maxicount) {			__uint64_t	icount;			icount = sbp->sb_dblocks * sbp->sb_imax_pct;			do_div(icount, 100);			icount += sbp->sb_agblocks - 1;			do_div(icount, sbp->sb_agblocks);			max_metadata = icount;		} else {			max_metadata = agcount;		}		for (index = 0; index < agcount; index++) {			ino = XFS_AGINO_TO_INO(mp, index, agino);			if (ino > max_inum) {				index++;				break;			}			/* This ag is preferred for inodes */			pag = &mp->m_perag[index];			pag->pagi_inodeok = 1;			if (index < max_metadata)				pag->pagf_metadata = 1;			xfs_initialize_perag_icache(pag);		}	} else {		/* Setup default behavior for smaller filesystems */		for (index = 0; index < agcount; index++) {			pag = &mp->m_perag[index];			pag->pagi_inodeok = 1;			xfs_initialize_perag_icache(pag);		}	}	return index;}voidxfs_sb_from_disk(	xfs_sb_t	*to,	xfs_dsb_t	*from){	to->sb_magicnum = be32_to_cpu(from->sb_magicnum);	to->sb_blocksize = be32_to_cpu(from->sb_blocksize);	to->sb_dblocks = be64_to_cpu(from->sb_dblocks);	to->sb_rblocks = be64_to_cpu(from->sb_rblocks);	to->sb_rextents = be64_to_cpu(from->sb_rextents);	memcpy(&to->sb_uuid, &from->sb_uuid, sizeof(to->sb_uuid));	to->sb_logstart = be64_to_cpu(from->sb_logstart);	to->sb_rootino = be64_to_cpu(from->sb_rootino);	to->sb_rbmino = be64_to_cpu(from->sb_rbmino);	to->sb_rsumino = be64_to_cpu(from->sb_rsumino);	to->sb_rextsize = be32_to_cpu(from->sb_rextsize);	to->sb_agblocks = be32_to_cpu(from->sb_agblocks);	to->sb_agcount = be32_to_cpu(from->sb_agcount);	to->sb_rbmblocks = be32_to_cpu(from->sb_rbmblocks);	to->sb_logblocks = be32_to_cpu(from->sb_logblocks);	to->sb_versionnum = be16_to_cpu(from->sb_versionnum);	to->sb_sectsize = be16_to_cpu(from->sb_sectsize);	to->sb_inodesize = be16_to_cpu(from->sb_inodesize);	to->sb_inopblock = be16_to_cpu(from->sb_inopblock);	memcpy(&to->sb_fname, &from->sb_fname, sizeof(to->sb_fname));	to->sb_blocklog = from->sb_blocklog;	to->sb_sectlog = from->sb_sectlog;	to->sb_inodelog = from->sb_inodelog;	to->sb_inopblog = from->sb_inopblog;	to->sb_agblklog = from->sb_agblklog;	to->sb_rextslog = from->sb_rextslog;	to->sb_inprogress = from->sb_inprogress;	to->sb_imax_pct = from->sb_imax_pct;	to->sb_icount = be64_to_cpu(from->sb_icount);	to->sb_ifree = be64_to_cpu(from->sb_ifree);	to->sb_fdblocks = be64_to_cpu(from->sb_fdblocks);	to->sb_frextents = be64_to_cpu(from->sb_frextents);	to->sb_uquotino = be64_to_cpu(from->sb_uquotino);	to->sb_gquotino = be64_to_cpu(from->sb_gquotino);	to->sb_qflags = be16_to_cpu(from->sb_qflags);	to->sb_flags = from->sb_flags;	to->sb_shared_vn = from->sb_shared_vn;	to->sb_inoalignmt = be32_to_cpu(from->sb_inoalignmt);	to->sb_unit = be32_to_cpu(from->sb_unit);	to->sb_width = be32_to_cpu(from->sb_width);	to->sb_dirblklog = from->sb_dirblklog;	to->sb_logsectlog = from->sb_logsectlog;	to->sb_logsectsize = be16_to_cpu(from->sb_logsectsize);	to->sb_logsunit = be32_to_cpu(from->sb_logsunit);	to->sb_features2 = be32_to_cpu(from->sb_features2);}/* * Copy in core superblock to ondisk one. * * The fields argument is mask of superblock fields to copy. */voidxfs_sb_to_disk(	xfs_dsb_t	*to,	xfs_sb_t	*from,	__int64_t	fields){	xfs_caddr_t	to_ptr = (xfs_caddr_t)to;	xfs_caddr_t	from_ptr = (xfs_caddr_t)from;	xfs_sb_field_t	f;	int		first;	int		size;	ASSERT(fields);	if (!fields)		return;	while (fields) {		f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);		first = xfs_sb_info[f].offset;		size = xfs_sb_info[f + 1].offset - first;		ASSERT(xfs_sb_info[f].type == 0 || xfs_sb_info[f].type == 1);

⌨️ 快捷键说明

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