aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMark Fasheh <mark.fasheh@oracle.com>2007-09-16 23:10:16 -0400
committerMark Fasheh <mark.fasheh@oracle.com>2007-09-20 18:06:09 -0400
commit415cb800375cc4e89fb5a6a454e484bd4adbffb4 (patch)
tree816021a5279047702d5fa8180783b1c710f31746 /fs
parent6d0b842d3bf0cc027dcff57a89fb8a6b1fd610e1 (diff)
ocfs2: Allow smaller allocations during large writes
The ocfs2 write code loops through a page much like the block code, except that ocfs2 allocation units can be any size, including larger than page size. Typically it's equal to or larger than page size - most kernels run 4k pages, the minimum ocfs2 allocation (cluster) size. Some changes introduced during 2.6.23 changed the way writes to pages are handled, and inadvertantly broke support for > 4k page size. Instead of just writing one cluster at a time, we now handle the whole page in one pass. This means that multiple (small) seperate allocations might happen in the same pass. The allocation code howver typically optimizes by getting the maximum which was reserved. This triggered a BUG_ON in the extend code where it'd ask for a single bit (for one part of a > 4k page) and get back more than it asked for. Fix this by providing a variant of the high level allocation function which allows the caller to specify a maximum. The traditional function remains and just calls the new one with a maximum determined from the initial reservation. Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/ocfs2/file.c4
-rw-r--r--fs/ocfs2/localalloc.c4
-rw-r--r--fs/ocfs2/localalloc.h2
-rw-r--r--fs/ocfs2/suballoc.c29
-rw-r--r--fs/ocfs2/suballoc.h11
5 files changed, 36 insertions, 14 deletions
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 7e34e66159c6..f3bc3658e7a5 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -491,8 +491,8 @@ int ocfs2_do_extend_allocation(struct ocfs2_super *osb,
491 goto leave; 491 goto leave;
492 } 492 }
493 493
494 status = ocfs2_claim_clusters(osb, handle, data_ac, 1, 494 status = __ocfs2_claim_clusters(osb, handle, data_ac, 1,
495 &bit_off, &num_bits); 495 clusters_to_add, &bit_off, &num_bits);
496 if (status < 0) { 496 if (status < 0) {
497 if (status != -ENOSPC) 497 if (status != -ENOSPC)
498 mlog_errno(status); 498 mlog_errno(status);
diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c
index 545f7892cdf3..de984d272576 100644
--- a/fs/ocfs2/localalloc.c
+++ b/fs/ocfs2/localalloc.c
@@ -524,13 +524,12 @@ bail:
524int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb, 524int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb,
525 handle_t *handle, 525 handle_t *handle,
526 struct ocfs2_alloc_context *ac, 526 struct ocfs2_alloc_context *ac,
527 u32 min_bits, 527 u32 bits_wanted,
528 u32 *bit_off, 528 u32 *bit_off,
529 u32 *num_bits) 529 u32 *num_bits)
530{ 530{
531 int status, start; 531 int status, start;
532 struct inode *local_alloc_inode; 532 struct inode *local_alloc_inode;
533 u32 bits_wanted;
534 void *bitmap; 533 void *bitmap;
535 struct ocfs2_dinode *alloc; 534 struct ocfs2_dinode *alloc;
536 struct ocfs2_local_alloc *la; 535 struct ocfs2_local_alloc *la;
@@ -538,7 +537,6 @@ int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb,
538 mlog_entry_void(); 537 mlog_entry_void();
539 BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL); 538 BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL);
540 539
541 bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given;
542 local_alloc_inode = ac->ac_inode; 540 local_alloc_inode = ac->ac_inode;
543 alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data; 541 alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data;
544 la = OCFS2_LOCAL_ALLOC(alloc); 542 la = OCFS2_LOCAL_ALLOC(alloc);
diff --git a/fs/ocfs2/localalloc.h b/fs/ocfs2/localalloc.h
index 385a10152f9c..3f76631e110c 100644
--- a/fs/ocfs2/localalloc.h
+++ b/fs/ocfs2/localalloc.h
@@ -48,7 +48,7 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
48int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb, 48int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb,
49 handle_t *handle, 49 handle_t *handle,
50 struct ocfs2_alloc_context *ac, 50 struct ocfs2_alloc_context *ac,
51 u32 min_bits, 51 u32 bits_wanted,
52 u32 *bit_off, 52 u32 *bit_off,
53 u32 *num_bits); 53 u32 *num_bits);
54 54
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
index d9c5c9fcb30f..8f09f5235e3a 100644
--- a/fs/ocfs2/suballoc.c
+++ b/fs/ocfs2/suballoc.c
@@ -1486,21 +1486,21 @@ static inline void ocfs2_block_to_cluster_group(struct inode *inode,
1486 * contig. allocation, set to '1' to indicate we can deal with extents 1486 * contig. allocation, set to '1' to indicate we can deal with extents
1487 * of any size. 1487 * of any size.
1488 */ 1488 */
1489int ocfs2_claim_clusters(struct ocfs2_super *osb, 1489int __ocfs2_claim_clusters(struct ocfs2_super *osb,
1490 handle_t *handle, 1490 handle_t *handle,
1491 struct ocfs2_alloc_context *ac, 1491 struct ocfs2_alloc_context *ac,
1492 u32 min_clusters, 1492 u32 min_clusters,
1493 u32 *cluster_start, 1493 u32 max_clusters,
1494 u32 *num_clusters) 1494 u32 *cluster_start,
1495 u32 *num_clusters)
1495{ 1496{
1496 int status; 1497 int status;
1497 unsigned int bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given; 1498 unsigned int bits_wanted = max_clusters;
1498 u64 bg_blkno = 0; 1499 u64 bg_blkno = 0;
1499 u16 bg_bit_off; 1500 u16 bg_bit_off;
1500 1501
1501 mlog_entry_void(); 1502 mlog_entry_void();
1502 1503
1503 BUG_ON(!ac);
1504 BUG_ON(ac->ac_bits_given >= ac->ac_bits_wanted); 1504 BUG_ON(ac->ac_bits_given >= ac->ac_bits_wanted);
1505 1505
1506 BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL 1506 BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL
@@ -1557,6 +1557,19 @@ bail:
1557 return status; 1557 return status;
1558} 1558}
1559 1559
1560int ocfs2_claim_clusters(struct ocfs2_super *osb,
1561 handle_t *handle,
1562 struct ocfs2_alloc_context *ac,
1563 u32 min_clusters,
1564 u32 *cluster_start,
1565 u32 *num_clusters)
1566{
1567 unsigned int bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given;
1568
1569 return __ocfs2_claim_clusters(osb, handle, ac, min_clusters,
1570 bits_wanted, cluster_start, num_clusters);
1571}
1572
1560static inline int ocfs2_block_group_clear_bits(handle_t *handle, 1573static inline int ocfs2_block_group_clear_bits(handle_t *handle,
1561 struct inode *alloc_inode, 1574 struct inode *alloc_inode,
1562 struct ocfs2_group_desc *bg, 1575 struct ocfs2_group_desc *bg,
diff --git a/fs/ocfs2/suballoc.h b/fs/ocfs2/suballoc.h
index f212dc01a84b..cafe93703095 100644
--- a/fs/ocfs2/suballoc.h
+++ b/fs/ocfs2/suballoc.h
@@ -85,6 +85,17 @@ int ocfs2_claim_clusters(struct ocfs2_super *osb,
85 u32 min_clusters, 85 u32 min_clusters,
86 u32 *cluster_start, 86 u32 *cluster_start,
87 u32 *num_clusters); 87 u32 *num_clusters);
88/*
89 * Use this variant of ocfs2_claim_clusters to specify a maxiumum
90 * number of clusters smaller than the allocation reserved.
91 */
92int __ocfs2_claim_clusters(struct ocfs2_super *osb,
93 handle_t *handle,
94 struct ocfs2_alloc_context *ac,
95 u32 min_clusters,
96 u32 max_clusters,
97 u32 *cluster_start,
98 u32 *num_clusters);
88 99
89int ocfs2_free_suballoc_bits(handle_t *handle, 100int ocfs2_free_suballoc_bits(handle_t *handle,
90 struct inode *alloc_inode, 101 struct inode *alloc_inode,