diff options
author | Darrick J. Wong <djwong@kernel.org> | 2021-09-01 10:47:30 -0700 |
---|---|---|
committer | Darrick J. Wong <djwong@kernel.org> | 2021-12-15 17:28:59 -0800 |
commit | 93dda3ad1c4e1a0e5a0130ef176977266fdec1fc (patch) | |
tree | 166a3b0b18f558c07629493d77f43b90172846b5 /fs | |
parent | ea7ddde15643d6711c865c21950990aee849f60b (diff) |
xfs: create a log incompat flag for atomic extent swapping
Create a log incompat flag so that we only attempt to process swap
extent log items if the filesystem supports it.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/libxfs/xfs_format.h | 17 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_fs.h | 1 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_sb.c | 5 | ||||
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_mount.c | 23 | ||||
-rw-r--r-- | fs/xfs/xfs_mount.h | 33 |
6 files changed, 55 insertions, 25 deletions
diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index ccf7c369fdc2..592a1505d2e8 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -388,6 +388,7 @@ xfs_sb_has_incompat_feature( return (sbp->sb_features_incompat & feature) != 0; } +#define XFS_SB_FEAT_INCOMPAT_LOG_ATOMIC_SWAP (1 << 0) #define XFS_SB_FEAT_INCOMPAT_LOG_ALL 0 #define XFS_SB_FEAT_INCOMPAT_LOG_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_LOG_ALL static inline bool @@ -398,22 +399,6 @@ xfs_sb_has_incompat_log_feature( return (sbp->sb_features_log_incompat & feature) != 0; } -static inline void -xfs_sb_remove_incompat_log_features( - struct xfs_sb *sbp) -{ - sbp->sb_features_log_incompat &= ~XFS_SB_FEAT_INCOMPAT_LOG_ALL; -} - -static inline void -xfs_sb_add_incompat_log_features( - struct xfs_sb *sbp, - unsigned int features) -{ - sbp->sb_features_log_incompat |= features; -} - - static inline bool xfs_is_quota_inode(struct xfs_sb *sbp, xfs_ino_t ino) { diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index 98f53eb619cf..16ca677d4985 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -252,6 +252,7 @@ typedef struct xfs_fsop_resblks { #define XFS_FSOP_GEOM_FLAGS_REFLINK (1 << 20) /* files can share blocks */ #define XFS_FSOP_GEOM_FLAGS_BIGTIME (1 << 21) /* 64-bit nsec timestamps */ #define XFS_FSOP_GEOM_FLAGS_INOBTCNT (1 << 22) /* inobt btree counter */ +#define XFS_FSOP_GEOM_FLAGS_ATOMIC_SWAP (1 << 23) /* atomic swapext */ /* * Minimum and maximum sizes need for growth checks. diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index 901d219e16de..3c8afd2cd1b1 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -124,6 +124,9 @@ xfs_sb_version_to_features( features |= XFS_FEAT_BIGTIME; if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR) features |= XFS_FEAT_NEEDSREPAIR; + + if (sbp->sb_features_log_incompat & XFS_SB_FEAT_INCOMPAT_LOG_ATOMIC_SWAP) + features |= XFS_FEAT_ATOMIC_SWAP; return features; } @@ -1135,6 +1138,8 @@ xfs_fs_geometry( } else { geo->logsectsize = BBSIZE; } + if (xfs_can_atomicswap(mp)) + geo->flags |= XFS_FSOP_GEOM_FLAGS_ATOMIC_SWAP; geo->rtsectsize = sbp->sb_blocksize; geo->dirblocksize = xfs_dir2_dirblock_bytes(sbp); diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 53366cc0bc9e..1bc081f3e466 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -3344,6 +3344,7 @@ xlog_do_recover( xfs_buf_relse(bp); /* re-initialise in-core superblock and geometry structures */ + mp->m_features &= ~XFS_FEAT_INCOMPAT_LOG_ALL; mp->m_features |= xfs_sb_version_to_features(sbp); xfs_reinit_percpu_counters(mp); error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi); diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 804adb6cf650..490bf1266661 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -1278,13 +1278,15 @@ xfs_force_summary_recalc( int xfs_add_incompat_log_feature( struct xfs_mount *mp, - uint32_t feature) + uint64_t mount_feature, + uint32_t sb_feature) { struct xfs_dsb *dsb; int error; - ASSERT(hweight32(feature) == 1); - ASSERT(!(feature & XFS_SB_FEAT_INCOMPAT_LOG_UNKNOWN)); + ASSERT(hweight32(sb_feature) == 1); + ASSERT(!(sb_feature & XFS_SB_FEAT_INCOMPAT_LOG_UNKNOWN)); + ASSERT(!(mount_feature & ~XFS_FEAT_INCOMPAT_LOG_ALL)); /* * Force the log to disk and kick the background AIL thread to reduce @@ -1309,7 +1311,7 @@ xfs_add_incompat_log_feature( goto rele; } - if (xfs_sb_has_incompat_log_feature(&mp->m_sb, feature)) + if (xfs_sb_has_incompat_log_feature(&mp->m_sb, sb_feature)) goto rele; /* @@ -1319,7 +1321,7 @@ xfs_add_incompat_log_feature( */ dsb = mp->m_sb_bp->b_addr; xfs_sb_to_disk(dsb, &mp->m_sb); - dsb->sb_features_log_incompat |= cpu_to_be32(feature); + dsb->sb_features_log_incompat |= cpu_to_be32(sb_feature); error = xfs_bwrite(mp->m_sb_bp); if (error) goto shutdown; @@ -1328,7 +1330,10 @@ xfs_add_incompat_log_feature( * Add the feature bits to the incore superblock before we unlock the * buffer. */ - xfs_sb_add_incompat_log_features(&mp->m_sb, feature); + spin_lock(&mp->m_sb_lock); + mp->m_features |= mount_feature; + mp->m_sb.sb_features_log_incompat |= sb_feature; + spin_unlock(&mp->m_sb_lock); xfs_buf_relse(mp->m_sb_bp); /* Log the superblock to disk. */ @@ -1369,14 +1374,18 @@ xfs_clear_incompat_log_features( */ xfs_buf_lock(mp->m_sb_bp); xfs_buf_hold(mp->m_sb_bp); + spin_lock(&mp->m_sb_lock); if (xfs_sb_has_incompat_log_feature(&mp->m_sb, XFS_SB_FEAT_INCOMPAT_LOG_ALL)) { xfs_info(mp, "Clearing log incompat feature flags."); - xfs_sb_remove_incompat_log_features(&mp->m_sb); + mp->m_features &= ~XFS_FEAT_INCOMPAT_LOG_ALL; + mp->m_sb.sb_features_log_incompat &= + ~XFS_SB_FEAT_INCOMPAT_LOG_ALL; ret = true; } + spin_unlock(&mp->m_sb_lock); xfs_buf_relse(mp->m_sb_bp); return ret; } diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index b9a93d782175..504b504ebfe1 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -299,6 +299,7 @@ typedef struct xfs_mount { #define XFS_FEAT_INOBTCNT (1ULL << 23) /* inobt block counts */ #define XFS_FEAT_BIGTIME (1ULL << 24) /* large timestamps */ #define XFS_FEAT_NEEDSREPAIR (1ULL << 25) /* needs xfs_repair */ +#define XFS_FEAT_ATOMIC_SWAP (1ULL << 26) /* extent swap log items */ /* Mount features */ #define XFS_FEAT_NOATTR2 (1ULL << 48) /* disable attr2 creation */ @@ -334,6 +335,24 @@ static inline void xfs_add_ ## name (struct xfs_mount *mp) \ xfs_sb_version_add ## name(&mp->m_sb); \ } +/* + * Log incompat features are added one at a time, but they are all cleared when + * the log is cleaned. + */ +#define XFS_FEAT_INCOMPAT_LOG_ALL (XFS_FEAT_ATOMIC_SWAP) + +int xfs_add_incompat_log_feature(struct xfs_mount *mp, uint64_t mount_feature, + uint32_t sb_feature); +bool xfs_clear_incompat_log_features(struct xfs_mount *mp); + +#define __XFS_LOG_FEAT(name, NAME) \ + __XFS_HAS_FEAT(name, NAME); \ +static inline int xfs_add_ ## name (struct xfs_mount *mp) \ +{ \ + return xfs_add_incompat_log_feature((mp), XFS_FEAT_ ## NAME, \ + XFS_SB_FEAT_INCOMPAT_LOG_ ## NAME); \ +} + /* Superblock features */ __XFS_ADD_FEAT(attr, ATTR) __XFS_HAS_FEAT(nlink, NLINK) @@ -361,6 +380,18 @@ __XFS_HAS_FEAT(realtime, REALTIME) __XFS_HAS_FEAT(inobtcounts, INOBTCNT) __XFS_HAS_FEAT(bigtime, BIGTIME) __XFS_HAS_FEAT(needsrepair, NEEDSREPAIR) +__XFS_LOG_FEAT(atomicswap, ATOMIC_SWAP) + +/* + * Decide if this filesystem can use log-assisted ("atomic") extent swapping. + * The atomic swap log intent items depend on the block mapping log intent + * items introduced with reflink and rmap. Realtime is not supported yet. + */ +static inline bool xfs_can_atomicswap(struct xfs_mount *mp) +{ + return (xfs_has_reflink(mp) || xfs_has_rmapbt(mp)) && + !xfs_has_realtime(mp); +} /* * Mount features @@ -521,8 +552,6 @@ int xfs_zero_extent(struct xfs_inode *ip, xfs_fsblock_t start_fsb, struct xfs_error_cfg * xfs_error_get_cfg(struct xfs_mount *mp, int error_class, int error); void xfs_force_summary_recalc(struct xfs_mount *mp); -int xfs_add_incompat_log_feature(struct xfs_mount *mp, uint32_t feature); -bool xfs_clear_incompat_log_features(struct xfs_mount *mp); void xfs_mod_delalloc(struct xfs_mount *mp, int64_t delta); #endif /* __XFS_MOUNT_H__ */ |