📄 xfs_vfsops.c
字号:
/* * 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 + -