Commit 0fc9655ec67ec5d4dfd08e469e0e9f0a494bf5bc
1 parent
95820a3651
Exists in
master
and in
7 other branches
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>
Showing 3 changed files with 34 additions and 130 deletions Side-by-side Diff
fs/9p/vfs_file.c
... | ... | @@ -136,7 +136,7 @@ |
136 | 136 | |
137 | 137 | P9_DPRINTK(P9_DEBUG_VFS, "\n"); |
138 | 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 | 140 | if (ret > 0) |
141 | 141 | *offset += ret; |
142 | 142 | |
... | ... | @@ -164,7 +164,7 @@ |
164 | 164 | (int)count, (int)*offset); |
165 | 165 | |
166 | 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 | 168 | if (ret > 0) { |
169 | 169 | invalidate_inode_pages2_range(inode->i_mapping, *offset, |
170 | 170 | *offset+ret); |
include/net/9p/client.h
... | ... | @@ -201,13 +201,11 @@ |
201 | 201 | char *extension); |
202 | 202 | int p9_client_clunk(struct p9_fid *fid); |
203 | 203 | int p9_client_remove(struct p9_fid *fid); |
204 | -int p9_client_read(struct p9_fid *fid, char *data, u64 offset, u32 count); | |
204 | +int p9_client_read(struct p9_fid *fid, char *data, char __user *udata, | |
205 | + u64 offset, u32 count); | |
205 | 206 | int p9_client_readn(struct p9_fid *fid, char *data, u64 offset, u32 count); |
206 | -int p9_client_write(struct p9_fid *fid, char *data, u64 offset, u32 count); | |
207 | -int p9_client_uread(struct p9_fid *fid, char __user *data, u64 offset, | |
208 | - u32 count); | |
209 | -int p9_client_uwrite(struct p9_fid *fid, const char __user *data, u64 offset, | |
210 | - u32 count); | |
207 | +int p9_client_write(struct p9_fid *fid, char *data, const char __user *udata, | |
208 | + u64 offset, u32 count); | |
211 | 209 | struct p9_stat *p9_client_stat(struct p9_fid *fid); |
212 | 210 | int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst); |
213 | 211 | struct p9_stat *p9_client_dirread(struct p9_fid *fid, u64 offset); |
net/9p/client.c
... | ... | @@ -1016,7 +1016,9 @@ |
1016 | 1016 | } |
1017 | 1017 | EXPORT_SYMBOL(p9_client_remove); |
1018 | 1018 | |
1019 | -int p9_client_read(struct p9_fid *fid, char *data, u64 offset, u32 count) | |
1019 | +int | |
1020 | +p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, | |
1021 | + u32 count) | |
1020 | 1022 | { |
1021 | 1023 | int err, n, rsize, total; |
1022 | 1024 | struct p9_fcall *tc, *rc; |
1023 | 1025 | |
1024 | 1026 | |
1025 | 1027 | |
... | ... | @@ -1053,125 +1055,21 @@ |
1053 | 1055 | if (n > count) |
1054 | 1056 | n = count; |
1055 | 1057 | |
1056 | - memmove(data, rc->params.rread.data, n); | |
1057 | - count -= n; | |
1058 | - 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 | - | |
1069 | -error: | |
1070 | - kfree(tc); | |
1071 | - kfree(rc); | |
1072 | - return err; | |
1073 | -} | |
1074 | -EXPORT_SYMBOL(p9_client_read); | |
1075 | - | |
1076 | -int 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; | |
1058 | + if (data) { | |
1059 | + memmove(data, rc->params.rread.data, n); | |
1060 | + data += n; | |
1103 | 1061 | } |
1104 | 1062 | |
1105 | - err = p9_client_rpc(clnt, tc, &rc); | |
1106 | - if (err) | |
1107 | - goto error; | |
1108 | - | |
1109 | - n = rc->params.rread.count; | |
1110 | - count -= n; | |
1111 | - data += 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 | - | |
1122 | -error: | |
1123 | - kfree(tc); | |
1124 | - kfree(rc); | |
1125 | - return err; | |
1126 | -} | |
1127 | -EXPORT_SYMBOL(p9_client_write); | |
1128 | - | |
1129 | -int | |
1130 | -p9_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; | |
1063 | + if (udata) { | |
1064 | + err = copy_to_user(udata, rc->params.rread.data, n); | |
1065 | + if (err) { | |
1066 | + err = -EFAULT; | |
1067 | + goto error; | |
1068 | + } | |
1069 | + udata += n; | |
1157 | 1070 | } |
1158 | 1071 | |
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 | - } | |
1172 | - | |
1173 | 1072 | count -= n; |
1174 | - data += n; | |
1175 | 1073 | offset += n; |
1176 | 1074 | total += n; |
1177 | 1075 | kfree(tc); |
1178 | 1076 | |
... | ... | @@ -1187,11 +1085,11 @@ |
1187 | 1085 | kfree(rc); |
1188 | 1086 | return err; |
1189 | 1087 | } |
1190 | -EXPORT_SYMBOL(p9_client_uread); | |
1088 | +EXPORT_SYMBOL(p9_client_read); | |
1191 | 1089 | |
1192 | 1090 | int |
1193 | -p9_client_uwrite(struct p9_fid *fid, const char __user *data, u64 offset, | |
1194 | - u32 count) | |
1091 | +p9_client_write(struct p9_fid *fid, char *data, const char __user *udata, | |
1092 | + u64 offset, u32 count) | |
1195 | 1093 | { |
1196 | 1094 | int err, n, rsize, total; |
1197 | 1095 | struct p9_fcall *tc, *rc; |
... | ... | @@ -1213,7 +1111,10 @@ |
1213 | 1111 | if (count < rsize) |
1214 | 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 | 1118 | if (IS_ERR(tc)) { |
1218 | 1119 | err = PTR_ERR(tc); |
1219 | 1120 | tc = NULL; |
... | ... | @@ -1226,7 +1127,12 @@ |
1226 | 1127 | |
1227 | 1128 | n = rc->params.rread.count; |
1228 | 1129 | count -= n; |
1229 | - data += n; | |
1130 | + | |
1131 | + if (data) | |
1132 | + data += n; | |
1133 | + else | |
1134 | + udata += n; | |
1135 | + | |
1230 | 1136 | offset += n; |
1231 | 1137 | total += n; |
1232 | 1138 | kfree(tc); |
... | ... | @@ -1242,7 +1148,7 @@ |
1242 | 1148 | kfree(rc); |
1243 | 1149 | return err; |
1244 | 1150 | } |
1245 | -EXPORT_SYMBOL(p9_client_uwrite); | |
1151 | +EXPORT_SYMBOL(p9_client_write); | |
1246 | 1152 | |
1247 | 1153 | int p9_client_readn(struct p9_fid *fid, char *data, u64 offset, u32 count) |
1248 | 1154 | { |
... | ... | @@ -1253,7 +1159,7 @@ |
1253 | 1159 | n = 0; |
1254 | 1160 | total = 0; |
1255 | 1161 | while (count) { |
1256 | - n = p9_client_read(fid, data, offset, count); | |
1162 | + n = p9_client_read(fid, data, NULL, offset, count); | |
1257 | 1163 | if (n <= 0) |
1258 | 1164 | break; |
1259 | 1165 |