diff options
author | Joseph Qi <joseph.qi@huawei.com> | 2015-02-16 19:00:03 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-16 20:56:05 -0500 |
commit | 49255dce65dba3d06a0f642fee788f0a50d48d5b (patch) | |
tree | e44f7b0b437ef98a359c9d21b63f3175232beef7 /fs/ocfs2 | |
parent | 24c40b329e03dd38a1ca2225c739db67f4441343 (diff) |
ocfs2: allocate blocks in ocfs2_direct_IO_get_blocks
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>
Diffstat (limited to 'fs/ocfs2')
-rw-r--r-- | fs/ocfs2/aops.c | 45 |
1 files changed, 42 insertions, 3 deletions
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index be5986b7e5c6..44db1808cdb5 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -510,18 +510,21 @@ bail: | |||
510 | * | 510 | * |
511 | * called like this: dio->get_blocks(dio->inode, fs_startblk, | 511 | * called like this: dio->get_blocks(dio->inode, fs_startblk, |
512 | * fs_count, map_bh, dio->rw == WRITE); | 512 | * fs_count, map_bh, dio->rw == WRITE); |
513 | * | ||
514 | * Note that we never bother to allocate blocks here, and thus ignore the | ||
515 | * create argument. | ||
516 | */ | 513 | */ |
517 | static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock, | 514 | static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock, |
518 | struct buffer_head *bh_result, int create) | 515 | struct buffer_head *bh_result, int create) |
519 | { | 516 | { |
520 | int ret; | 517 | int ret; |
518 | u32 cpos = 0; | ||
519 | int alloc_locked = 0; | ||
521 | u64 p_blkno, inode_blocks, contig_blocks; | 520 | u64 p_blkno, inode_blocks, contig_blocks; |
522 | unsigned int ext_flags; | 521 | unsigned int ext_flags; |
523 | unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits; | 522 | unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits; |
524 | unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits; | 523 | unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits; |
524 | unsigned long len = bh_result->b_size; | ||
525 | unsigned int clusters_to_alloc = 0; | ||
526 | |||
527 | cpos = ocfs2_blocks_to_clusters(inode->i_sb, iblock); | ||
525 | 528 | ||
526 | /* This function won't even be called if the request isn't all | 529 | /* This function won't even be called if the request isn't all |
527 | * nicely aligned and of the right size, so there's no need | 530 | * 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, | |||
543 | /* We should already CoW the refcounted extent in case of create. */ | 546 | /* We should already CoW the refcounted extent in case of create. */ |
544 | BUG_ON(create && (ext_flags & OCFS2_EXT_REFCOUNTED)); | 547 | BUG_ON(create && (ext_flags & OCFS2_EXT_REFCOUNTED)); |
545 | 548 | ||
549 | /* allocate blocks if no p_blkno is found, and create == 1 */ | ||
550 | if (!p_blkno && create) { | ||
551 | ret = ocfs2_inode_lock(inode, NULL, 1); | ||
552 | if (ret < 0) { | ||
553 | mlog_errno(ret); | ||
554 | goto bail; | ||
555 | } | ||
556 | |||
557 | alloc_locked = 1; | ||
558 | |||
559 | /* fill hole, allocate blocks can't be larger than the size | ||
560 | * of the hole */ | ||
561 | clusters_to_alloc = ocfs2_clusters_for_bytes(inode->i_sb, len); | ||
562 | if (clusters_to_alloc > contig_blocks) | ||
563 | clusters_to_alloc = contig_blocks; | ||
564 | |||
565 | /* allocate extent and insert them into the extent tree */ | ||
566 | ret = ocfs2_extend_allocation(inode, cpos, | ||
567 | clusters_to_alloc, 0); | ||
568 | if (ret < 0) { | ||
569 | mlog_errno(ret); | ||
570 | goto bail; | ||
571 | } | ||
572 | |||
573 | ret = ocfs2_extent_map_get_blocks(inode, iblock, &p_blkno, | ||
574 | &contig_blocks, &ext_flags); | ||
575 | if (ret < 0) { | ||
576 | mlog(ML_ERROR, "get_blocks() failed iblock=%llu\n", | ||
577 | (unsigned long long)iblock); | ||
578 | ret = -EIO; | ||
579 | goto bail; | ||
580 | } | ||
581 | } | ||
582 | |||
546 | /* | 583 | /* |
547 | * get_more_blocks() expects us to describe a hole by clearing | 584 | * get_more_blocks() expects us to describe a hole by clearing |
548 | * the mapped bit on bh_result(). | 585 | * the mapped bit on bh_result(). |
@@ -560,6 +597,8 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock, | |||
560 | contig_blocks = max_blocks; | 597 | contig_blocks = max_blocks; |
561 | bh_result->b_size = contig_blocks << blocksize_bits; | 598 | bh_result->b_size = contig_blocks << blocksize_bits; |
562 | bail: | 599 | bail: |
600 | if (alloc_locked) | ||
601 | ocfs2_inode_unlock(inode, 1); | ||
563 | return ret; | 602 | return ret; |
564 | } | 603 | } |
565 | 604 | ||