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/linux | |
| 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/linux')
| -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 |
