]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/ocfs2/localalloc.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/agk/linux-2.6-dm
[linux-2.6-omap-h63xx.git] / fs / ocfs2 / localalloc.c
index b889f10d8090feaa597822f62365f85e24e12c02..687b28713c3253631b3588ceb41d90ca51cfa867 100644 (file)
@@ -76,8 +76,6 @@ static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb,
 
 #ifdef CONFIG_OCFS2_FS_STATS
 
-DEFINE_MUTEX(la_debug_mutex);
-
 static int ocfs2_la_debug_open(struct inode *inode, struct file *file)
 {
        file->private_data = inode->i_private;
@@ -89,6 +87,7 @@ static int ocfs2_la_debug_open(struct inode *inode, struct file *file)
 static ssize_t ocfs2_la_debug_read(struct file *file, char __user *userbuf,
                                   size_t count, loff_t *ppos)
 {
+       static DEFINE_MUTEX(la_debug_mutex);
        struct ocfs2_super *osb = file->private_data;
        int written, ret;
        char *buf = osb->local_alloc_debug_buf;
@@ -249,8 +248,8 @@ int ocfs2_load_local_alloc(struct ocfs2_super *osb)
                goto bail;
        }
 
-       status = ocfs2_read_block(osb, OCFS2_I(inode)->ip_blkno,
-                                 &alloc_bh, 0, inode);
+       status = ocfs2_read_blocks(inode, OCFS2_I(inode)->ip_blkno, 1,
+                                  &alloc_bh, OCFS2_BH_IGNORE_CACHE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -295,8 +294,7 @@ int ocfs2_load_local_alloc(struct ocfs2_super *osb)
 
 bail:
        if (status < 0)
-               if (alloc_bh)
-                       brelse(alloc_bh);
+               brelse(alloc_bh);
        if (inode)
                iput(inode);
 
@@ -412,8 +410,7 @@ out_commit:
        ocfs2_commit_trans(osb, handle);
 
 out_unlock:
-       if (main_bm_bh)
-               brelse(main_bm_bh);
+       brelse(main_bm_bh);
 
        ocfs2_inode_unlock(main_bm_inode, 1);
 
@@ -462,8 +459,8 @@ int ocfs2_begin_local_alloc_recovery(struct ocfs2_super *osb,
 
        mutex_lock(&inode->i_mutex);
 
-       status = ocfs2_read_block(osb, OCFS2_I(inode)->ip_blkno,
-                                 &alloc_bh, 0, inode);
+       status = ocfs2_read_blocks(inode, OCFS2_I(inode)->ip_blkno, 1,
+                                  &alloc_bh, OCFS2_BH_IGNORE_CACHE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -489,8 +486,7 @@ bail:
                *alloc_copy = NULL;
        }
 
-       if (alloc_bh)
-               brelse(alloc_bh);
+       brelse(alloc_bh);
 
        if (inode) {
                mutex_unlock(&inode->i_mutex);
@@ -558,8 +554,7 @@ out_unlock:
 out_mutex:
        mutex_unlock(&main_bm_inode->i_mutex);
 
-       if (main_bm_bh)
-               brelse(main_bm_bh);
+       brelse(main_bm_bh);
 
        iput(main_bm_inode);
 
@@ -570,6 +565,46 @@ out:
        return status;
 }
 
+/* Check to see if the local alloc window is within ac->ac_max_block */
+static int ocfs2_local_alloc_in_range(struct inode *inode,
+                                     struct ocfs2_alloc_context *ac,
+                                     u32 bits_wanted)
+{
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct ocfs2_dinode *alloc;
+       struct ocfs2_local_alloc *la;
+       int start;
+       u64 block_off;
+
+       if (!ac->ac_max_block)
+               return 1;
+
+       alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data;
+       la = OCFS2_LOCAL_ALLOC(alloc);
+
+       start = ocfs2_local_alloc_find_clear_bits(osb, alloc, bits_wanted);
+       if (start == -1) {
+               mlog_errno(-ENOSPC);
+               return 0;
+       }
+
+       /*
+        * Converting (bm_off + start + bits_wanted) to blocks gives us
+        * the blkno just past our actual allocation.  This is perfect
+        * to compare with ac_max_block.
+        */
+       block_off = ocfs2_clusters_to_blocks(inode->i_sb,
+                                            le32_to_cpu(la->la_bm_off) +
+                                            start + bits_wanted);
+       mlog(0, "Checking %llu against %llu\n",
+            (unsigned long long)block_off,
+            (unsigned long long)ac->ac_max_block);
+       if (block_off > ac->ac_max_block)
+               return 0;
+
+       return 1;
+}
+
 /*
  * make sure we've got at least bits_wanted contiguous bits in the
  * local alloc. You lose them when you drop i_mutex.
@@ -658,6 +693,21 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
                        goto bail;
        }
 
+       if (ac->ac_max_block)
+               mlog(0, "Calling in_range for max block %llu\n",
+                    (unsigned long long)ac->ac_max_block);
+
+       if (!ocfs2_local_alloc_in_range(local_alloc_inode, ac,
+                                       bits_wanted)) {
+               /*
+                * The window is outside ac->ac_max_block.
+                * This errno tells the caller to keep localalloc enabled
+                * but to get the allocation from the main bitmap.
+                */
+               status = -EFBIG;
+               goto bail;
+       }
+
        ac->ac_inode = local_alloc_inode;
        /* We should never use localalloc from another slot */
        ac->ac_alloc_slot = osb->slot_num;
@@ -1227,8 +1277,7 @@ bail:
        if (handle)
                ocfs2_commit_trans(osb, handle);
 
-       if (main_bm_bh)
-               brelse(main_bm_bh);
+       brelse(main_bm_bh);
 
        if (main_bm_inode)
                iput(main_bm_inode);