diff options
Diffstat (limited to 'fs/xfs/xfs_mount.c')
-rw-r--r-- | fs/xfs/xfs_mount.c | 154 |
1 files changed, 148 insertions, 6 deletions
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 5de1f392e632..f6fe47d8c4dc 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -643,6 +643,64 @@ xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp) | |||
643 | sbp->sb_inopblock); | 643 | sbp->sb_inopblock); |
644 | mp->m_ialloc_blks = mp->m_ialloc_inos >> sbp->sb_inopblog; | 644 | mp->m_ialloc_blks = mp->m_ialloc_inos >> sbp->sb_inopblog; |
645 | } | 645 | } |
646 | |||
647 | /* | ||
648 | * xfs_initialize_perag_data | ||
649 | * | ||
650 | * Read in each per-ag structure so we can count up the number of | ||
651 | * allocated inodes, free inodes and used filesystem blocks as this | ||
652 | * information is no longer persistent in the superblock. Once we have | ||
653 | * this information, write it into the in-core superblock structure. | ||
654 | */ | ||
655 | STATIC int | ||
656 | xfs_initialize_perag_data(xfs_mount_t *mp, xfs_agnumber_t agcount) | ||
657 | { | ||
658 | xfs_agnumber_t index; | ||
659 | xfs_perag_t *pag; | ||
660 | xfs_sb_t *sbp = &mp->m_sb; | ||
661 | uint64_t ifree = 0; | ||
662 | uint64_t ialloc = 0; | ||
663 | uint64_t bfree = 0; | ||
664 | uint64_t bfreelst = 0; | ||
665 | uint64_t btree = 0; | ||
666 | int error; | ||
667 | int s; | ||
668 | |||
669 | for (index = 0; index < agcount; index++) { | ||
670 | /* | ||
671 | * read the agf, then the agi. This gets us | ||
672 | * all the inforamtion we need and populates the | ||
673 | * per-ag structures for us. | ||
674 | */ | ||
675 | error = xfs_alloc_pagf_init(mp, NULL, index, 0); | ||
676 | if (error) | ||
677 | return error; | ||
678 | |||
679 | error = xfs_ialloc_pagi_init(mp, NULL, index); | ||
680 | if (error) | ||
681 | return error; | ||
682 | pag = &mp->m_perag[index]; | ||
683 | ifree += pag->pagi_freecount; | ||
684 | ialloc += pag->pagi_count; | ||
685 | bfree += pag->pagf_freeblks; | ||
686 | bfreelst += pag->pagf_flcount; | ||
687 | btree += pag->pagf_btreeblks; | ||
688 | } | ||
689 | /* | ||
690 | * Overwrite incore superblock counters with just-read data | ||
691 | */ | ||
692 | s = XFS_SB_LOCK(mp); | ||
693 | sbp->sb_ifree = ifree; | ||
694 | sbp->sb_icount = ialloc; | ||
695 | sbp->sb_fdblocks = bfree + bfreelst + btree; | ||
696 | XFS_SB_UNLOCK(mp, s); | ||
697 | |||
698 | /* Fixup the per-cpu counters as well. */ | ||
699 | xfs_icsb_reinit_counters(mp); | ||
700 | |||
701 | return 0; | ||
702 | } | ||
703 | |||
646 | /* | 704 | /* |
647 | * xfs_mountfs | 705 | * xfs_mountfs |
648 | * | 706 | * |
@@ -987,6 +1045,34 @@ xfs_mountfs( | |||
987 | } | 1045 | } |
988 | 1046 | ||
989 | /* | 1047 | /* |
1048 | * Now the log is mounted, we know if it was an unclean shutdown or | ||
1049 | * not. If it was, with the first phase of recovery has completed, we | ||
1050 | * have consistent AG blocks on disk. We have not recovered EFIs yet, | ||
1051 | * but they are recovered transactionally in the second recovery phase | ||
1052 | * later. | ||
1053 | * | ||
1054 | * Hence we can safely re-initialise incore superblock counters from | ||
1055 | * the per-ag data. These may not be correct if the filesystem was not | ||
1056 | * cleanly unmounted, so we need to wait for recovery to finish before | ||
1057 | * doing this. | ||
1058 | * | ||
1059 | * If the filesystem was cleanly unmounted, then we can trust the | ||
1060 | * values in the superblock to be correct and we don't need to do | ||
1061 | * anything here. | ||
1062 | * | ||
1063 | * If we are currently making the filesystem, the initialisation will | ||
1064 | * fail as the perag data is in an undefined state. | ||
1065 | */ | ||
1066 | |||
1067 | if (xfs_sb_version_haslazysbcount(&mp->m_sb) && | ||
1068 | !XFS_LAST_UNMOUNT_WAS_CLEAN(mp) && | ||
1069 | !mp->m_sb.sb_inprogress) { | ||
1070 | error = xfs_initialize_perag_data(mp, sbp->sb_agcount); | ||
1071 | if (error) { | ||
1072 | goto error2; | ||
1073 | } | ||
1074 | } | ||
1075 | /* | ||
990 | * Get and sanity-check the root inode. | 1076 | * Get and sanity-check the root inode. |
991 | * Save the pointer to it in the mount structure. | 1077 | * Save the pointer to it in the mount structure. |
992 | */ | 1078 | */ |
@@ -1049,6 +1135,7 @@ xfs_mountfs( | |||
1049 | goto error4; | 1135 | goto error4; |
1050 | } | 1136 | } |
1051 | 1137 | ||
1138 | |||
1052 | /* | 1139 | /* |
1053 | * Complete the quota initialisation, post-log-replay component. | 1140 | * Complete the quota initialisation, post-log-replay component. |
1054 | */ | 1141 | */ |
@@ -1111,10 +1198,9 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr) | |||
1111 | xfs_binval(mp->m_rtdev_targp); | 1198 | xfs_binval(mp->m_rtdev_targp); |
1112 | } | 1199 | } |
1113 | 1200 | ||
1201 | xfs_log_sbcount(mp, 1); | ||
1114 | xfs_unmountfs_writesb(mp); | 1202 | xfs_unmountfs_writesb(mp); |
1115 | |||
1116 | xfs_unmountfs_wait(mp); /* wait for async bufs */ | 1203 | xfs_unmountfs_wait(mp); /* wait for async bufs */ |
1117 | |||
1118 | xfs_log_unmount(mp); /* Done! No more fs ops. */ | 1204 | xfs_log_unmount(mp); /* Done! No more fs ops. */ |
1119 | 1205 | ||
1120 | xfs_freesb(mp); | 1206 | xfs_freesb(mp); |
@@ -1161,6 +1247,62 @@ xfs_unmountfs_wait(xfs_mount_t *mp) | |||
1161 | } | 1247 | } |
1162 | 1248 | ||
1163 | int | 1249 | int |
1250 | xfs_fs_writable(xfs_mount_t *mp) | ||
1251 | { | ||
1252 | bhv_vfs_t *vfsp = XFS_MTOVFS(mp); | ||
1253 | |||
1254 | return !(vfs_test_for_freeze(vfsp) || XFS_FORCED_SHUTDOWN(mp) || | ||
1255 | (vfsp->vfs_flag & VFS_RDONLY)); | ||
1256 | } | ||
1257 | |||
1258 | /* | ||
1259 | * xfs_log_sbcount | ||
1260 | * | ||
1261 | * Called either periodically to keep the on disk superblock values | ||
1262 | * roughly up to date or from unmount to make sure the values are | ||
1263 | * correct on a clean unmount. | ||
1264 | * | ||
1265 | * Note this code can be called during the process of freezing, so | ||
1266 | * we may need to use the transaction allocator which does not not | ||
1267 | * block when the transaction subsystem is in its frozen state. | ||
1268 | */ | ||
1269 | int | ||
1270 | xfs_log_sbcount( | ||
1271 | xfs_mount_t *mp, | ||
1272 | uint sync) | ||
1273 | { | ||
1274 | xfs_trans_t *tp; | ||
1275 | int error; | ||
1276 | |||
1277 | if (!xfs_fs_writable(mp)) | ||
1278 | return 0; | ||
1279 | |||
1280 | xfs_icsb_sync_counters(mp); | ||
1281 | |||
1282 | /* | ||
1283 | * we don't need to do this if we are updating the superblock | ||
1284 | * counters on every modification. | ||
1285 | */ | ||
1286 | if (!xfs_sb_version_haslazysbcount(&mp->m_sb)) | ||
1287 | return 0; | ||
1288 | |||
1289 | tp = _xfs_trans_alloc(mp, XFS_TRANS_SB_COUNT); | ||
1290 | error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0, | ||
1291 | XFS_DEFAULT_LOG_COUNT); | ||
1292 | if (error) { | ||
1293 | xfs_trans_cancel(tp, 0); | ||
1294 | return error; | ||
1295 | } | ||
1296 | |||
1297 | xfs_mod_sb(tp, XFS_SB_IFREE | XFS_SB_ICOUNT | XFS_SB_FDBLOCKS); | ||
1298 | if (sync) | ||
1299 | xfs_trans_set_sync(tp); | ||
1300 | xfs_trans_commit(tp, 0); | ||
1301 | |||
1302 | return 0; | ||
1303 | } | ||
1304 | |||
1305 | int | ||
1164 | xfs_unmountfs_writesb(xfs_mount_t *mp) | 1306 | xfs_unmountfs_writesb(xfs_mount_t *mp) |
1165 | { | 1307 | { |
1166 | xfs_buf_t *sbp; | 1308 | xfs_buf_t *sbp; |
@@ -1171,16 +1313,15 @@ xfs_unmountfs_writesb(xfs_mount_t *mp) | |||
1171 | * skip superblock write if fs is read-only, or | 1313 | * skip superblock write if fs is read-only, or |
1172 | * if we are doing a forced umount. | 1314 | * if we are doing a forced umount. |
1173 | */ | 1315 | */ |
1174 | sbp = xfs_getsb(mp, 0); | ||
1175 | if (!(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY || | 1316 | if (!(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY || |
1176 | XFS_FORCED_SHUTDOWN(mp))) { | 1317 | XFS_FORCED_SHUTDOWN(mp))) { |
1177 | 1318 | ||
1178 | xfs_icsb_sync_counters(mp); | 1319 | sbp = xfs_getsb(mp, 0); |
1320 | sb = XFS_BUF_TO_SBP(sbp); | ||
1179 | 1321 | ||
1180 | /* | 1322 | /* |
1181 | * mark shared-readonly if desired | 1323 | * mark shared-readonly if desired |
1182 | */ | 1324 | */ |
1183 | sb = XFS_BUF_TO_SBP(sbp); | ||
1184 | if (mp->m_mk_sharedro) { | 1325 | if (mp->m_mk_sharedro) { |
1185 | if (!(sb->sb_flags & XFS_SBF_READONLY)) | 1326 | if (!(sb->sb_flags & XFS_SBF_READONLY)) |
1186 | sb->sb_flags |= XFS_SBF_READONLY; | 1327 | sb->sb_flags |= XFS_SBF_READONLY; |
@@ -1189,6 +1330,7 @@ xfs_unmountfs_writesb(xfs_mount_t *mp) | |||
1189 | xfs_fs_cmn_err(CE_NOTE, mp, | 1330 | xfs_fs_cmn_err(CE_NOTE, mp, |
1190 | "Unmounting, marking shared read-only"); | 1331 | "Unmounting, marking shared read-only"); |
1191 | } | 1332 | } |
1333 | |||
1192 | XFS_BUF_UNDONE(sbp); | 1334 | XFS_BUF_UNDONE(sbp); |
1193 | XFS_BUF_UNREAD(sbp); | 1335 | XFS_BUF_UNREAD(sbp); |
1194 | XFS_BUF_UNDELAYWRITE(sbp); | 1336 | XFS_BUF_UNDELAYWRITE(sbp); |
@@ -1203,8 +1345,8 @@ xfs_unmountfs_writesb(xfs_mount_t *mp) | |||
1203 | mp, sbp, XFS_BUF_ADDR(sbp)); | 1345 | mp, sbp, XFS_BUF_ADDR(sbp)); |
1204 | if (error && mp->m_mk_sharedro) | 1346 | if (error && mp->m_mk_sharedro) |
1205 | xfs_fs_cmn_err(CE_ALERT, mp, "Superblock write error detected while unmounting. Filesystem may not be marked shared readonly"); | 1347 | xfs_fs_cmn_err(CE_ALERT, mp, "Superblock write error detected while unmounting. Filesystem may not be marked shared readonly"); |
1348 | xfs_buf_relse(sbp); | ||
1206 | } | 1349 | } |
1207 | xfs_buf_relse(sbp); | ||
1208 | return error; | 1350 | return error; |
1209 | } | 1351 | } |
1210 | 1352 | ||