xfs_vfsops.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,927 行 · 第 1/4 页

C
1,927
字号
/* * XFS filesystem operations. * * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 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. * * Further, this software is distributed without any warranty that it is * free of the rightful claim of any third person regarding infringement * or the like.  Any license provided herein, whether implied or * otherwise, applies only to this software file.  Patent licenses, if * any, provided herein do not apply to combinations of this program with * other software, or any other product whatsoever. * * You should have received a copy of the GNU General Public License along * with this program; if not, write the Free Software Foundation, Inc., 59 * Temple Place - Suite 330, Boston MA 02111-1307, USA. * * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, * Mountain View, CA  94043, or: * * http://www.sgi.com * * For further information regarding this notice, see: * * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ */#include "xfs.h"#include "xfs_macros.h"#include "xfs_types.h"#include "xfs_inum.h"#include "xfs_log.h"#include "xfs_trans.h"#include "xfs_sb.h"#include "xfs_dir.h"#include "xfs_dir2.h"#include "xfs_dmapi.h"#include "xfs_mount.h"#include "xfs_bmap_btree.h"#include "xfs_ialloc_btree.h"#include "xfs_alloc_btree.h"#include "xfs_btree.h"#include "xfs_alloc.h"#include "xfs_ialloc.h"#include "xfs_attr_sf.h"#include "xfs_dir_sf.h"#include "xfs_dir2_sf.h"#include "xfs_dinode.h"#include "xfs_inode_item.h"#include "xfs_inode.h"#include "xfs_ag.h"#include "xfs_error.h"#include "xfs_bmap.h"#include "xfs_da_btree.h"#include "xfs_rw.h"#include "xfs_refcache.h"#include "xfs_buf_item.h"#include "xfs_extfree_item.h"#include "xfs_quota.h"#include "xfs_dir2_trace.h"#include "xfs_acl.h"#include "xfs_attr.h"#include "xfs_clnt.h"#include "xfs_log_priv.h"STATIC int xfs_sync(bhv_desc_t *, int, cred_t *);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_inode_zone = kmem_zone_init(sizeof(xfs_inode_t), "xfs_inode");	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");	/*	 * 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");	xfs_ifork_zone = kmem_zone_init(sizeof(xfs_ifork_t), "xfs_ifork");	xfs_ili_zone = kmem_zone_init(sizeof(xfs_inode_log_item_t), "xfs_ili");	xfs_chashlist_zone = kmem_zone_init(sizeof(xfs_chashlist_t),					    "xfs_chashlist");	xfs_acl_zone_init(xfs_acl_zone, "xfs_acl");	/*	 * 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_DIR_TRACE	xfs_dir_trace_buf = ktrace_alloc(XFS_DIR_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_chashlist_zone;	xfs_cleanup_procfs();	xfs_sysctl_unregister();	xfs_refcache_destroy();	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_DIR_TRACE	ktrace_free(xfs_dir_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_cache_destroy(xfs_bmap_free_item_zone);	kmem_cache_destroy(xfs_btree_cur_zone);	kmem_cache_destroy(xfs_inode_zone);	kmem_cache_destroy(xfs_trans_zone);	kmem_cache_destroy(xfs_da_state_zone);	kmem_cache_destroy(xfs_dabuf_zone);	kmem_cache_destroy(xfs_buf_item_zone);	kmem_cache_destroy(xfs_efd_zone);	kmem_cache_destroy(xfs_efi_zone);	kmem_cache_destroy(xfs_ifork_zone);	kmem_cache_destroy(xfs_ili_zone);	kmem_cache_destroy(xfs_chashlist_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 vfs		*vfs,	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 &&#if defined(DEBUG) || defined(XLOG_NOLOG)	    ap->logbufs != 0 &&#endif	    (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 != 16 * 1024 &&	    ap->logbufsize != 32 * 1024 &&	    ap->logbufsize != 64 * 1024 &&	    ap->logbufsize != 128 * 1024 &&	    ap->logbufsize != 256 * 1024) {		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);	/*	 * Pull in the 'wsync' and 'ino64' mount options before we do the real	 * work of mounting and recovery.  The arg pointer will	 * be NULL when we are being called from the root mount code.	 */	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_NOATIME)		mp->m_flags |= XFS_MOUNT_NOATIME;	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 | XFS_MOUNT_32BITINOOPT);	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;	/*	 * no recovery flag requires a read-only mount	 */	if (ap->flags & XFSMNT_NORECOVERY) {		if (!(vfs->vfs_flag & VFS_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_NOLOGFLUSH)		mp->m_flags |= XFS_MOUNT_NOLOGFLUSH;	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 vfs		*vfs,	struct xfs_mount_args	*ap,	struct xfs_mount	*mp){	int			ronly = (vfs->vfs_flag & VFS_RDONLY);	/* Fail a mount where the logbuf is smaller then the log stripe */	if (XFS_SB_VERSION_HASLOGV2(&mp->m_sb)) {		if ((ap->logbufsize == -1) &&		    (mp->m_sb.sb_logsunit > XLOG_BIG_RECORD_BSIZE)) {			mp->m_logbsize = mp->m_sb.sb_logsunit;		} else if (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);		}	}	/*	 * 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);	}	/*	 * disallow mount attempts with (IRIX) project quota enabled	 */	if (XFS_SB_VERSION_HASQUOTA(&mp->m_sb) &&	    (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT)) {		cmn_err(CE_WARN,	"XFS: cannot mount a filesystem with IRIX project quota enabled");		return XFS_ERROR(ENOSYS);	}	/*	 * 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);	}	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. */STATIC intxfs_mount(	struct bhv_desc		*bhvp,	struct xfs_mount_args	*args,	cred_t			*credp){	struct vfs		*vfsp = bhvtovfs(bhvp);	struct bhv_desc		*p;	struct xfs_mount	*mp = XFS_BHVTOM(bhvp);	struct block_device	*ddev, *logdev, *rtdev;	int			flags = 0, error;	ddev = vfsp->vfs_super->s_bdev;	logdev = rtdev = NULL;	/*	 * Setup xfs_mount function vectors from available behaviors	 */	p = vfs_bhv_lookup(vfsp, VFS_POSITION_DM);	mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_stub;	p = vfs_bhv_lookup(vfsp, VFS_POSITION_QM);	mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_stub;	p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO);	mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs;	/*	 * 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);	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);		if (!mp->m_rtdev_targp)			goto error0;	}	mp->m_logdev_targp = (logdev && logdev != ddev) ?

⌨️ 快捷键说明

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