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 + -
显示快捷键?