diff options
-rw-r--r-- | fs/xfs/xfs_fsops.c | 10 | ||||
-rw-r--r-- | fs/xfs/xfs_iomap.c | 22 | ||||
-rw-r--r-- | fs/xfs/xfs_mount.c | 37 |
3 files changed, 50 insertions, 19 deletions
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index ddd45e5b9383..2251a49f3e17 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c | |||
@@ -177,6 +177,7 @@ xfs_growfs_data_private( | |||
177 | up_write(&mp->m_peraglock); | 177 | up_write(&mp->m_peraglock); |
178 | } | 178 | } |
179 | tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS); | 179 | tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS); |
180 | tp->t_flags |= XFS_TRANS_RESERVE; | ||
180 | if ((error = xfs_trans_reserve(tp, XFS_GROWFS_SPACE_RES(mp), | 181 | if ((error = xfs_trans_reserve(tp, XFS_GROWFS_SPACE_RES(mp), |
181 | XFS_GROWDATA_LOG_RES(mp), 0, 0, 0))) { | 182 | XFS_GROWDATA_LOG_RES(mp), 0, 0, 0))) { |
182 | xfs_trans_cancel(tp, 0); | 183 | xfs_trans_cancel(tp, 0); |
@@ -499,8 +500,9 @@ xfs_reserve_blocks( | |||
499 | unsigned long s; | 500 | unsigned long s; |
500 | 501 | ||
501 | /* If inval is null, report current values and return */ | 502 | /* If inval is null, report current values and return */ |
502 | |||
503 | if (inval == (__uint64_t *)NULL) { | 503 | if (inval == (__uint64_t *)NULL) { |
504 | if (!outval) | ||
505 | return EINVAL; | ||
504 | outval->resblks = mp->m_resblks; | 506 | outval->resblks = mp->m_resblks; |
505 | outval->resblks_avail = mp->m_resblks_avail; | 507 | outval->resblks_avail = mp->m_resblks_avail; |
506 | return 0; | 508 | return 0; |
@@ -563,8 +565,10 @@ retry: | |||
563 | } | 565 | } |
564 | } | 566 | } |
565 | out: | 567 | out: |
566 | outval->resblks = mp->m_resblks; | 568 | if (outval) { |
567 | outval->resblks_avail = mp->m_resblks_avail; | 569 | outval->resblks = mp->m_resblks; |
570 | outval->resblks_avail = mp->m_resblks_avail; | ||
571 | } | ||
568 | XFS_SB_UNLOCK(mp, s); | 572 | XFS_SB_UNLOCK(mp, s); |
569 | 573 | ||
570 | if (fdblks_delta) { | 574 | if (fdblks_delta) { |
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 3f2b9f2a7b94..ab5062199f55 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c | |||
@@ -489,13 +489,13 @@ xfs_iomap_write_direct( | |||
489 | if (unlikely(rt)) { | 489 | if (unlikely(rt)) { |
490 | resrtextents = qblocks = resaligned; | 490 | resrtextents = qblocks = resaligned; |
491 | resrtextents /= mp->m_sb.sb_rextsize; | 491 | resrtextents /= mp->m_sb.sb_rextsize; |
492 | resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0); | 492 | resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0); |
493 | quota_flag = XFS_QMOPT_RES_RTBLKS; | 493 | quota_flag = XFS_QMOPT_RES_RTBLKS; |
494 | } else { | 494 | } else { |
495 | resrtextents = 0; | 495 | resrtextents = 0; |
496 | resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, resaligned); | 496 | resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, resaligned); |
497 | quota_flag = XFS_QMOPT_RES_REGBLKS; | 497 | quota_flag = XFS_QMOPT_RES_REGBLKS; |
498 | } | 498 | } |
499 | 499 | ||
500 | /* | 500 | /* |
501 | * Allocate and setup the transaction | 501 | * Allocate and setup the transaction |
@@ -788,18 +788,12 @@ xfs_iomap_write_allocate( | |||
788 | nimaps = 0; | 788 | nimaps = 0; |
789 | while (nimaps == 0) { | 789 | while (nimaps == 0) { |
790 | tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE); | 790 | tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE); |
791 | tp->t_flags |= XFS_TRANS_RESERVE; | ||
791 | nres = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK); | 792 | nres = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK); |
792 | error = xfs_trans_reserve(tp, nres, | 793 | error = xfs_trans_reserve(tp, nres, |
793 | XFS_WRITE_LOG_RES(mp), | 794 | XFS_WRITE_LOG_RES(mp), |
794 | 0, XFS_TRANS_PERM_LOG_RES, | 795 | 0, XFS_TRANS_PERM_LOG_RES, |
795 | XFS_WRITE_LOG_COUNT); | 796 | XFS_WRITE_LOG_COUNT); |
796 | if (error == ENOSPC) { | ||
797 | error = xfs_trans_reserve(tp, 0, | ||
798 | XFS_WRITE_LOG_RES(mp), | ||
799 | 0, | ||
800 | XFS_TRANS_PERM_LOG_RES, | ||
801 | XFS_WRITE_LOG_COUNT); | ||
802 | } | ||
803 | if (error) { | 797 | if (error) { |
804 | xfs_trans_cancel(tp, 0); | 798 | xfs_trans_cancel(tp, 0); |
805 | return XFS_ERROR(error); | 799 | return XFS_ERROR(error); |
@@ -917,8 +911,8 @@ xfs_iomap_write_unwritten( | |||
917 | * from unwritten to real. Do allocations in a loop until | 911 | * from unwritten to real. Do allocations in a loop until |
918 | * we have covered the range passed in. | 912 | * we have covered the range passed in. |
919 | */ | 913 | */ |
920 | |||
921 | tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE); | 914 | tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE); |
915 | tp->t_flags |= XFS_TRANS_RESERVE; | ||
922 | error = xfs_trans_reserve(tp, resblks, | 916 | error = xfs_trans_reserve(tp, resblks, |
923 | XFS_WRITE_LOG_RES(mp), 0, | 917 | XFS_WRITE_LOG_RES(mp), 0, |
924 | XFS_TRANS_PERM_LOG_RES, | 918 | XFS_TRANS_PERM_LOG_RES, |
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 39cf6f3267c3..31453ca0f3dd 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -725,7 +725,7 @@ xfs_mountfs( | |||
725 | bhv_vnode_t *rvp = NULL; | 725 | bhv_vnode_t *rvp = NULL; |
726 | int readio_log, writeio_log; | 726 | int readio_log, writeio_log; |
727 | xfs_daddr_t d; | 727 | xfs_daddr_t d; |
728 | __uint64_t ret64; | 728 | __uint64_t resblks; |
729 | __int64_t update_flags; | 729 | __int64_t update_flags; |
730 | uint quotamount, quotaflags; | 730 | uint quotamount, quotaflags; |
731 | int agno; | 731 | int agno; |
@@ -842,6 +842,7 @@ xfs_mountfs( | |||
842 | */ | 842 | */ |
843 | if ((mfsi_flags & XFS_MFSI_SECOND) == 0 && | 843 | if ((mfsi_flags & XFS_MFSI_SECOND) == 0 && |
844 | (mp->m_flags & XFS_MOUNT_NOUUID) == 0) { | 844 | (mp->m_flags & XFS_MOUNT_NOUUID) == 0) { |
845 | __uint64_t ret64; | ||
845 | if (xfs_uuid_mount(mp)) { | 846 | if (xfs_uuid_mount(mp)) { |
846 | error = XFS_ERROR(EINVAL); | 847 | error = XFS_ERROR(EINVAL); |
847 | goto error1; | 848 | goto error1; |
@@ -1135,13 +1136,27 @@ xfs_mountfs( | |||
1135 | goto error4; | 1136 | goto error4; |
1136 | } | 1137 | } |
1137 | 1138 | ||
1138 | |||
1139 | /* | 1139 | /* |
1140 | * Complete the quota initialisation, post-log-replay component. | 1140 | * Complete the quota initialisation, post-log-replay component. |
1141 | */ | 1141 | */ |
1142 | if ((error = XFS_QM_MOUNT(mp, quotamount, quotaflags, mfsi_flags))) | 1142 | if ((error = XFS_QM_MOUNT(mp, quotamount, quotaflags, mfsi_flags))) |
1143 | goto error4; | 1143 | goto error4; |
1144 | 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 = min_t(__uint64_t, mp->m_sb.sb_dblocks / 20, 1024); | ||
1158 | xfs_reserve_blocks(mp, &resblks, NULL); | ||
1159 | |||
1145 | return 0; | 1160 | return 0; |
1146 | 1161 | ||
1147 | error4: | 1162 | error4: |
@@ -1181,6 +1196,7 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr) | |||
1181 | #if defined(DEBUG) || defined(INDUCE_IO_ERROR) | 1196 | #if defined(DEBUG) || defined(INDUCE_IO_ERROR) |
1182 | int64_t fsid; | 1197 | int64_t fsid; |
1183 | #endif | 1198 | #endif |
1199 | __uint64_t resblks; | ||
1184 | 1200 | ||
1185 | /* | 1201 | /* |
1186 | * We can potentially deadlock here if we have an inode cluster | 1202 | * We can potentially deadlock here if we have an inode cluster |
@@ -1209,6 +1225,23 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr) | |||
1209 | xfs_binval(mp->m_rtdev_targp); | 1225 | xfs_binval(mp->m_rtdev_targp); |
1210 | } | 1226 | } |
1211 | 1227 | ||
1228 | /* | ||
1229 | * Unreserve any blocks we have so that when we unmount we don't account | ||
1230 | * the reserved free space as used. This is really only necessary for | ||
1231 | * lazy superblock counting because it trusts the incore superblock | ||
1232 | * counters to be aboslutely correct on clean unmount. | ||
1233 | * | ||
1234 | * We don't bother correcting this elsewhere for lazy superblock | ||
1235 | * counting because on mount of an unclean filesystem we reconstruct the | ||
1236 | * correct counter value and this is irrelevant. | ||
1237 | * | ||
1238 | * For non-lazy counter filesystems, this doesn't matter at all because | ||
1239 | * we only every apply deltas to the superblock and hence the incore | ||
1240 | * value does not matter.... | ||
1241 | */ | ||
1242 | resblks = 0; | ||
1243 | xfs_reserve_blocks(mp, &resblks, NULL); | ||
1244 | |||
1212 | xfs_log_sbcount(mp, 1); | 1245 | xfs_log_sbcount(mp, 1); |
1213 | xfs_unmountfs_writesb(mp); | 1246 | xfs_unmountfs_writesb(mp); |
1214 | xfs_unmountfs_wait(mp); /* wait for async bufs */ | 1247 | xfs_unmountfs_wait(mp); /* wait for async bufs */ |