diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2015-04-11 22:28:58 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2015-04-11 22:28:58 -0400 |
commit | c48722c6364ec94738afa42e48b1e1f8f20e3192 (patch) | |
tree | b2abd188e9d7dac738e7d5ddad6b0bc022cd1db8 /fs | |
parent | 34d0640e268923bb1fb9d244a047cdfcd3f77909 (diff) | |
parent | dcdbd7b269003bec7d729ca3fd143f93cf98f56e (diff) |
Merge branch '9p-iov_iter' into for-next
Diffstat (limited to 'fs')
-rw-r--r-- | fs/9p/v9fs_vfs.h | 4 | ||||
-rw-r--r-- | fs/9p/vfs_addr.c | 80 | ||||
-rw-r--r-- | fs/9p/vfs_dir.c | 15 | ||||
-rw-r--r-- | fs/9p/vfs_file.c | 326 | ||||
-rw-r--r-- | fs/9p/xattr.c | 80 |
5 files changed, 139 insertions, 366 deletions
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h index b83ebfbf3fdc..5a0db6dec8d1 100644 --- a/fs/9p/v9fs_vfs.h +++ b/fs/9p/v9fs_vfs.h | |||
@@ -68,14 +68,10 @@ int v9fs_file_open(struct inode *inode, struct file *file); | |||
68 | void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat); | 68 | void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat); |
69 | int v9fs_uflags2omode(int uflags, int extended); | 69 | int v9fs_uflags2omode(int uflags, int extended); |
70 | 70 | ||
71 | ssize_t v9fs_file_readn(struct file *, char *, char __user *, u32, u64); | ||
72 | ssize_t v9fs_fid_readn(struct p9_fid *, char *, char __user *, u32, u64); | ||
73 | void v9fs_blank_wstat(struct p9_wstat *wstat); | 71 | void v9fs_blank_wstat(struct p9_wstat *wstat); |
74 | int v9fs_vfs_setattr_dotl(struct dentry *, struct iattr *); | 72 | int v9fs_vfs_setattr_dotl(struct dentry *, struct iattr *); |
75 | int v9fs_file_fsync_dotl(struct file *filp, loff_t start, loff_t end, | 73 | int v9fs_file_fsync_dotl(struct file *filp, loff_t start, loff_t end, |
76 | int datasync); | 74 | int datasync); |
77 | ssize_t v9fs_file_write_internal(struct inode *, struct p9_fid *, | ||
78 | const char __user *, size_t, loff_t *, int); | ||
79 | int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode); | 75 | int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode); |
80 | int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode); | 76 | int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode); |
81 | static inline void v9fs_invalidate_inode_attr(struct inode *inode) | 77 | static inline void v9fs_invalidate_inode_attr(struct inode *inode) |
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c index ff1a5bac4200..2e38f9a5b472 100644 --- a/fs/9p/vfs_addr.c +++ b/fs/9p/vfs_addr.c | |||
@@ -51,12 +51,11 @@ | |||
51 | */ | 51 | */ |
52 | static int v9fs_fid_readpage(struct p9_fid *fid, struct page *page) | 52 | static int v9fs_fid_readpage(struct p9_fid *fid, struct page *page) |
53 | { | 53 | { |
54 | int retval; | 54 | struct inode *inode = page->mapping->host; |
55 | loff_t offset; | 55 | struct bio_vec bvec = {.bv_page = page, .bv_len = PAGE_SIZE}; |
56 | char *buffer; | 56 | struct iov_iter to; |
57 | struct inode *inode; | 57 | int retval, err; |
58 | 58 | ||
59 | inode = page->mapping->host; | ||
60 | p9_debug(P9_DEBUG_VFS, "\n"); | 59 | p9_debug(P9_DEBUG_VFS, "\n"); |
61 | 60 | ||
62 | BUG_ON(!PageLocked(page)); | 61 | BUG_ON(!PageLocked(page)); |
@@ -65,16 +64,16 @@ static int v9fs_fid_readpage(struct p9_fid *fid, struct page *page) | |||
65 | if (retval == 0) | 64 | if (retval == 0) |
66 | return retval; | 65 | return retval; |
67 | 66 | ||
68 | buffer = kmap(page); | 67 | iov_iter_bvec(&to, ITER_BVEC | READ, &bvec, 1, PAGE_SIZE); |
69 | offset = page_offset(page); | ||
70 | 68 | ||
71 | retval = v9fs_fid_readn(fid, buffer, NULL, PAGE_CACHE_SIZE, offset); | 69 | retval = p9_client_read(fid, page_offset(page), &to, &err); |
72 | if (retval < 0) { | 70 | if (err) { |
73 | v9fs_uncache_page(inode, page); | 71 | v9fs_uncache_page(inode, page); |
72 | retval = err; | ||
74 | goto done; | 73 | goto done; |
75 | } | 74 | } |
76 | 75 | ||
77 | memset(buffer + retval, 0, PAGE_CACHE_SIZE - retval); | 76 | zero_user(page, retval, PAGE_SIZE - retval); |
78 | flush_dcache_page(page); | 77 | flush_dcache_page(page); |
79 | SetPageUptodate(page); | 78 | SetPageUptodate(page); |
80 | 79 | ||
@@ -82,7 +81,6 @@ static int v9fs_fid_readpage(struct p9_fid *fid, struct page *page) | |||
82 | retval = 0; | 81 | retval = 0; |
83 | 82 | ||
84 | done: | 83 | done: |
85 | kunmap(page); | ||
86 | unlock_page(page); | 84 | unlock_page(page); |
87 | return retval; | 85 | return retval; |
88 | } | 86 | } |
@@ -161,41 +159,32 @@ static void v9fs_invalidate_page(struct page *page, unsigned int offset, | |||
161 | 159 | ||
162 | static int v9fs_vfs_writepage_locked(struct page *page) | 160 | static int v9fs_vfs_writepage_locked(struct page *page) |
163 | { | 161 | { |
164 | char *buffer; | ||
165 | int retval, len; | ||
166 | loff_t offset, size; | ||
167 | mm_segment_t old_fs; | ||
168 | struct v9fs_inode *v9inode; | ||
169 | struct inode *inode = page->mapping->host; | 162 | struct inode *inode = page->mapping->host; |
163 | struct v9fs_inode *v9inode = V9FS_I(inode); | ||
164 | loff_t size = i_size_read(inode); | ||
165 | struct iov_iter from; | ||
166 | struct bio_vec bvec; | ||
167 | int err, len; | ||
170 | 168 | ||
171 | v9inode = V9FS_I(inode); | ||
172 | size = i_size_read(inode); | ||
173 | if (page->index == size >> PAGE_CACHE_SHIFT) | 169 | if (page->index == size >> PAGE_CACHE_SHIFT) |
174 | len = size & ~PAGE_CACHE_MASK; | 170 | len = size & ~PAGE_CACHE_MASK; |
175 | else | 171 | else |
176 | len = PAGE_CACHE_SIZE; | 172 | len = PAGE_CACHE_SIZE; |
177 | 173 | ||
178 | set_page_writeback(page); | 174 | bvec.bv_page = page; |
179 | 175 | bvec.bv_offset = 0; | |
180 | buffer = kmap(page); | 176 | bvec.bv_len = len; |
181 | offset = page_offset(page); | 177 | iov_iter_bvec(&from, ITER_BVEC | WRITE, &bvec, 1, len); |
182 | 178 | ||
183 | old_fs = get_fs(); | ||
184 | set_fs(get_ds()); | ||
185 | /* We should have writeback_fid always set */ | 179 | /* We should have writeback_fid always set */ |
186 | BUG_ON(!v9inode->writeback_fid); | 180 | BUG_ON(!v9inode->writeback_fid); |
187 | 181 | ||
188 | retval = v9fs_file_write_internal(inode, | 182 | set_page_writeback(page); |
189 | v9inode->writeback_fid, | 183 | |
190 | (__force const char __user *)buffer, | 184 | p9_client_write(v9inode->writeback_fid, page_offset(page), &from, &err); |
191 | len, &offset, 0); | ||
192 | if (retval > 0) | ||
193 | retval = 0; | ||
194 | 185 | ||
195 | set_fs(old_fs); | ||
196 | kunmap(page); | ||
197 | end_page_writeback(page); | 186 | end_page_writeback(page); |
198 | return retval; | 187 | return err; |
199 | } | 188 | } |
200 | 189 | ||
201 | static int v9fs_vfs_writepage(struct page *page, struct writeback_control *wbc) | 190 | static int v9fs_vfs_writepage(struct page *page, struct writeback_control *wbc) |
@@ -261,16 +250,21 @@ static int v9fs_launder_page(struct page *page) | |||
261 | static ssize_t | 250 | static ssize_t |
262 | v9fs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, loff_t pos) | 251 | v9fs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, loff_t pos) |
263 | { | 252 | { |
264 | /* | 253 | struct file *file = iocb->ki_filp; |
265 | * FIXME | 254 | ssize_t n; |
266 | * Now that we do caching with cache mode enabled, We need | 255 | int err = 0; |
267 | * to support direct IO | 256 | if (rw & WRITE) { |
268 | */ | 257 | n = p9_client_write(file->private_data, pos, iter, &err); |
269 | p9_debug(P9_DEBUG_VFS, "v9fs_direct_IO: v9fs_direct_IO (%pD) off/no(%lld/%lu) EINVAL\n", | 258 | if (n) { |
270 | iocb->ki_filp, | 259 | struct inode *inode = file_inode(file); |
271 | (long long)pos, iter->nr_segs); | 260 | loff_t i_size = i_size_read(inode); |
272 | 261 | if (pos + n > i_size) | |
273 | return -EINVAL; | 262 | inode_add_bytes(inode, pos + n - i_size); |
263 | } | ||
264 | } else { | ||
265 | n = p9_client_read(file->private_data, pos, iter, &err); | ||
266 | } | ||
267 | return n ? n : err; | ||
274 | } | 268 | } |
275 | 269 | ||
276 | static int v9fs_write_begin(struct file *filp, struct address_space *mapping, | 270 | static int v9fs_write_begin(struct file *filp, struct address_space *mapping, |
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index 4f1151088ebe..76c3b1ab6361 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/inet.h> | 33 | #include <linux/inet.h> |
34 | #include <linux/idr.h> | 34 | #include <linux/idr.h> |
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/uio.h> | ||
36 | #include <net/9p/9p.h> | 37 | #include <net/9p/9p.h> |
37 | #include <net/9p/client.h> | 38 | #include <net/9p/client.h> |
38 | 39 | ||
@@ -115,6 +116,7 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx) | |||
115 | int buflen; | 116 | int buflen; |
116 | int reclen = 0; | 117 | int reclen = 0; |
117 | struct p9_rdir *rdir; | 118 | struct p9_rdir *rdir; |
119 | struct kvec kvec; | ||
118 | 120 | ||
119 | p9_debug(P9_DEBUG_VFS, "name %pD\n", file); | 121 | p9_debug(P9_DEBUG_VFS, "name %pD\n", file); |
120 | fid = file->private_data; | 122 | fid = file->private_data; |
@@ -124,16 +126,21 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx) | |||
124 | rdir = v9fs_alloc_rdir_buf(file, buflen); | 126 | rdir = v9fs_alloc_rdir_buf(file, buflen); |
125 | if (!rdir) | 127 | if (!rdir) |
126 | return -ENOMEM; | 128 | return -ENOMEM; |
129 | kvec.iov_base = rdir->buf; | ||
130 | kvec.iov_len = buflen; | ||
127 | 131 | ||
128 | while (1) { | 132 | while (1) { |
129 | if (rdir->tail == rdir->head) { | 133 | if (rdir->tail == rdir->head) { |
130 | err = v9fs_file_readn(file, rdir->buf, NULL, | 134 | struct iov_iter to; |
131 | buflen, ctx->pos); | 135 | int n; |
132 | if (err <= 0) | 136 | iov_iter_kvec(&to, READ | ITER_KVEC, &kvec, 1, buflen); |
137 | n = p9_client_read(file->private_data, ctx->pos, &to, | ||
138 | &err); | ||
139 | if (err) | ||
133 | return err; | 140 | return err; |
134 | 141 | ||
135 | rdir->head = 0; | 142 | rdir->head = 0; |
136 | rdir->tail = err; | 143 | rdir->tail = n; |
137 | } | 144 | } |
138 | while (rdir->head < rdir->tail) { | 145 | while (rdir->head < rdir->tail) { |
139 | p9stat_init(&st); | 146 | p9stat_init(&st); |
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index b40133796b87..55cc9c80e187 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
@@ -36,6 +36,8 @@ | |||
36 | #include <linux/utsname.h> | 36 | #include <linux/utsname.h> |
37 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
38 | #include <linux/idr.h> | 38 | #include <linux/idr.h> |
39 | #include <linux/uio.h> | ||
40 | #include <linux/slab.h> | ||
39 | #include <net/9p/9p.h> | 41 | #include <net/9p/9p.h> |
40 | #include <net/9p/client.h> | 42 | #include <net/9p/client.h> |
41 | 43 | ||
@@ -285,6 +287,7 @@ static int v9fs_file_getlock(struct file *filp, struct file_lock *fl) | |||
285 | fl->fl_end = glock.start + glock.length - 1; | 287 | fl->fl_end = glock.start + glock.length - 1; |
286 | fl->fl_pid = glock.proc_id; | 288 | fl->fl_pid = glock.proc_id; |
287 | } | 289 | } |
290 | kfree(glock.client_id); | ||
288 | return res; | 291 | return res; |
289 | } | 292 | } |
290 | 293 | ||
@@ -364,63 +367,6 @@ out_err: | |||
364 | } | 367 | } |
365 | 368 | ||
366 | /** | 369 | /** |
367 | * v9fs_fid_readn - read from a fid | ||
368 | * @fid: fid to read | ||
369 | * @data: data buffer to read data into | ||
370 | * @udata: user data buffer to read data into | ||
371 | * @count: size of buffer | ||
372 | * @offset: offset at which to read data | ||
373 | * | ||
374 | */ | ||
375 | ssize_t | ||
376 | v9fs_fid_readn(struct p9_fid *fid, char *data, char __user *udata, u32 count, | ||
377 | u64 offset) | ||
378 | { | ||
379 | int n, total, size; | ||
380 | |||
381 | p9_debug(P9_DEBUG_VFS, "fid %d offset %llu count %d\n", | ||
382 | fid->fid, (long long unsigned)offset, count); | ||
383 | n = 0; | ||
384 | total = 0; | ||
385 | size = fid->iounit ? fid->iounit : fid->clnt->msize - P9_IOHDRSZ; | ||
386 | do { | ||
387 | n = p9_client_read(fid, data, udata, offset, count); | ||
388 | if (n <= 0) | ||
389 | break; | ||
390 | |||
391 | if (data) | ||
392 | data += n; | ||
393 | if (udata) | ||
394 | udata += n; | ||
395 | |||
396 | offset += n; | ||
397 | count -= n; | ||
398 | total += n; | ||
399 | } while (count > 0 && n == size); | ||
400 | |||
401 | if (n < 0) | ||
402 | total = n; | ||
403 | |||
404 | return total; | ||
405 | } | ||
406 | |||
407 | /** | ||
408 | * v9fs_file_readn - read from a file | ||
409 | * @filp: file pointer to read | ||
410 | * @data: data buffer to read data into | ||
411 | * @udata: user data buffer to read data into | ||
412 | * @count: size of buffer | ||
413 | * @offset: offset at which to read data | ||
414 | * | ||
415 | */ | ||
416 | ssize_t | ||
417 | v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count, | ||
418 | u64 offset) | ||
419 | { | ||
420 | return v9fs_fid_readn(filp->private_data, data, udata, count, offset); | ||
421 | } | ||
422 | |||
423 | /** | ||
424 | * v9fs_file_read - read from a file | 370 | * v9fs_file_read - read from a file |
425 | * @filp: file pointer to read | 371 | * @filp: file pointer to read |
426 | * @udata: user data buffer to read data into | 372 | * @udata: user data buffer to read data into |
@@ -430,69 +376,22 @@ v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count, | |||
430 | */ | 376 | */ |
431 | 377 | ||
432 | static ssize_t | 378 | static ssize_t |
433 | v9fs_file_read(struct file *filp, char __user *udata, size_t count, | 379 | v9fs_file_read_iter(struct kiocb *iocb, struct iov_iter *to) |
434 | loff_t * offset) | ||
435 | { | 380 | { |
436 | int ret; | 381 | struct p9_fid *fid = iocb->ki_filp->private_data; |
437 | struct p9_fid *fid; | 382 | int ret, err; |
438 | size_t size; | ||
439 | 383 | ||
440 | p9_debug(P9_DEBUG_VFS, "count %zu offset %lld\n", count, *offset); | 384 | p9_debug(P9_DEBUG_VFS, "count %zu offset %lld\n", |
441 | fid = filp->private_data; | 385 | iov_iter_count(to), iocb->ki_pos); |
442 | 386 | ||
443 | size = fid->iounit ? fid->iounit : fid->clnt->msize - P9_IOHDRSZ; | 387 | ret = p9_client_read(fid, iocb->ki_pos, to, &err); |
444 | if (count > size) | 388 | if (!ret) |
445 | ret = v9fs_file_readn(filp, NULL, udata, count, *offset); | 389 | return err; |
446 | else | ||
447 | ret = p9_client_read(fid, NULL, udata, *offset, count); | ||
448 | |||
449 | if (ret > 0) | ||
450 | *offset += ret; | ||
451 | 390 | ||
391 | iocb->ki_pos += ret; | ||
452 | return ret; | 392 | return ret; |
453 | } | 393 | } |
454 | 394 | ||
455 | ssize_t | ||
456 | v9fs_file_write_internal(struct inode *inode, struct p9_fid *fid, | ||
457 | const char __user *data, size_t count, | ||
458 | loff_t *offset, int invalidate) | ||
459 | { | ||
460 | int n; | ||
461 | loff_t i_size; | ||
462 | size_t total = 0; | ||
463 | loff_t origin = *offset; | ||
464 | unsigned long pg_start, pg_end; | ||
465 | |||
466 | p9_debug(P9_DEBUG_VFS, "data %p count %d offset %x\n", | ||
467 | data, (int)count, (int)*offset); | ||
468 | |||
469 | do { | ||
470 | n = p9_client_write(fid, NULL, data+total, origin+total, count); | ||
471 | if (n <= 0) | ||
472 | break; | ||
473 | count -= n; | ||
474 | total += n; | ||
475 | } while (count > 0); | ||
476 | |||
477 | if (invalidate && (total > 0)) { | ||
478 | pg_start = origin >> PAGE_CACHE_SHIFT; | ||
479 | pg_end = (origin + total - 1) >> PAGE_CACHE_SHIFT; | ||
480 | if (inode->i_mapping && inode->i_mapping->nrpages) | ||
481 | invalidate_inode_pages2_range(inode->i_mapping, | ||
482 | pg_start, pg_end); | ||
483 | *offset += total; | ||
484 | i_size = i_size_read(inode); | ||
485 | if (*offset > i_size) { | ||
486 | inode_add_bytes(inode, *offset - i_size); | ||
487 | i_size_write(inode, *offset); | ||
488 | } | ||
489 | } | ||
490 | if (n < 0) | ||
491 | return n; | ||
492 | |||
493 | return total; | ||
494 | } | ||
495 | |||
496 | /** | 395 | /** |
497 | * v9fs_file_write - write to a file | 396 | * v9fs_file_write - write to a file |
498 | * @filp: file pointer to write | 397 | * @filp: file pointer to write |
@@ -502,35 +401,45 @@ v9fs_file_write_internal(struct inode *inode, struct p9_fid *fid, | |||
502 | * | 401 | * |
503 | */ | 402 | */ |
504 | static ssize_t | 403 | static ssize_t |
505 | v9fs_file_write(struct file *filp, const char __user * data, | 404 | v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) |
506 | size_t count, loff_t *offset) | ||
507 | { | 405 | { |
406 | struct file *file = iocb->ki_filp; | ||
508 | ssize_t retval = 0; | 407 | ssize_t retval = 0; |
509 | loff_t origin = *offset; | 408 | loff_t origin = iocb->ki_pos; |
409 | size_t count = iov_iter_count(from); | ||
410 | int err = 0; | ||
510 | 411 | ||
511 | 412 | retval = generic_write_checks(file, &origin, &count, 0); | |
512 | retval = generic_write_checks(filp, &origin, &count, 0); | ||
513 | if (retval) | 413 | if (retval) |
514 | goto out; | 414 | return retval; |
415 | |||
416 | iov_iter_truncate(from, count); | ||
515 | 417 | ||
516 | retval = -EINVAL; | ||
517 | if ((ssize_t) count < 0) | ||
518 | goto out; | ||
519 | retval = 0; | ||
520 | if (!count) | 418 | if (!count) |
521 | goto out; | 419 | return 0; |
522 | 420 | ||
523 | retval = v9fs_file_write_internal(file_inode(filp), | 421 | retval = p9_client_write(file->private_data, origin, from, &err); |
524 | filp->private_data, | 422 | if (retval > 0) { |
525 | data, count, &origin, 1); | 423 | struct inode *inode = file_inode(file); |
526 | /* update offset on successful write */ | 424 | loff_t i_size; |
527 | if (retval > 0) | 425 | unsigned long pg_start, pg_end; |
528 | *offset = origin; | 426 | pg_start = origin >> PAGE_CACHE_SHIFT; |
529 | out: | 427 | pg_end = (origin + retval - 1) >> PAGE_CACHE_SHIFT; |
530 | return retval; | 428 | if (inode->i_mapping && inode->i_mapping->nrpages) |
429 | invalidate_inode_pages2_range(inode->i_mapping, | ||
430 | pg_start, pg_end); | ||
431 | origin += retval; | ||
432 | i_size = i_size_read(inode); | ||
433 | iocb->ki_pos = origin; | ||
434 | if (origin > i_size) { | ||
435 | inode_add_bytes(inode, origin - i_size); | ||
436 | i_size_write(inode, origin); | ||
437 | } | ||
438 | return retval; | ||
439 | } | ||
440 | return err; | ||
531 | } | 441 | } |
532 | 442 | ||
533 | |||
534 | static int v9fs_file_fsync(struct file *filp, loff_t start, loff_t end, | 443 | static int v9fs_file_fsync(struct file *filp, loff_t start, loff_t end, |
535 | int datasync) | 444 | int datasync) |
536 | { | 445 | { |
@@ -657,44 +566,6 @@ out_unlock: | |||
657 | return VM_FAULT_NOPAGE; | 566 | return VM_FAULT_NOPAGE; |
658 | } | 567 | } |
659 | 568 | ||
660 | static ssize_t | ||
661 | v9fs_direct_read(struct file *filp, char __user *udata, size_t count, | ||
662 | loff_t *offsetp) | ||
663 | { | ||
664 | loff_t size, offset; | ||
665 | struct inode *inode; | ||
666 | struct address_space *mapping; | ||
667 | |||
668 | offset = *offsetp; | ||
669 | mapping = filp->f_mapping; | ||
670 | inode = mapping->host; | ||
671 | if (!count) | ||
672 | return 0; | ||
673 | size = i_size_read(inode); | ||
674 | if (offset < size) | ||
675 | filemap_write_and_wait_range(mapping, offset, | ||
676 | offset + count - 1); | ||
677 | |||
678 | return v9fs_file_read(filp, udata, count, offsetp); | ||
679 | } | ||
680 | |||
681 | /** | ||
682 | * v9fs_cached_file_read - read from a file | ||
683 | * @filp: file pointer to read | ||
684 | * @data: user data buffer to read data into | ||
685 | * @count: size of buffer | ||
686 | * @offset: offset at which to read data | ||
687 | * | ||
688 | */ | ||
689 | static ssize_t | ||
690 | v9fs_cached_file_read(struct file *filp, char __user *data, size_t count, | ||
691 | loff_t *offset) | ||
692 | { | ||
693 | if (filp->f_flags & O_DIRECT) | ||
694 | return v9fs_direct_read(filp, data, count, offset); | ||
695 | return new_sync_read(filp, data, count, offset); | ||
696 | } | ||
697 | |||
698 | /** | 569 | /** |
699 | * v9fs_mmap_file_read - read from a file | 570 | * v9fs_mmap_file_read - read from a file |
700 | * @filp: file pointer to read | 571 | * @filp: file pointer to read |
@@ -704,84 +575,12 @@ v9fs_cached_file_read(struct file *filp, char __user *data, size_t count, | |||
704 | * | 575 | * |
705 | */ | 576 | */ |
706 | static ssize_t | 577 | static ssize_t |
707 | v9fs_mmap_file_read(struct file *filp, char __user *data, size_t count, | 578 | v9fs_mmap_file_read_iter(struct kiocb *iocb, struct iov_iter *to) |
708 | loff_t *offset) | ||
709 | { | 579 | { |
710 | /* TODO: Check if there are dirty pages */ | 580 | /* TODO: Check if there are dirty pages */ |
711 | return v9fs_file_read(filp, data, count, offset); | 581 | return v9fs_file_read_iter(iocb, to); |
712 | } | 582 | } |
713 | 583 | ||
714 | static ssize_t | ||
715 | v9fs_direct_write(struct file *filp, const char __user * data, | ||
716 | size_t count, loff_t *offsetp) | ||
717 | { | ||
718 | loff_t offset; | ||
719 | ssize_t retval; | ||
720 | struct inode *inode; | ||
721 | struct address_space *mapping; | ||
722 | |||
723 | offset = *offsetp; | ||
724 | mapping = filp->f_mapping; | ||
725 | inode = mapping->host; | ||
726 | if (!count) | ||
727 | return 0; | ||
728 | |||
729 | mutex_lock(&inode->i_mutex); | ||
730 | retval = filemap_write_and_wait_range(mapping, offset, | ||
731 | offset + count - 1); | ||
732 | if (retval) | ||
733 | goto err_out; | ||
734 | /* | ||
735 | * After a write we want buffered reads to be sure to go to disk to get | ||
736 | * the new data. We invalidate clean cached page from the region we're | ||
737 | * about to write. We do this *before* the write so that if we fail | ||
738 | * here we fall back to buffered write | ||
739 | */ | ||
740 | if (mapping->nrpages) { | ||
741 | pgoff_t pg_start = offset >> PAGE_CACHE_SHIFT; | ||
742 | pgoff_t pg_end = (offset + count - 1) >> PAGE_CACHE_SHIFT; | ||
743 | |||
744 | retval = invalidate_inode_pages2_range(mapping, | ||
745 | pg_start, pg_end); | ||
746 | /* | ||
747 | * If a page can not be invalidated, fall back | ||
748 | * to buffered write. | ||
749 | */ | ||
750 | if (retval) { | ||
751 | if (retval == -EBUSY) | ||
752 | goto buff_write; | ||
753 | goto err_out; | ||
754 | } | ||
755 | } | ||
756 | retval = v9fs_file_write(filp, data, count, offsetp); | ||
757 | err_out: | ||
758 | mutex_unlock(&inode->i_mutex); | ||
759 | return retval; | ||
760 | |||
761 | buff_write: | ||
762 | mutex_unlock(&inode->i_mutex); | ||
763 | return new_sync_write(filp, data, count, offsetp); | ||
764 | } | ||
765 | |||
766 | /** | ||
767 | * v9fs_cached_file_write - write to a file | ||
768 | * @filp: file pointer to write | ||
769 | * @data: data buffer to write data from | ||
770 | * @count: size of buffer | ||
771 | * @offset: offset at which to write data | ||
772 | * | ||
773 | */ | ||
774 | static ssize_t | ||
775 | v9fs_cached_file_write(struct file *filp, const char __user * data, | ||
776 | size_t count, loff_t *offset) | ||
777 | { | ||
778 | |||
779 | if (filp->f_flags & O_DIRECT) | ||
780 | return v9fs_direct_write(filp, data, count, offset); | ||
781 | return new_sync_write(filp, data, count, offset); | ||
782 | } | ||
783 | |||
784 | |||
785 | /** | 584 | /** |
786 | * v9fs_mmap_file_write - write to a file | 585 | * v9fs_mmap_file_write - write to a file |
787 | * @filp: file pointer to write | 586 | * @filp: file pointer to write |
@@ -791,14 +590,13 @@ v9fs_cached_file_write(struct file *filp, const char __user * data, | |||
791 | * | 590 | * |
792 | */ | 591 | */ |
793 | static ssize_t | 592 | static ssize_t |
794 | v9fs_mmap_file_write(struct file *filp, const char __user *data, | 593 | v9fs_mmap_file_write_iter(struct kiocb *iocb, struct iov_iter *from) |
795 | size_t count, loff_t *offset) | ||
796 | { | 594 | { |
797 | /* | 595 | /* |
798 | * TODO: invalidate mmaps on filp's inode between | 596 | * TODO: invalidate mmaps on filp's inode between |
799 | * offset and offset+count | 597 | * offset and offset+count |
800 | */ | 598 | */ |
801 | return v9fs_file_write(filp, data, count, offset); | 599 | return v9fs_file_write_iter(iocb, from); |
802 | } | 600 | } |
803 | 601 | ||
804 | static void v9fs_mmap_vm_close(struct vm_area_struct *vma) | 602 | static void v9fs_mmap_vm_close(struct vm_area_struct *vma) |
@@ -843,8 +641,8 @@ static const struct vm_operations_struct v9fs_mmap_file_vm_ops = { | |||
843 | 641 | ||
844 | const struct file_operations v9fs_cached_file_operations = { | 642 | const struct file_operations v9fs_cached_file_operations = { |
845 | .llseek = generic_file_llseek, | 643 | .llseek = generic_file_llseek, |
846 | .read = v9fs_cached_file_read, | 644 | .read = new_sync_read, |
847 | .write = v9fs_cached_file_write, | 645 | .write = new_sync_write, |
848 | .read_iter = generic_file_read_iter, | 646 | .read_iter = generic_file_read_iter, |
849 | .write_iter = generic_file_write_iter, | 647 | .write_iter = generic_file_write_iter, |
850 | .open = v9fs_file_open, | 648 | .open = v9fs_file_open, |
@@ -856,8 +654,8 @@ const struct file_operations v9fs_cached_file_operations = { | |||
856 | 654 | ||
857 | const struct file_operations v9fs_cached_file_operations_dotl = { | 655 | const struct file_operations v9fs_cached_file_operations_dotl = { |
858 | .llseek = generic_file_llseek, | 656 | .llseek = generic_file_llseek, |
859 | .read = v9fs_cached_file_read, | 657 | .read = new_sync_read, |
860 | .write = v9fs_cached_file_write, | 658 | .write = new_sync_write, |
861 | .read_iter = generic_file_read_iter, | 659 | .read_iter = generic_file_read_iter, |
862 | .write_iter = generic_file_write_iter, | 660 | .write_iter = generic_file_write_iter, |
863 | .open = v9fs_file_open, | 661 | .open = v9fs_file_open, |
@@ -870,8 +668,10 @@ const struct file_operations v9fs_cached_file_operations_dotl = { | |||
870 | 668 | ||
871 | const struct file_operations v9fs_file_operations = { | 669 | const struct file_operations v9fs_file_operations = { |
872 | .llseek = generic_file_llseek, | 670 | .llseek = generic_file_llseek, |
873 | .read = v9fs_file_read, | 671 | .read = new_sync_read, |
874 | .write = v9fs_file_write, | 672 | .write = new_sync_write, |
673 | .read_iter = v9fs_file_read_iter, | ||
674 | .write_iter = v9fs_file_write_iter, | ||
875 | .open = v9fs_file_open, | 675 | .open = v9fs_file_open, |
876 | .release = v9fs_dir_release, | 676 | .release = v9fs_dir_release, |
877 | .lock = v9fs_file_lock, | 677 | .lock = v9fs_file_lock, |
@@ -881,8 +681,10 @@ const struct file_operations v9fs_file_operations = { | |||
881 | 681 | ||
882 | const struct file_operations v9fs_file_operations_dotl = { | 682 | const struct file_operations v9fs_file_operations_dotl = { |
883 | .llseek = generic_file_llseek, | 683 | .llseek = generic_file_llseek, |
884 | .read = v9fs_file_read, | 684 | .read = new_sync_read, |
885 | .write = v9fs_file_write, | 685 | .write = new_sync_write, |
686 | .read_iter = v9fs_file_read_iter, | ||
687 | .write_iter = v9fs_file_write_iter, | ||
886 | .open = v9fs_file_open, | 688 | .open = v9fs_file_open, |
887 | .release = v9fs_dir_release, | 689 | .release = v9fs_dir_release, |
888 | .lock = v9fs_file_lock_dotl, | 690 | .lock = v9fs_file_lock_dotl, |
@@ -893,8 +695,10 @@ const struct file_operations v9fs_file_operations_dotl = { | |||
893 | 695 | ||
894 | const struct file_operations v9fs_mmap_file_operations = { | 696 | const struct file_operations v9fs_mmap_file_operations = { |
895 | .llseek = generic_file_llseek, | 697 | .llseek = generic_file_llseek, |
896 | .read = v9fs_mmap_file_read, | 698 | .read = new_sync_read, |
897 | .write = v9fs_mmap_file_write, | 699 | .write = new_sync_write, |
700 | .read_iter = v9fs_mmap_file_read_iter, | ||
701 | .write_iter = v9fs_mmap_file_write_iter, | ||
898 | .open = v9fs_file_open, | 702 | .open = v9fs_file_open, |
899 | .release = v9fs_dir_release, | 703 | .release = v9fs_dir_release, |
900 | .lock = v9fs_file_lock, | 704 | .lock = v9fs_file_lock, |
@@ -904,8 +708,10 @@ const struct file_operations v9fs_mmap_file_operations = { | |||
904 | 708 | ||
905 | const struct file_operations v9fs_mmap_file_operations_dotl = { | 709 | const struct file_operations v9fs_mmap_file_operations_dotl = { |
906 | .llseek = generic_file_llseek, | 710 | .llseek = generic_file_llseek, |
907 | .read = v9fs_mmap_file_read, | 711 | .read = new_sync_read, |
908 | .write = v9fs_mmap_file_write, | 712 | .write = new_sync_write, |
713 | .read_iter = v9fs_mmap_file_read_iter, | ||
714 | .write_iter = v9fs_mmap_file_write_iter, | ||
909 | .open = v9fs_file_open, | 715 | .open = v9fs_file_open, |
910 | .release = v9fs_dir_release, | 716 | .release = v9fs_dir_release, |
911 | .lock = v9fs_file_lock_dotl, | 717 | .lock = v9fs_file_lock_dotl, |
diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c index f95e01e058e4..0cf44b6cccd6 100644 --- a/fs/9p/xattr.c +++ b/fs/9p/xattr.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/fs.h> | 16 | #include <linux/fs.h> |
17 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
18 | #include <linux/uio.h> | ||
18 | #include <net/9p/9p.h> | 19 | #include <net/9p/9p.h> |
19 | #include <net/9p/client.h> | 20 | #include <net/9p/client.h> |
20 | 21 | ||
@@ -25,50 +26,34 @@ ssize_t v9fs_fid_xattr_get(struct p9_fid *fid, const char *name, | |||
25 | void *buffer, size_t buffer_size) | 26 | void *buffer, size_t buffer_size) |
26 | { | 27 | { |
27 | ssize_t retval; | 28 | ssize_t retval; |
28 | int msize, read_count; | 29 | u64 attr_size; |
29 | u64 offset = 0, attr_size; | ||
30 | struct p9_fid *attr_fid; | 30 | struct p9_fid *attr_fid; |
31 | struct kvec kvec = {.iov_base = buffer, .iov_len = buffer_size}; | ||
32 | struct iov_iter to; | ||
33 | int err; | ||
34 | |||
35 | iov_iter_kvec(&to, READ | ITER_KVEC, &kvec, 1, buffer_size); | ||
31 | 36 | ||
32 | attr_fid = p9_client_xattrwalk(fid, name, &attr_size); | 37 | attr_fid = p9_client_xattrwalk(fid, name, &attr_size); |
33 | if (IS_ERR(attr_fid)) { | 38 | if (IS_ERR(attr_fid)) { |
34 | retval = PTR_ERR(attr_fid); | 39 | retval = PTR_ERR(attr_fid); |
35 | p9_debug(P9_DEBUG_VFS, "p9_client_attrwalk failed %zd\n", | 40 | p9_debug(P9_DEBUG_VFS, "p9_client_attrwalk failed %zd\n", |
36 | retval); | 41 | retval); |
37 | attr_fid = NULL; | 42 | return retval; |
38 | goto error; | ||
39 | } | ||
40 | if (!buffer_size) { | ||
41 | /* request to get the attr_size */ | ||
42 | retval = attr_size; | ||
43 | goto error; | ||
44 | } | 43 | } |
45 | if (attr_size > buffer_size) { | 44 | if (attr_size > buffer_size) { |
46 | retval = -ERANGE; | 45 | if (!buffer_size) /* request to get the attr_size */ |
47 | goto error; | 46 | retval = attr_size; |
48 | } | ||
49 | msize = attr_fid->clnt->msize; | ||
50 | while (attr_size) { | ||
51 | if (attr_size > (msize - P9_IOHDRSZ)) | ||
52 | read_count = msize - P9_IOHDRSZ; | ||
53 | else | 47 | else |
54 | read_count = attr_size; | 48 | retval = -ERANGE; |
55 | read_count = p9_client_read(attr_fid, ((char *)buffer)+offset, | 49 | } else { |
56 | NULL, offset, read_count); | 50 | iov_iter_truncate(&to, attr_size); |
57 | if (read_count < 0) { | 51 | retval = p9_client_read(attr_fid, 0, &to, &err); |
58 | /* error in xattr read */ | 52 | if (err) |
59 | retval = read_count; | 53 | retval = err; |
60 | goto error; | ||
61 | } | ||
62 | offset += read_count; | ||
63 | attr_size -= read_count; | ||
64 | } | 54 | } |
65 | /* Total read xattr bytes */ | 55 | p9_client_clunk(attr_fid); |
66 | retval = offset; | ||
67 | error: | ||
68 | if (attr_fid) | ||
69 | p9_client_clunk(attr_fid); | ||
70 | return retval; | 56 | return retval; |
71 | |||
72 | } | 57 | } |
73 | 58 | ||
74 | 59 | ||
@@ -120,8 +105,11 @@ int v9fs_xattr_set(struct dentry *dentry, const char *name, | |||
120 | int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name, | 105 | int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name, |
121 | const void *value, size_t value_len, int flags) | 106 | const void *value, size_t value_len, int flags) |
122 | { | 107 | { |
123 | u64 offset = 0; | 108 | struct kvec kvec = {.iov_base = (void *)value, .iov_len = value_len}; |
124 | int retval, msize, write_count; | 109 | struct iov_iter from; |
110 | int retval; | ||
111 | |||
112 | iov_iter_kvec(&from, WRITE | ITER_KVEC, &kvec, 1, value_len); | ||
125 | 113 | ||
126 | p9_debug(P9_DEBUG_VFS, "name = %s value_len = %zu flags = %d\n", | 114 | p9_debug(P9_DEBUG_VFS, "name = %s value_len = %zu flags = %d\n", |
127 | name, value_len, flags); | 115 | name, value_len, flags); |
@@ -135,29 +123,11 @@ int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name, | |||
135 | * On success fid points to xattr | 123 | * On success fid points to xattr |
136 | */ | 124 | */ |
137 | retval = p9_client_xattrcreate(fid, name, value_len, flags); | 125 | retval = p9_client_xattrcreate(fid, name, value_len, flags); |
138 | if (retval < 0) { | 126 | if (retval < 0) |
139 | p9_debug(P9_DEBUG_VFS, "p9_client_xattrcreate failed %d\n", | 127 | p9_debug(P9_DEBUG_VFS, "p9_client_xattrcreate failed %d\n", |
140 | retval); | 128 | retval); |
141 | goto err; | 129 | else |
142 | } | 130 | p9_client_write(fid, 0, &from, &retval); |
143 | msize = fid->clnt->msize; | ||
144 | while (value_len) { | ||
145 | if (value_len > (msize - P9_IOHDRSZ)) | ||
146 | write_count = msize - P9_IOHDRSZ; | ||
147 | else | ||
148 | write_count = value_len; | ||
149 | write_count = p9_client_write(fid, ((char *)value)+offset, | ||
150 | NULL, offset, write_count); | ||
151 | if (write_count < 0) { | ||
152 | /* error in xattr write */ | ||
153 | retval = write_count; | ||
154 | goto err; | ||
155 | } | ||
156 | offset += write_count; | ||
157 | value_len -= write_count; | ||
158 | } | ||
159 | retval = 0; | ||
160 | err: | ||
161 | p9_client_clunk(fid); | 131 | p9_client_clunk(fid); |
162 | return retval; | 132 | return retval; |
163 | } | 133 | } |