return 0;
}
+STATIC void
+xfs_save_resvblks(struct xfs_mount *mp)
+{
+ __uint64_t resblks = 0;
+
+ mp->m_resblks_save = mp->m_resblks;
+ xfs_reserve_blocks(mp, &resblks, NULL);
+}
+
+STATIC void
+xfs_restore_resvblks(struct xfs_mount *mp)
+{
+ __uint64_t resblks;
+
+ if (mp->m_resblks_save) {
+ resblks = mp->m_resblks_save;
+ mp->m_resblks_save = 0;
+ } else
+ resblks = xfs_default_resblks(mp);
+
+ xfs_reserve_blocks(mp, &resblks, NULL);
+}
+
STATIC int
xfs_fs_remount(
struct super_block *sb,
/* ro -> rw */
if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(*flags & MS_RDONLY)) {
- __uint64_t resblks;
-
mp->m_flags &= ~XFS_MOUNT_RDONLY;
if (mp->m_flags & XFS_MOUNT_BARRIER)
xfs_mountfs_check_barriers(mp);
* Fill out the reserve pool if it is empty. Use the stashed
* value if it is non-zero, otherwise go with the default.
*/
- if (mp->m_resblks_save) {
- resblks = mp->m_resblks_save;
- mp->m_resblks_save = 0;
- } else {
- resblks = mp->m_sb.sb_dblocks;
- do_div(resblks, 20);
- resblks = min_t(__uint64_t, resblks, 1024);
- }
- xfs_reserve_blocks(mp, &resblks, NULL);
+ xfs_restore_resvblks(mp);
}
/* rw -> ro */
* so that if we get remounted rw, we can return it to the same
* size.
*/
- __uint64_t resblks = 0;
xfs_quiesce_data(mp);
- mp->m_resblks_save = mp->m_resblks;
- xfs_reserve_blocks(mp, &resblks, NULL);
+ xfs_save_resvblks(mp);
xfs_quiesce_attr(mp);
mp->m_flags |= XFS_MOUNT_RDONLY;
}
{
struct xfs_mount *mp = XFS_M(sb);
+ xfs_save_resvblks(mp);
xfs_quiesce_attr(mp);
return -xfs_fs_log_dummy(mp);
}
+STATIC int
+xfs_fs_unfreeze(
+ struct super_block *sb)
+{
+ struct xfs_mount *mp = XFS_M(sb);
+
+ xfs_restore_resvblks(mp);
+ return 0;
+}
+
STATIC int
xfs_fs_show_options(
struct seq_file *m,
.put_super = xfs_fs_put_super,
.sync_fs = xfs_fs_sync_fs,
.freeze_fs = xfs_fs_freeze,
+ .unfreeze_fs = xfs_fs_unfreeze,
.statfs = xfs_fs_statfs,
.remount_fs = xfs_fs_remount,
.show_options = xfs_fs_show_options,
return xfs_trans_commit(tp, 0);
}
+__uint64_t
+xfs_default_resblks(xfs_mount_t *mp)
+{
+ __uint64_t resblks;
+
+ /*
+ * We default to 5% or 1024 fsbs of space reserved, whichever is smaller.
+ * This may drive us straight to ENOSPC on mount, but that implies
+ * we were already there on the last unmount. Warn if this occurs.
+ */
+ resblks = mp->m_sb.sb_dblocks;
+ do_div(resblks, 20);
+ resblks = min_t(__uint64_t, resblks, 1024);
+ return resblks;
+}
+
/*
* This function does the following on an initial mount of a file system:
* - reads the superblock from disk and init the mount struct
* when at ENOSPC. This is needed for operations like create with
* attr, unwritten extent conversion at ENOSPC, etc. Data allocations
* are not allowed to use this reserved space.
- *
- * We default to 5% or 1024 fsbs of space reserved, whichever is smaller.
- * This may drive us straight to ENOSPC on mount, but that implies
- * we were already there on the last unmount. Warn if this occurs.
*/
- resblks = mp->m_sb.sb_dblocks;
- do_div(resblks, 20);
- resblks = min_t(__uint64_t, resblks, 1024);
- error = xfs_reserve_blocks(mp, &resblks, NULL);
- if (error)
- cmn_err(CE_WARN, "XFS: Unable to allocate reserve blocks. "
- "Continuing without a reserve pool.");
+ if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
+ resblks = xfs_default_resblks(mp);
+ error = xfs_reserve_blocks(mp, &resblks, NULL);
+ if (error)
+ cmn_err(CE_WARN, "XFS: Unable to allocate reserve "
+ "blocks. Continuing without a reserve pool.");
+ }
return 0;