diff options
author | Mike Marshall | 2019-03-25 15:52:29 -0400 |
---|---|---|
committer | Mike Marshall | 2019-05-03 14:32:39 -0400 |
commit | c2549f8c7a28c00facaf911f700c4811cfd6f52b (patch) | |
tree | 9fb589307265149e3af3029002d1d6a81de5d82e | |
parent | 8f04e1be784858ba0288c7c09b9de06627a800c9 (diff) |
orangefs: remember count when reading.
Orangefs wins when it can do IO on large (up to four meg) blocks at a time,
and looses when it has to do tiny "small io" reads and writes. Accessing
Orangefs through the pagecache with the kernel module helps with small io,
both reading and writing, a great deal. Readpage generally tries to fetch a
page (four k) at a time. We'll let users use "count" (as in read(2) or
pread(2) for example) as a knob to control how much data they get from
Orangefs at a time and we'll try to use the data to fill extra
pagecache pages when we get to ->readpage, hopefully resulting in
fewer calls to readpage and Orangefs userspace.
We need a way to remember how they set count so that we can still have
it available when we get to ->readpage.
- We'll use file->private_data to keep track of "count".
We'll wrap generic_file_open with orangefs_file_open and
initialize private_data to NULL there.
- In ->read_iter we have access to both "count" and file, so
we'll kmalloc some space onto file->private_data and store
"count" there.
- We'll kfree file->private_data each time we visit ->flush and
reinitialize it to NULL.
Signed-off-by: Mike Marshall <hubcap@omnibond.com>
Signed-off-by: Martin Brandenburg <martin@omnibond.com>
-rw-r--r-- | fs/orangefs/file.c | 26 | ||||
-rw-r--r-- | fs/orangefs/orangefs-kernel.h | 4 |
2 files changed, 29 insertions, 1 deletions
diff --git a/fs/orangefs/file.c b/fs/orangefs/file.c index faa5b61cdfd6..74292d31d113 100644 --- a/fs/orangefs/file.c +++ b/fs/orangefs/file.c @@ -286,8 +286,23 @@ static ssize_t orangefs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter) { int ret; + struct orangefs_read_options *ro; + orangefs_stats.reads++; + /* + * Remember how they set "count" in read(2) or pread(2) or whatever - + * users can use count as a knob to control orangefs io size and later + * we can try to help them fill as many pages as possible in readpage. + */ + if (!iocb->ki_filp->private_data) { + iocb->ki_filp->private_data = kmalloc(sizeof *ro, GFP_KERNEL); + if (!iocb->ki_filp->private_data) + return(ENOMEM); + ro = iocb->ki_filp->private_data; + ro->blksiz = iter->count; + } + down_read(&file_inode(iocb->ki_filp)->i_rwsem); ret = orangefs_revalidate_mapping(file_inode(iocb->ki_filp)); if (ret) @@ -556,6 +571,12 @@ static int orangefs_lock(struct file *filp, int cmd, struct file_lock *fl) return rc; } +static int orangefs_file_open(struct inode * inode, struct file *file) +{ + file->private_data = NULL; + return generic_file_open(inode, file); +} + static int orangefs_flush(struct file *file, fl_owner_t id) { /* @@ -569,6 +590,9 @@ static int orangefs_flush(struct file *file, fl_owner_t id) struct inode *inode = file->f_mapping->host; int r; + kfree(file->private_data); + file->private_data = NULL; + if (inode->i_state & I_DIRTY_TIME) { spin_lock(&inode->i_lock); inode->i_state &= ~I_DIRTY_TIME; @@ -591,7 +615,7 @@ const struct file_operations orangefs_file_operations = { .lock = orangefs_lock, .unlocked_ioctl = orangefs_ioctl, .mmap = orangefs_file_mmap, - .open = generic_file_open, + .open = orangefs_file_open, .flush = orangefs_flush, .release = orangefs_file_release, .fsync = orangefs_fsync, diff --git a/fs/orangefs/orangefs-kernel.h b/fs/orangefs/orangefs-kernel.h index 87beab10326a..3ae2f129b9c7 100644 --- a/fs/orangefs/orangefs-kernel.h +++ b/fs/orangefs/orangefs-kernel.h @@ -239,6 +239,10 @@ struct orangefs_write_range { kgid_t gid; }; +struct orangefs_read_options { + ssize_t blksiz; +}; + extern struct orangefs_stats orangefs_stats; /* |