xfs_mount.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,582 行 · 第 1/3 页
C
1,582 行
goto fail; } ASSERT(XFS_BUF_ISBUSY(bp)); ASSERT(XFS_BUF_VALUSEMA(bp) <= 0); } mp->m_sb_bp = bp; xfs_buf_relse(bp); ASSERT(XFS_BUF_VALUSEMA(bp) > 0); return 0; fail: if (bp) { XFS_BUF_UNMANAGE(bp); xfs_buf_relse(bp); } return error;}/* * xfs_mount_common * * Mount initialization code establishing various mount * fields from the superblock associated with the given * mount structure */voidxfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp){ int i; mp->m_agfrotor = mp->m_agirotor = 0; spinlock_init(&mp->m_agirotor_lock, "m_agirotor_lock"); mp->m_maxagi = mp->m_sb.sb_agcount; mp->m_blkbit_log = sbp->sb_blocklog + XFS_NBBYLOG; mp->m_blkbb_log = sbp->sb_blocklog - BBSHIFT; mp->m_sectbb_log = sbp->sb_sectlog - BBSHIFT; mp->m_agno_log = xfs_highbit32(sbp->sb_agcount - 1) + 1; mp->m_agino_log = sbp->sb_inopblog + sbp->sb_agblklog; mp->m_litino = sbp->sb_inodesize - ((uint)sizeof(xfs_dinode_core_t) + (uint)sizeof(xfs_agino_t)); mp->m_blockmask = sbp->sb_blocksize - 1; mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG; mp->m_blockwmask = mp->m_blockwsize - 1; INIT_LIST_HEAD(&mp->m_del_inodes); /* * Setup for attributes, in case they get created. * This value is for inodes getting attributes for the first time, * the per-inode value is for old attribute values. */ ASSERT(sbp->sb_inodesize >= 256 && sbp->sb_inodesize <= 2048); switch (sbp->sb_inodesize) { case 256: mp->m_attroffset = XFS_LITINO(mp) - XFS_BMDR_SPACE_CALC(2); break; case 512: case 1024: case 2048: mp->m_attroffset = XFS_BMDR_SPACE_CALC(12); break; default: ASSERT(0); } ASSERT(mp->m_attroffset < XFS_LITINO(mp)); for (i = 0; i < 2; i++) { mp->m_alloc_mxr[i] = XFS_BTREE_BLOCK_MAXRECS(sbp->sb_blocksize, xfs_alloc, i == 0); mp->m_alloc_mnr[i] = XFS_BTREE_BLOCK_MINRECS(sbp->sb_blocksize, xfs_alloc, i == 0); } for (i = 0; i < 2; i++) { mp->m_bmap_dmxr[i] = XFS_BTREE_BLOCK_MAXRECS(sbp->sb_blocksize, xfs_bmbt, i == 0); mp->m_bmap_dmnr[i] = XFS_BTREE_BLOCK_MINRECS(sbp->sb_blocksize, xfs_bmbt, i == 0); } for (i = 0; i < 2; i++) { mp->m_inobt_mxr[i] = XFS_BTREE_BLOCK_MAXRECS(sbp->sb_blocksize, xfs_inobt, i == 0); mp->m_inobt_mnr[i] = XFS_BTREE_BLOCK_MINRECS(sbp->sb_blocksize, xfs_inobt, i == 0); } mp->m_bsize = XFS_FSB_TO_BB(mp, 1); mp->m_ialloc_inos = (int)MAX((__uint16_t)XFS_INODES_PER_CHUNK, sbp->sb_inopblock); mp->m_ialloc_blks = mp->m_ialloc_inos >> sbp->sb_inopblog;}/* * xfs_mountfs * * This function does the following on an initial mount of a file system: * - reads the superblock from disk and init the mount struct * - if we're a 32-bit kernel, do a size check on the superblock * so we don't mount terabyte filesystems * - init mount struct realtime fields * - allocate inode hash table for fs * - init directory manager * - perform recovery and init the log manager */intxfs_mountfs( vfs_t *vfsp, xfs_mount_t *mp, int mfsi_flags){ xfs_buf_t *bp; xfs_sb_t *sbp = &(mp->m_sb); xfs_inode_t *rip; vnode_t *rvp = NULL; int readio_log, writeio_log; xfs_daddr_t d; __uint64_t ret64; __int64_t update_flags; uint quotamount, quotaflags; int agno; int uuid_mounted = 0; int error = 0; if (mp->m_sb_bp == NULL) { if ((error = xfs_readsb(mp))) { return (error); } } xfs_mount_common(mp, sbp); /* * Check if sb_agblocks is aligned at stripe boundary * If sb_agblocks is NOT aligned turn off m_dalign since * allocator alignment is within an ag, therefore ag has * to be aligned at stripe boundary. */ update_flags = 0LL; if (mp->m_dalign && !(mfsi_flags & XFS_MFSI_SECOND)) { /* * If stripe unit and stripe width are not multiples * of the fs blocksize turn off alignment. */ if ((BBTOB(mp->m_dalign) & mp->m_blockmask) || (BBTOB(mp->m_swidth) & mp->m_blockmask)) { if (mp->m_flags & XFS_MOUNT_RETERR) { cmn_err(CE_WARN, "XFS: alignment check 1 failed"); error = XFS_ERROR(EINVAL); goto error1; } mp->m_dalign = mp->m_swidth = 0; } else { /* * Convert the stripe unit and width to FSBs. */ mp->m_dalign = XFS_BB_TO_FSBT(mp, mp->m_dalign); if (mp->m_dalign && (sbp->sb_agblocks % mp->m_dalign)) { if (mp->m_flags & XFS_MOUNT_RETERR) { error = XFS_ERROR(EINVAL); goto error1; } xfs_fs_cmn_err(CE_WARN, mp,"stripe alignment turned off: sunit(%d)/swidth(%d) incompatible with agsize(%d)", mp->m_dalign, mp->m_swidth, sbp->sb_agblocks); mp->m_dalign = 0; mp->m_swidth = 0; } else if (mp->m_dalign) { mp->m_swidth = XFS_BB_TO_FSBT(mp, mp->m_swidth); } else { if (mp->m_flags & XFS_MOUNT_RETERR) { xfs_fs_cmn_err(CE_WARN, mp,"stripe alignment turned off: sunit(%d) less than bsize(%d)", mp->m_dalign, mp->m_blockmask +1); error = XFS_ERROR(EINVAL); goto error1; } mp->m_swidth = 0; } } /* * Update superblock with new values * and log changes */ if (XFS_SB_VERSION_HASDALIGN(sbp)) { if (sbp->sb_unit != mp->m_dalign) { sbp->sb_unit = mp->m_dalign; update_flags |= XFS_SB_UNIT; } if (sbp->sb_width != mp->m_swidth) { sbp->sb_width = mp->m_swidth; update_flags |= XFS_SB_WIDTH; } } } else if ((mp->m_flags & XFS_MOUNT_NOALIGN) != XFS_MOUNT_NOALIGN && XFS_SB_VERSION_HASDALIGN(&mp->m_sb)) { mp->m_dalign = sbp->sb_unit; mp->m_swidth = sbp->sb_width; } xfs_alloc_compute_maxlevels(mp); xfs_bmap_compute_maxlevels(mp, XFS_DATA_FORK); xfs_bmap_compute_maxlevels(mp, XFS_ATTR_FORK); xfs_ialloc_compute_maxlevels(mp); if (sbp->sb_imax_pct) { __uint64_t icount; /* Make sure the maximum inode count is a multiple of the * units we allocate inodes in. */ icount = sbp->sb_dblocks * sbp->sb_imax_pct; do_div(icount, 100); do_div(icount, mp->m_ialloc_blks); mp->m_maxicount = (icount * mp->m_ialloc_blks) << sbp->sb_inopblog; } else mp->m_maxicount = 0; mp->m_maxioffset = xfs_max_file_offset(sbp->sb_blocklog); /* * XFS uses the uuid from the superblock as the unique * identifier for fsid. We can not use the uuid from the volume * since a single partition filesystem is identical to a single * partition volume/filesystem. */ if ((mfsi_flags & XFS_MFSI_SECOND) == 0 && (mp->m_flags & XFS_MOUNT_NOUUID) == 0) { if (xfs_uuid_mount(mp)) { error = XFS_ERROR(EINVAL); goto error1; } uuid_mounted=1; ret64 = uuid_hash64(&sbp->sb_uuid); memcpy(&vfsp->vfs_fsid, &ret64, sizeof(ret64)); } /* * Set the default minimum read and write sizes unless * already specified in a mount option. * We use smaller I/O sizes when the file system * is being used for NFS service (wsync mount option). */ if (!(mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)) { if (mp->m_flags & XFS_MOUNT_WSYNC) { readio_log = XFS_WSYNC_READIO_LOG; writeio_log = XFS_WSYNC_WRITEIO_LOG; } else { readio_log = XFS_READIO_LOG_LARGE; writeio_log = XFS_WRITEIO_LOG_LARGE; } } else { readio_log = mp->m_readio_log; writeio_log = mp->m_writeio_log; } /* * Set the number of readahead buffers to use based on * physical memory size. */ if (xfs_physmem <= 4096) /* <= 16MB */ mp->m_nreadaheads = XFS_RW_NREADAHEAD_16MB; else if (xfs_physmem <= 8192) /* <= 32MB */ mp->m_nreadaheads = XFS_RW_NREADAHEAD_32MB; else mp->m_nreadaheads = XFS_RW_NREADAHEAD_K32; if (sbp->sb_blocklog > readio_log) { mp->m_readio_log = sbp->sb_blocklog; } else { mp->m_readio_log = readio_log; } mp->m_readio_blocks = 1 << (mp->m_readio_log - sbp->sb_blocklog); if (sbp->sb_blocklog > writeio_log) { mp->m_writeio_log = sbp->sb_blocklog; } else { mp->m_writeio_log = writeio_log; } mp->m_writeio_blocks = 1 << (mp->m_writeio_log - sbp->sb_blocklog); /* * Set the inode cluster size based on the physical memory * size. This may still be overridden by the file system * block size if it is larger than the chosen cluster size. */ if (xfs_physmem <= btoc(32 * 1024 * 1024)) { /* <= 32 MB */ mp->m_inode_cluster_size = XFS_INODE_SMALL_CLUSTER_SIZE; } else { mp->m_inode_cluster_size = XFS_INODE_BIG_CLUSTER_SIZE; } /* * Set whether we're using inode alignment. */ if (XFS_SB_VERSION_HASALIGN(&mp->m_sb) && mp->m_sb.sb_inoalignmt >= XFS_B_TO_FSBT(mp, mp->m_inode_cluster_size)) mp->m_inoalign_mask = mp->m_sb.sb_inoalignmt - 1; else mp->m_inoalign_mask = 0; /* * If we are using stripe alignment, check whether * the stripe unit is a multiple of the inode alignment */ if (mp->m_dalign && mp->m_inoalign_mask && !(mp->m_dalign & mp->m_inoalign_mask)) mp->m_sinoalign = mp->m_dalign; else mp->m_sinoalign = 0; /* * Check that the data (and log if separate) are an ok size. */ d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks); if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) { cmn_err(CE_WARN, "XFS: size check 1 failed"); error = XFS_ERROR(E2BIG); goto error1; } error = xfs_read_buf(mp, mp->m_ddev_targp, d - XFS_FSS_TO_BB(mp, 1), XFS_FSS_TO_BB(mp, 1), 0, &bp); if (!error) { xfs_buf_relse(bp); } else { cmn_err(CE_WARN, "XFS: size check 2 failed"); if (error == ENOSPC) { error = XFS_ERROR(E2BIG); } goto error1; } if (((mfsi_flags & XFS_MFSI_CLIENT) == 0) && mp->m_logdev_targp != mp->m_ddev_targp) { d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks); if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) { cmn_err(CE_WARN, "XFS: size check 3 failed"); error = XFS_ERROR(E2BIG); goto error1; } error = xfs_read_buf(mp, mp->m_logdev_targp, d - XFS_FSB_TO_BB(mp, 1), XFS_FSB_TO_BB(mp, 1), 0, &bp); if (!error) { xfs_buf_relse(bp); } else { cmn_err(CE_WARN, "XFS: size check 3 failed"); if (error == ENOSPC) { error = XFS_ERROR(E2BIG); } goto error1; } } /* * Initialize realtime fields in the mount structure */ if ((error = xfs_rtmount_init(mp))) { cmn_err(CE_WARN, "XFS: RT mount failed"); goto error1; } /* * For client case we are done now */ if (mfsi_flags & XFS_MFSI_CLIENT) { return(0); } /* * Copies the low order bits of the timestamp and the randomly * set "sequence" number out of a UUID. */ uuid_getnodeuniq(&sbp->sb_uuid, mp->m_fixedfsid); /* * The vfs structure needs to have a file system independent * way of checking for the invariant file system ID. Since it * can't look at mount structures it has a pointer to the data * in the mount structure. * * File systems that don't support user level file handles (i.e. * all of them except for XFS) will leave vfs_altfsid as NULL. */ vfsp->vfs_altfsid = (xfs_fsid_t *)mp->m_fixedfsid; mp->m_dmevmask = 0; /* not persistent; set after each mount */ /* * Select the right directory manager. */ mp->m_dirops = XFS_SB_VERSION_HASDIRV2(&mp->m_sb) ? xfsv2_dirops : xfsv1_dirops; /* * Initialize directory manager's entries. */ XFS_DIR_MOUNT(mp); /* * Initialize the attribute manager's entries. */ mp->m_attr_magicpct = (mp->m_sb.sb_blocksize * 37) / 100; /* * Initialize the precomputed transaction reservations values. */ xfs_trans_init(mp); /* * Allocate and initialize the inode hash table for this * file system. */ xfs_ihash_init(mp); xfs_chash_init(mp); /* * Allocate and initialize the per-ag data. */ init_rwsem(&mp->m_peraglock); mp->m_perag = kmem_zalloc(sbp->sb_agcount * sizeof(xfs_perag_t), KM_SLEEP); mp->m_maxagi = xfs_initialize_perag(mp, sbp->sb_agcount); /* * log's mount-time initialization. Perform 1st part recovery if needed */ if (likely(sbp->sb_logblocks > 0)) { /* check for volume case */ error = xfs_log_mount(mp, mp->m_logdev_targp, XFS_FSB_TO_DADDR(mp, sbp->sb_logstart), XFS_FSB_TO_BB(mp, sbp->sb_logblocks)); if (error) { cmn_err(CE_WARN, "XFS: log mount failed"); goto error2; } } else { /* No log has been defined */ cmn_err(CE_WARN, "XFS: no log defined"); XFS_ERROR_REPORT("xfs_mountfs_int(1)", XFS_ERRLEVEL_LOW, mp); error = XFS_ERROR(EFSCORRUPTED); goto error2; } /* * Get and sanity-check the root inode. * Save the pointer to it in the mount structure. */ error = xfs_iget(mp, NULL, sbp->sb_rootino, XFS_ILOCK_EXCL, &rip, 0); if (error) { cmn_err(CE_WARN, "XFS: failed to read root inode"); goto error3; } ASSERT(rip != NULL); rvp = XFS_ITOV(rip); if (unlikely((rip->i_d.di_mode & S_IFMT) != S_IFDIR)) { cmn_err(CE_WARN, "XFS: corrupted root inode"); prdev("Root inode %llu is not a directory", mp->m_ddev_targp, (unsigned long long)rip->i_ino); xfs_iunlock(rip, XFS_ILOCK_EXCL); XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW, mp); error = XFS_ERROR(EFSCORRUPTED); goto error4; } mp->m_rootip = rip; /* save it */ xfs_iunlock(rip, XFS_ILOCK_EXCL); /* * Initialize realtime inode pointers in the mount structure */ if ((error = xfs_rtmount_inodes(mp))) { /* * Free up the root inode. */ cmn_err(CE_WARN, "XFS: failed to read RT inodes"); goto error4; } /* * If fs is not mounted readonly, then update the superblock * unit and width changes. */ if (update_flags && !(vfsp->vfs_flag & VFS_RDONLY)) xfs_mount_log_sbunit(mp, update_flags); /* * Initialise the XFS quota management subsystem for this mount */ if ((error = XFS_QM_INIT(mp, "amount, "aflags))) goto error4; /* * Finish recovering the file system. This part needed to be * delayed until after the root and real-time bitmap inodes * were consistently read in. */ error = xfs_log_mount_finish(mp, mfsi_flags); if (error) { cmn_err(CE_WARN, "XFS: log mount finish failed"); goto error4; } /* * Complete the quota initialisation, post-log-replay component. */ if ((error = XFS_QM_MOUNT(mp, quotamount, quotaflags))) goto error4; return 0; error4: /* * Free up the root inode. */ VN_RELE(rvp); error3: xfs_log_unmount_dealloc(mp); error2: xfs_ihash_free(mp); xfs_chash_free(mp); for (agno = 0; agno < sbp->sb_agcount; agno++) if (mp->m_perag[agno].pagb_list) kmem_free(mp->m_perag[agno].pagb_list,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?