diff options
Diffstat (limited to 'fs/xfs/xfs_mount.c')
-rw-r--r-- | fs/xfs/xfs_mount.c | 242 |
1 files changed, 118 insertions, 124 deletions
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index a66b3980517..ebdb76da527 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -139,7 +139,7 @@ xfs_mount_init(void) AIL_LOCKINIT(&mp->m_ail_lock, "xfs_ail"); spinlock_init(&mp->m_sb_lock, "xfs_sb"); mutex_init(&mp->m_ilock); - initnsema(&mp->m_growlock, 1, "xfs_grow"); + mutex_init(&mp->m_growlock); /* * Initialize the AIL. */ @@ -157,14 +157,8 @@ xfs_mount_init(void) */ void xfs_mount_free( - xfs_mount_t *mp, - int remove_bhv) + xfs_mount_t *mp) { - if (mp->m_ihash) - xfs_ihash_free(mp); - if (mp->m_chash) - xfs_chash_free(mp); - if (mp->m_perag) { int agno; @@ -180,7 +174,7 @@ xfs_mount_free( AIL_LOCK_DESTROY(&mp->m_ail_lock); spinlock_destroy(&mp->m_sb_lock); mutex_destroy(&mp->m_ilock); - freesema(&mp->m_growlock); + mutex_destroy(&mp->m_growlock); if (mp->m_quotainfo) XFS_QM_DONE(mp); @@ -191,15 +185,7 @@ xfs_mount_free( if (mp->m_logname != NULL) kmem_free(mp->m_logname, strlen(mp->m_logname) + 1); - if (remove_bhv) { - struct bhv_vfs *vfsp = XFS_MTOVFS(mp); - - bhv_remove_all_vfsops(vfsp, 0); - VFS_REMOVEBHV(vfsp, &mp->m_bhv); - } - xfs_icsb_destroy_counters(mp); - kmem_free(mp, sizeof(xfs_mount_t)); } /* @@ -342,9 +328,19 @@ xfs_mount_validate_sb( return 0; } +STATIC void +xfs_initialize_perag_icache( + xfs_perag_t *pag) +{ + if (!pag->pag_ici_init) { + rwlock_init(&pag->pag_ici_lock); + INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC); + pag->pag_ici_init = 1; + } +} + xfs_agnumber_t xfs_initialize_perag( - bhv_vfs_t *vfs, xfs_mount_t *mp, xfs_agnumber_t agcount) { @@ -362,7 +358,7 @@ xfs_initialize_perag( /* Clear the mount flag if no inode can overflow 32 bits * on this filesystem, or if specifically requested.. */ - if ((vfs->vfs_flag & VFS_32BITINODES) && ino > max_inum) { + if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) && ino > max_inum) { mp->m_flags |= XFS_MOUNT_32BITINODES; } else { mp->m_flags &= ~XFS_MOUNT_32BITINODES; @@ -396,48 +392,92 @@ xfs_initialize_perag( pag->pagi_inodeok = 1; if (index < max_metadata) pag->pagf_metadata = 1; + xfs_initialize_perag_icache(pag); } } else { /* Setup default behavior for smaller filesystems */ for (index = 0; index < agcount; index++) { pag = &mp->m_perag[index]; pag->pagi_inodeok = 1; + xfs_initialize_perag_icache(pag); } } return index; } +void +xfs_sb_from_disk( + xfs_sb_t *to, + xfs_dsb_t *from) +{ + to->sb_magicnum = be32_to_cpu(from->sb_magicnum); + to->sb_blocksize = be32_to_cpu(from->sb_blocksize); + to->sb_dblocks = be64_to_cpu(from->sb_dblocks); + to->sb_rblocks = be64_to_cpu(from->sb_rblocks); + to->sb_rextents = be64_to_cpu(from->sb_rextents); + memcpy(&to->sb_uuid, &from->sb_uuid, sizeof(to->sb_uuid)); + to->sb_logstart = be64_to_cpu(from->sb_logstart); + to->sb_rootino = be64_to_cpu(from->sb_rootino); + to->sb_rbmino = be64_to_cpu(from->sb_rbmino); + to->sb_rsumino = be64_to_cpu(from->sb_rsumino); + to->sb_rextsize = be32_to_cpu(from->sb_rextsize); + to->sb_agblocks = be32_to_cpu(from->sb_agblocks); + to->sb_agcount = be32_to_cpu(from->sb_agcount); + to->sb_rbmblocks = be32_to_cpu(from->sb_rbmblocks); + to->sb_logblocks = be32_to_cpu(from->sb_logblocks); + to->sb_versionnum = be16_to_cpu(from->sb_versionnum); + to->sb_sectsize = be16_to_cpu(from->sb_sectsize); + to->sb_inodesize = be16_to_cpu(from->sb_inodesize); + to->sb_inopblock = be16_to_cpu(from->sb_inopblock); + memcpy(&to->sb_fname, &from->sb_fname, sizeof(to->sb_fname)); + to->sb_blocklog = from->sb_blocklog; + to->sb_sectlog = from->sb_sectlog; + to->sb_inodelog = from->sb_inodelog; + to->sb_inopblog = from->sb_inopblog; + to->sb_agblklog = from->sb_agblklog; + to->sb_rextslog = from->sb_rextslog; + to->sb_inprogress = from->sb_inprogress; + to->sb_imax_pct = from->sb_imax_pct; + to->sb_icount = be64_to_cpu(from->sb_icount); + to->sb_ifree = be64_to_cpu(from->sb_ifree); + to->sb_fdblocks = be64_to_cpu(from->sb_fdblocks); + to->sb_frextents = be64_to_cpu(from->sb_frextents); + to->sb_uquotino = be64_to_cpu(from->sb_uquotino); + to->sb_gquotino = be64_to_cpu(from->sb_gquotino); + to->sb_qflags = be16_to_cpu(from->sb_qflags); + to->sb_flags = from->sb_flags; + to->sb_shared_vn = from->sb_shared_vn; + to->sb_inoalignmt = be32_to_cpu(from->sb_inoalignmt); + to->sb_unit = be32_to_cpu(from->sb_unit); + to->sb_width = be32_to_cpu(from->sb_width); + to->sb_dirblklog = from->sb_dirblklog; + to->sb_logsectlog = from->sb_logsectlog; + to->sb_logsectsize = be16_to_cpu(from->sb_logsectsize); + to->sb_logsunit = be32_to_cpu(from->sb_logsunit); + to->sb_features2 = be32_to_cpu(from->sb_features2); +} + /* - * xfs_xlatesb + * Copy in core superblock to ondisk one. * - * data - on disk version of sb - * sb - a superblock - * dir - conversion direction: <0 - convert sb to buf - * >0 - convert buf to sb - * fields - which fields to copy (bitmask) + * The fields argument is mask of superblock fields to copy. */ void -xfs_xlatesb( - void *data, - xfs_sb_t *sb, - int dir, +xfs_sb_to_disk( + xfs_dsb_t *to, + xfs_sb_t *from, __int64_t fields) { - xfs_caddr_t buf_ptr; - xfs_caddr_t mem_ptr; + xfs_caddr_t to_ptr = (xfs_caddr_t)to; + xfs_caddr_t from_ptr = (xfs_caddr_t)from; xfs_sb_field_t f; int first; int size; - ASSERT(dir); ASSERT(fields); - if (!fields) return; - buf_ptr = (xfs_caddr_t)data; - mem_ptr = (xfs_caddr_t)sb; - while (fields) { f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields); first = xfs_sb_info[f].offset; @@ -446,26 +486,20 @@ xfs_xlatesb( ASSERT(xfs_sb_info[f].type == 0 || xfs_sb_info[f].type == 1); if (size == 1 || xfs_sb_info[f].type == 1) { - if (dir > 0) { - memcpy(mem_ptr + first, buf_ptr + first, size); - } else { - memcpy(buf_ptr + first, mem_ptr + first, size); - } + memcpy(to_ptr + first, from_ptr + first, size); } else { switch (size) { case 2: - INT_XLATE(*(__uint16_t*)(buf_ptr+first), - *(__uint16_t*)(mem_ptr+first), - dir, ARCH_CONVERT); + *(__be16 *)(to_ptr + first) = + cpu_to_be16(*(__u16 *)(from_ptr + first)); break; case 4: - INT_XLATE(*(__uint32_t*)(buf_ptr+first), - *(__uint32_t*)(mem_ptr+first), - dir, ARCH_CONVERT); + *(__be32 *)(to_ptr + first) = + cpu_to_be32(*(__u32 *)(from_ptr + first)); break; case 8: - INT_XLATE(*(__uint64_t*)(buf_ptr+first), - *(__uint64_t*)(mem_ptr+first), dir, ARCH_CONVERT); + *(__be64 *)(to_ptr + first) = + cpu_to_be64(*(__u64 *)(from_ptr + first)); break; default: ASSERT(0); @@ -487,7 +521,6 @@ xfs_readsb(xfs_mount_t *mp, int flags) unsigned int sector_size; unsigned int extra_flags; xfs_buf_t *bp; - xfs_sb_t *sbp; int error; ASSERT(mp->m_sb_bp == NULL); @@ -515,8 +548,7 @@ xfs_readsb(xfs_mount_t *mp, int flags) * Initialize the mount structure from the superblock. * But first do some basic consistency checking. */ - sbp = XFS_BUF_TO_SBP(bp); - xfs_xlatesb(XFS_BUF_PTR(bp), &(mp->m_sb), 1, XFS_SB_ALL_BITS); + xfs_sb_from_disk(&mp->m_sb, XFS_BUF_TO_SBP(bp)); error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags); if (error) { @@ -715,7 +747,6 @@ xfs_initialize_perag_data(xfs_mount_t *mp, xfs_agnumber_t agcount) */ int xfs_mountfs( - bhv_vfs_t *vfsp, xfs_mount_t *mp, int mfsi_flags) { @@ -842,14 +873,11 @@ xfs_mountfs( */ if ((mfsi_flags & XFS_MFSI_SECOND) == 0 && (mp->m_flags & XFS_MOUNT_NOUUID) == 0) { - __uint64_t ret64; 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)); } /* @@ -871,16 +899,6 @@ xfs_mountfs( 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 { @@ -895,15 +913,12 @@ xfs_mountfs( 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 + * Set the inode cluster 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; - } + mp->m_inode_cluster_size = XFS_INODE_BIG_CLUSTER_SIZE; + /* * Set whether we're using inode alignment. */ @@ -987,16 +1002,6 @@ xfs_mountfs( */ 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 */ xfs_dir_mount(mp); @@ -1012,20 +1017,13 @@ xfs_mountfs( 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(vfsp, mp, sbp->sb_agcount); + mp->m_maxagi = xfs_initialize_perag(mp, sbp->sb_agcount); /* * log's mount-time initialization. Perform 1st part recovery if needed @@ -1116,7 +1114,7 @@ xfs_mountfs( * If fs is not mounted readonly, then update the superblock * unit and width changes. */ - if (update_flags && !(vfsp->vfs_flag & VFS_RDONLY)) + if (update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY)) xfs_mount_log_sbunit(mp, update_flags); /* @@ -1169,8 +1167,6 @@ xfs_mountfs( 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, @@ -1194,10 +1190,6 @@ xfs_mountfs( int xfs_unmountfs(xfs_mount_t *mp, struct cred *cr) { - struct bhv_vfs *vfsp = XFS_MTOVFS(mp); -#if defined(DEBUG) || defined(INDUCE_IO_ERROR) - int64_t fsid; -#endif __uint64_t resblks; /* @@ -1261,21 +1253,17 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr) xfs_uuid_unmount(mp); #if defined(DEBUG) || defined(INDUCE_IO_ERROR) - /* - * clear all error tags on this filesystem - */ - memcpy(&fsid, &vfsp->vfs_fsid, sizeof(int64_t)); - xfs_errortag_clearall_umount(fsid, mp->m_fsname, 0); + xfs_errortag_clearall(mp, 0); #endif - XFS_IODONE(vfsp); - xfs_mount_free(mp, 1); + XFS_IODONE(mp); + xfs_mount_free(mp); return 0; } void xfs_unmountfs_close(xfs_mount_t *mp, struct cred *cr) { - if (mp->m_logdev_targp != mp->m_ddev_targp) + if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp) xfs_free_buftarg(mp->m_logdev_targp, 1); if (mp->m_rtdev_targp) xfs_free_buftarg(mp->m_rtdev_targp, 1); @@ -1295,10 +1283,8 @@ xfs_unmountfs_wait(xfs_mount_t *mp) int xfs_fs_writable(xfs_mount_t *mp) { - bhv_vfs_t *vfsp = XFS_MTOVFS(mp); - - return !(vfs_test_for_freeze(vfsp) || XFS_FORCED_SHUTDOWN(mp) || - (vfsp->vfs_flag & VFS_RDONLY)); + return !(xfs_test_for_freeze(mp) || XFS_FORCED_SHUTDOWN(mp) || + (mp->m_flags & XFS_MOUNT_RDONLY)); } /* @@ -1348,34 +1334,44 @@ xfs_log_sbcount( return 0; } +STATIC void +xfs_mark_shared_ro( + xfs_mount_t *mp, + xfs_buf_t *bp) +{ + xfs_dsb_t *sb = XFS_BUF_TO_SBP(bp); + __uint16_t version; + + if (!(sb->sb_flags & XFS_SBF_READONLY)) + sb->sb_flags |= XFS_SBF_READONLY; + + version = be16_to_cpu(sb->sb_versionnum); + if ((version & XFS_SB_VERSION_NUMBITS) != XFS_SB_VERSION_4 || + !(version & XFS_SB_VERSION_SHAREDBIT)) + version |= XFS_SB_VERSION_SHAREDBIT; + sb->sb_versionnum = cpu_to_be16(version); +} + int xfs_unmountfs_writesb(xfs_mount_t *mp) { xfs_buf_t *sbp; - xfs_sb_t *sb; int error = 0; /* * skip superblock write if fs is read-only, or * if we are doing a forced umount. */ - if (!(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY || + if (!((mp->m_flags & XFS_MOUNT_RDONLY) || XFS_FORCED_SHUTDOWN(mp))) { sbp = xfs_getsb(mp, 0); - sb = XFS_BUF_TO_SBP(sbp); /* * mark shared-readonly if desired */ - if (mp->m_mk_sharedro) { - if (!(sb->sb_flags & XFS_SBF_READONLY)) - sb->sb_flags |= XFS_SBF_READONLY; - if (!XFS_SB_VERSION_HASSHARED(sb)) - XFS_SB_VERSION_ADDSHARED(sb); - xfs_fs_cmn_err(CE_NOTE, mp, - "Unmounting, marking shared read-only"); - } + if (mp->m_mk_sharedro) + xfs_mark_shared_ro(mp, sbp); XFS_BUF_UNDONE(sbp); XFS_BUF_UNREAD(sbp); @@ -1410,7 +1406,6 @@ xfs_mod_sb(xfs_trans_t *tp, __int64_t fields) int first; int last; xfs_mount_t *mp; - xfs_sb_t *sbp; xfs_sb_field_t f; ASSERT(fields); @@ -1418,13 +1413,12 @@ xfs_mod_sb(xfs_trans_t *tp, __int64_t fields) return; mp = tp->t_mountp; bp = xfs_trans_getsb(tp, mp, 0); - sbp = XFS_BUF_TO_SBP(bp); first = sizeof(xfs_sb_t); last = 0; /* translate/copy */ - xfs_xlatesb(XFS_BUF_PTR(bp), &(mp->m_sb), -1, fields); + xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, fields); /* find modified range */ |