ocfs2: allocate blocks in ocfs2_direct_IO_get_blocks
authorJoseph Qi <joseph.qi@huawei.com>
Tue, 17 Feb 2015 00:00:03 +0000 (16:00 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 17 Feb 2015 01:56:05 +0000 (17:56 -0800)
Allow blocks allocation in ocfs2_direct_IO_get_blocks.

Signed-off-by: Joseph Qi <joseph.qi@huawei.com>
Cc: Weiwei Wang <wangww631@huawei.com>
Cc: Junxiao Bi <junxiao.bi@oracle.com>
Cc: Joel Becker <jlbec@evilplan.org>
Cc: Mark Fasheh <mfasheh@suse.com>
Cc: Xuejiufei <xuejiufei@huawei.com>
Cc: alex chen <alex.chen@huawei.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
fs/ocfs2/aops.c

index be5986b7e5c6afbd91893abbbcf91355544d278e..44db1808cdb598df6b91548410b3634480c06c31 100644 (file)
@@ -510,18 +510,21 @@ bail:
  *
  * called like this: dio->get_blocks(dio->inode, fs_startblk,
  *                                     fs_count, map_bh, dio->rw == WRITE);
- *
- * Note that we never bother to allocate blocks here, and thus ignore the
- * create argument.
  */
 static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock,
                                     struct buffer_head *bh_result, int create)
 {
        int ret;
+       u32 cpos = 0;
+       int alloc_locked = 0;
        u64 p_blkno, inode_blocks, contig_blocks;
        unsigned int ext_flags;
        unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
        unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits;
+       unsigned long len = bh_result->b_size;
+       unsigned int clusters_to_alloc = 0;
+
+       cpos = ocfs2_blocks_to_clusters(inode->i_sb, iblock);
 
        /* This function won't even be called if the request isn't all
         * nicely aligned and of the right size, so there's no need
@@ -543,6 +546,40 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock,
        /* We should already CoW the refcounted extent in case of create. */
        BUG_ON(create && (ext_flags & OCFS2_EXT_REFCOUNTED));
 
+       /* allocate blocks if no p_blkno is found, and create == 1 */
+       if (!p_blkno && create) {
+               ret = ocfs2_inode_lock(inode, NULL, 1);
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       goto bail;
+               }
+
+               alloc_locked = 1;
+
+               /* fill hole, allocate blocks can't be larger than the size
+                * of the hole */
+               clusters_to_alloc = ocfs2_clusters_for_bytes(inode->i_sb, len);
+               if (clusters_to_alloc > contig_blocks)
+                       clusters_to_alloc = contig_blocks;
+
+               /* allocate extent and insert them into the extent tree */
+               ret = ocfs2_extend_allocation(inode, cpos,
+                               clusters_to_alloc, 0);
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       goto bail;
+               }
+
+               ret = ocfs2_extent_map_get_blocks(inode, iblock, &p_blkno,
+                               &contig_blocks, &ext_flags);
+               if (ret < 0) {
+                       mlog(ML_ERROR, "get_blocks() failed iblock=%llu\n",
+                                       (unsigned long long)iblock);
+                       ret = -EIO;
+                       goto bail;
+               }
+       }
+
        /*
         * get_more_blocks() expects us to describe a hole by clearing
         * the mapped bit on bh_result().
@@ -560,6 +597,8 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock,
                contig_blocks = max_blocks;
        bh_result->b_size = contig_blocks << blocksize_bits;
 bail:
+       if (alloc_locked)
+               ocfs2_inode_unlock(inode, 1);
        return ret;
 }