]> err.no Git - linux-2.6/blobdiff - fs/ext4/extents.c
reiserfs: convert j_commit_lock to mutex
[linux-2.6] / fs / ext4 / extents.c
index 7844bbb2bac0ed700d25ecf13267aa6696ef2af2..42c4c0c892ed9b442617207b00acbdc7be99249f 100644 (file)
@@ -248,6 +248,36 @@ static int ext4_ext_space_root_idx(struct inode *inode)
        return size;
 }
 
+/*
+ * Calculate the number of metadata blocks needed
+ * to allocate @blocks
+ * Worse case is one block per extent
+ */
+int ext4_ext_calc_metadata_amount(struct inode *inode, int blocks)
+{
+       int lcap, icap, rcap, leafs, idxs, num;
+       int newextents = blocks;
+
+       rcap = ext4_ext_space_root_idx(inode);
+       lcap = ext4_ext_space_block(inode);
+       icap = ext4_ext_space_block_idx(inode);
+
+       /* number of new leaf blocks needed */
+       num = leafs = (newextents + lcap - 1) / lcap;
+
+       /*
+        * Worse case, we need separate index block(s)
+        * to link all new leaf blocks
+        */
+       idxs = (leafs + icap - 1) / icap;
+       do {
+               num += idxs;
+               idxs = (idxs + icap - 1) / icap;
+       } while (idxs > rcap);
+
+       return num;
+}
+
 static int
 ext4_ext_max_entries(struct inode *inode, int depth)
 {
@@ -2535,6 +2565,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
        int err = 0, depth, ret;
        unsigned long allocated = 0;
        struct ext4_allocation_request ar;
+       loff_t disksize;
 
        __clear_bit(BH_New, &bh_result->b_state);
        ext_debug("blocks %u/%lu requested for inode %u\n",
@@ -2725,8 +2756,13 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
        newblock = ext_pblock(&newex);
        allocated = ext4_ext_get_actual_len(&newex);
 outnew:
-       if (extend_disksize && inode->i_size > EXT4_I(inode)->i_disksize)
-               EXT4_I(inode)->i_disksize = inode->i_size;
+       if (extend_disksize) {
+               disksize = ((loff_t) iblock + ar.len) << inode->i_blkbits;
+               if (disksize > i_size_read(inode))
+                       disksize = i_size_read(inode);
+               if (disksize > EXT4_I(inode)->i_disksize)
+                       EXT4_I(inode)->i_disksize = disksize;
+       }
 
        set_buffer_new(bh_result);
 
@@ -2910,7 +2946,7 @@ retry:
                }
                ret = ext4_get_blocks_wrap(handle, inode, block,
                                          max_blocks, &map_bh,
-                                         EXT4_CREATE_UNINITIALIZED_EXT, 0);
+                                         EXT4_CREATE_UNINITIALIZED_EXT, 0, 0);
                if (ret <= 0) {
 #ifdef EXT4FS_DEBUG
                        WARN_ON(ret <= 0);