Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=415cb800375cc4e89fb5a6a454e484bd4adbffb4
Commit:     415cb800375cc4e89fb5a6a454e484bd4adbffb4
Parent:     6d0b842d3bf0cc027dcff57a89fb8a6b1fd610e1
Author:     Mark Fasheh <[EMAIL PROTECTED]>
AuthorDate: Sun Sep 16 20:10:16 2007 -0700
Committer:  Mark Fasheh <[EMAIL PROTECTED]>
CommitDate: Thu Sep 20 15:06:09 2007 -0700

    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 <[EMAIL PROTECTED]>
---
 fs/ocfs2/file.c       |    4 ++--
 fs/ocfs2/localalloc.c |    4 +---
 fs/ocfs2/localalloc.h |    2 +-
 fs/ocfs2/suballoc.c   |   29 +++++++++++++++++++++--------
 fs/ocfs2/suballoc.h   |   11 +++++++++++
 5 files changed, 36 insertions(+), 14 deletions(-)

diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 7e34e66..f3bc365 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -491,8 +491,8 @@ int ocfs2_do_extend_allocation(struct ocfs2_super *osb,
                goto leave;
        }
 
-       status = ocfs2_claim_clusters(osb, handle, data_ac, 1,
-                                     &bit_off, &num_bits);
+       status = __ocfs2_claim_clusters(osb, handle, data_ac, 1,
+                                       clusters_to_add, &bit_off, &num_bits);
        if (status < 0) {
                if (status != -ENOSPC)
                        mlog_errno(status);
diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c
index 545f789..de984d2 100644
--- a/fs/ocfs2/localalloc.c
+++ b/fs/ocfs2/localalloc.c
@@ -524,13 +524,12 @@ bail:
 int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb,
                                 handle_t *handle,
                                 struct ocfs2_alloc_context *ac,
-                                u32 min_bits,
+                                u32 bits_wanted,
                                 u32 *bit_off,
                                 u32 *num_bits)
 {
        int status, start;
        struct inode *local_alloc_inode;
-       u32 bits_wanted;
        void *bitmap;
        struct ocfs2_dinode *alloc;
        struct ocfs2_local_alloc *la;
@@ -538,7 +537,6 @@ int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb,
        mlog_entry_void();
        BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL);
 
-       bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given;
        local_alloc_inode = ac->ac_inode;
        alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data;
        la = OCFS2_LOCAL_ALLOC(alloc);
diff --git a/fs/ocfs2/localalloc.h b/fs/ocfs2/localalloc.h
index 385a101..3f76631 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,
 int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb,
                                 handle_t *handle,
                                 struct ocfs2_alloc_context *ac,
-                                u32 min_bits,
+                                u32 bits_wanted,
                                 u32 *bit_off,
                                 u32 *num_bits);
 
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
index d9c5c9f..8f09f52 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,
  * contig. allocation, set to '1' to indicate we can deal with extents
  * of any size.
  */
-int ocfs2_claim_clusters(struct ocfs2_super *osb,
-                        handle_t *handle,
-                        struct ocfs2_alloc_context *ac,
-                        u32 min_clusters,
-                        u32 *cluster_start,
-                        u32 *num_clusters)
+int __ocfs2_claim_clusters(struct ocfs2_super *osb,
+                          handle_t *handle,
+                          struct ocfs2_alloc_context *ac,
+                          u32 min_clusters,
+                          u32 max_clusters,
+                          u32 *cluster_start,
+                          u32 *num_clusters)
 {
        int status;
-       unsigned int bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given;
+       unsigned int bits_wanted = max_clusters;
        u64 bg_blkno = 0;
        u16 bg_bit_off;
 
        mlog_entry_void();
 
-       BUG_ON(!ac);
        BUG_ON(ac->ac_bits_given >= ac->ac_bits_wanted);
 
        BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL
@@ -1557,6 +1557,19 @@ bail:
        return status;
 }
 
+int ocfs2_claim_clusters(struct ocfs2_super *osb,
+                        handle_t *handle,
+                        struct ocfs2_alloc_context *ac,
+                        u32 min_clusters,
+                        u32 *cluster_start,
+                        u32 *num_clusters)
+{
+       unsigned int bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given;
+
+       return __ocfs2_claim_clusters(osb, handle, ac, min_clusters,
+                                     bits_wanted, cluster_start, num_clusters);
+}
+
 static inline int ocfs2_block_group_clear_bits(handle_t *handle,
                                               struct inode *alloc_inode,
                                               struct ocfs2_group_desc *bg,
diff --git a/fs/ocfs2/suballoc.h b/fs/ocfs2/suballoc.h
index f212dc0..cafe937 100644
--- a/fs/ocfs2/suballoc.h
+++ b/fs/ocfs2/suballoc.h
@@ -85,6 +85,17 @@ int ocfs2_claim_clusters(struct ocfs2_super *osb,
                         u32 min_clusters,
                         u32 *cluster_start,
                         u32 *num_clusters);
+/*
+ * Use this variant of ocfs2_claim_clusters to specify a maxiumum
+ * number of clusters smaller than the allocation reserved.
+ */
+int __ocfs2_claim_clusters(struct ocfs2_super *osb,
+                          handle_t *handle,
+                          struct ocfs2_alloc_context *ac,
+                          u32 min_clusters,
+                          u32 max_clusters,
+                          u32 *cluster_start,
+                          u32 *num_clusters);
 
 int ocfs2_free_suballoc_bits(handle_t *handle,
                             struct inode *alloc_inode,
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to