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

📄 xfs_vfsops.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * 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_da_btree.h"#include "xfs_bmap_btree.h"#include "xfs_ialloc_btree.h"#include "xfs_alloc_btree.h"#include "xfs_dir2_sf.h"#include "xfs_attr_sf.h"#include "xfs_dinode.h"#include "xfs_inode.h"#include "xfs_inode_item.h"#include "xfs_btree.h"#include "xfs_alloc.h"#include "xfs_ialloc.h"#include "xfs_quota.h"#include "xfs_error.h"#include "xfs_bmap.h"#include "xfs_rw.h"#include "xfs_refcache.h"#include "xfs_buf_item.h"#include "xfs_log_priv.h"#include "xfs_dir2_trace.h"#include "xfs_extfree_item.h"#include "xfs_acl.h"#include "xfs_attr.h"#include "xfs_clnt.h"#include "xfs_mru_cache.h"#include "xfs_filestream.h"#include "xfs_fsops.h"#include "xfs_vnodeops.h"#include "xfs_vfsops.h"intxfs_init(void){	extern kmem_zone_t	*xfs_bmap_free_item_zone;	extern kmem_zone_t	*xfs_btree_cur_zone;	extern kmem_zone_t	*xfs_trans_zone;	extern kmem_zone_t	*xfs_buf_item_zone;	extern kmem_zone_t	*xfs_dabuf_zone;#ifdef XFS_DABUF_DEBUG	extern lock_t	        xfs_dabuf_global_lock;	spinlock_init(&xfs_dabuf_global_lock, "xfsda");#endif	/*	 * Initialize all of the zone allocators we use.	 */	xfs_bmap_free_item_zone = kmem_zone_init(sizeof(xfs_bmap_free_item_t),						 "xfs_bmap_free_item");	xfs_btree_cur_zone = kmem_zone_init(sizeof(xfs_btree_cur_t),					    "xfs_btree_cur");	xfs_trans_zone = kmem_zone_init(sizeof(xfs_trans_t), "xfs_trans");	xfs_da_state_zone =		kmem_zone_init(sizeof(xfs_da_state_t), "xfs_da_state");	xfs_dabuf_zone = kmem_zone_init(sizeof(xfs_dabuf_t), "xfs_dabuf");	xfs_ifork_zone = kmem_zone_init(sizeof(xfs_ifork_t), "xfs_ifork");	xfs_acl_zone_init(xfs_acl_zone, "xfs_acl");	xfs_mru_cache_init();	xfs_filestream_init();	/*	 * The size of the zone allocated buf log item is the maximum	 * size possible under XFS.  This wastes a little bit of memory,	 * but it is much faster.	 */	xfs_buf_item_zone =		kmem_zone_init((sizeof(xfs_buf_log_item_t) +				(((XFS_MAX_BLOCKSIZE / XFS_BLI_CHUNK) /				  NBWORD) * sizeof(int))),			       "xfs_buf_item");	xfs_efd_zone =		kmem_zone_init((sizeof(xfs_efd_log_item_t) +			       ((XFS_EFD_MAX_FAST_EXTENTS - 1) *				 sizeof(xfs_extent_t))),				      "xfs_efd_item");	xfs_efi_zone =		kmem_zone_init((sizeof(xfs_efi_log_item_t) +			       ((XFS_EFI_MAX_FAST_EXTENTS - 1) *				 sizeof(xfs_extent_t))),				      "xfs_efi_item");	/*	 * These zones warrant special memory allocator hints	 */	xfs_inode_zone =		kmem_zone_init_flags(sizeof(xfs_inode_t), "xfs_inode",					KM_ZONE_HWALIGN | KM_ZONE_RECLAIM |					KM_ZONE_SPREAD, NULL);	xfs_ili_zone =		kmem_zone_init_flags(sizeof(xfs_inode_log_item_t), "xfs_ili",					KM_ZONE_SPREAD, NULL);	xfs_icluster_zone =		kmem_zone_init_flags(sizeof(xfs_icluster_t), "xfs_icluster",					KM_ZONE_SPREAD, NULL);	/*	 * Allocate global trace buffers.	 */#ifdef XFS_ALLOC_TRACE	xfs_alloc_trace_buf = ktrace_alloc(XFS_ALLOC_TRACE_SIZE, KM_SLEEP);#endif#ifdef XFS_BMAP_TRACE	xfs_bmap_trace_buf = ktrace_alloc(XFS_BMAP_TRACE_SIZE, KM_SLEEP);#endif#ifdef XFS_BMBT_TRACE	xfs_bmbt_trace_buf = ktrace_alloc(XFS_BMBT_TRACE_SIZE, KM_SLEEP);#endif#ifdef XFS_ATTR_TRACE	xfs_attr_trace_buf = ktrace_alloc(XFS_ATTR_TRACE_SIZE, KM_SLEEP);#endif#ifdef XFS_DIR2_TRACE	xfs_dir2_trace_buf = ktrace_alloc(XFS_DIR2_GTRACE_SIZE, KM_SLEEP);#endif	xfs_dir_startup();#if (defined(DEBUG) || defined(INDUCE_IO_ERROR))	xfs_error_test_init();#endif /* DEBUG || INDUCE_IO_ERROR */	xfs_init_procfs();	xfs_sysctl_register();	return 0;}voidxfs_cleanup(void){	extern kmem_zone_t	*xfs_bmap_free_item_zone;	extern kmem_zone_t	*xfs_btree_cur_zone;	extern kmem_zone_t	*xfs_inode_zone;	extern kmem_zone_t	*xfs_trans_zone;	extern kmem_zone_t	*xfs_da_state_zone;	extern kmem_zone_t	*xfs_dabuf_zone;	extern kmem_zone_t	*xfs_efd_zone;	extern kmem_zone_t	*xfs_efi_zone;	extern kmem_zone_t	*xfs_buf_item_zone;	extern kmem_zone_t	*xfs_icluster_zone;	xfs_cleanup_procfs();	xfs_sysctl_unregister();	xfs_refcache_destroy();	xfs_filestream_uninit();	xfs_mru_cache_uninit();	xfs_acl_zone_destroy(xfs_acl_zone);#ifdef XFS_DIR2_TRACE	ktrace_free(xfs_dir2_trace_buf);#endif#ifdef XFS_ATTR_TRACE	ktrace_free(xfs_attr_trace_buf);#endif#ifdef XFS_BMBT_TRACE	ktrace_free(xfs_bmbt_trace_buf);#endif#ifdef XFS_BMAP_TRACE	ktrace_free(xfs_bmap_trace_buf);#endif#ifdef XFS_ALLOC_TRACE	ktrace_free(xfs_alloc_trace_buf);#endif	kmem_zone_destroy(xfs_bmap_free_item_zone);	kmem_zone_destroy(xfs_btree_cur_zone);	kmem_zone_destroy(xfs_inode_zone);	kmem_zone_destroy(xfs_trans_zone);	kmem_zone_destroy(xfs_da_state_zone);	kmem_zone_destroy(xfs_dabuf_zone);	kmem_zone_destroy(xfs_buf_item_zone);	kmem_zone_destroy(xfs_efd_zone);	kmem_zone_destroy(xfs_efi_zone);	kmem_zone_destroy(xfs_ifork_zone);	kmem_zone_destroy(xfs_ili_zone);	kmem_zone_destroy(xfs_icluster_zone);}/* * xfs_start_flags * * This function fills in xfs_mount_t fields based on mount args. * Note: the superblock has _not_ yet been read in. */STATIC intxfs_start_flags(	struct xfs_mount_args	*ap,	struct xfs_mount	*mp){	/* Values are in BBs */	if ((ap->flags & XFSMNT_NOALIGN) != XFSMNT_NOALIGN) {		/*		 * At this point the superblock has not been read		 * in, therefore we do not know the block size.		 * Before the mount call ends we will convert		 * these to FSBs.		 */		mp->m_dalign = ap->sunit;		mp->m_swidth = ap->swidth;	}	if (ap->logbufs != -1 &&	    ap->logbufs != 0 &&	    (ap->logbufs < XLOG_MIN_ICLOGS ||	     ap->logbufs > XLOG_MAX_ICLOGS)) {		cmn_err(CE_WARN,			"XFS: invalid logbufs value: %d [not %d-%d]",			ap->logbufs, XLOG_MIN_ICLOGS, XLOG_MAX_ICLOGS);		return XFS_ERROR(EINVAL);	}	mp->m_logbufs = ap->logbufs;	if (ap->logbufsize != -1 &&	    ap->logbufsize !=  0 &&	    (ap->logbufsize < XLOG_MIN_RECORD_BSIZE ||	     ap->logbufsize > XLOG_MAX_RECORD_BSIZE ||	     !is_power_of_2(ap->logbufsize))) {		cmn_err(CE_WARN,	"XFS: invalid logbufsize: %d [not 16k,32k,64k,128k or 256k]",			ap->logbufsize);		return XFS_ERROR(EINVAL);	}	mp->m_logbsize = ap->logbufsize;	mp->m_fsname_len = strlen(ap->fsname) + 1;	mp->m_fsname = kmem_alloc(mp->m_fsname_len, KM_SLEEP);	strcpy(mp->m_fsname, ap->fsname);	if (ap->rtname[0]) {		mp->m_rtname = kmem_alloc(strlen(ap->rtname) + 1, KM_SLEEP);		strcpy(mp->m_rtname, ap->rtname);	}	if (ap->logname[0]) {		mp->m_logname = kmem_alloc(strlen(ap->logname) + 1, KM_SLEEP);		strcpy(mp->m_logname, ap->logname);	}	if (ap->flags & XFSMNT_WSYNC)		mp->m_flags |= XFS_MOUNT_WSYNC;#if XFS_BIG_INUMS	if (ap->flags & XFSMNT_INO64) {		mp->m_flags |= XFS_MOUNT_INO64;		mp->m_inoadd = XFS_INO64_OFFSET;	}#endif	if (ap->flags & XFSMNT_RETERR)		mp->m_flags |= XFS_MOUNT_RETERR;	if (ap->flags & XFSMNT_NOALIGN)		mp->m_flags |= XFS_MOUNT_NOALIGN;	if (ap->flags & XFSMNT_SWALLOC)		mp->m_flags |= XFS_MOUNT_SWALLOC;	if (ap->flags & XFSMNT_OSYNCISOSYNC)		mp->m_flags |= XFS_MOUNT_OSYNCISOSYNC;	if (ap->flags & XFSMNT_32BITINODES)		mp->m_flags |= XFS_MOUNT_32BITINODES;	if (ap->flags & XFSMNT_IOSIZE) {		if (ap->iosizelog > XFS_MAX_IO_LOG ||		    ap->iosizelog < XFS_MIN_IO_LOG) {			cmn_err(CE_WARN,		"XFS: invalid log iosize: %d [not %d-%d]",				ap->iosizelog, XFS_MIN_IO_LOG,				XFS_MAX_IO_LOG);			return XFS_ERROR(EINVAL);		}		mp->m_flags |= XFS_MOUNT_DFLT_IOSIZE;		mp->m_readio_log = mp->m_writeio_log = ap->iosizelog;	}	if (ap->flags & XFSMNT_IDELETE)		mp->m_flags |= XFS_MOUNT_IDELETE;	if (ap->flags & XFSMNT_DIRSYNC)		mp->m_flags |= XFS_MOUNT_DIRSYNC;	if (ap->flags & XFSMNT_ATTR2)		mp->m_flags |= XFS_MOUNT_ATTR2;	if (ap->flags2 & XFSMNT2_COMPAT_IOSIZE)		mp->m_flags |= XFS_MOUNT_COMPAT_IOSIZE;	/*	 * no recovery flag requires a read-only mount	 */	if (ap->flags & XFSMNT_NORECOVERY) {		if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {			cmn_err(CE_WARN,	"XFS: tried to mount a FS read-write without recovery!");			return XFS_ERROR(EINVAL);		}		mp->m_flags |= XFS_MOUNT_NORECOVERY;	}	if (ap->flags & XFSMNT_NOUUID)		mp->m_flags |= XFS_MOUNT_NOUUID;	if (ap->flags & XFSMNT_BARRIER)		mp->m_flags |= XFS_MOUNT_BARRIER;	else		mp->m_flags &= ~XFS_MOUNT_BARRIER;	if (ap->flags2 & XFSMNT2_FILESTREAMS)		mp->m_flags |= XFS_MOUNT_FILESTREAMS;	if (ap->flags & XFSMNT_DMAPI)		mp->m_flags |= XFS_MOUNT_DMAPI;	return 0;}/* * This function fills in xfs_mount_t fields based on mount args. * Note: the superblock _has_ now been read in. */STATIC intxfs_finish_flags(	struct xfs_mount_args	*ap,	struct xfs_mount	*mp){	int			ronly = (mp->m_flags & XFS_MOUNT_RDONLY);	/* Fail a mount where the logbuf is smaller then the log stripe */	if (XFS_SB_VERSION_HASLOGV2(&mp->m_sb)) {		if ((ap->logbufsize <= 0) &&		    (mp->m_sb.sb_logsunit > XLOG_BIG_RECORD_BSIZE)) {			mp->m_logbsize = mp->m_sb.sb_logsunit;		} else if (ap->logbufsize > 0 &&			   ap->logbufsize < mp->m_sb.sb_logsunit) {			cmn_err(CE_WARN,	"XFS: logbuf size must be greater than or equal to log stripe size");			return XFS_ERROR(EINVAL);		}	} else {		/* Fail a mount if the logbuf is larger than 32K */		if (ap->logbufsize > XLOG_BIG_RECORD_BSIZE) {			cmn_err(CE_WARN,	"XFS: logbuf size for version 1 logs must be 16K or 32K");			return XFS_ERROR(EINVAL);		}	}	if (XFS_SB_VERSION_HASATTR2(&mp->m_sb)) {		mp->m_flags |= XFS_MOUNT_ATTR2;	}	/*	 * prohibit r/w mounts of read-only filesystems	 */	if ((mp->m_sb.sb_flags & XFS_SBF_READONLY) && !ronly) {		cmn_err(CE_WARN,	"XFS: cannot mount a read-only filesystem as read-write");		return XFS_ERROR(EROFS);	}	/*	 * check for shared mount.	 */	if (ap->flags & XFSMNT_SHARED) {		if (!XFS_SB_VERSION_HASSHARED(&mp->m_sb))			return XFS_ERROR(EINVAL);		/*		 * For IRIX 6.5, shared mounts must have the shared		 * version bit set, have the persistent readonly		 * field set, must be version 0 and can only be mounted		 * read-only.		 */		if (!ronly || !(mp->m_sb.sb_flags & XFS_SBF_READONLY) ||		     (mp->m_sb.sb_shared_vn != 0))			return XFS_ERROR(EINVAL);		mp->m_flags |= XFS_MOUNT_SHARED;		/*		 * Shared XFS V0 can't deal with DMI.  Return EINVAL.		 */		if (mp->m_sb.sb_shared_vn == 0 && (ap->flags & XFSMNT_DMAPI))			return XFS_ERROR(EINVAL);	}	if (ap->flags & XFSMNT_UQUOTA) {		mp->m_qflags |= (XFS_UQUOTA_ACCT | XFS_UQUOTA_ACTIVE);		if (ap->flags & XFSMNT_UQUOTAENF)			mp->m_qflags |= XFS_UQUOTA_ENFD;	}	if (ap->flags & XFSMNT_GQUOTA) {		mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE);		if (ap->flags & XFSMNT_GQUOTAENF)			mp->m_qflags |= XFS_OQUOTA_ENFD;	} else if (ap->flags & XFSMNT_PQUOTA) {		mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE);		if (ap->flags & XFSMNT_PQUOTAENF)			mp->m_qflags |= XFS_OQUOTA_ENFD;	}	return 0;}/* * xfs_mount * * The file system configurations are: *	(1) device (partition) with data and internal log *	(2) logical volume with data and log subvolumes. *	(3) logical volume with data, log, and realtime subvolumes. * * We only have to handle opening the log and realtime volumes here if * they are present.  The data subvolume has already been opened by * get_sb_bdev() and is stored in vfsp->vfs_super->s_bdev. */intxfs_mount(	struct xfs_mount	*mp,	struct xfs_mount_args	*args,	cred_t			*credp){	struct block_device	*ddev, *logdev, *rtdev;	int			flags = 0, error;	ddev = mp->m_super->s_bdev;	logdev = rtdev = NULL;	error = xfs_dmops_get(mp, args);	if (error)		return error;	error = xfs_qmops_get(mp, args);	if (error)		return error;	mp->m_io_ops = xfs_iocore_xfs;	if (args->flags & XFSMNT_QUIET)		flags |= XFS_MFSI_QUIET;	/*	 * Open real time and log devices - order is important.	 */	if (args->logname[0]) {		error = xfs_blkdev_get(mp, args->logname, &logdev);		if (error)			return error;	}	if (args->rtname[0]) {		error = xfs_blkdev_get(mp, args->rtname, &rtdev);		if (error) {			xfs_blkdev_put(logdev);			return error;		}		if (rtdev == ddev || rtdev == logdev) {			cmn_err(CE_WARN,	"XFS: Cannot mount filesystem with identical rtdev and ddev/logdev.");			xfs_blkdev_put(logdev);			xfs_blkdev_put(rtdev);			return EINVAL;		}	}	/*	 * Setup xfs_mount buffer target pointers	 */	error = ENOMEM;	mp->m_ddev_targp = xfs_alloc_buftarg(ddev, 0);	if (!mp->m_ddev_targp) {		xfs_blkdev_put(logdev);		xfs_blkdev_put(rtdev);		return error;	}	if (rtdev) {		mp->m_rtdev_targp = xfs_alloc_buftarg(rtdev, 1);		if (!mp->m_rtdev_targp) {			xfs_blkdev_put(logdev);			xfs_blkdev_put(rtdev);			goto error0;		}	}	mp->m_logdev_targp = (logdev && logdev != ddev) ?				xfs_alloc_buftarg(logdev, 1) : mp->m_ddev_targp;	if (!mp->m_logdev_targp) {		xfs_blkdev_put(logdev);		xfs_blkdev_put(rtdev);		goto error0;	}	/*	 * Setup flags based on mount(2) options and then the superblock	 */	error = xfs_start_flags(args, mp);	if (error)		goto error1;	error = xfs_readsb(mp, flags);	if (error)		goto error1;	error = xfs_finish_flags(args, mp);	if (error)		goto error2;	/*	 * Setup xfs_mount buffer target pointers based on superblock	 */	error = xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_blocksize,				    mp->m_sb.sb_sectsize);	if (!error && logdev && logdev != ddev) {		unsigned int	log_sector_size = BBSIZE;		if (XFS_SB_VERSION_HASSECTOR(&mp->m_sb))			log_sector_size = mp->m_sb.sb_logsectsize;		error = xfs_setsize_buftarg(mp->m_logdev_targp,					    mp->m_sb.sb_blocksize,					    log_sector_size);

⌨️ 快捷键说明

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