Commit d5db0f97fbbeff11c88dec1aaf1536a975afbaeb

Authored by Eric Sandeen
Committed by Alex Elder
1 parent 388f1f0c34

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>

Showing 4 changed files with 64 additions and 25 deletions Side-by-side Diff

fs/xfs/linux-2.6/xfs_ioctl.c
... ... @@ -1431,6 +1431,9 @@
1431 1431 if (!capable(CAP_SYS_ADMIN))
1432 1432 return -EPERM;
1433 1433  
  1434 + if (mp->m_flags & XFS_MOUNT_RDONLY)
  1435 + return -XFS_ERROR(EROFS);
  1436 +
1434 1437 if (copy_from_user(&inout, arg, sizeof(inout)))
1435 1438 return -XFS_ERROR(EFAULT);
1436 1439  
fs/xfs/linux-2.6/xfs_super.c
... ... @@ -1256,6 +1256,29 @@
1256 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 1282 STATIC int
1260 1283 xfs_fs_remount(
1261 1284 struct super_block *sb,
... ... @@ -1318,8 +1341,6 @@
1318 1341  
1319 1342 /* ro -> rw */
1320 1343 if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(*flags & MS_RDONLY)) {
1321   - __uint64_t resblks;
1322   -
1323 1344 mp->m_flags &= ~XFS_MOUNT_RDONLY;
1324 1345 if (mp->m_flags & XFS_MOUNT_BARRIER)
1325 1346 xfs_mountfs_check_barriers(mp);
... ... @@ -1342,15 +1363,7 @@
1342 1363 * Fill out the reserve pool if it is empty. Use the stashed
1343 1364 * value if it is non-zero, otherwise go with the default.
1344 1365 */
1345   - if (mp->m_resblks_save) {
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);
  1366 + xfs_restore_resvblks(mp);
1354 1367 }
1355 1368  
1356 1369 /* rw -> ro */
1357 1370  
... ... @@ -1363,11 +1376,9 @@
1363 1376 * so that if we get remounted rw, we can return it to the same
1364 1377 * size.
1365 1378 */
1366   - __uint64_t resblks = 0;
1367 1379  
1368 1380 xfs_quiesce_data(mp);
1369   - mp->m_resblks_save = mp->m_resblks;
1370   - xfs_reserve_blocks(mp, &resblks, NULL);
  1381 + xfs_save_resvblks(mp);
1371 1382 xfs_quiesce_attr(mp);
1372 1383 mp->m_flags |= XFS_MOUNT_RDONLY;
1373 1384 }
1374 1385  
... ... @@ -1386,11 +1397,22 @@
1386 1397 {
1387 1398 struct xfs_mount *mp = XFS_M(sb);
1388 1399  
  1400 + xfs_save_resvblks(mp);
1389 1401 xfs_quiesce_attr(mp);
1390 1402 return -xfs_fs_log_dummy(mp);
1391 1403 }
1392 1404  
1393 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 1416 xfs_fs_show_options(
1395 1417 struct seq_file *m,
1396 1418 struct vfsmount *mnt)
... ... @@ -1612,6 +1634,7 @@
1612 1634 .put_super = xfs_fs_put_super,
1613 1635 .sync_fs = xfs_fs_sync_fs,
1614 1636 .freeze_fs = xfs_fs_freeze,
  1637 + .unfreeze_fs = xfs_fs_unfreeze,
1615 1638 .statfs = xfs_fs_statfs,
1616 1639 .remount_fs = xfs_fs_remount,
1617 1640 .show_options = xfs_fs_show_options,
... ... @@ -1091,6 +1091,22 @@
1091 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 1111 * This function does the following on an initial mount of a file system:
1096 1112 * - reads the superblock from disk and init the mount struct
1097 1113  
... ... @@ -1401,18 +1417,14 @@
1401 1417 * when at ENOSPC. This is needed for operations like create with
1402 1418 * attr, unwritten extent conversion at ENOSPC, etc. Data allocations
1403 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;
1410   - do_div(resblks, 20);
1411   - resblks = min_t(__uint64_t, resblks, 1024);
1412   - error = xfs_reserve_blocks(mp, &resblks, NULL);
1413   - if (error)
1414   - cmn_err(CE_WARN, "XFS: Unable to allocate reserve blocks. "
1415   - "Continuing without a reserve pool.");
  1421 + if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
  1422 + resblks = xfs_default_resblks(mp);
  1423 + error = xfs_reserve_blocks(mp, &resblks, NULL);
  1424 + if (error)
  1425 + cmn_err(CE_WARN, "XFS: Unable to allocate reserve "
  1426 + "blocks. Continuing without a reserve pool.");
  1427 + }
1416 1428  
1417 1429 return 0;
1418 1430  
... ... @@ -421,6 +421,7 @@
421 421 } xfs_mod_sb_t;
422 422  
423 423 extern int xfs_log_sbcount(xfs_mount_t *, uint);
  424 +extern __uint64_t xfs_default_resblks(xfs_mount_t *mp);
424 425 extern int xfs_mountfs(xfs_mount_t *mp);
425 426  
426 427 extern void xfs_unmountfs(xfs_mount_t *);