Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 44005
b: refs/heads/master
c: 6d544bb
h: refs/heads/master
i:
  44003: c640df3
v: v3
  • Loading branch information
Zach Brown authored and Linus Torvalds committed Dec 10, 2006
1 parent 0cffd4f commit 81d2b60
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 53 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1757128438d41670ded8bc3bc735325cc07dc8f9
refs/heads/master: 6d544bb4d9019c3a0d7ee4af1e4bbbd61a6e16dc
94 changes: 42 additions & 52 deletions trunk/fs/direct-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,19 +210,46 @@ static struct page *dio_get_page(struct dio *dio)
return dio->pages[dio->head++];
}

/*
* Called when all DIO BIO I/O has been completed - let the filesystem
* know, if it registered an interest earlier via get_block. Pass the
* private field of the map buffer_head so that filesystems can use it
* to hold additional state between get_block calls and dio_complete.
/**
* dio_complete() - called when all DIO BIO I/O has been completed
* @offset: the byte offset in the file of the completed operation
*
* This releases locks as dictated by the locking type, lets interested parties
* know that a DIO operation has completed, and calculates the resulting return
* code for the operation.
*
* It lets the filesystem know if it registered an interest earlier via
* get_block. Pass the private field of the map buffer_head so that
* filesystems can use it to hold additional state between get_block calls and
* dio_complete.
*/
static void dio_complete(struct dio *dio, loff_t offset, ssize_t bytes)
static int dio_complete(struct dio *dio, loff_t offset, int ret)
{
ssize_t transferred = 0;

if (dio->result) {
transferred = dio->result;

/* Check for short read case */
if ((dio->rw == READ) && ((offset + transferred) > dio->i_size))
transferred = dio->i_size - offset;
}

if (dio->end_io && dio->result)
dio->end_io(dio->iocb, offset, bytes, dio->map_bh.b_private);
dio->end_io(dio->iocb, offset, transferred,
dio->map_bh.b_private);
if (dio->lock_type == DIO_LOCKING)
/* lockdep: non-owner release */
up_read_non_owner(&dio->inode->i_alloc_sem);

if (ret == 0)
ret = dio->page_errors;
if (ret == 0)
ret = dio->io_error;
if (ret == 0)
ret = transferred;

return ret;
}

/*
Expand All @@ -236,33 +263,20 @@ static void finished_one_bio(struct dio *dio)
spin_lock_irqsave(&dio->bio_lock, flags);
if (dio->bio_count == 1) {
if (dio->is_async) {
ssize_t transferred;
loff_t offset;
int ret;

/*
* Last reference to the dio is going away.
* Drop spinlock and complete the DIO.
*/
spin_unlock_irqrestore(&dio->bio_lock, flags);

/* Check for short read case */
transferred = dio->result;
offset = dio->iocb->ki_pos;

if ((dio->rw == READ) &&
((offset + transferred) > dio->i_size))
transferred = dio->i_size - offset;

/* check for error in completion path */
if (dio->io_error)
transferred = dio->io_error;

dio_complete(dio, offset, transferred);
ret = dio_complete(dio, dio->iocb->ki_pos, 0);

/* Complete AIO later if falling back to buffered i/o */
if (dio->result == dio->size ||
((dio->rw == READ) && dio->result)) {
aio_complete(dio->iocb, transferred, 0);
aio_complete(dio->iocb, ret, 0);
kfree(dio);
return;
} else {
Expand Down Expand Up @@ -434,10 +448,8 @@ static int dio_bio_complete(struct dio *dio, struct bio *bio)
/*
* Wait on and process all in-flight BIOs.
*/
static int dio_await_completion(struct dio *dio)
static void dio_await_completion(struct dio *dio)
{
int ret = 0;

if (dio->bio)
dio_bio_submit(dio);

Expand All @@ -448,13 +460,9 @@ static int dio_await_completion(struct dio *dio)
*/
while (dio->bio_count) {
struct bio *bio = dio_await_one(dio);
int ret2;

ret2 = dio_bio_complete(dio, bio);
if (ret == 0)
ret = ret2;
/* io errors are propogated through dio->io_error */
dio_bio_complete(dio, bio);
}
return ret;
}

/*
Expand Down Expand Up @@ -1127,28 +1135,10 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
kfree(dio);
}
} else {
ssize_t transferred = 0;

finished_one_bio(dio);
ret2 = dio_await_completion(dio);
if (ret == 0)
ret = ret2;
if (ret == 0)
ret = dio->page_errors;
if (dio->result) {
loff_t i_size = i_size_read(inode);
dio_await_completion(dio);

transferred = dio->result;
/*
* Adjust the return value if the read crossed a
* non-block-aligned EOF.
*/
if (rw == READ && (offset + transferred > i_size))
transferred = i_size - offset;
}
dio_complete(dio, offset, transferred);
if (ret == 0)
ret = transferred;
ret = dio_complete(dio, offset, ret);

/* We could have also come here on an AIO file extend */
if (!is_sync_kiocb(iocb) && (rw & WRITE) &&
Expand Down

0 comments on commit 81d2b60

Please sign in to comment.