diff options
author | Eric Sandeen <sandeen@sandeen.net> | 2010-02-05 17:59:53 -0500 |
---|---|---|
committer | Alex Elder <aelder@sgi.com> | 2010-02-08 18:41:48 -0500 |
commit | d5db0f97fbbeff11c88dec1aaf1536a975afbaeb (patch) | |
tree | 3e81db2cb8c5004f3c30ccaa35e54fbf1549897f /fs/xfs | |
parent | 388f1f0c346b533b06d8bc792f7204ebc3e4b7da (diff) |
xfs: more reserved blocks fixups
This mangles the reserved blocks counts a little more.
1) add a helper function for the default reserved count
2) add helper functions to save/restore counts on ro/rw
3) save/restore reserved blocks on freeze/thaw
4) disallow changing reserved count while readonly
V2: changed field name to match Dave's changes
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
Signed-off-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl.c | 3 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_super.c | 51 | ||||
-rw-r--r-- | fs/xfs/xfs_mount.c | 34 | ||||
-rw-r--r-- | fs/xfs/xfs_mount.h | 1 |
4 files changed, 64 insertions, 25 deletions
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index 3906e85abfdc..4ea1ee18aded 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c | |||
@@ -1431,6 +1431,9 @@ xfs_file_ioctl( | |||
1431 | if (!capable(CAP_SYS_ADMIN)) | 1431 | if (!capable(CAP_SYS_ADMIN)) |
1432 | return -EPERM; | 1432 | return -EPERM; |
1433 | 1433 | ||
1434 | if (mp->m_flags & XFS_MOUNT_RDONLY) | ||
1435 | return -XFS_ERROR(EROFS); | ||
1436 | |||
1434 | if (copy_from_user(&inout, arg, sizeof(inout))) | 1437 | if (copy_from_user(&inout, arg, sizeof(inout))) |
1435 | return -XFS_ERROR(EFAULT); | 1438 | return -XFS_ERROR(EFAULT); |
1436 | 1439 | ||
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index e9c21454b9e2..6ce828e0e17b 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
@@ -1256,6 +1256,29 @@ xfs_fs_statfs( | |||
1256 | return 0; | 1256 | return 0; |
1257 | } | 1257 | } |
1258 | 1258 | ||
1259 | STATIC void | ||
1260 | xfs_save_resvblks(struct xfs_mount *mp) | ||
1261 | { | ||
1262 | __uint64_t resblks = 0; | ||
1263 | |||
1264 | mp->m_resblks_save = mp->m_resblks; | ||
1265 | xfs_reserve_blocks(mp, &resblks, NULL); | ||
1266 | } | ||
1267 | |||
1268 | STATIC void | ||
1269 | xfs_restore_resvblks(struct xfs_mount *mp) | ||
1270 | { | ||
1271 | __uint64_t resblks; | ||
1272 | |||
1273 | if (mp->m_resblks_save) { | ||
1274 | resblks = mp->m_resblks_save; | ||
1275 | mp->m_resblks_save = 0; | ||
1276 | } else | ||
1277 | resblks = xfs_default_resblks(mp); | ||
1278 | |||
1279 | xfs_reserve_blocks(mp, &resblks, NULL); | ||
1280 | } | ||
1281 | |||
1259 | STATIC int | 1282 | STATIC int |
1260 | xfs_fs_remount( | 1283 | xfs_fs_remount( |
1261 | struct super_block *sb, | 1284 | struct super_block *sb, |
@@ -1318,8 +1341,6 @@ xfs_fs_remount( | |||
1318 | 1341 | ||
1319 | /* ro -> rw */ | 1342 | /* ro -> rw */ |
1320 | if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(*flags & MS_RDONLY)) { | 1343 | if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(*flags & MS_RDONLY)) { |
1321 | __uint64_t resblks; | ||
1322 | |||
1323 | mp->m_flags &= ~XFS_MOUNT_RDONLY; | 1344 | mp->m_flags &= ~XFS_MOUNT_RDONLY; |
1324 | if (mp->m_flags & XFS_MOUNT_BARRIER) | 1345 | if (mp->m_flags & XFS_MOUNT_BARRIER) |
1325 | xfs_mountfs_check_barriers(mp); | 1346 | xfs_mountfs_check_barriers(mp); |
@@ -1342,15 +1363,7 @@ xfs_fs_remount( | |||
1342 | * Fill out the reserve pool if it is empty. Use the stashed | 1363 | * Fill out the reserve pool if it is empty. Use the stashed |
1343 | * value if it is non-zero, otherwise go with the default. | 1364 | * value if it is non-zero, otherwise go with the default. |
1344 | */ | 1365 | */ |
1345 | if (mp->m_resblks_save) { | 1366 | xfs_restore_resvblks(mp); |
1346 | resblks = mp->m_resblks_save; | ||
1347 | mp->m_resblks_save = 0; | ||
1348 | } else { | ||
1349 | resblks = mp->m_sb.sb_dblocks; | ||
1350 | do_div(resblks, 20); | ||
1351 | resblks = min_t(__uint64_t, resblks, 1024); | ||
1352 | } | ||
1353 | xfs_reserve_blocks(mp, &resblks, NULL); | ||
1354 | } | 1367 | } |
1355 | 1368 | ||
1356 | /* rw -> ro */ | 1369 | /* rw -> ro */ |
@@ -1363,11 +1376,9 @@ xfs_fs_remount( | |||
1363 | * so that if we get remounted rw, we can return it to the same | 1376 | * so that if we get remounted rw, we can return it to the same |
1364 | * size. | 1377 | * size. |
1365 | */ | 1378 | */ |
1366 | __uint64_t resblks = 0; | ||
1367 | 1379 | ||
1368 | xfs_quiesce_data(mp); | 1380 | xfs_quiesce_data(mp); |
1369 | mp->m_resblks_save = mp->m_resblks; | 1381 | xfs_save_resvblks(mp); |
1370 | xfs_reserve_blocks(mp, &resblks, NULL); | ||
1371 | xfs_quiesce_attr(mp); | 1382 | xfs_quiesce_attr(mp); |
1372 | mp->m_flags |= XFS_MOUNT_RDONLY; | 1383 | mp->m_flags |= XFS_MOUNT_RDONLY; |
1373 | } | 1384 | } |
@@ -1386,11 +1397,22 @@ xfs_fs_freeze( | |||
1386 | { | 1397 | { |
1387 | struct xfs_mount *mp = XFS_M(sb); | 1398 | struct xfs_mount *mp = XFS_M(sb); |
1388 | 1399 | ||
1400 | xfs_save_resvblks(mp); | ||
1389 | xfs_quiesce_attr(mp); | 1401 | xfs_quiesce_attr(mp); |
1390 | return -xfs_fs_log_dummy(mp); | 1402 | return -xfs_fs_log_dummy(mp); |
1391 | } | 1403 | } |
1392 | 1404 | ||
1393 | STATIC int | 1405 | STATIC int |
1406 | xfs_fs_unfreeze( | ||
1407 | struct super_block *sb) | ||
1408 | { | ||
1409 | struct xfs_mount *mp = XFS_M(sb); | ||
1410 | |||
1411 | xfs_restore_resvblks(mp); | ||
1412 | return 0; | ||
1413 | } | ||
1414 | |||
1415 | STATIC int | ||
1394 | xfs_fs_show_options( | 1416 | xfs_fs_show_options( |
1395 | struct seq_file *m, | 1417 | struct seq_file *m, |
1396 | struct vfsmount *mnt) | 1418 | struct vfsmount *mnt) |
@@ -1612,6 +1634,7 @@ static const struct super_operations xfs_super_operations = { | |||
1612 | .put_super = xfs_fs_put_super, | 1634 | .put_super = xfs_fs_put_super, |
1613 | .sync_fs = xfs_fs_sync_fs, | 1635 | .sync_fs = xfs_fs_sync_fs, |
1614 | .freeze_fs = xfs_fs_freeze, | 1636 | .freeze_fs = xfs_fs_freeze, |
1637 | .unfreeze_fs = xfs_fs_unfreeze, | ||
1615 | .statfs = xfs_fs_statfs, | 1638 | .statfs = xfs_fs_statfs, |
1616 | .remount_fs = xfs_fs_remount, | 1639 | .remount_fs = xfs_fs_remount, |
1617 | .show_options = xfs_fs_show_options, | 1640 | .show_options = xfs_fs_show_options, |
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 7f81ed72c875..5061149b2cc4 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -1091,6 +1091,22 @@ xfs_mount_reset_sbqflags( | |||
1091 | return xfs_trans_commit(tp, 0); | 1091 | return xfs_trans_commit(tp, 0); |
1092 | } | 1092 | } |
1093 | 1093 | ||
1094 | __uint64_t | ||
1095 | xfs_default_resblks(xfs_mount_t *mp) | ||
1096 | { | ||
1097 | __uint64_t resblks; | ||
1098 | |||
1099 | /* | ||
1100 | * We default to 5% or 1024 fsbs of space reserved, whichever is smaller. | ||
1101 | * This may drive us straight to ENOSPC on mount, but that implies | ||
1102 | * we were already there on the last unmount. Warn if this occurs. | ||
1103 | */ | ||
1104 | resblks = mp->m_sb.sb_dblocks; | ||
1105 | do_div(resblks, 20); | ||
1106 | resblks = min_t(__uint64_t, resblks, 1024); | ||
1107 | return resblks; | ||
1108 | } | ||
1109 | |||
1094 | /* | 1110 | /* |
1095 | * This function does the following on an initial mount of a file system: | 1111 | * This function does the following on an initial mount of a file system: |
1096 | * - reads the superblock from disk and init the mount struct | 1112 | * - reads the superblock from disk and init the mount struct |
@@ -1401,18 +1417,14 @@ xfs_mountfs( | |||
1401 | * when at ENOSPC. This is needed for operations like create with | 1417 | * when at ENOSPC. This is needed for operations like create with |
1402 | * attr, unwritten extent conversion at ENOSPC, etc. Data allocations | 1418 | * attr, unwritten extent conversion at ENOSPC, etc. Data allocations |
1403 | * are not allowed to use this reserved space. | 1419 | * are not allowed to use this reserved space. |
1404 | * | ||
1405 | * We default to 5% or 1024 fsbs of space reserved, whichever is smaller. | ||
1406 | * This may drive us straight to ENOSPC on mount, but that implies | ||
1407 | * we were already there on the last unmount. Warn if this occurs. | ||
1408 | */ | 1420 | */ |
1409 | resblks = mp->m_sb.sb_dblocks; | 1421 | if (!(mp->m_flags & XFS_MOUNT_RDONLY)) { |
1410 | do_div(resblks, 20); | 1422 | resblks = xfs_default_resblks(mp); |
1411 | resblks = min_t(__uint64_t, resblks, 1024); | 1423 | error = xfs_reserve_blocks(mp, &resblks, NULL); |
1412 | error = xfs_reserve_blocks(mp, &resblks, NULL); | 1424 | if (error) |
1413 | if (error) | 1425 | cmn_err(CE_WARN, "XFS: Unable to allocate reserve " |
1414 | cmn_err(CE_WARN, "XFS: Unable to allocate reserve blocks. " | 1426 | "blocks. Continuing without a reserve pool."); |
1415 | "Continuing without a reserve pool."); | 1427 | } |
1416 | 1428 | ||
1417 | return 0; | 1429 | return 0; |
1418 | 1430 | ||
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 02d45f213e58..70504fcf14cd 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h | |||
@@ -421,6 +421,7 @@ typedef struct xfs_mod_sb { | |||
421 | } xfs_mod_sb_t; | 421 | } xfs_mod_sb_t; |
422 | 422 | ||
423 | extern int xfs_log_sbcount(xfs_mount_t *, uint); | 423 | extern int xfs_log_sbcount(xfs_mount_t *, uint); |
424 | extern __uint64_t xfs_default_resblks(xfs_mount_t *mp); | ||
424 | extern int xfs_mountfs(xfs_mount_t *mp); | 425 | extern int xfs_mountfs(xfs_mount_t *mp); |
425 | 426 | ||
426 | extern void xfs_unmountfs(xfs_mount_t *); | 427 | extern void xfs_unmountfs(xfs_mount_t *); |