summaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_mount.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_mount.c')
-rw-r--r--fs/xfs/xfs_mount.c242
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 */