diff options
Diffstat (limited to 'fs/nfs/direct.c')
-rw-r--r-- | fs/nfs/direct.c | 32 |
1 files changed, 26 insertions, 6 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 1ba385b7c90d..cae26cbd59ee 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <linux/kref.h> | 46 | #include <linux/kref.h> |
47 | #include <linux/slab.h> | 47 | #include <linux/slab.h> |
48 | #include <linux/task_io_accounting_ops.h> | 48 | #include <linux/task_io_accounting_ops.h> |
49 | #include <linux/module.h> | ||
49 | 50 | ||
50 | #include <linux/nfs_fs.h> | 51 | #include <linux/nfs_fs.h> |
51 | #include <linux/nfs_page.h> | 52 | #include <linux/nfs_page.h> |
@@ -78,6 +79,7 @@ struct nfs_direct_req { | |||
78 | atomic_t io_count; /* i/os we're waiting for */ | 79 | atomic_t io_count; /* i/os we're waiting for */ |
79 | spinlock_t lock; /* protect completion state */ | 80 | spinlock_t lock; /* protect completion state */ |
80 | ssize_t count, /* bytes actually processed */ | 81 | ssize_t count, /* bytes actually processed */ |
82 | bytes_left, /* bytes left to be sent */ | ||
81 | error; /* any reported error */ | 83 | error; /* any reported error */ |
82 | struct completion completion; /* wait for i/o completion */ | 84 | struct completion completion; /* wait for i/o completion */ |
83 | 85 | ||
@@ -190,6 +192,12 @@ static void nfs_direct_req_release(struct nfs_direct_req *dreq) | |||
190 | kref_put(&dreq->kref, nfs_direct_req_free); | 192 | kref_put(&dreq->kref, nfs_direct_req_free); |
191 | } | 193 | } |
192 | 194 | ||
195 | ssize_t nfs_dreq_bytes_left(struct nfs_direct_req *dreq) | ||
196 | { | ||
197 | return dreq->bytes_left; | ||
198 | } | ||
199 | EXPORT_SYMBOL_GPL(nfs_dreq_bytes_left); | ||
200 | |||
193 | /* | 201 | /* |
194 | * Collects and returns the final error value/byte-count. | 202 | * Collects and returns the final error value/byte-count. |
195 | */ | 203 | */ |
@@ -390,6 +398,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_pageio_descriptor *de | |||
390 | user_addr += req_len; | 398 | user_addr += req_len; |
391 | pos += req_len; | 399 | pos += req_len; |
392 | count -= req_len; | 400 | count -= req_len; |
401 | dreq->bytes_left -= req_len; | ||
393 | } | 402 | } |
394 | /* The nfs_page now hold references to these pages */ | 403 | /* The nfs_page now hold references to these pages */ |
395 | nfs_direct_release_pages(pagevec, npages); | 404 | nfs_direct_release_pages(pagevec, npages); |
@@ -450,23 +459,28 @@ static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov, | |||
450 | ssize_t result = -ENOMEM; | 459 | ssize_t result = -ENOMEM; |
451 | struct inode *inode = iocb->ki_filp->f_mapping->host; | 460 | struct inode *inode = iocb->ki_filp->f_mapping->host; |
452 | struct nfs_direct_req *dreq; | 461 | struct nfs_direct_req *dreq; |
462 | struct nfs_lock_context *l_ctx; | ||
453 | 463 | ||
454 | dreq = nfs_direct_req_alloc(); | 464 | dreq = nfs_direct_req_alloc(); |
455 | if (dreq == NULL) | 465 | if (dreq == NULL) |
456 | goto out; | 466 | goto out; |
457 | 467 | ||
458 | dreq->inode = inode; | 468 | dreq->inode = inode; |
469 | dreq->bytes_left = iov_length(iov, nr_segs); | ||
459 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); | 470 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); |
460 | dreq->l_ctx = nfs_get_lock_context(dreq->ctx); | 471 | l_ctx = nfs_get_lock_context(dreq->ctx); |
461 | if (dreq->l_ctx == NULL) | 472 | if (IS_ERR(l_ctx)) { |
473 | result = PTR_ERR(l_ctx); | ||
462 | goto out_release; | 474 | goto out_release; |
475 | } | ||
476 | dreq->l_ctx = l_ctx; | ||
463 | if (!is_sync_kiocb(iocb)) | 477 | if (!is_sync_kiocb(iocb)) |
464 | dreq->iocb = iocb; | 478 | dreq->iocb = iocb; |
465 | 479 | ||
480 | NFS_I(inode)->read_io += iov_length(iov, nr_segs); | ||
466 | result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos, uio); | 481 | result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos, uio); |
467 | if (!result) | 482 | if (!result) |
468 | result = nfs_direct_wait(dreq); | 483 | result = nfs_direct_wait(dreq); |
469 | NFS_I(inode)->read_io += result; | ||
470 | out_release: | 484 | out_release: |
471 | nfs_direct_req_release(dreq); | 485 | nfs_direct_req_release(dreq); |
472 | out: | 486 | out: |
@@ -706,6 +720,7 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_pageio_descriptor *d | |||
706 | user_addr += req_len; | 720 | user_addr += req_len; |
707 | pos += req_len; | 721 | pos += req_len; |
708 | count -= req_len; | 722 | count -= req_len; |
723 | dreq->bytes_left -= req_len; | ||
709 | } | 724 | } |
710 | /* The nfs_page now hold references to these pages */ | 725 | /* The nfs_page now hold references to these pages */ |
711 | nfs_direct_release_pages(pagevec, npages); | 726 | nfs_direct_release_pages(pagevec, npages); |
@@ -814,6 +829,7 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, | |||
814 | get_dreq(dreq); | 829 | get_dreq(dreq); |
815 | atomic_inc(&inode->i_dio_count); | 830 | atomic_inc(&inode->i_dio_count); |
816 | 831 | ||
832 | NFS_I(dreq->inode)->write_io += iov_length(iov, nr_segs); | ||
817 | for (seg = 0; seg < nr_segs; seg++) { | 833 | for (seg = 0; seg < nr_segs; seg++) { |
818 | const struct iovec *vec = &iov[seg]; | 834 | const struct iovec *vec = &iov[seg]; |
819 | result = nfs_direct_write_schedule_segment(&desc, vec, pos, uio); | 835 | result = nfs_direct_write_schedule_segment(&desc, vec, pos, uio); |
@@ -825,7 +841,6 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, | |||
825 | pos += vec->iov_len; | 841 | pos += vec->iov_len; |
826 | } | 842 | } |
827 | nfs_pageio_complete(&desc); | 843 | nfs_pageio_complete(&desc); |
828 | NFS_I(dreq->inode)->write_io += desc.pg_bytes_written; | ||
829 | 844 | ||
830 | /* | 845 | /* |
831 | * If no bytes were started, return the error, and let the | 846 | * If no bytes were started, return the error, and let the |
@@ -849,16 +864,21 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
849 | ssize_t result = -ENOMEM; | 864 | ssize_t result = -ENOMEM; |
850 | struct inode *inode = iocb->ki_filp->f_mapping->host; | 865 | struct inode *inode = iocb->ki_filp->f_mapping->host; |
851 | struct nfs_direct_req *dreq; | 866 | struct nfs_direct_req *dreq; |
867 | struct nfs_lock_context *l_ctx; | ||
852 | 868 | ||
853 | dreq = nfs_direct_req_alloc(); | 869 | dreq = nfs_direct_req_alloc(); |
854 | if (!dreq) | 870 | if (!dreq) |
855 | goto out; | 871 | goto out; |
856 | 872 | ||
857 | dreq->inode = inode; | 873 | dreq->inode = inode; |
874 | dreq->bytes_left = count; | ||
858 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); | 875 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); |
859 | dreq->l_ctx = nfs_get_lock_context(dreq->ctx); | 876 | l_ctx = nfs_get_lock_context(dreq->ctx); |
860 | if (dreq->l_ctx == NULL) | 877 | if (IS_ERR(l_ctx)) { |
878 | result = PTR_ERR(l_ctx); | ||
861 | goto out_release; | 879 | goto out_release; |
880 | } | ||
881 | dreq->l_ctx = l_ctx; | ||
862 | if (!is_sync_kiocb(iocb)) | 882 | if (!is_sync_kiocb(iocb)) |
863 | dreq->iocb = iocb; | 883 | dreq->iocb = iocb; |
864 | 884 | ||