aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/suballoc.c
diff options
context:
space:
mode:
authorMark Fasheh <mfasheh@suse.com>2008-07-28 21:02:53 -0400
committerMark Fasheh <mfasheh@suse.com>2008-10-13 16:57:57 -0400
commit9c7af40b210e87f8fddd97b0badc0a352862234a (patch)
treedeb248e5295439b96ad9bd1789e8512f93803142 /fs/ocfs2/suballoc.c
parentebcee4b5c9136096f64ee6f691a013d7c0a4bc34 (diff)
ocfs2: throttle back local alloc when low on disk space
Ocfs2's local allocator disables itself for the duration of a mount point when it has trouble allocating a large enough area from the primary bitmap. That can cause performance problems, especially for disks which were only temporarily full or fragmented. This patch allows for the allocator to shrink it's window first, before being disabled. Later, it can also be re-enabled so that any performance drop is minimized. To do this, we allow the value of osb->local_alloc_bits to be shrunk when needed. The default value is recorded in a mostly read-only variable so that we can re-initialize when required. Locking had to be updated so that we could protect changes to local_alloc_bits. Mostly this involves protecting various local alloc values with the osb spinlock. A new state is also added, OCFS2_LA_THROTTLED, which is used when the local allocator is has shrunk, but is not disabled. If the available space dips below 1 megabyte, the local alloc file is disabled. In either case, local alloc is re-enabled 30 seconds after the event, or when an appropriate amount of bits is seen in the primary bitmap. Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs/ocfs2/suballoc.c')
-rw-r--r--fs/ocfs2/suballoc.c31
1 files changed, 17 insertions, 14 deletions
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
index d2d278fb9819..de7b93d76d12 100644
--- a/fs/ocfs2/suballoc.c
+++ b/fs/ocfs2/suballoc.c
@@ -111,7 +111,7 @@ static inline void ocfs2_block_to_cluster_group(struct inode *inode,
111 u64 *bg_blkno, 111 u64 *bg_blkno,
112 u16 *bg_bit_off); 112 u16 *bg_bit_off);
113 113
114static void ocfs2_free_ac_resource(struct ocfs2_alloc_context *ac) 114void ocfs2_free_ac_resource(struct ocfs2_alloc_context *ac)
115{ 115{
116 struct inode *inode = ac->ac_inode; 116 struct inode *inode = ac->ac_inode;
117 117
@@ -686,15 +686,6 @@ int ocfs2_reserve_clusters(struct ocfs2_super *osb,
686 if ((status < 0) && (status != -ENOSPC)) { 686 if ((status < 0) && (status != -ENOSPC)) {
687 mlog_errno(status); 687 mlog_errno(status);
688 goto bail; 688 goto bail;
689 } else if (status == -ENOSPC) {
690 /* reserve_local_bits will return enospc with
691 * the local alloc inode still locked, so we
692 * can change this safely here. */
693 mlog(0, "Disabling local alloc\n");
694 /* We set to OCFS2_LA_DISABLED so that umount
695 * can clean up what's left of the local
696 * allocation */
697 osb->local_alloc_state = OCFS2_LA_DISABLED;
698 } 689 }
699 } 690 }
700 691
@@ -1005,6 +996,7 @@ static int ocfs2_cluster_group_search(struct inode *inode,
1005 int search = -ENOSPC; 996 int search = -ENOSPC;
1006 int ret; 997 int ret;
1007 struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *) group_bh->b_data; 998 struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *) group_bh->b_data;
999 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
1008 u16 tmp_off, tmp_found; 1000 u16 tmp_off, tmp_found;
1009 unsigned int max_bits, gd_cluster_off; 1001 unsigned int max_bits, gd_cluster_off;
1010 1002
@@ -1045,6 +1037,12 @@ static int ocfs2_cluster_group_search(struct inode *inode,
1045 *bit_off = tmp_off; 1037 *bit_off = tmp_off;
1046 *bits_found = tmp_found; 1038 *bits_found = tmp_found;
1047 search = 0; /* success */ 1039 search = 0; /* success */
1040 } else if (tmp_found) {
1041 /*
1042 * Don't show bits which we'll be returning
1043 * for allocation to the local alloc bitmap.
1044 */
1045 ocfs2_local_alloc_seen_free_bits(osb, tmp_found);
1048 } 1046 }
1049 } 1047 }
1050 1048
@@ -1203,9 +1201,8 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
1203 status = -ENOSPC; 1201 status = -ENOSPC;
1204 /* for now, the chain search is a bit simplistic. We just use 1202 /* for now, the chain search is a bit simplistic. We just use
1205 * the 1st group with any empty bits. */ 1203 * the 1st group with any empty bits. */
1206 while ((status = ac->ac_group_search(alloc_inode, group_bh, 1204 while ((status = ac->ac_group_search(alloc_inode, group_bh, bits_wanted,
1207 bits_wanted, min_bits, bit_off, 1205 min_bits, bit_off, &tmp_bits)) == -ENOSPC) {
1208 &tmp_bits)) == -ENOSPC) {
1209 if (!bg->bg_next_group) 1206 if (!bg->bg_next_group)
1210 break; 1207 break;
1211 1208
@@ -1838,9 +1835,15 @@ int ocfs2_free_clusters(handle_t *handle,
1838 status = ocfs2_free_suballoc_bits(handle, bitmap_inode, bitmap_bh, 1835 status = ocfs2_free_suballoc_bits(handle, bitmap_inode, bitmap_bh,
1839 bg_start_bit, bg_blkno, 1836 bg_start_bit, bg_blkno,
1840 num_clusters); 1837 num_clusters);
1841 if (status < 0) 1838 if (status < 0) {
1842 mlog_errno(status); 1839 mlog_errno(status);
1840 goto out;
1841 }
1842
1843 ocfs2_local_alloc_seen_free_bits(OCFS2_SB(bitmap_inode->i_sb),
1844 num_clusters);
1843 1845
1846out:
1844 mlog_exit(status); 1847 mlog_exit(status);
1845 return status; 1848 return status;
1846} 1849}