NFS: track direct IO left bytes
Subsystems (2)
PATCH v3 1/3 NFS: track direct IO left bytes
Signed-off-by Peng Tao <[email protected]>
--- fs/nfs/direct.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)
fs/nfs/direct.c +5 -0
@@ -78,6 +78,7 @@ struct nfs_direct_req {atomic_t io_count;/* i/os we're waiting for */ spinlock_t lock;/* protect completion state */ ssize_t count,/* bytes actually processed */ + bytes_left,/* bytes left to be sent */ error;/* any reported error */ struct completion completion;/* wait for i/o completion */
@@ -390,6 +391,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_pageio_descriptor *de user_addr += req_len; pos += req_len; count -= req_len; + dreq->bytes_left -= req_len; }/* The nfs_page now hold references to these pages */ nfs_direct_release_pages (pagevec, npages);
@@ -456,6 +458,7 @@ static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov, goto out; dreq->inode = inode; + dreq->bytes_left =iov_length (iov, nr_segs); dreq->ctx =get_nfs_open_context (nfs_file_open_context (iocb->ki_filp)); dreq->l_ctx =nfs_get_lock_context (dreq->ctx);if (dreq->l_ctx ==NULL )
@@ -706,6 +709,7 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_pageio_descriptor *d user_addr += req_len; pos += req_len; count -= req_len; + dreq->bytes_left -= req_len; }/* The nfs_page now hold references to these pages */ nfs_direct_release_pages (pagevec, npages);
@@ -855,6 +859,7 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, goto out; dreq->inode = inode; + dreq->bytes_left = count; dreq->ctx =get_nfs_open_context (nfs_file_open_context (iocb->ki_filp)); dreq->l_ctx =nfs_get_lock_context (dreq->ctx);if (dreq->l_ctx ==NULL )
Signature · 1 line
1.7.1.262.g5ef3d
PATCH v3 2/3 NFS41: send real write size in layoutget
For buffer write, block layout client scan inode mapping to find next hole and use offset-to-hole as layoutget length. Object layout client uses offset-to-isize as layoutget length.
For direct write, both block layout and object layout use dreq->bytes_left.
Signed-off-by Peng Tao <[email protected]>
--- fs/nfs/blocklayout/blocklayout.c | 38 +++++++++++++++++++++++++++++++++++--- fs/nfs/direct.c | 7 +++++++ fs/nfs/internal.h | 1 + fs/nfs/objlayout/objio_osd.c | 9 ++++++++- fs/nfs/pnfs.c | 6 ++++-- fs/nfs/pnfs.h | 3 ++- 6 files changed, 57 insertions(+), 7 deletions(-)
fs/nfs/blocklayout/blocklayout.c +35 -3
@@ -37,6 +37,7 @@#include <linux/bio.h> /* struct bio */ #include <linux/buffer_head.h> /* various write calls */ #include <linux/prefetch.h> +#include <linux/pagevec.h> #include "../pnfs.h" #include "../internal.h"
@@ -1204,14 +1205,45 @@ bl_pg_test_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,return pnfs_generic_pg_test (pgio, prev, req); } +/* +* Return the number of contiguous bytes for a given inode +* starting at page frame idx. +*/ +static u64 pnfs_num_cont_bytes (struct inode *inode,pgoff_t idx) +{ +struct address_space *mapping = inode->i_mapping; +pgoff_t end; + +/* Optimize common case that writes from 0 to end of file */ + end =DIV_ROUND_UP (i_size_read (inode),PAGE_CACHE_SIZE ); +if (end !=NFS_I (inode)->npages) { +rcu_read_lock (); + end =radix_tree_next_hole (&mapping->page_tree, idx +1 ,ULONG_MAX ); +rcu_read_unlock (); + } + +if (!end) +return i_size_read (inode) - (idx <<PAGE_CACHE_SHIFT ); +else +return (end - idx) <<PAGE_CACHE_SHIFT ; +} +void bl_pg_init_write (struct nfs_pageio_descriptor *pgio,struct nfs_page *req) {if (pgio->pg_dreq !=NULL && - !is_aligned_req (req,PAGE_CACHE_SIZE )) + !is_aligned_req (req,PAGE_CACHE_SIZE )) {nfs_pageio_reset_write_mds (pgio); -else -pnfs_generic_pg_init_write (pgio, req); + }else { +u64 wb_size; +if (pgio->pg_dreq ==NULL ) + wb_size =pnfs_num_cont_bytes (pgio->pg_inode, + req->wb_index); +else + wb_size =nfs_dreq_bytes_left (pgio->pg_dreq); + +pnfs_generic_pg_init_write (pgio, req, wb_size); + } } static bool
fs/nfs/direct.c +7 -0
@@ -46,6 +46,7 @@#include <linux/kref.h> #include <linux/slab.h> #include <linux/task_io_accounting_ops.h> +#include <linux/module.h> #include <linux/nfs_fs.h> #include <linux/nfs_page.h>
@@ -191,6 +192,12 @@ static void nfs_direct_req_release(struct nfs_direct_req *dreq)kref_put (&dreq->kref, nfs_direct_req_free); } +ssize_t nfs_dreq_bytes_left (struct nfs_direct_req *dreq) +{ +return dreq->bytes_left; +} +EXPORT_SYMBOL_GPL (nfs_dreq_bytes_left); +/* * Collects and returns the final error value/byte-count. */
fs/nfs/internal.h +1 -0
@@ -464,6 +464,7 @@ static inline void nfs_inode_dio_wait(struct inode *inode) {inode_dio_wait (inode); } +extern ssize_t nfs_dreq_bytes_left (struct nfs_direct_req *dreq);/* nfs4proc.c */ extern void __nfs4_read_done_cb (struct nfs_read_data *);
fs/nfs/objlayout/objio_osd.c +8 -1
@@ -41,6 +41,7 @@#include <scsi/osd_ore.h> #include "objlayout.h" +#include "../internal.h" #define NFSDBG_FACILITY NFSDBG_PNFS_LD
@@ -606,8 +607,14 @@ static bool aligned_on_raid_stripe(u64 offset, struct ore_layout *layout,void objio_init_write (struct nfs_pageio_descriptor *pgio,struct nfs_page *req) {unsigned long stripe_end =0 ; +u64 wb_size; -pnfs_generic_pg_init_write (pgio, req); +if (pgio->pg_dreq ==NULL ) + wb_size =i_size_read (pgio->pg_inode) -req_offset (req); +else + wb_size =nfs_dreq_bytes_left (pgio->pg_dreq); + +pnfs_generic_pg_init_write (pgio, req, wb_size);if (unlikely (pgio->pg_lseg ==NULL ))return ;/* Not pNFS */
fs/nfs/pnfs.c +4 -2
@@ -1173,7 +1173,8 @@ pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *rEXPORT_SYMBOL_GPL (pnfs_generic_pg_init_read);void -pnfs_generic_pg_init_write (struct nfs_pageio_descriptor *pgio,struct nfs_page *req) +pnfs_generic_pg_init_write (struct nfs_pageio_descriptor *pgio, +struct nfs_page *req,u64 wb_size) {BUG_ON (pgio->pg_lseg !=NULL );
@@ -1181,10 +1182,11 @@ pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *nfs_pageio_reset_write_mds (pgio);return ; } + pgio->pg_lseg =pnfs_update_layout (pgio->pg_inode, req->wb_context,req_offset (req), - req->wb_bytes, + wb_size,IOMODE_RW ,GFP_NOFS );/* If no lseg, fall back to write through mds */
fs/nfs/pnfs.h +2 -1
@@ -188,7 +188,8 @@ void set_pnfs_layoutdriver(struct nfs_server *, const struct nfs_fh *, u32);void unset_pnfs_layoutdriver (struct nfs_server *);void pnfs_generic_pg_init_read (struct nfs_pageio_descriptor *,struct nfs_page *);int pnfs_generic_pg_readpages (struct nfs_pageio_descriptor *desc); -void pnfs_generic_pg_init_write (struct nfs_pageio_descriptor *,struct nfs_page *); +void pnfs_generic_pg_init_write (struct nfs_pageio_descriptor *pgio, +struct nfs_page *req,u64 wb_size);int pnfs_generic_pg_writepages (struct nfs_pageio_descriptor *desc);bool pnfs_generic_pg_test (struct nfs_pageio_descriptor *pgio,struct nfs_page *prev,struct nfs_page *req);void pnfs_set_lo_fail (struct pnfs_layout_segment *lseg);
Signature · 1 line
1.7.1.262.g5ef3d
PATCH v3 3/3 NFS41: send real read size in layoutget
In reply to Peng TaoFor buffer read, use offst-to-isize.
For direct read, use dreq->bytes_left.
Signed-off-by Peng Tao <[email protected]>
--- fs/nfs/pnfs.c | 10 +++++++++- 1 files changed, 9 insertions(+), 1 deletions(-)
fs/nfs/pnfs.c +9 -1
@@ -1153,16 +1153,24 @@ out_forget_reply:void pnfs_generic_pg_init_read (struct nfs_pageio_descriptor *pgio,struct nfs_page *req) { +u64 rd_size = req->wb_bytes; +BUG_ON (pgio->pg_lseg !=NULL );if (req->wb_offset != req->wb_pgbase) {nfs_pageio_reset_read_mds (pgio);return ; } + +if (pgio->pg_dreq ==NULL ) + rd_size =i_size_read (pgio->pg_inode) -req_offset (req); +else + rd_size =nfs_dreq_bytes_left (pgio->pg_dreq); + pgio->pg_lseg =pnfs_update_layout (pgio->pg_inode, req->wb_context,req_offset (req), - req->wb_bytes, + rd_size,IOMODE_READ ,GFP_KERNEL );/* If no lseg, fall back to read through mds */
Signature · 1 line
1.7.1.262.g5ef3d