diff options
author | Christoph Hellwig <hch@lst.de> | 2009-12-15 19:47:50 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-16 10:20:13 -0500 |
commit | 5fe878ae7f82fbf0830dbfaee4c5ca18f3aee442 (patch) | |
tree | 7e7ad290cfb30705948d8ebeb46b013afa913f42 /fs/ocfs2/aops.c | |
parent | 23aee091d804efa8cc732a31c1ae5d625e1ec886 (diff) |
direct-io: cleanup blockdev_direct_IO locking
Currently the locking in blockdev_direct_IO is a mess, we have three
different locking types and very confusing checks for some of them. The
most complicated one is DIO_OWN_LOCKING for reads, which happens to not
actually be used.
This patch gets rid of the DIO_OWN_LOCKING - as mentioned above the read
case is unused anyway, and the write side is almost identical to
DIO_NO_LOCKING. The difference is that DIO_NO_LOCKING always sets the
create argument for the get_blocks callback to zero, but we can easily
move that to the actual get_blocks callbacks. There are four users of the
DIO_NO_LOCKING mode: gfs already ignores the create argument and thus is
fine with the new version, ocfs2 only errors out if create were ever set,
and we can remove this dead code now, the block device code only ever uses
create for an error message if we are fully beyond the device which can
never happen, and last but not least XFS will need the new behavour for
writes.
Now we can replace the lock_type variable with a flags one, where no flag
means the DIO_NO_LOCKING behaviour and DIO_LOCKING is kept as the first
flag. Separate out the check for not allowing to fill holes into a
separate flag, although for now both flags always get set at the same
time.
Also revamp the documentation of the locking scheme to actually make
sense.
[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: Christoph Hellwig <hch@lst.de>
Cc: Dave Chinner <david@fromorbit.com>
Cc: Badari Pulavarty <pbadari@us.ibm.com>
Cc: Jeff Moyer <jmoyer@redhat.com>
Cc: Jens Axboe <jens.axboe@oracle.com>
Cc: Zach Brown <zach.brown@oracle.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Alex Elder <aelder@sgi.com>
Cc: Mark Fasheh <mfasheh@suse.com>
Cc: Joel Becker <joel.becker@oracle.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/ocfs2/aops.c')
-rw-r--r-- | fs/ocfs2/aops.c | 34 |
1 files changed, 4 insertions, 30 deletions
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index deb2b132ae5e..3dae4a13f6e4 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -547,6 +547,9 @@ bail: | |||
547 | * | 547 | * |
548 | * called like this: dio->get_blocks(dio->inode, fs_startblk, | 548 | * called like this: dio->get_blocks(dio->inode, fs_startblk, |
549 | * fs_count, map_bh, dio->rw == WRITE); | 549 | * fs_count, map_bh, dio->rw == WRITE); |
550 | * | ||
551 | * Note that we never bother to allocate blocks here, and thus ignore the | ||
552 | * create argument. | ||
550 | */ | 553 | */ |
551 | static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock, | 554 | static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock, |
552 | struct buffer_head *bh_result, int create) | 555 | struct buffer_head *bh_result, int create) |
@@ -563,14 +566,6 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock, | |||
563 | 566 | ||
564 | inode_blocks = ocfs2_blocks_for_bytes(inode->i_sb, i_size_read(inode)); | 567 | inode_blocks = ocfs2_blocks_for_bytes(inode->i_sb, i_size_read(inode)); |
565 | 568 | ||
566 | /* | ||
567 | * Any write past EOF is not allowed because we'd be extending. | ||
568 | */ | ||
569 | if (create && (iblock + max_blocks) > inode_blocks) { | ||
570 | ret = -EIO; | ||
571 | goto bail; | ||
572 | } | ||
573 | |||
574 | /* This figures out the size of the next contiguous block, and | 569 | /* This figures out the size of the next contiguous block, and |
575 | * our logical offset */ | 570 | * our logical offset */ |
576 | ret = ocfs2_extent_map_get_blocks(inode, iblock, &p_blkno, | 571 | ret = ocfs2_extent_map_get_blocks(inode, iblock, &p_blkno, |
@@ -582,15 +577,6 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock, | |||
582 | goto bail; | 577 | goto bail; |
583 | } | 578 | } |
584 | 579 | ||
585 | if (!ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb)) && !p_blkno && create) { | ||
586 | ocfs2_error(inode->i_sb, | ||
587 | "Inode %llu has a hole at block %llu\n", | ||
588 | (unsigned long long)OCFS2_I(inode)->ip_blkno, | ||
589 | (unsigned long long)iblock); | ||
590 | ret = -EROFS; | ||
591 | goto bail; | ||
592 | } | ||
593 | |||
594 | /* We should already CoW the refcounted extent. */ | 580 | /* We should already CoW the refcounted extent. */ |
595 | BUG_ON(ext_flags & OCFS2_EXT_REFCOUNTED); | 581 | BUG_ON(ext_flags & OCFS2_EXT_REFCOUNTED); |
596 | /* | 582 | /* |
@@ -601,20 +587,8 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock, | |||
601 | */ | 587 | */ |
602 | if (p_blkno && !(ext_flags & OCFS2_EXT_UNWRITTEN)) | 588 | if (p_blkno && !(ext_flags & OCFS2_EXT_UNWRITTEN)) |
603 | map_bh(bh_result, inode->i_sb, p_blkno); | 589 | map_bh(bh_result, inode->i_sb, p_blkno); |
604 | else { | 590 | else |
605 | /* | ||
606 | * ocfs2_prepare_inode_for_write() should have caught | ||
607 | * the case where we'd be filling a hole and triggered | ||
608 | * a buffered write instead. | ||
609 | */ | ||
610 | if (create) { | ||
611 | ret = -EIO; | ||
612 | mlog_errno(ret); | ||
613 | goto bail; | ||
614 | } | ||
615 | |||
616 | clear_buffer_mapped(bh_result); | 591 | clear_buffer_mapped(bh_result); |
617 | } | ||
618 | 592 | ||
619 | /* make sure we don't map more than max_blocks blocks here as | 593 | /* make sure we don't map more than max_blocks blocks here as |
620 | that's all the kernel will handle at this point. */ | 594 | that's all the kernel will handle at this point. */ |