diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-16 23:27:56 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-16 23:27:56 -0400 |
commit | 4fc8adcfec3da639da76e8314c9ccefe5bf9a045 (patch) | |
tree | e07a2dea8acf04d8bbbecd4fd3a571653ecdd953 /include | |
parent | 84588e7a5d8220446d677d7b909a20ee7a4496b9 (diff) | |
parent | aa4d86163e4e91a1ac560954a554bab417e338f4 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull third hunk of vfs changes from Al Viro:
"This contains the ->direct_IO() changes from Omar + saner
generic_write_checks() + dealing with fcntl()/{read,write}() races
(mirroring O_APPEND/O_DIRECT into iocb->ki_flags and instead of
repeatedly looking at ->f_flags, which can be changed by fcntl(2),
check ->ki_flags - which cannot) + infrastructure bits for dhowells'
d_inode annotations + Christophs switch of /dev/loop to
vfs_iter_write()"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (30 commits)
block: loop: switch to VFS ITER_BVEC
configfs: Fix inconsistent use of file_inode() vs file->f_path.dentry->d_inode
VFS: Make pathwalk use d_is_reg() rather than S_ISREG()
VFS: Fix up debugfs to use d_is_dir() in place of S_ISDIR()
VFS: Combine inode checks with d_is_negative() and d_is_positive() in pathwalk
NFS: Don't use d_inode as a variable name
VFS: Impose ordering on accesses of d_inode and d_flags
VFS: Add owner-filesystem positive/negative dentry checks
nfs: generic_write_checks() shouldn't be done on swapout...
ocfs2: use __generic_file_write_iter()
mirror O_APPEND and O_DIRECT into iocb->ki_flags
switch generic_write_checks() to iocb and iter
ocfs2: move generic_write_checks() before the alignment checks
ocfs2_file_write_iter: stop messing with ppos
udf_file_write_iter: reorder and simplify
fuse: ->direct_IO() doesn't need generic_write_checks()
ext4_file_write_iter: move generic_write_checks() up
xfs_file_aio_write_checks: switch to iocb/iov_iter
generic_write_checks(): drop isblk argument
blkdev_write_iter: expand generic_file_checks() call in there
...
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/dcache.h | 59 | ||||
-rw-r--r-- | include/linux/fs.h | 41 | ||||
-rw-r--r-- | include/linux/nfs_fs.h | 5 | ||||
-rw-r--r-- | include/linux/uio.h | 8 |
4 files changed, 80 insertions, 33 deletions
diff --git a/include/linux/dcache.h b/include/linux/dcache.h index d8358799c594..df334cbacc6d 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h | |||
@@ -404,26 +404,11 @@ static inline bool d_mountpoint(const struct dentry *dentry) | |||
404 | /* | 404 | /* |
405 | * Directory cache entry type accessor functions. | 405 | * Directory cache entry type accessor functions. |
406 | */ | 406 | */ |
407 | static inline void __d_set_type(struct dentry *dentry, unsigned type) | ||
408 | { | ||
409 | dentry->d_flags = (dentry->d_flags & ~DCACHE_ENTRY_TYPE) | type; | ||
410 | } | ||
411 | |||
412 | static inline void __d_clear_type(struct dentry *dentry) | ||
413 | { | ||
414 | __d_set_type(dentry, DCACHE_MISS_TYPE); | ||
415 | } | ||
416 | |||
417 | static inline void d_set_type(struct dentry *dentry, unsigned type) | ||
418 | { | ||
419 | spin_lock(&dentry->d_lock); | ||
420 | __d_set_type(dentry, type); | ||
421 | spin_unlock(&dentry->d_lock); | ||
422 | } | ||
423 | |||
424 | static inline unsigned __d_entry_type(const struct dentry *dentry) | 407 | static inline unsigned __d_entry_type(const struct dentry *dentry) |
425 | { | 408 | { |
426 | return dentry->d_flags & DCACHE_ENTRY_TYPE; | 409 | unsigned type = READ_ONCE(dentry->d_flags); |
410 | smp_rmb(); | ||
411 | return type & DCACHE_ENTRY_TYPE; | ||
427 | } | 412 | } |
428 | 413 | ||
429 | static inline bool d_is_miss(const struct dentry *dentry) | 414 | static inline bool d_is_miss(const struct dentry *dentry) |
@@ -482,6 +467,44 @@ static inline bool d_is_positive(const struct dentry *dentry) | |||
482 | return !d_is_negative(dentry); | 467 | return !d_is_negative(dentry); |
483 | } | 468 | } |
484 | 469 | ||
470 | /** | ||
471 | * d_really_is_negative - Determine if a dentry is really negative (ignoring fallthroughs) | ||
472 | * @dentry: The dentry in question | ||
473 | * | ||
474 | * Returns true if the dentry represents either an absent name or a name that | ||
475 | * doesn't map to an inode (ie. ->d_inode is NULL). The dentry could represent | ||
476 | * a true miss, a whiteout that isn't represented by a 0,0 chardev or a | ||
477 | * fallthrough marker in an opaque directory. | ||
478 | * | ||
479 | * Note! (1) This should be used *only* by a filesystem to examine its own | ||
480 | * dentries. It should not be used to look at some other filesystem's | ||
481 | * dentries. (2) It should also be used in combination with d_inode() to get | ||
482 | * the inode. (3) The dentry may have something attached to ->d_lower and the | ||
483 | * type field of the flags may be set to something other than miss or whiteout. | ||
484 | */ | ||
485 | static inline bool d_really_is_negative(const struct dentry *dentry) | ||
486 | { | ||
487 | return dentry->d_inode == NULL; | ||
488 | } | ||
489 | |||
490 | /** | ||
491 | * d_really_is_positive - Determine if a dentry is really positive (ignoring fallthroughs) | ||
492 | * @dentry: The dentry in question | ||
493 | * | ||
494 | * Returns true if the dentry represents a name that maps to an inode | ||
495 | * (ie. ->d_inode is not NULL). The dentry might still represent a whiteout if | ||
496 | * that is represented on medium as a 0,0 chardev. | ||
497 | * | ||
498 | * Note! (1) This should be used *only* by a filesystem to examine its own | ||
499 | * dentries. It should not be used to look at some other filesystem's | ||
500 | * dentries. (2) It should also be used in combination with d_inode() to get | ||
501 | * the inode. | ||
502 | */ | ||
503 | static inline bool d_really_is_positive(const struct dentry *dentry) | ||
504 | { | ||
505 | return dentry->d_inode != NULL; | ||
506 | } | ||
507 | |||
485 | extern void d_set_fallthru(struct dentry *dentry); | 508 | extern void d_set_fallthru(struct dentry *dentry); |
486 | 509 | ||
487 | static inline bool d_is_fallthru(const struct dentry *dentry) | 510 | static inline bool d_is_fallthru(const struct dentry *dentry) |
diff --git a/include/linux/fs.h b/include/linux/fs.h index f4fc60727b8d..f4d63544a791 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -315,6 +315,8 @@ struct address_space; | |||
315 | struct writeback_control; | 315 | struct writeback_control; |
316 | 316 | ||
317 | #define IOCB_EVENTFD (1 << 0) | 317 | #define IOCB_EVENTFD (1 << 0) |
318 | #define IOCB_APPEND (1 << 1) | ||
319 | #define IOCB_DIRECT (1 << 2) | ||
318 | 320 | ||
319 | struct kiocb { | 321 | struct kiocb { |
320 | struct file *ki_filp; | 322 | struct file *ki_filp; |
@@ -329,10 +331,13 @@ static inline bool is_sync_kiocb(struct kiocb *kiocb) | |||
329 | return kiocb->ki_complete == NULL; | 331 | return kiocb->ki_complete == NULL; |
330 | } | 332 | } |
331 | 333 | ||
334 | static inline int iocb_flags(struct file *file); | ||
335 | |||
332 | static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp) | 336 | static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp) |
333 | { | 337 | { |
334 | *kiocb = (struct kiocb) { | 338 | *kiocb = (struct kiocb) { |
335 | .ki_filp = filp, | 339 | .ki_filp = filp, |
340 | .ki_flags = iocb_flags(filp), | ||
336 | }; | 341 | }; |
337 | } | 342 | } |
338 | 343 | ||
@@ -383,7 +388,7 @@ struct address_space_operations { | |||
383 | void (*invalidatepage) (struct page *, unsigned int, unsigned int); | 388 | void (*invalidatepage) (struct page *, unsigned int, unsigned int); |
384 | int (*releasepage) (struct page *, gfp_t); | 389 | int (*releasepage) (struct page *, gfp_t); |
385 | void (*freepage)(struct page *); | 390 | void (*freepage)(struct page *); |
386 | ssize_t (*direct_IO)(int, struct kiocb *, struct iov_iter *iter, loff_t offset); | 391 | ssize_t (*direct_IO)(struct kiocb *, struct iov_iter *iter, loff_t offset); |
387 | /* | 392 | /* |
388 | * migrate the contents of a page to the specified target. If | 393 | * migrate the contents of a page to the specified target. If |
389 | * migrate_mode is MIGRATE_ASYNC, it must not block. | 394 | * migrate_mode is MIGRATE_ASYNC, it must not block. |
@@ -2566,7 +2571,7 @@ extern int sb_min_blocksize(struct super_block *, int); | |||
2566 | 2571 | ||
2567 | extern int generic_file_mmap(struct file *, struct vm_area_struct *); | 2572 | extern int generic_file_mmap(struct file *, struct vm_area_struct *); |
2568 | extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *); | 2573 | extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *); |
2569 | int generic_write_checks(struct file *file, loff_t *pos, size_t *count, int isblk); | 2574 | extern ssize_t generic_write_checks(struct kiocb *, struct iov_iter *); |
2570 | extern ssize_t generic_file_read_iter(struct kiocb *, struct iov_iter *); | 2575 | extern ssize_t generic_file_read_iter(struct kiocb *, struct iov_iter *); |
2571 | extern ssize_t __generic_file_write_iter(struct kiocb *, struct iov_iter *); | 2576 | extern ssize_t __generic_file_write_iter(struct kiocb *, struct iov_iter *); |
2572 | extern ssize_t generic_file_write_iter(struct kiocb *, struct iov_iter *); | 2577 | extern ssize_t generic_file_write_iter(struct kiocb *, struct iov_iter *); |
@@ -2609,8 +2614,8 @@ extern loff_t fixed_size_llseek(struct file *file, loff_t offset, | |||
2609 | extern int generic_file_open(struct inode * inode, struct file * filp); | 2614 | extern int generic_file_open(struct inode * inode, struct file * filp); |
2610 | extern int nonseekable_open(struct inode * inode, struct file * filp); | 2615 | extern int nonseekable_open(struct inode * inode, struct file * filp); |
2611 | 2616 | ||
2612 | ssize_t dax_do_io(int rw, struct kiocb *, struct inode *, struct iov_iter *, | 2617 | ssize_t dax_do_io(struct kiocb *, struct inode *, struct iov_iter *, loff_t, |
2613 | loff_t, get_block_t, dio_iodone_t, int flags); | 2618 | get_block_t, dio_iodone_t, int flags); |
2614 | int dax_clear_blocks(struct inode *, sector_t block, long size); | 2619 | int dax_clear_blocks(struct inode *, sector_t block, long size); |
2615 | int dax_zero_page_range(struct inode *, loff_t from, unsigned len, get_block_t); | 2620 | int dax_zero_page_range(struct inode *, loff_t from, unsigned len, get_block_t); |
2616 | int dax_truncate_page(struct inode *, loff_t from, get_block_t); | 2621 | int dax_truncate_page(struct inode *, loff_t from, get_block_t); |
@@ -2635,16 +2640,18 @@ enum { | |||
2635 | 2640 | ||
2636 | void dio_end_io(struct bio *bio, int error); | 2641 | void dio_end_io(struct bio *bio, int error); |
2637 | 2642 | ||
2638 | ssize_t __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, | 2643 | ssize_t __blockdev_direct_IO(struct kiocb *iocb, struct inode *inode, |
2639 | struct block_device *bdev, struct iov_iter *iter, loff_t offset, | 2644 | struct block_device *bdev, struct iov_iter *iter, |
2640 | get_block_t get_block, dio_iodone_t end_io, | 2645 | loff_t offset, get_block_t get_block, |
2641 | dio_submit_t submit_io, int flags); | 2646 | dio_iodone_t end_io, dio_submit_t submit_io, |
2647 | int flags); | ||
2642 | 2648 | ||
2643 | static inline ssize_t blockdev_direct_IO(int rw, struct kiocb *iocb, | 2649 | static inline ssize_t blockdev_direct_IO(struct kiocb *iocb, |
2644 | struct inode *inode, struct iov_iter *iter, loff_t offset, | 2650 | struct inode *inode, |
2645 | get_block_t get_block) | 2651 | struct iov_iter *iter, loff_t offset, |
2652 | get_block_t get_block) | ||
2646 | { | 2653 | { |
2647 | return __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iter, | 2654 | return __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev, iter, |
2648 | offset, get_block, NULL, NULL, | 2655 | offset, get_block, NULL, NULL, |
2649 | DIO_LOCKING | DIO_SKIP_HOLES); | 2656 | DIO_LOCKING | DIO_SKIP_HOLES); |
2650 | } | 2657 | } |
@@ -2777,6 +2784,16 @@ static inline bool io_is_direct(struct file *filp) | |||
2777 | return (filp->f_flags & O_DIRECT) || IS_DAX(file_inode(filp)); | 2784 | return (filp->f_flags & O_DIRECT) || IS_DAX(file_inode(filp)); |
2778 | } | 2785 | } |
2779 | 2786 | ||
2787 | static inline int iocb_flags(struct file *file) | ||
2788 | { | ||
2789 | int res = 0; | ||
2790 | if (file->f_flags & O_APPEND) | ||
2791 | res |= IOCB_APPEND; | ||
2792 | if (io_is_direct(file)) | ||
2793 | res |= IOCB_DIRECT; | ||
2794 | return res; | ||
2795 | } | ||
2796 | |||
2780 | static inline ino_t parent_ino(struct dentry *dentry) | 2797 | static inline ino_t parent_ino(struct dentry *dentry) |
2781 | { | 2798 | { |
2782 | ino_t res; | 2799 | ino_t res; |
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index b01ccf371fdc..410abd172feb 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
@@ -447,13 +447,12 @@ static inline struct rpc_cred *nfs_file_cred(struct file *file) | |||
447 | /* | 447 | /* |
448 | * linux/fs/nfs/direct.c | 448 | * linux/fs/nfs/direct.c |
449 | */ | 449 | */ |
450 | extern ssize_t nfs_direct_IO(int, struct kiocb *, struct iov_iter *, loff_t); | 450 | extern ssize_t nfs_direct_IO(struct kiocb *, struct iov_iter *, loff_t); |
451 | extern ssize_t nfs_file_direct_read(struct kiocb *iocb, | 451 | extern ssize_t nfs_file_direct_read(struct kiocb *iocb, |
452 | struct iov_iter *iter, | 452 | struct iov_iter *iter, |
453 | loff_t pos); | 453 | loff_t pos); |
454 | extern ssize_t nfs_file_direct_write(struct kiocb *iocb, | 454 | extern ssize_t nfs_file_direct_write(struct kiocb *iocb, |
455 | struct iov_iter *iter, | 455 | struct iov_iter *iter); |
456 | loff_t pos); | ||
457 | 456 | ||
458 | /* | 457 | /* |
459 | * linux/fs/nfs/dir.c | 458 | * linux/fs/nfs/dir.c |
diff --git a/include/linux/uio.h b/include/linux/uio.h index 15f11fb9fff6..8b01e1c3c614 100644 --- a/include/linux/uio.h +++ b/include/linux/uio.h | |||
@@ -112,6 +112,14 @@ static inline bool iter_is_iovec(struct iov_iter *i) | |||
112 | } | 112 | } |
113 | 113 | ||
114 | /* | 114 | /* |
115 | * Get one of READ or WRITE out of iter->type without any other flags OR'd in | ||
116 | * with it. | ||
117 | * | ||
118 | * The ?: is just for type safety. | ||
119 | */ | ||
120 | #define iov_iter_rw(i) ((0 ? (struct iov_iter *)0 : (i))->type & RW_MASK) | ||
121 | |||
122 | /* | ||
115 | * Cap the iov_iter by given limit; note that the second argument is | 123 | * Cap the iov_iter by given limit; note that the second argument is |
116 | * *not* the new size - it's upper limit for such. Passing it a value | 124 | * *not* the new size - it's upper limit for such. Passing it a value |
117 | * greater than the amount of data in iov_iter is fine - it'll just do | 125 | * greater than the amount of data in iov_iter is fine - it'll just do |