diff options
| author | Christoph Hellwig <hch@lst.de> | 2009-01-18 20:04:07 -0500 |
|---|---|---|
| committer | Lachlan McIlroy <lachlan@sgi.com> | 2009-01-18 22:45:04 -0500 |
| commit | 49739140e57a65114d9e1976c4c158d2145595fb (patch) | |
| tree | 9295a472e8d4040c9504f3c8b2b9d29207772cd4 | |
| parent | 5aa2dc0a0697c762874241fa9ddbecd2d878b934 (diff) | |
xfs: fix bad_features2 fixups for the root filesystem
Currently the bad_features2 fixup and the alignment updates in the superblock
are skipped if we mount a filesystem read-only. But for the root filesystem
the typical case is to mount read-only first and only later remount writeable
so we'll never perform this update at all. It's not a big problem but means
the logs of people needing the fixup get spammed at every boot because they
never happen on disk.
Reported-by: Arkadiusz Miskiewicz <arekm@maven.pl>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Dave Chinner <david@fromorbit.com>
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_super.c | 17 | ||||
| -rw-r--r-- | fs/xfs/xfs_mount.c | 26 | ||||
| -rw-r--r-- | fs/xfs/xfs_mount.h | 3 |
3 files changed, 32 insertions, 14 deletions
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 95a971080368..c71e226da7f5 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
| @@ -1197,6 +1197,7 @@ xfs_fs_remount( | |||
| 1197 | struct xfs_mount *mp = XFS_M(sb); | 1197 | struct xfs_mount *mp = XFS_M(sb); |
| 1198 | substring_t args[MAX_OPT_ARGS]; | 1198 | substring_t args[MAX_OPT_ARGS]; |
| 1199 | char *p; | 1199 | char *p; |
| 1200 | int error; | ||
| 1200 | 1201 | ||
| 1201 | while ((p = strsep(&options, ",")) != NULL) { | 1202 | while ((p = strsep(&options, ",")) != NULL) { |
| 1202 | int token; | 1203 | int token; |
| @@ -1247,11 +1248,25 @@ xfs_fs_remount( | |||
| 1247 | } | 1248 | } |
| 1248 | } | 1249 | } |
| 1249 | 1250 | ||
| 1250 | /* rw/ro -> rw */ | 1251 | /* ro -> rw */ |
| 1251 | if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(*flags & MS_RDONLY)) { | 1252 | if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(*flags & MS_RDONLY)) { |
| 1252 | mp->m_flags &= ~XFS_MOUNT_RDONLY; | 1253 | mp->m_flags &= ~XFS_MOUNT_RDONLY; |
| 1253 | if (mp->m_flags & XFS_MOUNT_BARRIER) | 1254 | if (mp->m_flags & XFS_MOUNT_BARRIER) |
| 1254 | xfs_mountfs_check_barriers(mp); | 1255 | xfs_mountfs_check_barriers(mp); |
| 1256 | |||
| 1257 | /* | ||
| 1258 | * If this is the first remount to writeable state we | ||
| 1259 | * might have some superblock changes to update. | ||
| 1260 | */ | ||
| 1261 | if (mp->m_update_flags) { | ||
| 1262 | error = xfs_mount_log_sb(mp, mp->m_update_flags); | ||
| 1263 | if (error) { | ||
| 1264 | cmn_err(CE_WARN, | ||
| 1265 | "XFS: failed to write sb changes"); | ||
| 1266 | return error; | ||
| 1267 | } | ||
| 1268 | mp->m_update_flags = 0; | ||
| 1269 | } | ||
| 1255 | } | 1270 | } |
| 1256 | 1271 | ||
| 1257 | /* rw -> ro */ | 1272 | /* rw -> ro */ |
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 3c97c6463a4e..35300250e86d 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
| @@ -45,7 +45,6 @@ | |||
| 45 | #include "xfs_fsops.h" | 45 | #include "xfs_fsops.h" |
| 46 | #include "xfs_utils.h" | 46 | #include "xfs_utils.h" |
| 47 | 47 | ||
| 48 | STATIC int xfs_mount_log_sb(xfs_mount_t *, __int64_t); | ||
| 49 | STATIC int xfs_uuid_mount(xfs_mount_t *); | 48 | STATIC int xfs_uuid_mount(xfs_mount_t *); |
| 50 | STATIC void xfs_unmountfs_wait(xfs_mount_t *); | 49 | STATIC void xfs_unmountfs_wait(xfs_mount_t *); |
| 51 | 50 | ||
| @@ -682,7 +681,7 @@ xfs_initialize_perag_data(xfs_mount_t *mp, xfs_agnumber_t agcount) | |||
| 682 | * Update alignment values based on mount options and sb values | 681 | * Update alignment values based on mount options and sb values |
| 683 | */ | 682 | */ |
| 684 | STATIC int | 683 | STATIC int |
| 685 | xfs_update_alignment(xfs_mount_t *mp, __uint64_t *update_flags) | 684 | xfs_update_alignment(xfs_mount_t *mp) |
| 686 | { | 685 | { |
| 687 | xfs_sb_t *sbp = &(mp->m_sb); | 686 | xfs_sb_t *sbp = &(mp->m_sb); |
| 688 | 687 | ||
| @@ -736,11 +735,11 @@ xfs_update_alignment(xfs_mount_t *mp, __uint64_t *update_flags) | |||
| 736 | if (xfs_sb_version_hasdalign(sbp)) { | 735 | if (xfs_sb_version_hasdalign(sbp)) { |
| 737 | if (sbp->sb_unit != mp->m_dalign) { | 736 | if (sbp->sb_unit != mp->m_dalign) { |
| 738 | sbp->sb_unit = mp->m_dalign; | 737 | sbp->sb_unit = mp->m_dalign; |
| 739 | *update_flags |= XFS_SB_UNIT; | 738 | mp->m_update_flags |= XFS_SB_UNIT; |
| 740 | } | 739 | } |
| 741 | if (sbp->sb_width != mp->m_swidth) { | 740 | if (sbp->sb_width != mp->m_swidth) { |
| 742 | sbp->sb_width = mp->m_swidth; | 741 | sbp->sb_width = mp->m_swidth; |
| 743 | *update_flags |= XFS_SB_WIDTH; | 742 | mp->m_update_flags |= XFS_SB_WIDTH; |
| 744 | } | 743 | } |
| 745 | } | 744 | } |
| 746 | } else if ((mp->m_flags & XFS_MOUNT_NOALIGN) != XFS_MOUNT_NOALIGN && | 745 | } else if ((mp->m_flags & XFS_MOUNT_NOALIGN) != XFS_MOUNT_NOALIGN && |
| @@ -905,7 +904,6 @@ xfs_mountfs( | |||
| 905 | xfs_sb_t *sbp = &(mp->m_sb); | 904 | xfs_sb_t *sbp = &(mp->m_sb); |
| 906 | xfs_inode_t *rip; | 905 | xfs_inode_t *rip; |
| 907 | __uint64_t resblks; | 906 | __uint64_t resblks; |
| 908 | __int64_t update_flags = 0LL; | ||
| 909 | uint quotamount, quotaflags; | 907 | uint quotamount, quotaflags; |
| 910 | int uuid_mounted = 0; | 908 | int uuid_mounted = 0; |
| 911 | int error = 0; | 909 | int error = 0; |
| @@ -933,7 +931,7 @@ xfs_mountfs( | |||
| 933 | "XFS: correcting sb_features alignment problem"); | 931 | "XFS: correcting sb_features alignment problem"); |
| 934 | sbp->sb_features2 |= sbp->sb_bad_features2; | 932 | sbp->sb_features2 |= sbp->sb_bad_features2; |
| 935 | sbp->sb_bad_features2 = sbp->sb_features2; | 933 | sbp->sb_bad_features2 = sbp->sb_features2; |
| 936 | update_flags |= XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2; | 934 | mp->m_update_flags |= XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2; |
| 937 | 935 | ||
| 938 | /* | 936 | /* |
| 939 | * Re-check for ATTR2 in case it was found in bad_features2 | 937 | * Re-check for ATTR2 in case it was found in bad_features2 |
| @@ -947,11 +945,11 @@ xfs_mountfs( | |||
| 947 | if (xfs_sb_version_hasattr2(&mp->m_sb) && | 945 | if (xfs_sb_version_hasattr2(&mp->m_sb) && |
| 948 | (mp->m_flags & XFS_MOUNT_NOATTR2)) { | 946 | (mp->m_flags & XFS_MOUNT_NOATTR2)) { |
| 949 | xfs_sb_version_removeattr2(&mp->m_sb); | 947 | xfs_sb_version_removeattr2(&mp->m_sb); |
| 950 | update_flags |= XFS_SB_FEATURES2; | 948 | mp->m_update_flags |= XFS_SB_FEATURES2; |
| 951 | 949 | ||
| 952 | /* update sb_versionnum for the clearing of the morebits */ | 950 | /* update sb_versionnum for the clearing of the morebits */ |
| 953 | if (!sbp->sb_features2) | 951 | if (!sbp->sb_features2) |
| 954 | update_flags |= XFS_SB_VERSIONNUM; | 952 | mp->m_update_flags |= XFS_SB_VERSIONNUM; |
| 955 | } | 953 | } |
| 956 | 954 | ||
| 957 | /* | 955 | /* |
| @@ -960,7 +958,7 @@ xfs_mountfs( | |||
| 960 | * allocator alignment is within an ag, therefore ag has | 958 | * allocator alignment is within an ag, therefore ag has |
| 961 | * to be aligned at stripe boundary. | 959 | * to be aligned at stripe boundary. |
| 962 | */ | 960 | */ |
| 963 | error = xfs_update_alignment(mp, &update_flags); | 961 | error = xfs_update_alignment(mp); |
| 964 | if (error) | 962 | if (error) |
| 965 | goto error1; | 963 | goto error1; |
| 966 | 964 | ||
| @@ -1137,10 +1135,12 @@ xfs_mountfs( | |||
| 1137 | } | 1135 | } |
| 1138 | 1136 | ||
| 1139 | /* | 1137 | /* |
| 1140 | * If fs is not mounted readonly, then update the superblock changes. | 1138 | * If this is a read-only mount defer the superblock updates until |
| 1139 | * the next remount into writeable mode. Otherwise we would never | ||
| 1140 | * perform the update e.g. for the root filesystem. | ||
| 1141 | */ | 1141 | */ |
| 1142 | if (update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY)) { | 1142 | if (mp->m_update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY)) { |
| 1143 | error = xfs_mount_log_sb(mp, update_flags); | 1143 | error = xfs_mount_log_sb(mp, mp->m_update_flags); |
| 1144 | if (error) { | 1144 | if (error) { |
| 1145 | cmn_err(CE_WARN, "XFS: failed to write sb changes"); | 1145 | cmn_err(CE_WARN, "XFS: failed to write sb changes"); |
| 1146 | goto error4; | 1146 | goto error4; |
| @@ -1820,7 +1820,7 @@ xfs_uuid_mount( | |||
| 1820 | * be altered by the mount options, as well as any potential sb_features2 | 1820 | * be altered by the mount options, as well as any potential sb_features2 |
| 1821 | * fixup. Only the first superblock is updated. | 1821 | * fixup. Only the first superblock is updated. |
| 1822 | */ | 1822 | */ |
| 1823 | STATIC int | 1823 | int |
| 1824 | xfs_mount_log_sb( | 1824 | xfs_mount_log_sb( |
| 1825 | xfs_mount_t *mp, | 1825 | xfs_mount_t *mp, |
| 1826 | __int64_t fields) | 1826 | __int64_t fields) |
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index c1e028467327..e37eff6761eb 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h | |||
| @@ -327,6 +327,8 @@ typedef struct xfs_mount { | |||
| 327 | spinlock_t m_sync_lock; /* work item list lock */ | 327 | spinlock_t m_sync_lock; /* work item list lock */ |
| 328 | int m_sync_seq; /* sync thread generation no. */ | 328 | int m_sync_seq; /* sync thread generation no. */ |
| 329 | wait_queue_head_t m_wait_single_sync_task; | 329 | wait_queue_head_t m_wait_single_sync_task; |
| 330 | __int64_t m_update_flags; /* sb flags we need to update | ||
| 331 | on the next remount,rw */ | ||
| 330 | } xfs_mount_t; | 332 | } xfs_mount_t; |
| 331 | 333 | ||
| 332 | /* | 334 | /* |
| @@ -514,6 +516,7 @@ extern int xfs_mod_incore_sb_unlocked(xfs_mount_t *, xfs_sb_field_t, | |||
| 514 | int64_t, int); | 516 | int64_t, int); |
| 515 | extern int xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *, | 517 | extern int xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *, |
| 516 | uint, int); | 518 | uint, int); |
| 519 | extern int xfs_mount_log_sb(xfs_mount_t *, __int64_t); | ||
| 517 | extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int); | 520 | extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int); |
| 518 | extern int xfs_readsb(xfs_mount_t *, int); | 521 | extern int xfs_readsb(xfs_mount_t *, int); |
| 519 | extern void xfs_freesb(xfs_mount_t *); | 522 | extern void xfs_freesb(xfs_mount_t *); |
