aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Van Hensbergen <ericvh@gmail.com>2008-10-13 21:36:17 -0400
committerEric Van Hensbergen <ericvh@gmail.com>2008-10-17 12:04:42 -0400
commit0fc9655ec67ec5d4dfd08e469e0e9f0a494bf5bc (patch)
treefc67e000acb43601a0dcb9c0288a94a3d737b6a2
parent95820a36516d12dcb49d066dd3d5b187a2557612 (diff)
9p: consolidate read/write functions
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 <ericvh@gmail.com>
-rw-r--r--fs/9p/vfs_file.c4
-rw-r--r--include/net/9p/client.h10
-rw-r--r--net/9p/client.c150
3 files changed, 34 insertions, 130 deletions
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 52944d2249a4..3819a195de8f 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -136,7 +136,7 @@ v9fs_file_read(struct file *filp, char __user * data, size_t count,
136 136
137 P9_DPRINTK(P9_DEBUG_VFS, "\n"); 137 P9_DPRINTK(P9_DEBUG_VFS, "\n");
138 fid = filp->private_data; 138 fid = filp->private_data;
139 ret = p9_client_uread(fid, data, *offset, count); 139 ret = p9_client_read(fid, NULL, data, *offset, count);
140 if (ret > 0) 140 if (ret > 0)
141 *offset += ret; 141 *offset += ret;
142 142
@@ -164,7 +164,7 @@ v9fs_file_write(struct file *filp, const char __user * data,
164 (int)count, (int)*offset); 164 (int)count, (int)*offset);
165 165
166 fid = filp->private_data; 166 fid = filp->private_data;
167 ret = p9_client_uwrite(fid, data, *offset, count); 167 ret = p9_client_write(fid, NULL, data, *offset, count);
168 if (ret > 0) { 168 if (ret > 0) {
169 invalidate_inode_pages2_range(inode->i_mapping, *offset, 169 invalidate_inode_pages2_range(inode->i_mapping, *offset,
170 *offset+ret); 170 *offset+ret);
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index 6a71d9067818..c70a0f0b448d 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -201,13 +201,11 @@ int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
201 char *extension); 201 char *extension);
202int p9_client_clunk(struct p9_fid *fid); 202int p9_client_clunk(struct p9_fid *fid);
203int p9_client_remove(struct p9_fid *fid); 203int p9_client_remove(struct p9_fid *fid);
204int p9_client_read(struct p9_fid *fid, char *data, u64 offset, u32 count); 204int p9_client_read(struct p9_fid *fid, char *data, char __user *udata,
205 u64 offset, u32 count);
205int p9_client_readn(struct p9_fid *fid, char *data, u64 offset, u32 count); 206int p9_client_readn(struct p9_fid *fid, char *data, u64 offset, u32 count);
206int p9_client_write(struct p9_fid *fid, char *data, u64 offset, u32 count); 207int p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
207int p9_client_uread(struct p9_fid *fid, char __user *data, u64 offset, 208 u64 offset, u32 count);
208 u32 count);
209int p9_client_uwrite(struct p9_fid *fid, const char __user *data, u64 offset,
210 u32 count);
211struct p9_stat *p9_client_stat(struct p9_fid *fid); 209struct p9_stat *p9_client_stat(struct p9_fid *fid);
212int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst); 210int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst);
213struct p9_stat *p9_client_dirread(struct p9_fid *fid, u64 offset); 211struct p9_stat *p9_client_dirread(struct p9_fid *fid, u64 offset);
diff --git a/net/9p/client.c b/net/9p/client.c
index 29934febecdb..5fc3aa1eb39b 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -1016,7 +1016,9 @@ done:
1016} 1016}
1017EXPORT_SYMBOL(p9_client_remove); 1017EXPORT_SYMBOL(p9_client_remove);
1018 1018
1019int p9_client_read(struct p9_fid *fid, char *data, u64 offset, u32 count) 1019int
1020p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
1021 u32 count)
1020{ 1022{
1021 int err, n, rsize, total; 1023 int err, n, rsize, total;
1022 struct p9_fcall *tc, *rc; 1024 struct p9_fcall *tc, *rc;
@@ -1053,125 +1055,21 @@ int p9_client_read(struct p9_fid *fid, char *data, u64 offset, u32 count)
1053 if (n > count) 1055 if (n > count)
1054 n = count; 1056 n = count;
1055 1057
1056 memmove(data, rc->params.rread.data, n); 1058 if (data) {
1057 count -= n; 1059 memmove(data, rc->params.rread.data, n);
1058 data += n; 1060 data += n;
1059 offset += n;
1060 total += n;
1061 kfree(tc);
1062 tc = NULL;
1063 kfree(rc);
1064 rc = NULL;
1065 } while (count > 0 && n == rsize);
1066
1067 return total;
1068
1069error:
1070 kfree(tc);
1071 kfree(rc);
1072 return err;
1073}
1074EXPORT_SYMBOL(p9_client_read);
1075
1076int p9_client_write(struct p9_fid *fid, char *data, u64 offset, u32 count)
1077{
1078 int err, n, rsize, total;
1079 struct p9_fcall *tc, *rc;
1080 struct p9_client *clnt;
1081
1082 P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid,
1083 (long long unsigned) offset, count);
1084 err = 0;
1085 tc = NULL;
1086 rc = NULL;
1087 clnt = fid->clnt;
1088 total = 0;
1089
1090 rsize = fid->iounit;
1091 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
1092 rsize = clnt->msize - P9_IOHDRSZ;
1093
1094 do {
1095 if (count < rsize)
1096 rsize = count;
1097
1098 tc = p9_create_twrite(fid->fid, offset, rsize, data);
1099 if (IS_ERR(tc)) {
1100 err = PTR_ERR(tc);
1101 tc = NULL;
1102 goto error;
1103 } 1061 }
1104 1062
1105 err = p9_client_rpc(clnt, tc, &rc); 1063 if (udata) {
1106 if (err) 1064 err = copy_to_user(udata, rc->params.rread.data, n);
1107 goto error; 1065 if (err) {
1108 1066 err = -EFAULT;
1109 n = rc->params.rread.count; 1067 goto error;
1110 count -= n; 1068 }
1111 data += n; 1069 udata += n;
1112 offset += n;
1113 total += n;
1114 kfree(tc);
1115 tc = NULL;
1116 kfree(rc);
1117 rc = NULL;
1118 } while (count > 0);
1119
1120 return total;
1121
1122error:
1123 kfree(tc);
1124 kfree(rc);
1125 return err;
1126}
1127EXPORT_SYMBOL(p9_client_write);
1128
1129int
1130p9_client_uread(struct p9_fid *fid, char __user *data, u64 offset, u32 count)
1131{
1132 int err, n, rsize, total;
1133 struct p9_fcall *tc, *rc;
1134 struct p9_client *clnt;
1135
1136 P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid,
1137 (long long unsigned) offset, count);
1138 err = 0;
1139 tc = NULL;
1140 rc = NULL;
1141 clnt = fid->clnt;
1142 total = 0;
1143
1144 rsize = fid->iounit;
1145 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
1146 rsize = clnt->msize - P9_IOHDRSZ;
1147
1148 do {
1149 if (count < rsize)
1150 rsize = count;
1151
1152 tc = p9_create_tread(fid->fid, offset, rsize);
1153 if (IS_ERR(tc)) {
1154 err = PTR_ERR(tc);
1155 tc = NULL;
1156 goto error;
1157 }
1158
1159 err = p9_client_rpc(clnt, tc, &rc);
1160 if (err)
1161 goto error;
1162
1163 n = rc->params.rread.count;
1164 if (n > count)
1165 n = count;
1166
1167 err = copy_to_user(data, rc->params.rread.data, n);
1168 if (err) {
1169 err = -EFAULT;
1170 goto error;
1171 } 1070 }
1172 1071
1173 count -= n; 1072 count -= n;
1174 data += n;
1175 offset += n; 1073 offset += n;
1176 total += n; 1074 total += n;
1177 kfree(tc); 1075 kfree(tc);
@@ -1187,11 +1085,11 @@ error:
1187 kfree(rc); 1085 kfree(rc);
1188 return err; 1086 return err;
1189} 1087}
1190EXPORT_SYMBOL(p9_client_uread); 1088EXPORT_SYMBOL(p9_client_read);
1191 1089
1192int 1090int
1193p9_client_uwrite(struct p9_fid *fid, const char __user *data, u64 offset, 1091p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
1194 u32 count) 1092 u64 offset, u32 count)
1195{ 1093{
1196 int err, n, rsize, total; 1094 int err, n, rsize, total;
1197 struct p9_fcall *tc, *rc; 1095 struct p9_fcall *tc, *rc;
@@ -1213,7 +1111,10 @@ p9_client_uwrite(struct p9_fid *fid, const char __user *data, u64 offset,
1213 if (count < rsize) 1111 if (count < rsize)
1214 rsize = count; 1112 rsize = count;
1215 1113
1216 tc = p9_create_twrite_u(fid->fid, offset, rsize, data); 1114 if (data)
1115 tc = p9_create_twrite(fid->fid, offset, rsize, data);
1116 else
1117 tc = p9_create_twrite_u(fid->fid, offset, rsize, udata);
1217 if (IS_ERR(tc)) { 1118 if (IS_ERR(tc)) {
1218 err = PTR_ERR(tc); 1119 err = PTR_ERR(tc);
1219 tc = NULL; 1120 tc = NULL;
@@ -1226,7 +1127,12 @@ p9_client_uwrite(struct p9_fid *fid, const char __user *data, u64 offset,
1226 1127
1227 n = rc->params.rread.count; 1128 n = rc->params.rread.count;
1228 count -= n; 1129 count -= n;
1229 data += n; 1130
1131 if (data)
1132 data += n;
1133 else
1134 udata += n;
1135
1230 offset += n; 1136 offset += n;
1231 total += n; 1137 total += n;
1232 kfree(tc); 1138 kfree(tc);
@@ -1242,7 +1148,7 @@ error:
1242 kfree(rc); 1148 kfree(rc);
1243 return err; 1149 return err;
1244} 1150}
1245EXPORT_SYMBOL(p9_client_uwrite); 1151EXPORT_SYMBOL(p9_client_write);
1246 1152
1247int p9_client_readn(struct p9_fid *fid, char *data, u64 offset, u32 count) 1153int p9_client_readn(struct p9_fid *fid, char *data, u64 offset, u32 count)
1248{ 1154{
@@ -1253,7 +1159,7 @@ int p9_client_readn(struct p9_fid *fid, char *data, u64 offset, u32 count)
1253 n = 0; 1159 n = 0;
1254 total = 0; 1160 total = 0;
1255 while (count) { 1161 while (count) {
1256 n = p9_client_read(fid, data, offset, count); 1162 n = p9_client_read(fid, data, NULL, offset, count);
1257 if (n <= 0) 1163 if (n <= 0)
1258 break; 1164 break;
1259 1165