diff options
Diffstat (limited to 'fs/compat.c')
-rw-r--r-- | fs/compat.c | 44 |
1 files changed, 11 insertions, 33 deletions
diff --git a/fs/compat.c b/fs/compat.c index 122b4e3992b5..6b90bf35f61d 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -70,6 +70,8 @@ int compat_printk(const char *fmt, ...) | |||
70 | return ret; | 70 | return ret; |
71 | } | 71 | } |
72 | 72 | ||
73 | #include "read_write.h" | ||
74 | |||
73 | /* | 75 | /* |
74 | * Not all architectures have sys_utime, so implement this in terms | 76 | * Not all architectures have sys_utime, so implement this in terms |
75 | * of sys_utimes. | 77 | * of sys_utimes. |
@@ -1149,9 +1151,6 @@ static ssize_t compat_do_readv_writev(int type, struct file *file, | |||
1149 | const struct compat_iovec __user *uvector, | 1151 | const struct compat_iovec __user *uvector, |
1150 | unsigned long nr_segs, loff_t *pos) | 1152 | unsigned long nr_segs, loff_t *pos) |
1151 | { | 1153 | { |
1152 | typedef ssize_t (*io_fn_t)(struct file *, char __user *, size_t, loff_t *); | ||
1153 | typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *); | ||
1154 | |||
1155 | compat_ssize_t tot_len; | 1154 | compat_ssize_t tot_len; |
1156 | struct iovec iovstack[UIO_FASTIOV]; | 1155 | struct iovec iovstack[UIO_FASTIOV]; |
1157 | struct iovec *iov=iovstack, *vector; | 1156 | struct iovec *iov=iovstack, *vector; |
@@ -1234,39 +1233,18 @@ static ssize_t compat_do_readv_writev(int type, struct file *file, | |||
1234 | fnv = NULL; | 1233 | fnv = NULL; |
1235 | if (type == READ) { | 1234 | if (type == READ) { |
1236 | fn = file->f_op->read; | 1235 | fn = file->f_op->read; |
1237 | fnv = file->f_op->readv; | 1236 | fnv = file->f_op->aio_read; |
1238 | } else { | 1237 | } else { |
1239 | fn = (io_fn_t)file->f_op->write; | 1238 | fn = (io_fn_t)file->f_op->write; |
1240 | fnv = file->f_op->writev; | 1239 | fnv = file->f_op->aio_write; |
1241 | } | ||
1242 | if (fnv) { | ||
1243 | ret = fnv(file, iov, nr_segs, pos); | ||
1244 | goto out; | ||
1245 | } | 1240 | } |
1246 | 1241 | ||
1247 | /* Do it by hand, with file-ops */ | 1242 | if (fnv) |
1248 | ret = 0; | 1243 | ret = do_sync_readv_writev(file, iov, nr_segs, tot_len, |
1249 | vector = iov; | 1244 | pos, fnv); |
1250 | while (nr_segs > 0) { | 1245 | else |
1251 | void __user * base; | 1246 | ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn); |
1252 | size_t len; | ||
1253 | ssize_t nr; | ||
1254 | |||
1255 | base = vector->iov_base; | ||
1256 | len = vector->iov_len; | ||
1257 | vector++; | ||
1258 | nr_segs--; | ||
1259 | |||
1260 | nr = fn(file, base, len, pos); | ||
1261 | 1247 | ||
1262 | if (nr < 0) { | ||
1263 | if (!ret) ret = nr; | ||
1264 | break; | ||
1265 | } | ||
1266 | ret += nr; | ||
1267 | if (nr != len) | ||
1268 | break; | ||
1269 | } | ||
1270 | out: | 1248 | out: |
1271 | if (iov != iovstack) | 1249 | if (iov != iovstack) |
1272 | kfree(iov); | 1250 | kfree(iov); |
@@ -1294,7 +1272,7 @@ compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, unsign | |||
1294 | goto out; | 1272 | goto out; |
1295 | 1273 | ||
1296 | ret = -EINVAL; | 1274 | ret = -EINVAL; |
1297 | if (!file->f_op || (!file->f_op->readv && !file->f_op->read)) | 1275 | if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read)) |
1298 | goto out; | 1276 | goto out; |
1299 | 1277 | ||
1300 | ret = compat_do_readv_writev(READ, file, vec, vlen, &file->f_pos); | 1278 | ret = compat_do_readv_writev(READ, file, vec, vlen, &file->f_pos); |
@@ -1317,7 +1295,7 @@ compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, unsig | |||
1317 | goto out; | 1295 | goto out; |
1318 | 1296 | ||
1319 | ret = -EINVAL; | 1297 | ret = -EINVAL; |
1320 | if (!file->f_op || (!file->f_op->writev && !file->f_op->write)) | 1298 | if (!file->f_op || (!file->f_op->aio_write && !file->f_op->write)) |
1321 | goto out; | 1299 | goto out; |
1322 | 1300 | ||
1323 | ret = compat_do_readv_writev(WRITE, file, vec, vlen, &file->f_pos); | 1301 | ret = compat_do_readv_writev(WRITE, file, vec, vlen, &file->f_pos); |