Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 97 additions & 74 deletions module/lzfs_vnops.c
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,44 @@ int lzfs_vnop_fsync(struct file *filep, struct dentry *dentry, int datasync)
return err;
}

/* XXX --> Internal function used by lzfs_vnop_readlink and lzfs_readpage
*
* Performs the read operation
*
* Explanation of parameters
* buf = buffer pointer to data
* len = length of the data
* pos = offest within file to wite
* segment = indicates whether buf pointer points to
* user space buffer or kernel buffer.
* */
static inline ssize_t lzfs_read(vnode_t *vp, const char *buf, ssize_t len,
loff_t pos, uio_seg_t segment)
{
int err;

struct iovec iov = {
.iov_base = (void *) buf,
.iov_len = len,
};

uio_t uio = {
.uio_iov = &iov,
.uio_iovcnt = 1,
.uio_loffset = (offset_t) pos,
.uio_resid = len,
.uio_segflg = segment,
};

const cred_t *cred = get_current_cred();

err = zfs_read(vp, &uio, 0, (cred_t *) cred, NULL);
put_cred(cred);
if (unlikely(err))
return -err;
return (len - uio.uio_resid);
}

int copy_data(read_descriptor_t *desc, struct page *page,
unsigned long offset, unsigned long size)
{
Expand Down Expand Up @@ -636,11 +674,7 @@ int copy_data(read_descriptor_t *desc, struct page *page,
ssize_t
lzfs_vnop_read (struct file *filep, char __user *buf, size_t len, loff_t *ppos)
{
struct iovec iov = { .iov_base = buf, .iov_len = len };
int err;
const cred_t *cred = get_current_cred();
vnode_t *vp = NULL;
uio_t uio;
loff_t isize;
ssize_t size;

Expand All @@ -655,15 +689,25 @@ lzfs_vnop_read (struct file *filep, char __user *buf, size_t len, loff_t *ppos)
unsigned int prev_offset;
read_descriptor_t desc;

ENTRY;
vp = LZFS_ITOV(inode);

if (likely(!(vp->v_flag & VMMAPPED))) {
/* file is not memory mmapped, pass read directly to ZFS */
ssize_t rc;
rc = lzfs_read(vp, buf, len, *ppos, UIO_USERSPACE);
if (likely(rc > 0))
*ppos += rc;
tsd_exit();
EXIT;
return rc;
}

desc.written = 0;
desc.arg.buf = buf;
desc.count = len;
desc.error = 0;

ENTRY;

index = *ppos >> PAGE_CACHE_SHIFT;
prev_index = ra->prev_pos >> PAGE_CACHE_SHIFT;
prev_offset = ra->prev_pos & (PAGE_CACHE_SIZE - 1);
Expand Down Expand Up @@ -768,22 +812,13 @@ lzfs_vnop_read (struct file *filep, char __user *buf, size_t len, loff_t *ppos)
if (offset + size > isize)
size = isize - desc.written;


iov.iov_base = desc.arg.buf;
iov.iov_len = size;

uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
uio.uio_loffset = (offset_t) *ppos;
uio.uio_resid = size;
uio.uio_segflg = UIO_USERSPACE;
err = zfs_read(vp, &uio, 0,(cred_t *) cred, NULL);
if (unlikely(err)) {
err = -err;
goto out_error;
ret = lzfs_read(vp, desc.arg.buf, size, *ppos, UIO_USERSPACE);
if (unlikely(ret < 0)) {
tsd_exit();
EXIT;
return ret;
}

ret = size - uio.uio_resid;
desc.count = desc.count - ret;
desc.written += ret;
desc.arg.buf += ret;
Expand All @@ -805,17 +840,10 @@ lzfs_vnop_read (struct file *filep, char __user *buf, size_t len, loff_t *ppos)

out:
// *ppos = ((loff_t)index << PAGE_CACHE_SHIFT) + offset;

zfs_file_accessed(vp);
put_cred(cred);
tsd_exit();
EXIT;
return ((ssize_t) (desc.written));
out_error:
put_cred(cred);
tsd_exit();
EXIT;
return err;
}

/* XXX --> Internal function used by lzfs_vnop_write and lzfs_writepage
Expand All @@ -830,27 +858,32 @@ lzfs_vnop_read (struct file *filep, char __user *buf, size_t len, loff_t *ppos)
* segment = indicates whether buf pointer points to
* user space buffer or kernel buffer.
* */
ssize_t lzfs_write(vnode_t *vp, unsigned int file_flags,
static inline ssize_t lzfs_write(vnode_t *vp, unsigned int file_flags,
const char *buf, ssize_t len, loff_t pos, uio_seg_t segment)
{
uio_t uio;
const cred_t *cred = get_current_cred();
struct iovec iov;
int err;
int err;

struct iovec iov = {
.iov_base = (void *) buf,
.iov_len = len,
};

uio_t uio = {
.uio_iov = &iov,
.uio_resid = len,
.uio_iovcnt = 1,
.uio_loffset = (offset_t)(pos),
.uio_limit = MAXOFFSET_T,
.uio_segflg = segment,
};

iov.iov_base = (void *) buf;
iov.iov_len = len;

uio.uio_iov = &iov;
uio.uio_resid = len;
uio.uio_iovcnt = 1;
uio.uio_loffset = (offset_t)(pos);
uio.uio_limit = MAXOFFSET_T;
uio.uio_segflg = segment;
const cred_t *cred = get_current_cred();

err = zfs_write(vp, &uio, file_flags, (cred_t *)cred, NULL);
put_cred(cred);
return err;
if (unlikely(err))
return -err;
return (len - uio.uio_resid);
}

ssize_t
Expand Down Expand Up @@ -878,16 +911,15 @@ lzfs_vnop_write (struct file *filep, const char __user *buf, size_t len,

vp = LZFS_ITOV(inode);

if (!(vp->v_flag & VMMAPPED)) {
/* file is not memory mmapped, pass read directly to ZFS */
err = lzfs_write(vp, filep->f_flags, buf, len, *ppos, UIO_USERSPACE);
if (unlikely(err)) {
err = -err;
goto out_error;
}
*ppos += len;
written = len;
goto out_success;
if (likely(!(vp->v_flag & VMMAPPED))) {
/* file is not memory mmapped, pass write directly to ZFS */
ssize_t rc;
rc = lzfs_write(vp, filep->f_flags, buf, len, *ppos, UIO_USERSPACE);
if (likely(rc > 0))
*ppos += rc;
tsd_exit();
EXIT;
return rc;
}

i_size = i_size_read(inode);
Expand Down Expand Up @@ -968,21 +1000,20 @@ lzfs_vnop_write (struct file *filep, const char __user *buf, size_t len,
continue;

no_cached_page:
err = lzfs_write(vp, filep->f_flags, user_buf, size, *ppos, UIO_USERSPACE);
if (unlikely(err)) {
err = -err;
size = lzfs_write(vp, filep->f_flags, user_buf, size, *ppos, UIO_USERSPACE);
if (unlikely(size < 0)) {
err = size;
goto out_error;
}

*ppos += size;
*ppos += size;
pos_append += size;
user_buf += size;
written += size;
index = *ppos >> PAGE_CACHE_SHIFT;
offset = 0;
user_buf += size;
written += size;
index = *ppos >> PAGE_CACHE_SHIFT;
offset = 0;
}

out_success:
tsd_exit();
EXIT;
return ((ssize_t) written);
Expand Down Expand Up @@ -1091,6 +1122,7 @@ static int lzfs_readpage(struct file *file, struct page *page)
char *buf = NULL;
vnode_t *vp = NULL;
unsigned long fillsize = 0;
ssize_t rc;
struct iovec iov;
uio_t uio;

Expand Down Expand Up @@ -1121,17 +1153,8 @@ static int lzfs_readpage(struct file *file, struct page *page)
i_size -= offset;
fillsize = i_size > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE : i_size;

iov.iov_base = buf;
iov.iov_len = fillsize;

uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
uio.uio_loffset = (offset_t)(offset);
uio.uio_resid = fillsize;
uio.uio_segflg = UIO_SYSSPACE;

err = zfs_read(vp, &uio, 0, (cred_t *) cred, NULL);
if (err) {
rc = lzfs_read(vp, buf, fillsize, offset, UIO_SYSSPACE);
if (unlikely(rc < 0)) {
SetPageError(page);
fillsize = 0;
err = -EIO;
Expand Down Expand Up @@ -1203,8 +1226,8 @@ static int lzfs_writepage(struct page *page, struct writeback_control *wbc)
* to the end of the file, but the we are in writepage and data
* should be written to same offset that we provide to zfs_write.
* */
err = lzfs_write(vp, filep->f_flags & ~FAPPEND, buf, len, offset, UIO_SYSSPACE);
if (err) {
len = lzfs_write(vp, filep->f_flags & ~FAPPEND, buf, len, offset, UIO_SYSSPACE);
if (unlikely(len < 0)) {
SetPageError(page);
err = -EIO;
}
Expand Down