Skip to content

Commit

Permalink
9p: consolidate read/write functions
Browse files Browse the repository at this point in the history
Currently there are two separate versions of read and write.  One for
dealing with user buffers and the other for dealing with kernel buffers.
There is a tremendous amount of code duplication in the otherwise
identical versions of these functions.  This patch adds an additional
user buffer parameter to read and write and conditionalizes handling of
the buffer on whether the kernel buffer or the user buffer is populated.

Signed-off-by: Eric Van Hensbergen <[email protected]>
  • Loading branch information
ericvh committed Oct 17, 2008
1 parent 95820a3 commit 0fc9655
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 130 deletions.
4 changes: 2 additions & 2 deletions fs/9p/vfs_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ v9fs_file_read(struct file *filp, char __user * data, size_t count,

P9_DPRINTK(P9_DEBUG_VFS, "\n");
fid = filp->private_data;
ret = p9_client_uread(fid, data, *offset, count);
ret = p9_client_read(fid, NULL, data, *offset, count);
if (ret > 0)
*offset += ret;

Expand Down Expand Up @@ -164,7 +164,7 @@ v9fs_file_write(struct file *filp, const char __user * data,
(int)count, (int)*offset);

fid = filp->private_data;
ret = p9_client_uwrite(fid, data, *offset, count);
ret = p9_client_write(fid, NULL, data, *offset, count);
if (ret > 0) {
invalidate_inode_pages2_range(inode->i_mapping, *offset,
*offset+ret);
Expand Down
10 changes: 4 additions & 6 deletions include/net/9p/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,13 +201,11 @@ int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
char *extension);
int p9_client_clunk(struct p9_fid *fid);
int p9_client_remove(struct p9_fid *fid);
int p9_client_read(struct p9_fid *fid, char *data, u64 offset, u32 count);
int p9_client_read(struct p9_fid *fid, char *data, char __user *udata,
u64 offset, u32 count);
int p9_client_readn(struct p9_fid *fid, char *data, u64 offset, u32 count);
int p9_client_write(struct p9_fid *fid, char *data, u64 offset, u32 count);
int p9_client_uread(struct p9_fid *fid, char __user *data, u64 offset,
u32 count);
int p9_client_uwrite(struct p9_fid *fid, const char __user *data, u64 offset,
u32 count);
int p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
u64 offset, u32 count);
struct p9_stat *p9_client_stat(struct p9_fid *fid);
int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst);
struct p9_stat *p9_client_dirread(struct p9_fid *fid, u64 offset);
Expand Down
150 changes: 28 additions & 122 deletions net/9p/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -1016,7 +1016,9 @@ int p9_client_remove(struct p9_fid *fid)
}
EXPORT_SYMBOL(p9_client_remove);

int p9_client_read(struct p9_fid *fid, char *data, u64 offset, u32 count)
int
p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
u32 count)
{
int err, n, rsize, total;
struct p9_fcall *tc, *rc;
Expand Down Expand Up @@ -1053,125 +1055,21 @@ int p9_client_read(struct p9_fid *fid, char *data, u64 offset, u32 count)
if (n > count)
n = count;

memmove(data, rc->params.rread.data, n);
count -= n;
data += n;
offset += n;
total += n;
kfree(tc);
tc = NULL;
kfree(rc);
rc = NULL;
} while (count > 0 && n == rsize);

return total;

error:
kfree(tc);
kfree(rc);
return err;
}
EXPORT_SYMBOL(p9_client_read);

int p9_client_write(struct p9_fid *fid, char *data, u64 offset, u32 count)
{
int err, n, rsize, total;
struct p9_fcall *tc, *rc;
struct p9_client *clnt;

P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid,
(long long unsigned) offset, count);
err = 0;
tc = NULL;
rc = NULL;
clnt = fid->clnt;
total = 0;

rsize = fid->iounit;
if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
rsize = clnt->msize - P9_IOHDRSZ;

do {
if (count < rsize)
rsize = count;

tc = p9_create_twrite(fid->fid, offset, rsize, data);
if (IS_ERR(tc)) {
err = PTR_ERR(tc);
tc = NULL;
goto error;
if (data) {
memmove(data, rc->params.rread.data, n);
data += n;
}

err = p9_client_rpc(clnt, tc, &rc);
if (err)
goto error;

n = rc->params.rread.count;
count -= n;
data += n;
offset += n;
total += n;
kfree(tc);
tc = NULL;
kfree(rc);
rc = NULL;
} while (count > 0);

return total;

error:
kfree(tc);
kfree(rc);
return err;
}
EXPORT_SYMBOL(p9_client_write);

int
p9_client_uread(struct p9_fid *fid, char __user *data, u64 offset, u32 count)
{
int err, n, rsize, total;
struct p9_fcall *tc, *rc;
struct p9_client *clnt;

P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid,
(long long unsigned) offset, count);
err = 0;
tc = NULL;
rc = NULL;
clnt = fid->clnt;
total = 0;

rsize = fid->iounit;
if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
rsize = clnt->msize - P9_IOHDRSZ;

do {
if (count < rsize)
rsize = count;

tc = p9_create_tread(fid->fid, offset, rsize);
if (IS_ERR(tc)) {
err = PTR_ERR(tc);
tc = NULL;
goto error;
}

err = p9_client_rpc(clnt, tc, &rc);
if (err)
goto error;

n = rc->params.rread.count;
if (n > count)
n = count;

err = copy_to_user(data, rc->params.rread.data, n);
if (err) {
err = -EFAULT;
goto error;
if (udata) {
err = copy_to_user(udata, rc->params.rread.data, n);
if (err) {
err = -EFAULT;
goto error;
}
udata += n;
}

count -= n;
data += n;
offset += n;
total += n;
kfree(tc);
Expand All @@ -1187,11 +1085,11 @@ p9_client_uread(struct p9_fid *fid, char __user *data, u64 offset, u32 count)
kfree(rc);
return err;
}
EXPORT_SYMBOL(p9_client_uread);
EXPORT_SYMBOL(p9_client_read);

int
p9_client_uwrite(struct p9_fid *fid, const char __user *data, u64 offset,
u32 count)
p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
u64 offset, u32 count)
{
int err, n, rsize, total;
struct p9_fcall *tc, *rc;
Expand All @@ -1213,7 +1111,10 @@ p9_client_uwrite(struct p9_fid *fid, const char __user *data, u64 offset,
if (count < rsize)
rsize = count;

tc = p9_create_twrite_u(fid->fid, offset, rsize, data);
if (data)
tc = p9_create_twrite(fid->fid, offset, rsize, data);
else
tc = p9_create_twrite_u(fid->fid, offset, rsize, udata);
if (IS_ERR(tc)) {
err = PTR_ERR(tc);
tc = NULL;
Expand All @@ -1226,7 +1127,12 @@ p9_client_uwrite(struct p9_fid *fid, const char __user *data, u64 offset,

n = rc->params.rread.count;
count -= n;
data += n;

if (data)
data += n;
else
udata += n;

offset += n;
total += n;
kfree(tc);
Expand All @@ -1242,7 +1148,7 @@ p9_client_uwrite(struct p9_fid *fid, const char __user *data, u64 offset,
kfree(rc);
return err;
}
EXPORT_SYMBOL(p9_client_uwrite);
EXPORT_SYMBOL(p9_client_write);

int p9_client_readn(struct p9_fid *fid, char *data, u64 offset, u32 count)
{
Expand All @@ -1253,7 +1159,7 @@ int p9_client_readn(struct p9_fid *fid, char *data, u64 offset, u32 count)
n = 0;
total = 0;
while (count) {
n = p9_client_read(fid, data, offset, count);
n = p9_client_read(fid, data, NULL, offset, count);
if (n <= 0)
break;

Expand Down

0 comments on commit 0fc9655

Please sign in to comment.