diff options
author | Steve French <sfrench@us.ibm.com> | 2007-07-18 20:38:57 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2007-07-18 20:38:57 -0400 |
commit | 1ff8392c32a2645d2665ca779ecb91bb29361c13 (patch) | |
tree | 860b95e9a499ade4060848740fc6ce1fbb4e4e8d /fs/xfs/xfs_mount.c | |
parent | 70b315b0dd3879cb3ab8aadffb14f10b2d19b9c3 (diff) | |
parent | 5bae7ac9feba925fd0099057f6b23d7be80b7b41 (diff) |
Merge branch 'master' of /pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts:
fs/cifs/export.c
Diffstat (limited to 'fs/xfs/xfs_mount.c')
-rw-r--r-- | fs/xfs/xfs_mount.c | 237 |
1 files changed, 218 insertions, 19 deletions
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index a96bde6df96d..a66b39805176 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -202,6 +202,27 @@ xfs_mount_free( | |||
202 | kmem_free(mp, sizeof(xfs_mount_t)); | 202 | kmem_free(mp, sizeof(xfs_mount_t)); |
203 | } | 203 | } |
204 | 204 | ||
205 | /* | ||
206 | * Check size of device based on the (data/realtime) block count. | ||
207 | * Note: this check is used by the growfs code as well as mount. | ||
208 | */ | ||
209 | int | ||
210 | xfs_sb_validate_fsb_count( | ||
211 | xfs_sb_t *sbp, | ||
212 | __uint64_t nblocks) | ||
213 | { | ||
214 | ASSERT(PAGE_SHIFT >= sbp->sb_blocklog); | ||
215 | ASSERT(sbp->sb_blocklog >= BBSHIFT); | ||
216 | |||
217 | #if XFS_BIG_BLKNOS /* Limited by ULONG_MAX of page cache index */ | ||
218 | if (nblocks >> (PAGE_CACHE_SHIFT - sbp->sb_blocklog) > ULONG_MAX) | ||
219 | return E2BIG; | ||
220 | #else /* Limited by UINT_MAX of sectors */ | ||
221 | if (nblocks << (sbp->sb_blocklog - BBSHIFT) > UINT_MAX) | ||
222 | return E2BIG; | ||
223 | #endif | ||
224 | return 0; | ||
225 | } | ||
205 | 226 | ||
206 | /* | 227 | /* |
207 | * Check the validity of the SB found. | 228 | * Check the validity of the SB found. |
@@ -284,18 +305,8 @@ xfs_mount_validate_sb( | |||
284 | return XFS_ERROR(EFSCORRUPTED); | 305 | return XFS_ERROR(EFSCORRUPTED); |
285 | } | 306 | } |
286 | 307 | ||
287 | ASSERT(PAGE_SHIFT >= sbp->sb_blocklog); | 308 | if (xfs_sb_validate_fsb_count(sbp, sbp->sb_dblocks) || |
288 | ASSERT(sbp->sb_blocklog >= BBSHIFT); | 309 | xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) { |
289 | |||
290 | #if XFS_BIG_BLKNOS /* Limited by ULONG_MAX of page cache index */ | ||
291 | if (unlikely( | ||
292 | (sbp->sb_dblocks >> (PAGE_SHIFT - sbp->sb_blocklog)) > ULONG_MAX || | ||
293 | (sbp->sb_rblocks >> (PAGE_SHIFT - sbp->sb_blocklog)) > ULONG_MAX)) { | ||
294 | #else /* Limited by UINT_MAX of sectors */ | ||
295 | if (unlikely( | ||
296 | (sbp->sb_dblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX || | ||
297 | (sbp->sb_rblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX)) { | ||
298 | #endif | ||
299 | xfs_fs_mount_cmn_err(flags, | 310 | xfs_fs_mount_cmn_err(flags, |
300 | "file system too large to be mounted on this system."); | 311 | "file system too large to be mounted on this system."); |
301 | return XFS_ERROR(E2BIG); | 312 | return XFS_ERROR(E2BIG); |
@@ -632,6 +643,64 @@ xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp) | |||
632 | sbp->sb_inopblock); | 643 | sbp->sb_inopblock); |
633 | mp->m_ialloc_blks = mp->m_ialloc_inos >> sbp->sb_inopblog; | 644 | mp->m_ialloc_blks = mp->m_ialloc_inos >> sbp->sb_inopblog; |
634 | } | 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 | |||
635 | /* | 704 | /* |
636 | * xfs_mountfs | 705 | * xfs_mountfs |
637 | * | 706 | * |
@@ -656,7 +725,7 @@ xfs_mountfs( | |||
656 | bhv_vnode_t *rvp = NULL; | 725 | bhv_vnode_t *rvp = NULL; |
657 | int readio_log, writeio_log; | 726 | int readio_log, writeio_log; |
658 | xfs_daddr_t d; | 727 | xfs_daddr_t d; |
659 | __uint64_t ret64; | 728 | __uint64_t resblks; |
660 | __int64_t update_flags; | 729 | __int64_t update_flags; |
661 | uint quotamount, quotaflags; | 730 | uint quotamount, quotaflags; |
662 | int agno; | 731 | int agno; |
@@ -773,6 +842,7 @@ xfs_mountfs( | |||
773 | */ | 842 | */ |
774 | if ((mfsi_flags & XFS_MFSI_SECOND) == 0 && | 843 | if ((mfsi_flags & XFS_MFSI_SECOND) == 0 && |
775 | (mp->m_flags & XFS_MOUNT_NOUUID) == 0) { | 844 | (mp->m_flags & XFS_MOUNT_NOUUID) == 0) { |
845 | __uint64_t ret64; | ||
776 | if (xfs_uuid_mount(mp)) { | 846 | if (xfs_uuid_mount(mp)) { |
777 | error = XFS_ERROR(EINVAL); | 847 | error = XFS_ERROR(EINVAL); |
778 | goto error1; | 848 | goto error1; |
@@ -976,6 +1046,34 @@ xfs_mountfs( | |||
976 | } | 1046 | } |
977 | 1047 | ||
978 | /* | 1048 | /* |
1049 | * Now the log is mounted, we know if it was an unclean shutdown or | ||
1050 | * not. If it was, with the first phase of recovery has completed, we | ||
1051 | * have consistent AG blocks on disk. We have not recovered EFIs yet, | ||
1052 | * but they are recovered transactionally in the second recovery phase | ||
1053 | * later. | ||
1054 | * | ||
1055 | * Hence we can safely re-initialise incore superblock counters from | ||
1056 | * the per-ag data. These may not be correct if the filesystem was not | ||
1057 | * cleanly unmounted, so we need to wait for recovery to finish before | ||
1058 | * doing this. | ||
1059 | * | ||
1060 | * If the filesystem was cleanly unmounted, then we can trust the | ||
1061 | * values in the superblock to be correct and we don't need to do | ||
1062 | * anything here. | ||
1063 | * | ||
1064 | * If we are currently making the filesystem, the initialisation will | ||
1065 | * fail as the perag data is in an undefined state. | ||
1066 | */ | ||
1067 | |||
1068 | if (xfs_sb_version_haslazysbcount(&mp->m_sb) && | ||
1069 | !XFS_LAST_UNMOUNT_WAS_CLEAN(mp) && | ||
1070 | !mp->m_sb.sb_inprogress) { | ||
1071 | error = xfs_initialize_perag_data(mp, sbp->sb_agcount); | ||
1072 | if (error) { | ||
1073 | goto error2; | ||
1074 | } | ||
1075 | } | ||
1076 | /* | ||
979 | * Get and sanity-check the root inode. | 1077 | * Get and sanity-check the root inode. |
980 | * Save the pointer to it in the mount structure. | 1078 | * Save the pointer to it in the mount structure. |
981 | */ | 1079 | */ |
@@ -1044,6 +1142,23 @@ xfs_mountfs( | |||
1044 | if ((error = XFS_QM_MOUNT(mp, quotamount, quotaflags, mfsi_flags))) | 1142 | if ((error = XFS_QM_MOUNT(mp, quotamount, quotaflags, mfsi_flags))) |
1045 | goto error4; | 1143 | goto error4; |
1046 | 1144 | ||
1145 | /* | ||
1146 | * Now we are mounted, reserve a small amount of unused space for | ||
1147 | * privileged transactions. This is needed so that transaction | ||
1148 | * space required for critical operations can dip into this pool | ||
1149 | * when at ENOSPC. This is needed for operations like create with | ||
1150 | * attr, unwritten extent conversion at ENOSPC, etc. Data allocations | ||
1151 | * are not allowed to use this reserved space. | ||
1152 | * | ||
1153 | * We default to 5% or 1024 fsbs of space reserved, whichever is smaller. | ||
1154 | * This may drive us straight to ENOSPC on mount, but that implies | ||
1155 | * we were already there on the last unmount. | ||
1156 | */ | ||
1157 | resblks = mp->m_sb.sb_dblocks; | ||
1158 | do_div(resblks, 20); | ||
1159 | resblks = min_t(__uint64_t, resblks, 1024); | ||
1160 | xfs_reserve_blocks(mp, &resblks, NULL); | ||
1161 | |||
1047 | return 0; | 1162 | return 0; |
1048 | 1163 | ||
1049 | error4: | 1164 | error4: |
@@ -1083,7 +1198,19 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr) | |||
1083 | #if defined(DEBUG) || defined(INDUCE_IO_ERROR) | 1198 | #if defined(DEBUG) || defined(INDUCE_IO_ERROR) |
1084 | int64_t fsid; | 1199 | int64_t fsid; |
1085 | #endif | 1200 | #endif |
1201 | __uint64_t resblks; | ||
1086 | 1202 | ||
1203 | /* | ||
1204 | * We can potentially deadlock here if we have an inode cluster | ||
1205 | * that has been freed has it's buffer still pinned in memory because | ||
1206 | * the transaction is still sitting in a iclog. The stale inodes | ||
1207 | * on that buffer will have their flush locks held until the | ||
1208 | * transaction hits the disk and the callbacks run. the inode | ||
1209 | * flush takes the flush lock unconditionally and with nothing to | ||
1210 | * push out the iclog we will never get that unlocked. hence we | ||
1211 | * need to force the log first. | ||
1212 | */ | ||
1213 | xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE | XFS_LOG_SYNC); | ||
1087 | xfs_iflush_all(mp); | 1214 | xfs_iflush_all(mp); |
1088 | 1215 | ||
1089 | XFS_QM_DQPURGEALL(mp, XFS_QMOPT_QUOTALL | XFS_QMOPT_UMOUNTING); | 1216 | XFS_QM_DQPURGEALL(mp, XFS_QMOPT_QUOTALL | XFS_QMOPT_UMOUNTING); |
@@ -1100,10 +1227,26 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr) | |||
1100 | xfs_binval(mp->m_rtdev_targp); | 1227 | xfs_binval(mp->m_rtdev_targp); |
1101 | } | 1228 | } |
1102 | 1229 | ||
1103 | xfs_unmountfs_writesb(mp); | 1230 | /* |
1231 | * Unreserve any blocks we have so that when we unmount we don't account | ||
1232 | * the reserved free space as used. This is really only necessary for | ||
1233 | * lazy superblock counting because it trusts the incore superblock | ||
1234 | * counters to be aboslutely correct on clean unmount. | ||
1235 | * | ||
1236 | * We don't bother correcting this elsewhere for lazy superblock | ||
1237 | * counting because on mount of an unclean filesystem we reconstruct the | ||
1238 | * correct counter value and this is irrelevant. | ||
1239 | * | ||
1240 | * For non-lazy counter filesystems, this doesn't matter at all because | ||
1241 | * we only every apply deltas to the superblock and hence the incore | ||
1242 | * value does not matter.... | ||
1243 | */ | ||
1244 | resblks = 0; | ||
1245 | xfs_reserve_blocks(mp, &resblks, NULL); | ||
1104 | 1246 | ||
1247 | xfs_log_sbcount(mp, 1); | ||
1248 | xfs_unmountfs_writesb(mp); | ||
1105 | xfs_unmountfs_wait(mp); /* wait for async bufs */ | 1249 | xfs_unmountfs_wait(mp); /* wait for async bufs */ |
1106 | |||
1107 | xfs_log_unmount(mp); /* Done! No more fs ops. */ | 1250 | xfs_log_unmount(mp); /* Done! No more fs ops. */ |
1108 | 1251 | ||
1109 | xfs_freesb(mp); | 1252 | xfs_freesb(mp); |
@@ -1150,6 +1293,62 @@ xfs_unmountfs_wait(xfs_mount_t *mp) | |||
1150 | } | 1293 | } |
1151 | 1294 | ||
1152 | int | 1295 | int |
1296 | xfs_fs_writable(xfs_mount_t *mp) | ||
1297 | { | ||
1298 | bhv_vfs_t *vfsp = XFS_MTOVFS(mp); | ||
1299 | |||
1300 | return !(vfs_test_for_freeze(vfsp) || XFS_FORCED_SHUTDOWN(mp) || | ||
1301 | (vfsp->vfs_flag & VFS_RDONLY)); | ||
1302 | } | ||
1303 | |||
1304 | /* | ||
1305 | * xfs_log_sbcount | ||
1306 | * | ||
1307 | * Called either periodically to keep the on disk superblock values | ||
1308 | * roughly up to date or from unmount to make sure the values are | ||
1309 | * correct on a clean unmount. | ||
1310 | * | ||
1311 | * Note this code can be called during the process of freezing, so | ||
1312 | * we may need to use the transaction allocator which does not not | ||
1313 | * block when the transaction subsystem is in its frozen state. | ||
1314 | */ | ||
1315 | int | ||
1316 | xfs_log_sbcount( | ||
1317 | xfs_mount_t *mp, | ||
1318 | uint sync) | ||
1319 | { | ||
1320 | xfs_trans_t *tp; | ||
1321 | int error; | ||
1322 | |||
1323 | if (!xfs_fs_writable(mp)) | ||
1324 | return 0; | ||
1325 | |||
1326 | xfs_icsb_sync_counters(mp); | ||
1327 | |||
1328 | /* | ||
1329 | * we don't need to do this if we are updating the superblock | ||
1330 | * counters on every modification. | ||
1331 | */ | ||
1332 | if (!xfs_sb_version_haslazysbcount(&mp->m_sb)) | ||
1333 | return 0; | ||
1334 | |||
1335 | tp = _xfs_trans_alloc(mp, XFS_TRANS_SB_COUNT); | ||
1336 | error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0, | ||
1337 | XFS_DEFAULT_LOG_COUNT); | ||
1338 | if (error) { | ||
1339 | xfs_trans_cancel(tp, 0); | ||
1340 | return error; | ||
1341 | } | ||
1342 | |||
1343 | xfs_mod_sb(tp, XFS_SB_IFREE | XFS_SB_ICOUNT | XFS_SB_FDBLOCKS); | ||
1344 | if (sync) | ||
1345 | xfs_trans_set_sync(tp); | ||
1346 | xfs_trans_commit(tp, 0); | ||
1347 | |||
1348 | return 0; | ||
1349 | } | ||
1350 | |||
1351 | int | ||
1153 | xfs_unmountfs_writesb(xfs_mount_t *mp) | 1352 | xfs_unmountfs_writesb(xfs_mount_t *mp) |
1154 | { | 1353 | { |
1155 | xfs_buf_t *sbp; | 1354 | xfs_buf_t *sbp; |
@@ -1160,16 +1359,15 @@ xfs_unmountfs_writesb(xfs_mount_t *mp) | |||
1160 | * skip superblock write if fs is read-only, or | 1359 | * skip superblock write if fs is read-only, or |
1161 | * if we are doing a forced umount. | 1360 | * if we are doing a forced umount. |
1162 | */ | 1361 | */ |
1163 | sbp = xfs_getsb(mp, 0); | ||
1164 | if (!(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY || | 1362 | if (!(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY || |
1165 | XFS_FORCED_SHUTDOWN(mp))) { | 1363 | XFS_FORCED_SHUTDOWN(mp))) { |
1166 | 1364 | ||
1167 | xfs_icsb_sync_counters(mp); | 1365 | sbp = xfs_getsb(mp, 0); |
1366 | sb = XFS_BUF_TO_SBP(sbp); | ||
1168 | 1367 | ||
1169 | /* | 1368 | /* |
1170 | * mark shared-readonly if desired | 1369 | * mark shared-readonly if desired |
1171 | */ | 1370 | */ |
1172 | sb = XFS_BUF_TO_SBP(sbp); | ||
1173 | if (mp->m_mk_sharedro) { | 1371 | if (mp->m_mk_sharedro) { |
1174 | if (!(sb->sb_flags & XFS_SBF_READONLY)) | 1372 | if (!(sb->sb_flags & XFS_SBF_READONLY)) |
1175 | sb->sb_flags |= XFS_SBF_READONLY; | 1373 | sb->sb_flags |= XFS_SBF_READONLY; |
@@ -1178,6 +1376,7 @@ xfs_unmountfs_writesb(xfs_mount_t *mp) | |||
1178 | xfs_fs_cmn_err(CE_NOTE, mp, | 1376 | xfs_fs_cmn_err(CE_NOTE, mp, |
1179 | "Unmounting, marking shared read-only"); | 1377 | "Unmounting, marking shared read-only"); |
1180 | } | 1378 | } |
1379 | |||
1181 | XFS_BUF_UNDONE(sbp); | 1380 | XFS_BUF_UNDONE(sbp); |
1182 | XFS_BUF_UNREAD(sbp); | 1381 | XFS_BUF_UNREAD(sbp); |
1183 | XFS_BUF_UNDELAYWRITE(sbp); | 1382 | XFS_BUF_UNDELAYWRITE(sbp); |
@@ -1192,8 +1391,8 @@ xfs_unmountfs_writesb(xfs_mount_t *mp) | |||
1192 | mp, sbp, XFS_BUF_ADDR(sbp)); | 1391 | mp, sbp, XFS_BUF_ADDR(sbp)); |
1193 | if (error && mp->m_mk_sharedro) | 1392 | if (error && mp->m_mk_sharedro) |
1194 | xfs_fs_cmn_err(CE_ALERT, mp, "Superblock write error detected while unmounting. Filesystem may not be marked shared readonly"); | 1393 | xfs_fs_cmn_err(CE_ALERT, mp, "Superblock write error detected while unmounting. Filesystem may not be marked shared readonly"); |
1394 | xfs_buf_relse(sbp); | ||
1195 | } | 1395 | } |
1196 | xfs_buf_relse(sbp); | ||
1197 | return error; | 1396 | return error; |
1198 | } | 1397 | } |
1199 | 1398 | ||