diff options
Diffstat (limited to 'fs/xfs/xfs_mount.c')
-rw-r--r-- | fs/xfs/xfs_mount.c | 54 |
1 files changed, 31 insertions, 23 deletions
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index c0b1c2906880..10dbf203c62f 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -24,14 +24,12 @@ #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_ag.h" -#include "xfs_dir.h" #include "xfs_dir2.h" #include "xfs_dmapi.h" #include "xfs_mount.h" #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" -#include "xfs_dir_sf.h" #include "xfs_dir2_sf.h" #include "xfs_attr_sf.h" #include "xfs_dinode.h" @@ -196,7 +194,7 @@ xfs_mount_free( kmem_free(mp->m_logname, strlen(mp->m_logname) + 1); if (remove_bhv) { - struct vfs *vfsp = XFS_MTOVFS(mp); + struct bhv_vfs *vfsp = XFS_MTOVFS(mp); bhv_remove_all_vfsops(vfsp, 0); VFS_REMOVEBHV(vfsp, &mp->m_bhv); @@ -337,7 +335,7 @@ xfs_mount_validate_sb( xfs_agnumber_t xfs_initialize_perag( - struct vfs *vfs, + bhv_vfs_t *vfs, xfs_mount_t *mp, xfs_agnumber_t agcount) { @@ -651,14 +649,14 @@ xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp) */ int xfs_mountfs( - vfs_t *vfsp, + bhv_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; + bhv_vnode_t *rvp = NULL; int readio_log, writeio_log; xfs_daddr_t d; __uint64_t ret64; @@ -934,18 +932,7 @@ xfs_mountfs( 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); + xfs_dir_mount(mp); /* * Initialize the attribute manager's entries. @@ -1006,8 +993,9 @@ xfs_mountfs( 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); + cmn_err(CE_WARN, "Device %s - root %llu is not a directory", + XFS_BUFTARG_NAME(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); @@ -1094,7 +1082,7 @@ xfs_mountfs( int xfs_unmountfs(xfs_mount_t *mp, struct cred *cr) { - struct vfs *vfsp = XFS_MTOVFS(mp); + struct bhv_vfs *vfsp = XFS_MTOVFS(mp); #if defined(DEBUG) || defined(INDUCE_IO_ERROR) int64_t fsid; #endif @@ -1254,6 +1242,26 @@ xfs_mod_sb(xfs_trans_t *tp, __int64_t fields) xfs_trans_log_buf(tp, bp, first, last); } + +/* + * In order to avoid ENOSPC-related deadlock caused by + * out-of-order locking of AGF buffer (PV 947395), we place + * constraints on the relationship among actual allocations for + * data blocks, freelist blocks, and potential file data bmap + * btree blocks. However, these restrictions may result in no + * actual space allocated for a delayed extent, for example, a data + * block in a certain AG is allocated but there is no additional + * block for the additional bmap btree block due to a split of the + * bmap btree of the file. The result of this may lead to an + * infinite loop in xfssyncd when the file gets flushed to disk and + * all delayed extents need to be actually allocated. To get around + * this, we explicitly set aside a few blocks which will not be + * reserved in delayed allocation. Considering the minimum number of + * needed freelist blocks is 4 fsbs, a potential split of file's bmap + * btree requires 1 fsb, so we set the number of set-aside blocks to 8. +*/ +#define SET_ASIDE_BLOCKS 8 + /* * xfs_mod_incore_sb_unlocked() is a utility routine common used to apply * a delta to a specified field in the in-core superblock. Simply @@ -1298,7 +1306,7 @@ xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field, return 0; case XFS_SBS_FDBLOCKS: - lcounter = (long long)mp->m_sb.sb_fdblocks; + lcounter = (long long)mp->m_sb.sb_fdblocks - SET_ASIDE_BLOCKS; res_used = (long long)(mp->m_resblks - mp->m_resblks_avail); if (delta > 0) { /* Putting blocks back */ @@ -1332,7 +1340,7 @@ xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field, } } - mp->m_sb.sb_fdblocks = lcounter; + mp->m_sb.sb_fdblocks = lcounter + SET_ASIDE_BLOCKS; return 0; case XFS_SBS_FREXTENTS: lcounter = (long long)mp->m_sb.sb_frextents; |