diff options
Diffstat (limited to 'fs')
70 files changed, 666 insertions, 359 deletions
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c index adaf6f6dd858..e1cbdfdb7c68 100644 --- a/fs/9p/vfs_addr.c +++ b/fs/9p/vfs_addr.c | |||
@@ -310,9 +310,13 @@ static int v9fs_write_end(struct file *filp, struct address_space *mapping, | |||
310 | 310 | ||
311 | p9_debug(P9_DEBUG_VFS, "filp %p, mapping %p\n", filp, mapping); | 311 | p9_debug(P9_DEBUG_VFS, "filp %p, mapping %p\n", filp, mapping); |
312 | 312 | ||
313 | if (unlikely(copied < len && !PageUptodate(page))) { | 313 | if (!PageUptodate(page)) { |
314 | copied = 0; | 314 | if (unlikely(copied < len)) { |
315 | goto out; | 315 | copied = 0; |
316 | goto out; | ||
317 | } else if (len == PAGE_SIZE) { | ||
318 | SetPageUptodate(page); | ||
319 | } | ||
316 | } | 320 | } |
317 | /* | 321 | /* |
318 | * No need to use i_size_read() here, the i_size | 322 | * No need to use i_size_read() here, the i_size |
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index ce7181ea60fa..a7c5a9861bef 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c | |||
@@ -54,7 +54,7 @@ typedef struct { | |||
54 | int size; /* size of magic/mask */ | 54 | int size; /* size of magic/mask */ |
55 | char *magic; /* magic or filename extension */ | 55 | char *magic; /* magic or filename extension */ |
56 | char *mask; /* mask, NULL for exact match */ | 56 | char *mask; /* mask, NULL for exact match */ |
57 | char *interpreter; /* filename of interpreter */ | 57 | const char *interpreter; /* filename of interpreter */ |
58 | char *name; | 58 | char *name; |
59 | struct dentry *dentry; | 59 | struct dentry *dentry; |
60 | struct file *interp_file; | 60 | struct file *interp_file; |
@@ -131,27 +131,26 @@ static int load_misc_binary(struct linux_binprm *bprm) | |||
131 | { | 131 | { |
132 | Node *fmt; | 132 | Node *fmt; |
133 | struct file *interp_file = NULL; | 133 | struct file *interp_file = NULL; |
134 | char iname[BINPRM_BUF_SIZE]; | ||
135 | const char *iname_addr = iname; | ||
136 | int retval; | 134 | int retval; |
137 | int fd_binary = -1; | 135 | int fd_binary = -1; |
138 | 136 | ||
139 | retval = -ENOEXEC; | 137 | retval = -ENOEXEC; |
140 | if (!enabled) | 138 | if (!enabled) |
141 | goto ret; | 139 | return retval; |
142 | 140 | ||
143 | /* to keep locking time low, we copy the interpreter string */ | 141 | /* to keep locking time low, we copy the interpreter string */ |
144 | read_lock(&entries_lock); | 142 | read_lock(&entries_lock); |
145 | fmt = check_file(bprm); | 143 | fmt = check_file(bprm); |
146 | if (fmt) | 144 | if (fmt) |
147 | strlcpy(iname, fmt->interpreter, BINPRM_BUF_SIZE); | 145 | dget(fmt->dentry); |
148 | read_unlock(&entries_lock); | 146 | read_unlock(&entries_lock); |
149 | if (!fmt) | 147 | if (!fmt) |
150 | goto ret; | 148 | return retval; |
151 | 149 | ||
152 | /* Need to be able to load the file after exec */ | 150 | /* Need to be able to load the file after exec */ |
151 | retval = -ENOENT; | ||
153 | if (bprm->interp_flags & BINPRM_FLAGS_PATH_INACCESSIBLE) | 152 | if (bprm->interp_flags & BINPRM_FLAGS_PATH_INACCESSIBLE) |
154 | return -ENOENT; | 153 | goto ret; |
155 | 154 | ||
156 | if (!(fmt->flags & MISC_FMT_PRESERVE_ARGV0)) { | 155 | if (!(fmt->flags & MISC_FMT_PRESERVE_ARGV0)) { |
157 | retval = remove_arg_zero(bprm); | 156 | retval = remove_arg_zero(bprm); |
@@ -195,22 +194,22 @@ static int load_misc_binary(struct linux_binprm *bprm) | |||
195 | bprm->argc++; | 194 | bprm->argc++; |
196 | 195 | ||
197 | /* add the interp as argv[0] */ | 196 | /* add the interp as argv[0] */ |
198 | retval = copy_strings_kernel(1, &iname_addr, bprm); | 197 | retval = copy_strings_kernel(1, &fmt->interpreter, bprm); |
199 | if (retval < 0) | 198 | if (retval < 0) |
200 | goto error; | 199 | goto error; |
201 | bprm->argc++; | 200 | bprm->argc++; |
202 | 201 | ||
203 | /* Update interp in case binfmt_script needs it. */ | 202 | /* Update interp in case binfmt_script needs it. */ |
204 | retval = bprm_change_interp(iname, bprm); | 203 | retval = bprm_change_interp(fmt->interpreter, bprm); |
205 | if (retval < 0) | 204 | if (retval < 0) |
206 | goto error; | 205 | goto error; |
207 | 206 | ||
208 | if (fmt->flags & MISC_FMT_OPEN_FILE && fmt->interp_file) { | 207 | if (fmt->flags & MISC_FMT_OPEN_FILE) { |
209 | interp_file = filp_clone_open(fmt->interp_file); | 208 | interp_file = filp_clone_open(fmt->interp_file); |
210 | if (!IS_ERR(interp_file)) | 209 | if (!IS_ERR(interp_file)) |
211 | deny_write_access(interp_file); | 210 | deny_write_access(interp_file); |
212 | } else { | 211 | } else { |
213 | interp_file = open_exec(iname); | 212 | interp_file = open_exec(fmt->interpreter); |
214 | } | 213 | } |
215 | retval = PTR_ERR(interp_file); | 214 | retval = PTR_ERR(interp_file); |
216 | if (IS_ERR(interp_file)) | 215 | if (IS_ERR(interp_file)) |
@@ -238,6 +237,7 @@ static int load_misc_binary(struct linux_binprm *bprm) | |||
238 | goto error; | 237 | goto error; |
239 | 238 | ||
240 | ret: | 239 | ret: |
240 | dput(fmt->dentry); | ||
241 | return retval; | 241 | return retval; |
242 | error: | 242 | error: |
243 | if (fd_binary > 0) | 243 | if (fd_binary > 0) |
@@ -594,8 +594,13 @@ static struct inode *bm_get_inode(struct super_block *sb, int mode) | |||
594 | 594 | ||
595 | static void bm_evict_inode(struct inode *inode) | 595 | static void bm_evict_inode(struct inode *inode) |
596 | { | 596 | { |
597 | Node *e = inode->i_private; | ||
598 | |||
599 | if (e && e->flags & MISC_FMT_OPEN_FILE) | ||
600 | filp_close(e->interp_file, NULL); | ||
601 | |||
597 | clear_inode(inode); | 602 | clear_inode(inode); |
598 | kfree(inode->i_private); | 603 | kfree(e); |
599 | } | 604 | } |
600 | 605 | ||
601 | static void kill_node(Node *e) | 606 | static void kill_node(Node *e) |
@@ -603,24 +608,14 @@ static void kill_node(Node *e) | |||
603 | struct dentry *dentry; | 608 | struct dentry *dentry; |
604 | 609 | ||
605 | write_lock(&entries_lock); | 610 | write_lock(&entries_lock); |
606 | dentry = e->dentry; | 611 | list_del_init(&e->list); |
607 | if (dentry) { | ||
608 | list_del_init(&e->list); | ||
609 | e->dentry = NULL; | ||
610 | } | ||
611 | write_unlock(&entries_lock); | 612 | write_unlock(&entries_lock); |
612 | 613 | ||
613 | if ((e->flags & MISC_FMT_OPEN_FILE) && e->interp_file) { | 614 | dentry = e->dentry; |
614 | filp_close(e->interp_file, NULL); | 615 | drop_nlink(d_inode(dentry)); |
615 | e->interp_file = NULL; | 616 | d_drop(dentry); |
616 | } | 617 | dput(dentry); |
617 | 618 | simple_release_fs(&bm_mnt, &entry_count); | |
618 | if (dentry) { | ||
619 | drop_nlink(d_inode(dentry)); | ||
620 | d_drop(dentry); | ||
621 | dput(dentry); | ||
622 | simple_release_fs(&bm_mnt, &entry_count); | ||
623 | } | ||
624 | } | 619 | } |
625 | 620 | ||
626 | /* /<entry> */ | 621 | /* /<entry> */ |
@@ -665,7 +660,8 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer, | |||
665 | root = file_inode(file)->i_sb->s_root; | 660 | root = file_inode(file)->i_sb->s_root; |
666 | inode_lock(d_inode(root)); | 661 | inode_lock(d_inode(root)); |
667 | 662 | ||
668 | kill_node(e); | 663 | if (!list_empty(&e->list)) |
664 | kill_node(e); | ||
669 | 665 | ||
670 | inode_unlock(d_inode(root)); | 666 | inode_unlock(d_inode(root)); |
671 | break; | 667 | break; |
@@ -794,7 +790,7 @@ static ssize_t bm_status_write(struct file *file, const char __user *buffer, | |||
794 | inode_lock(d_inode(root)); | 790 | inode_lock(d_inode(root)); |
795 | 791 | ||
796 | while (!list_empty(&entries)) | 792 | while (!list_empty(&entries)) |
797 | kill_node(list_entry(entries.next, Node, list)); | 793 | kill_node(list_first_entry(&entries, Node, list)); |
798 | 794 | ||
799 | inode_unlock(d_inode(root)); | 795 | inode_unlock(d_inode(root)); |
800 | break; | 796 | break; |
diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c index afdf4e3cafc2..7cde3f46ad26 100644 --- a/fs/binfmt_script.c +++ b/fs/binfmt_script.c | |||
@@ -19,7 +19,6 @@ static int load_script(struct linux_binprm *bprm) | |||
19 | const char *i_arg, *i_name; | 19 | const char *i_arg, *i_name; |
20 | char *cp; | 20 | char *cp; |
21 | struct file *file; | 21 | struct file *file; |
22 | char interp[BINPRM_BUF_SIZE]; | ||
23 | int retval; | 22 | int retval; |
24 | 23 | ||
25 | if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!')) | 24 | if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!')) |
@@ -55,7 +54,7 @@ static int load_script(struct linux_binprm *bprm) | |||
55 | break; | 54 | break; |
56 | } | 55 | } |
57 | for (cp = bprm->buf+2; (*cp == ' ') || (*cp == '\t'); cp++); | 56 | for (cp = bprm->buf+2; (*cp == ' ') || (*cp == '\t'); cp++); |
58 | if (*cp == '\0') | 57 | if (*cp == '\0') |
59 | return -ENOEXEC; /* No interpreter name found */ | 58 | return -ENOEXEC; /* No interpreter name found */ |
60 | i_name = cp; | 59 | i_name = cp; |
61 | i_arg = NULL; | 60 | i_arg = NULL; |
@@ -65,7 +64,6 @@ static int load_script(struct linux_binprm *bprm) | |||
65 | *cp++ = '\0'; | 64 | *cp++ = '\0'; |
66 | if (*cp) | 65 | if (*cp) |
67 | i_arg = cp; | 66 | i_arg = cp; |
68 | strcpy (interp, i_name); | ||
69 | /* | 67 | /* |
70 | * OK, we've parsed out the interpreter name and | 68 | * OK, we've parsed out the interpreter name and |
71 | * (optional) argument. | 69 | * (optional) argument. |
@@ -80,24 +78,27 @@ static int load_script(struct linux_binprm *bprm) | |||
80 | if (retval) | 78 | if (retval) |
81 | return retval; | 79 | return retval; |
82 | retval = copy_strings_kernel(1, &bprm->interp, bprm); | 80 | retval = copy_strings_kernel(1, &bprm->interp, bprm); |
83 | if (retval < 0) return retval; | 81 | if (retval < 0) |
82 | return retval; | ||
84 | bprm->argc++; | 83 | bprm->argc++; |
85 | if (i_arg) { | 84 | if (i_arg) { |
86 | retval = copy_strings_kernel(1, &i_arg, bprm); | 85 | retval = copy_strings_kernel(1, &i_arg, bprm); |
87 | if (retval < 0) return retval; | 86 | if (retval < 0) |
87 | return retval; | ||
88 | bprm->argc++; | 88 | bprm->argc++; |
89 | } | 89 | } |
90 | retval = copy_strings_kernel(1, &i_name, bprm); | 90 | retval = copy_strings_kernel(1, &i_name, bprm); |
91 | if (retval) return retval; | 91 | if (retval) |
92 | return retval; | ||
92 | bprm->argc++; | 93 | bprm->argc++; |
93 | retval = bprm_change_interp(interp, bprm); | 94 | retval = bprm_change_interp(i_name, bprm); |
94 | if (retval < 0) | 95 | if (retval < 0) |
95 | return retval; | 96 | return retval; |
96 | 97 | ||
97 | /* | 98 | /* |
98 | * OK, now restart the process with the interpreter's dentry. | 99 | * OK, now restart the process with the interpreter's dentry. |
99 | */ | 100 | */ |
100 | file = open_exec(interp); | 101 | file = open_exec(i_name); |
101 | if (IS_ERR(file)) | 102 | if (IS_ERR(file)) |
102 | return PTR_ERR(file); | 103 | return PTR_ERR(file); |
103 | 104 | ||
diff --git a/fs/block_dev.c b/fs/block_dev.c index 93d088ffc05c..789f55e851ae 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -716,10 +716,12 @@ int bdev_write_page(struct block_device *bdev, sector_t sector, | |||
716 | 716 | ||
717 | set_page_writeback(page); | 717 | set_page_writeback(page); |
718 | result = ops->rw_page(bdev, sector + get_start_sect(bdev), page, true); | 718 | result = ops->rw_page(bdev, sector + get_start_sect(bdev), page, true); |
719 | if (result) | 719 | if (result) { |
720 | end_page_writeback(page); | 720 | end_page_writeback(page); |
721 | else | 721 | } else { |
722 | clean_page_buffers(page); | ||
722 | unlock_page(page); | 723 | unlock_page(page); |
724 | } | ||
723 | blk_queue_exit(bdev->bd_queue); | 725 | blk_queue_exit(bdev->bd_queue); |
724 | return result; | 726 | return result; |
725 | } | 727 | } |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 899ddaeeacec..8fc690384c58 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -722,7 +722,7 @@ struct btrfs_delayed_root; | |||
722 | * Indicate that a whole-filesystem exclusive operation is running | 722 | * Indicate that a whole-filesystem exclusive operation is running |
723 | * (device replace, resize, device add/delete, balance) | 723 | * (device replace, resize, device add/delete, balance) |
724 | */ | 724 | */ |
725 | #define BTRFS_FS_EXCL_OP 14 | 725 | #define BTRFS_FS_EXCL_OP 16 |
726 | 726 | ||
727 | struct btrfs_fs_info { | 727 | struct btrfs_fs_info { |
728 | u8 fsid[BTRFS_FSID_SIZE]; | 728 | u8 fsid[BTRFS_FSID_SIZE]; |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 12ab19a4b93e..970190cd347e 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -2801,7 +2801,7 @@ static int submit_extent_page(unsigned int opf, struct extent_io_tree *tree, | |||
2801 | } | 2801 | } |
2802 | } | 2802 | } |
2803 | 2803 | ||
2804 | bio = btrfs_bio_alloc(bdev, sector << 9); | 2804 | bio = btrfs_bio_alloc(bdev, (u64)sector << 9); |
2805 | bio_add_page(bio, page, page_size, offset); | 2805 | bio_add_page(bio, page, page_size, offset); |
2806 | bio->bi_end_io = end_io_func; | 2806 | bio->bi_end_io = end_io_func; |
2807 | bio->bi_private = tree; | 2807 | bio->bi_private = tree; |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 35a128acfbd1..161694b66038 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -1135,7 +1135,7 @@ static int btrfs_fill_super(struct super_block *sb, | |||
1135 | #ifdef CONFIG_BTRFS_FS_POSIX_ACL | 1135 | #ifdef CONFIG_BTRFS_FS_POSIX_ACL |
1136 | sb->s_flags |= MS_POSIXACL; | 1136 | sb->s_flags |= MS_POSIXACL; |
1137 | #endif | 1137 | #endif |
1138 | sb->s_flags |= MS_I_VERSION; | 1138 | sb->s_flags |= SB_I_VERSION; |
1139 | sb->s_iflags |= SB_I_CGROUPWB; | 1139 | sb->s_iflags |= SB_I_CGROUPWB; |
1140 | 1140 | ||
1141 | err = super_setup_bdi(sb); | 1141 | err = super_setup_bdi(sb); |
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 157fe59fbabe..1978a8cb1cb1 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c | |||
@@ -1991,6 +1991,7 @@ static int try_flush_caps(struct inode *inode, u64 *ptid) | |||
1991 | retry: | 1991 | retry: |
1992 | spin_lock(&ci->i_ceph_lock); | 1992 | spin_lock(&ci->i_ceph_lock); |
1993 | if (ci->i_ceph_flags & CEPH_I_NOFLUSH) { | 1993 | if (ci->i_ceph_flags & CEPH_I_NOFLUSH) { |
1994 | spin_unlock(&ci->i_ceph_lock); | ||
1994 | dout("try_flush_caps skipping %p I_NOFLUSH set\n", inode); | 1995 | dout("try_flush_caps skipping %p I_NOFLUSH set\n", inode); |
1995 | goto out; | 1996 | goto out; |
1996 | } | 1997 | } |
@@ -2008,8 +2009,10 @@ retry: | |||
2008 | mutex_lock(&session->s_mutex); | 2009 | mutex_lock(&session->s_mutex); |
2009 | goto retry; | 2010 | goto retry; |
2010 | } | 2011 | } |
2011 | if (cap->session->s_state < CEPH_MDS_SESSION_OPEN) | 2012 | if (cap->session->s_state < CEPH_MDS_SESSION_OPEN) { |
2013 | spin_unlock(&ci->i_ceph_lock); | ||
2012 | goto out; | 2014 | goto out; |
2015 | } | ||
2013 | 2016 | ||
2014 | flushing = __mark_caps_flushing(inode, session, true, | 2017 | flushing = __mark_caps_flushing(inode, session, true, |
2015 | &flush_tid, &oldest_flush_tid); | 2018 | &flush_tid, &oldest_flush_tid); |
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 84edfc60d87a..f23c820daaed 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c | |||
@@ -734,12 +734,13 @@ static int __choose_mds(struct ceph_mds_client *mdsc, | |||
734 | inode = req->r_inode; | 734 | inode = req->r_inode; |
735 | ihold(inode); | 735 | ihold(inode); |
736 | } else { | 736 | } else { |
737 | /* req->r_dentry is non-null for LSSNAP request. | 737 | /* req->r_dentry is non-null for LSSNAP request */ |
738 | * fall-thru */ | 738 | rcu_read_lock(); |
739 | WARN_ON_ONCE(!req->r_dentry); | 739 | inode = get_nonsnap_parent(req->r_dentry); |
740 | rcu_read_unlock(); | ||
741 | dout("__choose_mds using snapdir's parent %p\n", inode); | ||
740 | } | 742 | } |
741 | } | 743 | } else if (req->r_dentry) { |
742 | if (!inode && req->r_dentry) { | ||
743 | /* ignore race with rename; old or new d_parent is okay */ | 744 | /* ignore race with rename; old or new d_parent is okay */ |
744 | struct dentry *parent; | 745 | struct dentry *parent; |
745 | struct inode *dir; | 746 | struct inode *dir; |
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c index 1ffc8b426c1c..7fc0b850c352 100644 --- a/fs/ceph/snap.c +++ b/fs/ceph/snap.c | |||
@@ -374,12 +374,10 @@ static int build_snap_context(struct ceph_snap_realm *realm, | |||
374 | realm->ino, realm, snapc, snapc->seq, | 374 | realm->ino, realm, snapc, snapc->seq, |
375 | (unsigned int) snapc->num_snaps); | 375 | (unsigned int) snapc->num_snaps); |
376 | 376 | ||
377 | if (realm->cached_context) { | 377 | ceph_put_snap_context(realm->cached_context); |
378 | ceph_put_snap_context(realm->cached_context); | ||
379 | /* queue realm for cap_snap creation */ | ||
380 | list_add_tail(&realm->dirty_item, dirty_realms); | ||
381 | } | ||
382 | realm->cached_context = snapc; | 378 | realm->cached_context = snapc; |
379 | /* queue realm for cap_snap creation */ | ||
380 | list_add_tail(&realm->dirty_item, dirty_realms); | ||
383 | return 0; | 381 | return 0; |
384 | 382 | ||
385 | fail: | 383 | fail: |
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index f7243617316c..d5b2e12b5d02 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig | |||
@@ -5,9 +5,14 @@ config CIFS | |||
5 | select CRYPTO | 5 | select CRYPTO |
6 | select CRYPTO_MD4 | 6 | select CRYPTO_MD4 |
7 | select CRYPTO_MD5 | 7 | select CRYPTO_MD5 |
8 | select CRYPTO_SHA256 | ||
9 | select CRYPTO_CMAC | ||
8 | select CRYPTO_HMAC | 10 | select CRYPTO_HMAC |
9 | select CRYPTO_ARC4 | 11 | select CRYPTO_ARC4 |
12 | select CRYPTO_AEAD2 | ||
13 | select CRYPTO_CCM | ||
10 | select CRYPTO_ECB | 14 | select CRYPTO_ECB |
15 | select CRYPTO_AES | ||
11 | select CRYPTO_DES | 16 | select CRYPTO_DES |
12 | help | 17 | help |
13 | This is the client VFS module for the SMB3 family of NAS protocols, | 18 | This is the client VFS module for the SMB3 family of NAS protocols, |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index de5b2e1fcce5..e185b2853eab 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -661,7 +661,9 @@ struct TCP_Server_Info { | |||
661 | #endif | 661 | #endif |
662 | unsigned int max_read; | 662 | unsigned int max_read; |
663 | unsigned int max_write; | 663 | unsigned int max_write; |
664 | __u8 preauth_hash[512]; | 664 | #ifdef CONFIG_CIFS_SMB311 |
665 | __u8 preauth_sha_hash[64]; /* save initital negprot hash */ | ||
666 | #endif /* 3.1.1 */ | ||
665 | struct delayed_work reconnect; /* reconnect workqueue job */ | 667 | struct delayed_work reconnect; /* reconnect workqueue job */ |
666 | struct mutex reconnect_mutex; /* prevent simultaneous reconnects */ | 668 | struct mutex reconnect_mutex; /* prevent simultaneous reconnects */ |
667 | unsigned long echo_interval; | 669 | unsigned long echo_interval; |
@@ -849,7 +851,9 @@ struct cifs_ses { | |||
849 | __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE]; | 851 | __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE]; |
850 | __u8 smb3encryptionkey[SMB3_SIGN_KEY_SIZE]; | 852 | __u8 smb3encryptionkey[SMB3_SIGN_KEY_SIZE]; |
851 | __u8 smb3decryptionkey[SMB3_SIGN_KEY_SIZE]; | 853 | __u8 smb3decryptionkey[SMB3_SIGN_KEY_SIZE]; |
852 | __u8 preauth_hash[512]; | 854 | #ifdef CONFIG_CIFS_SMB311 |
855 | __u8 preauth_sha_hash[64]; | ||
856 | #endif /* 3.1.1 */ | ||
853 | }; | 857 | }; |
854 | 858 | ||
855 | static inline bool | 859 | static inline bool |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index e702d48bd023..81ba6e0d88d8 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -204,7 +204,8 @@ check_name(struct dentry *direntry, struct cifs_tcon *tcon) | |||
204 | struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb); | 204 | struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb); |
205 | int i; | 205 | int i; |
206 | 206 | ||
207 | if (unlikely(direntry->d_name.len > | 207 | if (unlikely(tcon->fsAttrInfo.MaxPathNameComponentLength && |
208 | direntry->d_name.len > | ||
208 | le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength))) | 209 | le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength))) |
209 | return -ENAMETOOLONG; | 210 | return -ENAMETOOLONG; |
210 | 211 | ||
@@ -520,7 +521,7 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, | |||
520 | 521 | ||
521 | rc = check_name(direntry, tcon); | 522 | rc = check_name(direntry, tcon); |
522 | if (rc) | 523 | if (rc) |
523 | goto out_free_xid; | 524 | goto out; |
524 | 525 | ||
525 | server = tcon->ses->server; | 526 | server = tcon->ses->server; |
526 | 527 | ||
diff --git a/fs/cifs/smb2maperror.c b/fs/cifs/smb2maperror.c index 7ca9808a0daa..62c88dfed57b 100644 --- a/fs/cifs/smb2maperror.c +++ b/fs/cifs/smb2maperror.c | |||
@@ -214,7 +214,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = { | |||
214 | {STATUS_DATATYPE_MISALIGNMENT, -EIO, "STATUS_DATATYPE_MISALIGNMENT"}, | 214 | {STATUS_DATATYPE_MISALIGNMENT, -EIO, "STATUS_DATATYPE_MISALIGNMENT"}, |
215 | {STATUS_BREAKPOINT, -EIO, "STATUS_BREAKPOINT"}, | 215 | {STATUS_BREAKPOINT, -EIO, "STATUS_BREAKPOINT"}, |
216 | {STATUS_SINGLE_STEP, -EIO, "STATUS_SINGLE_STEP"}, | 216 | {STATUS_SINGLE_STEP, -EIO, "STATUS_SINGLE_STEP"}, |
217 | {STATUS_BUFFER_OVERFLOW, -EIO, "STATUS_BUFFER_OVERFLOW"}, | 217 | {STATUS_BUFFER_OVERFLOW, -E2BIG, "STATUS_BUFFER_OVERFLOW"}, |
218 | {STATUS_NO_MORE_FILES, -ENODATA, "STATUS_NO_MORE_FILES"}, | 218 | {STATUS_NO_MORE_FILES, -ENODATA, "STATUS_NO_MORE_FILES"}, |
219 | {STATUS_WAKE_SYSTEM_DEBUGGER, -EIO, "STATUS_WAKE_SYSTEM_DEBUGGER"}, | 219 | {STATUS_WAKE_SYSTEM_DEBUGGER, -EIO, "STATUS_WAKE_SYSTEM_DEBUGGER"}, |
220 | {STATUS_HANDLES_CLOSED, -EIO, "STATUS_HANDLES_CLOSED"}, | 220 | {STATUS_HANDLES_CLOSED, -EIO, "STATUS_HANDLES_CLOSED"}, |
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 0dafdbae1f8c..bdb963d0ba32 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
@@ -522,6 +522,7 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, | |||
522 | struct cifs_open_parms oparms; | 522 | struct cifs_open_parms oparms; |
523 | struct cifs_fid fid; | 523 | struct cifs_fid fid; |
524 | struct smb2_file_full_ea_info *smb2_data; | 524 | struct smb2_file_full_ea_info *smb2_data; |
525 | int ea_buf_size = SMB2_MIN_EA_BUF; | ||
525 | 526 | ||
526 | utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); | 527 | utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); |
527 | if (!utf16_path) | 528 | if (!utf16_path) |
@@ -541,14 +542,32 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, | |||
541 | return rc; | 542 | return rc; |
542 | } | 543 | } |
543 | 544 | ||
544 | smb2_data = kzalloc(SMB2_MAX_EA_BUF, GFP_KERNEL); | 545 | while (1) { |
545 | if (smb2_data == NULL) { | 546 | smb2_data = kzalloc(ea_buf_size, GFP_KERNEL); |
546 | SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); | 547 | if (smb2_data == NULL) { |
547 | return -ENOMEM; | 548 | SMB2_close(xid, tcon, fid.persistent_fid, |
549 | fid.volatile_fid); | ||
550 | return -ENOMEM; | ||
551 | } | ||
552 | |||
553 | rc = SMB2_query_eas(xid, tcon, fid.persistent_fid, | ||
554 | fid.volatile_fid, | ||
555 | ea_buf_size, smb2_data); | ||
556 | |||
557 | if (rc != -E2BIG) | ||
558 | break; | ||
559 | |||
560 | kfree(smb2_data); | ||
561 | ea_buf_size <<= 1; | ||
562 | |||
563 | if (ea_buf_size > SMB2_MAX_EA_BUF) { | ||
564 | cifs_dbg(VFS, "EA size is too large\n"); | ||
565 | SMB2_close(xid, tcon, fid.persistent_fid, | ||
566 | fid.volatile_fid); | ||
567 | return -ENOMEM; | ||
568 | } | ||
548 | } | 569 | } |
549 | 570 | ||
550 | rc = SMB2_query_eas(xid, tcon, fid.persistent_fid, fid.volatile_fid, | ||
551 | smb2_data); | ||
552 | SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); | 571 | SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); |
553 | 572 | ||
554 | if (!rc) | 573 | if (!rc) |
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 6f0e6343c15e..5331631386a2 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
@@ -648,7 +648,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) | |||
648 | { | 648 | { |
649 | int rc = 0; | 649 | int rc = 0; |
650 | struct validate_negotiate_info_req vneg_inbuf; | 650 | struct validate_negotiate_info_req vneg_inbuf; |
651 | struct validate_negotiate_info_rsp *pneg_rsp; | 651 | struct validate_negotiate_info_rsp *pneg_rsp = NULL; |
652 | u32 rsplen; | 652 | u32 rsplen; |
653 | u32 inbuflen; /* max of 4 dialects */ | 653 | u32 inbuflen; /* max of 4 dialects */ |
654 | 654 | ||
@@ -727,8 +727,9 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) | |||
727 | rsplen); | 727 | rsplen); |
728 | 728 | ||
729 | /* relax check since Mac returns max bufsize allowed on ioctl */ | 729 | /* relax check since Mac returns max bufsize allowed on ioctl */ |
730 | if (rsplen > CIFSMaxBufSize) | 730 | if ((rsplen > CIFSMaxBufSize) |
731 | return -EIO; | 731 | || (rsplen < sizeof(struct validate_negotiate_info_rsp))) |
732 | goto err_rsp_free; | ||
732 | } | 733 | } |
733 | 734 | ||
734 | /* check validate negotiate info response matches what we got earlier */ | 735 | /* check validate negotiate info response matches what we got earlier */ |
@@ -747,10 +748,13 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) | |||
747 | 748 | ||
748 | /* validate negotiate successful */ | 749 | /* validate negotiate successful */ |
749 | cifs_dbg(FYI, "validate negotiate info successful\n"); | 750 | cifs_dbg(FYI, "validate negotiate info successful\n"); |
751 | kfree(pneg_rsp); | ||
750 | return 0; | 752 | return 0; |
751 | 753 | ||
752 | vneg_out: | 754 | vneg_out: |
753 | cifs_dbg(VFS, "protocol revalidation - security settings mismatch\n"); | 755 | cifs_dbg(VFS, "protocol revalidation - security settings mismatch\n"); |
756 | err_rsp_free: | ||
757 | kfree(pneg_rsp); | ||
754 | return -EIO; | 758 | return -EIO; |
755 | } | 759 | } |
756 | 760 | ||
@@ -1255,7 +1259,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, | |||
1255 | struct smb2_tree_connect_req *req; | 1259 | struct smb2_tree_connect_req *req; |
1256 | struct smb2_tree_connect_rsp *rsp = NULL; | 1260 | struct smb2_tree_connect_rsp *rsp = NULL; |
1257 | struct kvec iov[2]; | 1261 | struct kvec iov[2]; |
1258 | struct kvec rsp_iov; | 1262 | struct kvec rsp_iov = { NULL, 0 }; |
1259 | int rc = 0; | 1263 | int rc = 0; |
1260 | int resp_buftype; | 1264 | int resp_buftype; |
1261 | int unc_path_len; | 1265 | int unc_path_len; |
@@ -1372,7 +1376,7 @@ tcon_exit: | |||
1372 | return rc; | 1376 | return rc; |
1373 | 1377 | ||
1374 | tcon_error_exit: | 1378 | tcon_error_exit: |
1375 | if (rsp->hdr.sync_hdr.Status == STATUS_BAD_NETWORK_NAME) { | 1379 | if (rsp && rsp->hdr.sync_hdr.Status == STATUS_BAD_NETWORK_NAME) { |
1376 | cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree); | 1380 | cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree); |
1377 | } | 1381 | } |
1378 | goto tcon_exit; | 1382 | goto tcon_exit; |
@@ -1975,6 +1979,9 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, | |||
1975 | } else | 1979 | } else |
1976 | iov[0].iov_len = get_rfc1002_length(req) + 4; | 1980 | iov[0].iov_len = get_rfc1002_length(req) + 4; |
1977 | 1981 | ||
1982 | /* validate negotiate request must be signed - see MS-SMB2 3.2.5.5 */ | ||
1983 | if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO) | ||
1984 | req->hdr.sync_hdr.Flags |= SMB2_FLAGS_SIGNED; | ||
1978 | 1985 | ||
1979 | rc = SendReceive2(xid, ses, iov, n_iov, &resp_buftype, flags, &rsp_iov); | 1986 | rc = SendReceive2(xid, ses, iov, n_iov, &resp_buftype, flags, &rsp_iov); |
1980 | cifs_small_buf_release(req); | 1987 | cifs_small_buf_release(req); |
@@ -2191,9 +2198,13 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
2191 | req->PersistentFileId = persistent_fid; | 2198 | req->PersistentFileId = persistent_fid; |
2192 | req->VolatileFileId = volatile_fid; | 2199 | req->VolatileFileId = volatile_fid; |
2193 | req->AdditionalInformation = cpu_to_le32(additional_info); | 2200 | req->AdditionalInformation = cpu_to_le32(additional_info); |
2194 | /* 4 for rfc1002 length field and 1 for Buffer */ | 2201 | |
2195 | req->InputBufferOffset = | 2202 | /* |
2196 | cpu_to_le16(sizeof(struct smb2_query_info_req) - 1 - 4); | 2203 | * We do not use the input buffer (do not send extra byte) |
2204 | */ | ||
2205 | req->InputBufferOffset = 0; | ||
2206 | inc_rfc1001_len(req, -1); | ||
2207 | |||
2197 | req->OutputBufferLength = cpu_to_le32(output_len); | 2208 | req->OutputBufferLength = cpu_to_le32(output_len); |
2198 | 2209 | ||
2199 | iov[0].iov_base = (char *)req; | 2210 | iov[0].iov_base = (char *)req; |
@@ -2233,12 +2244,12 @@ qinf_exit: | |||
2233 | } | 2244 | } |
2234 | 2245 | ||
2235 | int SMB2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, | 2246 | int SMB2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, |
2236 | u64 persistent_fid, u64 volatile_fid, | 2247 | u64 persistent_fid, u64 volatile_fid, |
2237 | struct smb2_file_full_ea_info *data) | 2248 | int ea_buf_size, struct smb2_file_full_ea_info *data) |
2238 | { | 2249 | { |
2239 | return query_info(xid, tcon, persistent_fid, volatile_fid, | 2250 | return query_info(xid, tcon, persistent_fid, volatile_fid, |
2240 | FILE_FULL_EA_INFORMATION, SMB2_O_INFO_FILE, 0, | 2251 | FILE_FULL_EA_INFORMATION, SMB2_O_INFO_FILE, 0, |
2241 | SMB2_MAX_EA_BUF, | 2252 | ea_buf_size, |
2242 | sizeof(struct smb2_file_full_ea_info), | 2253 | sizeof(struct smb2_file_full_ea_info), |
2243 | (void **)&data, | 2254 | (void **)&data, |
2244 | NULL); | 2255 | NULL); |
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index 6c9653a130c8..c2ec934be968 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h | |||
@@ -832,7 +832,7 @@ struct smb2_flush_rsp { | |||
832 | /* Channel field for read and write: exactly one of following flags can be set*/ | 832 | /* Channel field for read and write: exactly one of following flags can be set*/ |
833 | #define SMB2_CHANNEL_NONE 0x00000000 | 833 | #define SMB2_CHANNEL_NONE 0x00000000 |
834 | #define SMB2_CHANNEL_RDMA_V1 0x00000001 /* SMB3 or later */ | 834 | #define SMB2_CHANNEL_RDMA_V1 0x00000001 /* SMB3 or later */ |
835 | #define SMB2_CHANNEL_RDMA_V1_INVALIDATE 0x00000001 /* SMB3.02 or later */ | 835 | #define SMB2_CHANNEL_RDMA_V1_INVALIDATE 0x00000002 /* SMB3.02 or later */ |
836 | 836 | ||
837 | /* SMB2 read request without RFC1001 length at the beginning */ | 837 | /* SMB2 read request without RFC1001 length at the beginning */ |
838 | struct smb2_read_plain_req { | 838 | struct smb2_read_plain_req { |
@@ -1178,7 +1178,8 @@ struct smb2_file_link_info { /* encoding of request for level 11 */ | |||
1178 | char FileName[0]; /* Name to be assigned to new link */ | 1178 | char FileName[0]; /* Name to be assigned to new link */ |
1179 | } __packed; /* level 11 Set */ | 1179 | } __packed; /* level 11 Set */ |
1180 | 1180 | ||
1181 | #define SMB2_MAX_EA_BUF 2048 | 1181 | #define SMB2_MIN_EA_BUF 2048 |
1182 | #define SMB2_MAX_EA_BUF 65536 | ||
1182 | 1183 | ||
1183 | struct smb2_file_full_ea_info { /* encoding of response for level 15 */ | 1184 | struct smb2_file_full_ea_info { /* encoding of response for level 15 */ |
1184 | __le32 next_entry_offset; | 1185 | __le32 next_entry_offset; |
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index 003217099ef3..e9ab5227e7a8 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h | |||
@@ -134,6 +134,7 @@ extern int SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, | |||
134 | u64 persistent_file_id, u64 volatile_file_id); | 134 | u64 persistent_file_id, u64 volatile_file_id); |
135 | extern int SMB2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, | 135 | extern int SMB2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, |
136 | u64 persistent_file_id, u64 volatile_file_id, | 136 | u64 persistent_file_id, u64 volatile_file_id, |
137 | int ea_buf_size, | ||
137 | struct smb2_file_full_ea_info *data); | 138 | struct smb2_file_full_ea_info *data); |
138 | extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon, | 139 | extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon, |
139 | u64 persistent_file_id, u64 volatile_file_id, | 140 | u64 persistent_file_id, u64 volatile_file_id, |
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c index 67367cf1f8cd..99493946e2f9 100644 --- a/fs/cifs/smb2transport.c +++ b/fs/cifs/smb2transport.c | |||
@@ -390,6 +390,7 @@ generate_smb30signingkey(struct cifs_ses *ses) | |||
390 | return generate_smb3signingkey(ses, &triplet); | 390 | return generate_smb3signingkey(ses, &triplet); |
391 | } | 391 | } |
392 | 392 | ||
393 | #ifdef CONFIG_CIFS_SMB311 | ||
393 | int | 394 | int |
394 | generate_smb311signingkey(struct cifs_ses *ses) | 395 | generate_smb311signingkey(struct cifs_ses *ses) |
395 | 396 | ||
@@ -398,25 +399,26 @@ generate_smb311signingkey(struct cifs_ses *ses) | |||
398 | struct derivation *d; | 399 | struct derivation *d; |
399 | 400 | ||
400 | d = &triplet.signing; | 401 | d = &triplet.signing; |
401 | d->label.iov_base = "SMB2AESCMAC"; | 402 | d->label.iov_base = "SMBSigningKey"; |
402 | d->label.iov_len = 12; | 403 | d->label.iov_len = 14; |
403 | d->context.iov_base = "SmbSign"; | 404 | d->context.iov_base = ses->preauth_sha_hash; |
404 | d->context.iov_len = 8; | 405 | d->context.iov_len = 64; |
405 | 406 | ||
406 | d = &triplet.encryption; | 407 | d = &triplet.encryption; |
407 | d->label.iov_base = "SMB2AESCCM"; | 408 | d->label.iov_base = "SMBC2SCipherKey"; |
408 | d->label.iov_len = 11; | 409 | d->label.iov_len = 16; |
409 | d->context.iov_base = "ServerIn "; | 410 | d->context.iov_base = ses->preauth_sha_hash; |
410 | d->context.iov_len = 10; | 411 | d->context.iov_len = 64; |
411 | 412 | ||
412 | d = &triplet.decryption; | 413 | d = &triplet.decryption; |
413 | d->label.iov_base = "SMB2AESCCM"; | 414 | d->label.iov_base = "SMBS2CCipherKey"; |
414 | d->label.iov_len = 11; | 415 | d->label.iov_len = 16; |
415 | d->context.iov_base = "ServerOut"; | 416 | d->context.iov_base = ses->preauth_sha_hash; |
416 | d->context.iov_len = 10; | 417 | d->context.iov_len = 64; |
417 | 418 | ||
418 | return generate_smb3signingkey(ses, &triplet); | 419 | return generate_smb3signingkey(ses, &triplet); |
419 | } | 420 | } |
421 | #endif /* 311 */ | ||
420 | 422 | ||
421 | int | 423 | int |
422 | smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | 424 | smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) |
diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index 018c588c7ac3..8e704d12a1cf 100644 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c | |||
@@ -109,6 +109,11 @@ static int validate_user_key(struct fscrypt_info *crypt_info, | |||
109 | goto out; | 109 | goto out; |
110 | } | 110 | } |
111 | ukp = user_key_payload_locked(keyring_key); | 111 | ukp = user_key_payload_locked(keyring_key); |
112 | if (!ukp) { | ||
113 | /* key was revoked before we acquired its semaphore */ | ||
114 | res = -EKEYREVOKED; | ||
115 | goto out; | ||
116 | } | ||
112 | if (ukp->datalen != sizeof(struct fscrypt_key)) { | 117 | if (ukp->datalen != sizeof(struct fscrypt_key)) { |
113 | res = -EINVAL; | 118 | res = -EINVAL; |
114 | goto out; | 119 | goto out; |
diff --git a/fs/direct-io.c b/fs/direct-io.c index 62cf812ed0e5..b53e66d9abd7 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c | |||
@@ -45,6 +45,12 @@ | |||
45 | #define DIO_PAGES 64 | 45 | #define DIO_PAGES 64 |
46 | 46 | ||
47 | /* | 47 | /* |
48 | * Flags for dio_complete() | ||
49 | */ | ||
50 | #define DIO_COMPLETE_ASYNC 0x01 /* This is async IO */ | ||
51 | #define DIO_COMPLETE_INVALIDATE 0x02 /* Can invalidate pages */ | ||
52 | |||
53 | /* | ||
48 | * This code generally works in units of "dio_blocks". A dio_block is | 54 | * This code generally works in units of "dio_blocks". A dio_block is |
49 | * somewhere between the hard sector size and the filesystem block size. it | 55 | * somewhere between the hard sector size and the filesystem block size. it |
50 | * is determined on a per-invocation basis. When talking to the filesystem | 56 | * is determined on a per-invocation basis. When talking to the filesystem |
@@ -225,7 +231,7 @@ static inline struct page *dio_get_page(struct dio *dio, | |||
225 | * filesystems can use it to hold additional state between get_block calls and | 231 | * filesystems can use it to hold additional state between get_block calls and |
226 | * dio_complete. | 232 | * dio_complete. |
227 | */ | 233 | */ |
228 | static ssize_t dio_complete(struct dio *dio, ssize_t ret, bool is_async) | 234 | static ssize_t dio_complete(struct dio *dio, ssize_t ret, unsigned int flags) |
229 | { | 235 | { |
230 | loff_t offset = dio->iocb->ki_pos; | 236 | loff_t offset = dio->iocb->ki_pos; |
231 | ssize_t transferred = 0; | 237 | ssize_t transferred = 0; |
@@ -259,14 +265,27 @@ static ssize_t dio_complete(struct dio *dio, ssize_t ret, bool is_async) | |||
259 | if (ret == 0) | 265 | if (ret == 0) |
260 | ret = transferred; | 266 | ret = transferred; |
261 | 267 | ||
268 | if (dio->end_io) { | ||
269 | // XXX: ki_pos?? | ||
270 | err = dio->end_io(dio->iocb, offset, ret, dio->private); | ||
271 | if (err) | ||
272 | ret = err; | ||
273 | } | ||
274 | |||
262 | /* | 275 | /* |
263 | * Try again to invalidate clean pages which might have been cached by | 276 | * Try again to invalidate clean pages which might have been cached by |
264 | * non-direct readahead, or faulted in by get_user_pages() if the source | 277 | * non-direct readahead, or faulted in by get_user_pages() if the source |
265 | * of the write was an mmap'ed region of the file we're writing. Either | 278 | * of the write was an mmap'ed region of the file we're writing. Either |
266 | * one is a pretty crazy thing to do, so we don't support it 100%. If | 279 | * one is a pretty crazy thing to do, so we don't support it 100%. If |
267 | * this invalidation fails, tough, the write still worked... | 280 | * this invalidation fails, tough, the write still worked... |
281 | * | ||
282 | * And this page cache invalidation has to be after dio->end_io(), as | ||
283 | * some filesystems convert unwritten extents to real allocations in | ||
284 | * end_io() when necessary, otherwise a racing buffer read would cache | ||
285 | * zeros from unwritten extents. | ||
268 | */ | 286 | */ |
269 | if (ret > 0 && dio->op == REQ_OP_WRITE && | 287 | if (flags & DIO_COMPLETE_INVALIDATE && |
288 | ret > 0 && dio->op == REQ_OP_WRITE && | ||
270 | dio->inode->i_mapping->nrpages) { | 289 | dio->inode->i_mapping->nrpages) { |
271 | err = invalidate_inode_pages2_range(dio->inode->i_mapping, | 290 | err = invalidate_inode_pages2_range(dio->inode->i_mapping, |
272 | offset >> PAGE_SHIFT, | 291 | offset >> PAGE_SHIFT, |
@@ -274,18 +293,10 @@ static ssize_t dio_complete(struct dio *dio, ssize_t ret, bool is_async) | |||
274 | WARN_ON_ONCE(err); | 293 | WARN_ON_ONCE(err); |
275 | } | 294 | } |
276 | 295 | ||
277 | if (dio->end_io) { | ||
278 | |||
279 | // XXX: ki_pos?? | ||
280 | err = dio->end_io(dio->iocb, offset, ret, dio->private); | ||
281 | if (err) | ||
282 | ret = err; | ||
283 | } | ||
284 | |||
285 | if (!(dio->flags & DIO_SKIP_DIO_COUNT)) | 296 | if (!(dio->flags & DIO_SKIP_DIO_COUNT)) |
286 | inode_dio_end(dio->inode); | 297 | inode_dio_end(dio->inode); |
287 | 298 | ||
288 | if (is_async) { | 299 | if (flags & DIO_COMPLETE_ASYNC) { |
289 | /* | 300 | /* |
290 | * generic_write_sync expects ki_pos to have been updated | 301 | * generic_write_sync expects ki_pos to have been updated |
291 | * already, but the submission path only does this for | 302 | * already, but the submission path only does this for |
@@ -306,7 +317,7 @@ static void dio_aio_complete_work(struct work_struct *work) | |||
306 | { | 317 | { |
307 | struct dio *dio = container_of(work, struct dio, complete_work); | 318 | struct dio *dio = container_of(work, struct dio, complete_work); |
308 | 319 | ||
309 | dio_complete(dio, 0, true); | 320 | dio_complete(dio, 0, DIO_COMPLETE_ASYNC | DIO_COMPLETE_INVALIDATE); |
310 | } | 321 | } |
311 | 322 | ||
312 | static blk_status_t dio_bio_complete(struct dio *dio, struct bio *bio); | 323 | static blk_status_t dio_bio_complete(struct dio *dio, struct bio *bio); |
@@ -348,7 +359,7 @@ static void dio_bio_end_aio(struct bio *bio) | |||
348 | queue_work(dio->inode->i_sb->s_dio_done_wq, | 359 | queue_work(dio->inode->i_sb->s_dio_done_wq, |
349 | &dio->complete_work); | 360 | &dio->complete_work); |
350 | } else { | 361 | } else { |
351 | dio_complete(dio, 0, true); | 362 | dio_complete(dio, 0, DIO_COMPLETE_ASYNC); |
352 | } | 363 | } |
353 | } | 364 | } |
354 | } | 365 | } |
@@ -866,7 +877,8 @@ out: | |||
866 | */ | 877 | */ |
867 | if (sdio->boundary) { | 878 | if (sdio->boundary) { |
868 | ret = dio_send_cur_page(dio, sdio, map_bh); | 879 | ret = dio_send_cur_page(dio, sdio, map_bh); |
869 | dio_bio_submit(dio, sdio); | 880 | if (sdio->bio) |
881 | dio_bio_submit(dio, sdio); | ||
870 | put_page(sdio->cur_page); | 882 | put_page(sdio->cur_page); |
871 | sdio->cur_page = NULL; | 883 | sdio->cur_page = NULL; |
872 | } | 884 | } |
@@ -1359,7 +1371,7 @@ do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode, | |||
1359 | dio_await_completion(dio); | 1371 | dio_await_completion(dio); |
1360 | 1372 | ||
1361 | if (drop_refcount(dio) == 0) { | 1373 | if (drop_refcount(dio) == 0) { |
1362 | retval = dio_complete(dio, retval, false); | 1374 | retval = dio_complete(dio, retval, DIO_COMPLETE_INVALIDATE); |
1363 | } else | 1375 | } else |
1364 | BUG_ON(retval != -EIOCBQUEUED); | 1376 | BUG_ON(retval != -EIOCBQUEUED); |
1365 | 1377 | ||
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 9c351bf757b2..3fbc0ff79699 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h | |||
@@ -84,11 +84,16 @@ struct ecryptfs_page_crypt_context { | |||
84 | static inline struct ecryptfs_auth_tok * | 84 | static inline struct ecryptfs_auth_tok * |
85 | ecryptfs_get_encrypted_key_payload_data(struct key *key) | 85 | ecryptfs_get_encrypted_key_payload_data(struct key *key) |
86 | { | 86 | { |
87 | if (key->type == &key_type_encrypted) | 87 | struct encrypted_key_payload *payload; |
88 | return (struct ecryptfs_auth_tok *) | 88 | |
89 | (&((struct encrypted_key_payload *)key->payload.data[0])->payload_data); | 89 | if (key->type != &key_type_encrypted) |
90 | else | ||
91 | return NULL; | 90 | return NULL; |
91 | |||
92 | payload = key->payload.data[0]; | ||
93 | if (!payload) | ||
94 | return ERR_PTR(-EKEYREVOKED); | ||
95 | |||
96 | return (struct ecryptfs_auth_tok *)payload->payload_data; | ||
92 | } | 97 | } |
93 | 98 | ||
94 | static inline struct key *ecryptfs_get_encrypted_key(char *sig) | 99 | static inline struct key *ecryptfs_get_encrypted_key(char *sig) |
@@ -114,12 +119,17 @@ static inline struct ecryptfs_auth_tok * | |||
114 | ecryptfs_get_key_payload_data(struct key *key) | 119 | ecryptfs_get_key_payload_data(struct key *key) |
115 | { | 120 | { |
116 | struct ecryptfs_auth_tok *auth_tok; | 121 | struct ecryptfs_auth_tok *auth_tok; |
122 | struct user_key_payload *ukp; | ||
117 | 123 | ||
118 | auth_tok = ecryptfs_get_encrypted_key_payload_data(key); | 124 | auth_tok = ecryptfs_get_encrypted_key_payload_data(key); |
119 | if (!auth_tok) | 125 | if (auth_tok) |
120 | return (struct ecryptfs_auth_tok *)user_key_payload_locked(key)->data; | ||
121 | else | ||
122 | return auth_tok; | 126 | return auth_tok; |
127 | |||
128 | ukp = user_key_payload_locked(key); | ||
129 | if (!ukp) | ||
130 | return ERR_PTR(-EKEYREVOKED); | ||
131 | |||
132 | return (struct ecryptfs_auth_tok *)ukp->data; | ||
123 | } | 133 | } |
124 | 134 | ||
125 | #define ECRYPTFS_MAX_KEYSET_SIZE 1024 | 135 | #define ECRYPTFS_MAX_KEYSET_SIZE 1024 |
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index 3cf1546dca82..fa218cd64f74 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c | |||
@@ -459,7 +459,8 @@ out: | |||
459 | * @auth_tok_key: key containing the authentication token | 459 | * @auth_tok_key: key containing the authentication token |
460 | * @auth_tok: authentication token | 460 | * @auth_tok: authentication token |
461 | * | 461 | * |
462 | * Returns zero on valid auth tok; -EINVAL otherwise | 462 | * Returns zero on valid auth tok; -EINVAL if the payload is invalid; or |
463 | * -EKEYREVOKED if the key was revoked before we acquired its semaphore. | ||
463 | */ | 464 | */ |
464 | static int | 465 | static int |
465 | ecryptfs_verify_auth_tok_from_key(struct key *auth_tok_key, | 466 | ecryptfs_verify_auth_tok_from_key(struct key *auth_tok_key, |
@@ -468,6 +469,12 @@ ecryptfs_verify_auth_tok_from_key(struct key *auth_tok_key, | |||
468 | int rc = 0; | 469 | int rc = 0; |
469 | 470 | ||
470 | (*auth_tok) = ecryptfs_get_key_payload_data(auth_tok_key); | 471 | (*auth_tok) = ecryptfs_get_key_payload_data(auth_tok_key); |
472 | if (IS_ERR(*auth_tok)) { | ||
473 | rc = PTR_ERR(*auth_tok); | ||
474 | *auth_tok = NULL; | ||
475 | goto out; | ||
476 | } | ||
477 | |||
471 | if (ecryptfs_verify_version((*auth_tok)->version)) { | 478 | if (ecryptfs_verify_version((*auth_tok)->version)) { |
472 | printk(KERN_ERR "Data structure version mismatch. Userspace " | 479 | printk(KERN_ERR "Data structure version mismatch. Userspace " |
473 | "tools must match eCryptfs kernel module with major " | 480 | "tools must match eCryptfs kernel module with major " |
@@ -1410,7 +1410,7 @@ static void free_bprm(struct linux_binprm *bprm) | |||
1410 | kfree(bprm); | 1410 | kfree(bprm); |
1411 | } | 1411 | } |
1412 | 1412 | ||
1413 | int bprm_change_interp(char *interp, struct linux_binprm *bprm) | 1413 | int bprm_change_interp(const char *interp, struct linux_binprm *bprm) |
1414 | { | 1414 | { |
1415 | /* If a binfmt changed the interp, free it first. */ | 1415 | /* If a binfmt changed the interp, free it first. */ |
1416 | if (bprm->interp != bprm->filename) | 1416 | if (bprm->interp != bprm->filename) |
@@ -1802,6 +1802,7 @@ static int do_execveat_common(int fd, struct filename *filename, | |||
1802 | /* execve succeeded */ | 1802 | /* execve succeeded */ |
1803 | current->fs->in_exec = 0; | 1803 | current->fs->in_exec = 0; |
1804 | current->in_execve = 0; | 1804 | current->in_execve = 0; |
1805 | membarrier_execve(current); | ||
1805 | acct_update_integrals(current); | 1806 | acct_update_integrals(current); |
1806 | task_numa_free(current); | 1807 | task_numa_free(current); |
1807 | free_bprm(bprm); | 1808 | free_bprm(bprm); |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index b104096fce9e..b0915b734a38 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -1677,7 +1677,7 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token, | |||
1677 | sbi->s_mount_flags |= EXT4_MF_FS_ABORTED; | 1677 | sbi->s_mount_flags |= EXT4_MF_FS_ABORTED; |
1678 | return 1; | 1678 | return 1; |
1679 | case Opt_i_version: | 1679 | case Opt_i_version: |
1680 | sb->s_flags |= MS_I_VERSION; | 1680 | sb->s_flags |= SB_I_VERSION; |
1681 | return 1; | 1681 | return 1; |
1682 | case Opt_lazytime: | 1682 | case Opt_lazytime: |
1683 | sb->s_flags |= MS_LAZYTIME; | 1683 | sb->s_flags |= MS_LAZYTIME; |
@@ -2060,7 +2060,7 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb, | |||
2060 | SEQ_OPTS_PRINT("min_batch_time=%u", sbi->s_min_batch_time); | 2060 | SEQ_OPTS_PRINT("min_batch_time=%u", sbi->s_min_batch_time); |
2061 | if (nodefs || sbi->s_max_batch_time != EXT4_DEF_MAX_BATCH_TIME) | 2061 | if (nodefs || sbi->s_max_batch_time != EXT4_DEF_MAX_BATCH_TIME) |
2062 | SEQ_OPTS_PRINT("max_batch_time=%u", sbi->s_max_batch_time); | 2062 | SEQ_OPTS_PRINT("max_batch_time=%u", sbi->s_max_batch_time); |
2063 | if (sb->s_flags & MS_I_VERSION) | 2063 | if (sb->s_flags & SB_I_VERSION) |
2064 | SEQ_OPTS_PUTS("i_version"); | 2064 | SEQ_OPTS_PUTS("i_version"); |
2065 | if (nodefs || sbi->s_stripe) | 2065 | if (nodefs || sbi->s_stripe) |
2066 | SEQ_OPTS_PRINT("stripe=%lu", sbi->s_stripe); | 2066 | SEQ_OPTS_PRINT("stripe=%lu", sbi->s_stripe); |
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 9a7c90386947..4b4a72f392be 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h | |||
@@ -2525,7 +2525,7 @@ void invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr); | |||
2525 | bool is_checkpointed_data(struct f2fs_sb_info *sbi, block_t blkaddr); | 2525 | bool is_checkpointed_data(struct f2fs_sb_info *sbi, block_t blkaddr); |
2526 | void refresh_sit_entry(struct f2fs_sb_info *sbi, block_t old, block_t new); | 2526 | void refresh_sit_entry(struct f2fs_sb_info *sbi, block_t old, block_t new); |
2527 | void stop_discard_thread(struct f2fs_sb_info *sbi); | 2527 | void stop_discard_thread(struct f2fs_sb_info *sbi); |
2528 | void f2fs_wait_discard_bios(struct f2fs_sb_info *sbi); | 2528 | void f2fs_wait_discard_bios(struct f2fs_sb_info *sbi, bool umount); |
2529 | void clear_prefree_segments(struct f2fs_sb_info *sbi, struct cp_control *cpc); | 2529 | void clear_prefree_segments(struct f2fs_sb_info *sbi, struct cp_control *cpc); |
2530 | void release_discard_addrs(struct f2fs_sb_info *sbi); | 2530 | void release_discard_addrs(struct f2fs_sb_info *sbi); |
2531 | int npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra); | 2531 | int npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra); |
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 621b9b3d320b..c695ff462ee6 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c | |||
@@ -1210,11 +1210,11 @@ void stop_discard_thread(struct f2fs_sb_info *sbi) | |||
1210 | } | 1210 | } |
1211 | 1211 | ||
1212 | /* This comes from f2fs_put_super and f2fs_trim_fs */ | 1212 | /* This comes from f2fs_put_super and f2fs_trim_fs */ |
1213 | void f2fs_wait_discard_bios(struct f2fs_sb_info *sbi) | 1213 | void f2fs_wait_discard_bios(struct f2fs_sb_info *sbi, bool umount) |
1214 | { | 1214 | { |
1215 | __issue_discard_cmd(sbi, false); | 1215 | __issue_discard_cmd(sbi, false); |
1216 | __drop_discard_cmd(sbi); | 1216 | __drop_discard_cmd(sbi); |
1217 | __wait_discard_cmd(sbi, false); | 1217 | __wait_discard_cmd(sbi, !umount); |
1218 | } | 1218 | } |
1219 | 1219 | ||
1220 | static void mark_discard_range_all(struct f2fs_sb_info *sbi) | 1220 | static void mark_discard_range_all(struct f2fs_sb_info *sbi) |
@@ -2244,7 +2244,7 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range) | |||
2244 | } | 2244 | } |
2245 | /* It's time to issue all the filed discards */ | 2245 | /* It's time to issue all the filed discards */ |
2246 | mark_discard_range_all(sbi); | 2246 | mark_discard_range_all(sbi); |
2247 | f2fs_wait_discard_bios(sbi); | 2247 | f2fs_wait_discard_bios(sbi, false); |
2248 | out: | 2248 | out: |
2249 | range->len = F2FS_BLK_TO_BYTES(cpc.trimmed); | 2249 | range->len = F2FS_BLK_TO_BYTES(cpc.trimmed); |
2250 | return err; | 2250 | return err; |
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 89f61eb3d167..933c3d529e65 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c | |||
@@ -801,7 +801,7 @@ static void f2fs_put_super(struct super_block *sb) | |||
801 | } | 801 | } |
802 | 802 | ||
803 | /* be sure to wait for any on-going discard commands */ | 803 | /* be sure to wait for any on-going discard commands */ |
804 | f2fs_wait_discard_bios(sbi); | 804 | f2fs_wait_discard_bios(sbi, true); |
805 | 805 | ||
806 | if (f2fs_discard_en(sbi) && !sbi->discard_blks) { | 806 | if (f2fs_discard_en(sbi) && !sbi->discard_blks) { |
807 | struct cp_control cpc = { | 807 | struct cp_control cpc = { |
diff --git a/fs/fscache/object-list.c b/fs/fscache/object-list.c index b5ab06fabc60..0438d4cd91ef 100644 --- a/fs/fscache/object-list.c +++ b/fs/fscache/object-list.c | |||
@@ -331,6 +331,13 @@ static void fscache_objlist_config(struct fscache_objlist_data *data) | |||
331 | rcu_read_lock(); | 331 | rcu_read_lock(); |
332 | 332 | ||
333 | confkey = user_key_payload_rcu(key); | 333 | confkey = user_key_payload_rcu(key); |
334 | if (!confkey) { | ||
335 | /* key was revoked */ | ||
336 | rcu_read_unlock(); | ||
337 | key_put(key); | ||
338 | goto no_config; | ||
339 | } | ||
340 | |||
334 | buf = confkey->data; | 341 | buf = confkey->data; |
335 | 342 | ||
336 | for (len = confkey->datalen - 1; len >= 0; len--) { | 343 | for (len = confkey->datalen - 1; len >= 0; len--) { |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 622081b97426..24967382a7b1 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -1308,7 +1308,8 @@ static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file, | |||
1308 | */ | 1308 | */ |
1309 | over = !dir_emit(ctx, dirent->name, dirent->namelen, | 1309 | over = !dir_emit(ctx, dirent->name, dirent->namelen, |
1310 | dirent->ino, dirent->type); | 1310 | dirent->ino, dirent->type); |
1311 | ctx->pos = dirent->off; | 1311 | if (!over) |
1312 | ctx->pos = dirent->off; | ||
1312 | } | 1313 | } |
1313 | 1314 | ||
1314 | buf += reclen; | 1315 | buf += reclen; |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 65c88379a3a1..94a745acaef8 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -1059,7 +1059,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) | |||
1059 | if (sb->s_flags & MS_MANDLOCK) | 1059 | if (sb->s_flags & MS_MANDLOCK) |
1060 | goto err; | 1060 | goto err; |
1061 | 1061 | ||
1062 | sb->s_flags &= ~(MS_NOSEC | MS_I_VERSION); | 1062 | sb->s_flags &= ~(MS_NOSEC | SB_I_VERSION); |
1063 | 1063 | ||
1064 | if (!parse_fuse_opt(data, &d, is_bdev)) | 1064 | if (!parse_fuse_opt(data, &d, is_bdev)) |
1065 | goto err; | 1065 | goto err; |
diff --git a/fs/iomap.c b/fs/iomap.c index be61cf742b5e..d4801f8dd4fd 100644 --- a/fs/iomap.c +++ b/fs/iomap.c | |||
@@ -714,23 +714,9 @@ static ssize_t iomap_dio_complete(struct iomap_dio *dio) | |||
714 | { | 714 | { |
715 | struct kiocb *iocb = dio->iocb; | 715 | struct kiocb *iocb = dio->iocb; |
716 | struct inode *inode = file_inode(iocb->ki_filp); | 716 | struct inode *inode = file_inode(iocb->ki_filp); |
717 | loff_t offset = iocb->ki_pos; | ||
717 | ssize_t ret; | 718 | ssize_t ret; |
718 | 719 | ||
719 | /* | ||
720 | * Try again to invalidate clean pages which might have been cached by | ||
721 | * non-direct readahead, or faulted in by get_user_pages() if the source | ||
722 | * of the write was an mmap'ed region of the file we're writing. Either | ||
723 | * one is a pretty crazy thing to do, so we don't support it 100%. If | ||
724 | * this invalidation fails, tough, the write still worked... | ||
725 | */ | ||
726 | if (!dio->error && | ||
727 | (dio->flags & IOMAP_DIO_WRITE) && inode->i_mapping->nrpages) { | ||
728 | ret = invalidate_inode_pages2_range(inode->i_mapping, | ||
729 | iocb->ki_pos >> PAGE_SHIFT, | ||
730 | (iocb->ki_pos + dio->size - 1) >> PAGE_SHIFT); | ||
731 | WARN_ON_ONCE(ret); | ||
732 | } | ||
733 | |||
734 | if (dio->end_io) { | 720 | if (dio->end_io) { |
735 | ret = dio->end_io(iocb, | 721 | ret = dio->end_io(iocb, |
736 | dio->error ? dio->error : dio->size, | 722 | dio->error ? dio->error : dio->size, |
@@ -742,12 +728,33 @@ static ssize_t iomap_dio_complete(struct iomap_dio *dio) | |||
742 | if (likely(!ret)) { | 728 | if (likely(!ret)) { |
743 | ret = dio->size; | 729 | ret = dio->size; |
744 | /* check for short read */ | 730 | /* check for short read */ |
745 | if (iocb->ki_pos + ret > dio->i_size && | 731 | if (offset + ret > dio->i_size && |
746 | !(dio->flags & IOMAP_DIO_WRITE)) | 732 | !(dio->flags & IOMAP_DIO_WRITE)) |
747 | ret = dio->i_size - iocb->ki_pos; | 733 | ret = dio->i_size - offset; |
748 | iocb->ki_pos += ret; | 734 | iocb->ki_pos += ret; |
749 | } | 735 | } |
750 | 736 | ||
737 | /* | ||
738 | * Try again to invalidate clean pages which might have been cached by | ||
739 | * non-direct readahead, or faulted in by get_user_pages() if the source | ||
740 | * of the write was an mmap'ed region of the file we're writing. Either | ||
741 | * one is a pretty crazy thing to do, so we don't support it 100%. If | ||
742 | * this invalidation fails, tough, the write still worked... | ||
743 | * | ||
744 | * And this page cache invalidation has to be after dio->end_io(), as | ||
745 | * some filesystems convert unwritten extents to real allocations in | ||
746 | * end_io() when necessary, otherwise a racing buffer read would cache | ||
747 | * zeros from unwritten extents. | ||
748 | */ | ||
749 | if (!dio->error && | ||
750 | (dio->flags & IOMAP_DIO_WRITE) && inode->i_mapping->nrpages) { | ||
751 | int err; | ||
752 | err = invalidate_inode_pages2_range(inode->i_mapping, | ||
753 | offset >> PAGE_SHIFT, | ||
754 | (offset + dio->size - 1) >> PAGE_SHIFT); | ||
755 | WARN_ON_ONCE(err); | ||
756 | } | ||
757 | |||
751 | inode_dio_end(file_inode(iocb->ki_filp)); | 758 | inode_dio_end(file_inode(iocb->ki_filp)); |
752 | kfree(dio); | 759 | kfree(dio); |
753 | 760 | ||
diff --git a/fs/mpage.c b/fs/mpage.c index 37bb77c1302c..c991faec70b9 100644 --- a/fs/mpage.c +++ b/fs/mpage.c | |||
@@ -468,6 +468,16 @@ static void clean_buffers(struct page *page, unsigned first_unmapped) | |||
468 | try_to_free_buffers(page); | 468 | try_to_free_buffers(page); |
469 | } | 469 | } |
470 | 470 | ||
471 | /* | ||
472 | * For situations where we want to clean all buffers attached to a page. | ||
473 | * We don't need to calculate how many buffers are attached to the page, | ||
474 | * we just need to specify a number larger than the maximum number of buffers. | ||
475 | */ | ||
476 | void clean_page_buffers(struct page *page) | ||
477 | { | ||
478 | clean_buffers(page, ~0U); | ||
479 | } | ||
480 | |||
471 | static int __mpage_writepage(struct page *page, struct writeback_control *wbc, | 481 | static int __mpage_writepage(struct page *page, struct writeback_control *wbc, |
472 | void *data) | 482 | void *data) |
473 | { | 483 | { |
@@ -605,10 +615,8 @@ alloc_new: | |||
605 | if (bio == NULL) { | 615 | if (bio == NULL) { |
606 | if (first_unmapped == blocks_per_page) { | 616 | if (first_unmapped == blocks_per_page) { |
607 | if (!bdev_write_page(bdev, blocks[0] << (blkbits - 9), | 617 | if (!bdev_write_page(bdev, blocks[0] << (blkbits - 9), |
608 | page, wbc)) { | 618 | page, wbc)) |
609 | clean_buffers(page, first_unmapped); | ||
610 | goto out; | 619 | goto out; |
611 | } | ||
612 | } | 620 | } |
613 | bio = mpage_alloc(bdev, blocks[0] << (blkbits - 9), | 621 | bio = mpage_alloc(bdev, blocks[0] << (blkbits - 9), |
614 | BIO_MAX_PAGES, GFP_NOFS|__GFP_HIGH); | 622 | BIO_MAX_PAGES, GFP_NOFS|__GFP_HIGH); |
diff --git a/fs/namespace.c b/fs/namespace.c index 54059b142d6b..d18deb4c410b 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -468,7 +468,9 @@ static inline int may_write_real(struct file *file) | |||
468 | 468 | ||
469 | /* File refers to upper, writable layer? */ | 469 | /* File refers to upper, writable layer? */ |
470 | upperdentry = d_real(dentry, NULL, 0, D_REAL_UPPER); | 470 | upperdentry = d_real(dentry, NULL, 0, D_REAL_UPPER); |
471 | if (upperdentry && file_inode(file) == d_inode(upperdentry)) | 471 | if (upperdentry && |
472 | (file_inode(file) == d_inode(upperdentry) || | ||
473 | file_inode(file) == d_inode(dentry))) | ||
472 | return 0; | 474 | return 0; |
473 | 475 | ||
474 | /* Lower layer: can't write to real file, sorry... */ | 476 | /* Lower layer: can't write to real file, sorry... */ |
@@ -2823,7 +2825,8 @@ long do_mount(const char *dev_name, const char __user *dir_name, | |||
2823 | SB_MANDLOCK | | 2825 | SB_MANDLOCK | |
2824 | SB_DIRSYNC | | 2826 | SB_DIRSYNC | |
2825 | SB_SILENT | | 2827 | SB_SILENT | |
2826 | SB_POSIXACL); | 2828 | SB_POSIXACL | |
2829 | SB_I_VERSION); | ||
2827 | 2830 | ||
2828 | if (flags & MS_REMOUNT) | 2831 | if (flags & MS_REMOUNT) |
2829 | retval = do_remount(&path, flags, sb_flags, mnt_flags, | 2832 | retval = do_remount(&path, flags, sb_flags, mnt_flags, |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index efebe6cf4378..22880ef6d8dd 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -218,7 +218,6 @@ static void nfs_cb_idr_remove_locked(struct nfs_client *clp) | |||
218 | static void pnfs_init_server(struct nfs_server *server) | 218 | static void pnfs_init_server(struct nfs_server *server) |
219 | { | 219 | { |
220 | rpc_init_wait_queue(&server->roc_rpcwaitq, "pNFS ROC"); | 220 | rpc_init_wait_queue(&server->roc_rpcwaitq, "pNFS ROC"); |
221 | rpc_init_wait_queue(&server->uoc_rpcwaitq, "NFS UOC"); | ||
222 | } | 221 | } |
223 | 222 | ||
224 | #else | 223 | #else |
@@ -888,6 +887,7 @@ struct nfs_server *nfs_alloc_server(void) | |||
888 | ida_init(&server->openowner_id); | 887 | ida_init(&server->openowner_id); |
889 | ida_init(&server->lockowner_id); | 888 | ida_init(&server->lockowner_id); |
890 | pnfs_init_server(server); | 889 | pnfs_init_server(server); |
890 | rpc_init_wait_queue(&server->uoc_rpcwaitq, "NFS UOC"); | ||
891 | 891 | ||
892 | return server; | 892 | return server; |
893 | } | 893 | } |
diff --git a/fs/nfs/filelayout/filelayout.c b/fs/nfs/filelayout/filelayout.c index 44c638b7876c..508126eb49f9 100644 --- a/fs/nfs/filelayout/filelayout.c +++ b/fs/nfs/filelayout/filelayout.c | |||
@@ -745,7 +745,8 @@ filelayout_free_lseg(struct pnfs_layout_segment *lseg) | |||
745 | struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg); | 745 | struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg); |
746 | 746 | ||
747 | dprintk("--> %s\n", __func__); | 747 | dprintk("--> %s\n", __func__); |
748 | nfs4_fl_put_deviceid(fl->dsaddr); | 748 | if (fl->dsaddr != NULL) |
749 | nfs4_fl_put_deviceid(fl->dsaddr); | ||
749 | /* This assumes a single RW lseg */ | 750 | /* This assumes a single RW lseg */ |
750 | if (lseg->pls_range.iomode == IOMODE_RW) { | 751 | if (lseg->pls_range.iomode == IOMODE_RW) { |
751 | struct nfs4_filelayout *flo; | 752 | struct nfs4_filelayout *flo; |
diff --git a/fs/nfs/nfs4idmap.c b/fs/nfs/nfs4idmap.c index dd5d27da8c0c..30426c1a1bbd 100644 --- a/fs/nfs/nfs4idmap.c +++ b/fs/nfs/nfs4idmap.c | |||
@@ -274,7 +274,7 @@ static struct key *nfs_idmap_request_key(const char *name, size_t namelen, | |||
274 | ssize_t ret; | 274 | ssize_t ret; |
275 | 275 | ||
276 | ret = nfs_idmap_get_desc(name, namelen, type, strlen(type), &desc); | 276 | ret = nfs_idmap_get_desc(name, namelen, type, strlen(type), &desc); |
277 | if (ret <= 0) | 277 | if (ret < 0) |
278 | return ERR_PTR(ret); | 278 | return ERR_PTR(ret); |
279 | 279 | ||
280 | rkey = request_key(&key_type_id_resolver, desc, ""); | 280 | rkey = request_key(&key_type_id_resolver, desc, ""); |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 6c61e2b99635..f90090e8c959 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -8399,8 +8399,7 @@ nfs4_layoutget_handle_exception(struct rpc_task *task, | |||
8399 | lo = NFS_I(inode)->layout; | 8399 | lo = NFS_I(inode)->layout; |
8400 | /* If the open stateid was bad, then recover it. */ | 8400 | /* If the open stateid was bad, then recover it. */ |
8401 | if (!lo || test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags) || | 8401 | if (!lo || test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags) || |
8402 | nfs4_stateid_match_other(&lgp->args.stateid, | 8402 | !nfs4_stateid_match_other(&lgp->args.stateid, &lo->plh_stateid)) { |
8403 | &lgp->args.ctx->state->stateid)) { | ||
8404 | spin_unlock(&inode->i_lock); | 8403 | spin_unlock(&inode->i_lock); |
8405 | exception->state = lgp->args.ctx->state; | 8404 | exception->state = lgp->args.ctx->state; |
8406 | exception->stateid = &lgp->args.stateid; | 8405 | exception->stateid = &lgp->args.stateid; |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 37c8af003275..14ed9791ec9c 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -1842,8 +1842,8 @@ static void encode_create_session(struct xdr_stream *xdr, | |||
1842 | * Assumes OPEN is the biggest non-idempotent compound. | 1842 | * Assumes OPEN is the biggest non-idempotent compound. |
1843 | * 2 is the verifier. | 1843 | * 2 is the verifier. |
1844 | */ | 1844 | */ |
1845 | max_resp_sz_cached = (NFS4_dec_open_sz + RPC_REPHDRSIZE + | 1845 | max_resp_sz_cached = (NFS4_dec_open_sz + RPC_REPHDRSIZE + 2) |
1846 | RPC_MAX_AUTH_SIZE + 2) * XDR_UNIT; | 1846 | * XDR_UNIT + RPC_MAX_AUTH_SIZE; |
1847 | 1847 | ||
1848 | encode_op_hdr(xdr, OP_CREATE_SESSION, decode_create_session_maxsz, hdr); | 1848 | encode_op_hdr(xdr, OP_CREATE_SESSION, decode_create_session_maxsz, hdr); |
1849 | p = reserve_space(xdr, 16 + 2*28 + 20 + clnt->cl_nodelen + 12); | 1849 | p = reserve_space(xdr, 16 + 2*28 + 20 + clnt->cl_nodelen + 12); |
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 3c69db7d4905..8487486ec496 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -927,6 +927,13 @@ nfsd4_secinfo_release(union nfsd4_op_u *u) | |||
927 | exp_put(u->secinfo.si_exp); | 927 | exp_put(u->secinfo.si_exp); |
928 | } | 928 | } |
929 | 929 | ||
930 | static void | ||
931 | nfsd4_secinfo_no_name_release(union nfsd4_op_u *u) | ||
932 | { | ||
933 | if (u->secinfo_no_name.sin_exp) | ||
934 | exp_put(u->secinfo_no_name.sin_exp); | ||
935 | } | ||
936 | |||
930 | static __be32 | 937 | static __be32 |
931 | nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | 938 | nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
932 | union nfsd4_op_u *u) | 939 | union nfsd4_op_u *u) |
@@ -2375,7 +2382,7 @@ static const struct nfsd4_operation nfsd4_ops[] = { | |||
2375 | }, | 2382 | }, |
2376 | [OP_SECINFO_NO_NAME] = { | 2383 | [OP_SECINFO_NO_NAME] = { |
2377 | .op_func = nfsd4_secinfo_no_name, | 2384 | .op_func = nfsd4_secinfo_no_name, |
2378 | .op_release = nfsd4_secinfo_release, | 2385 | .op_release = nfsd4_secinfo_no_name_release, |
2379 | .op_flags = OP_HANDLES_WRONGSEC, | 2386 | .op_flags = OP_HANDLES_WRONGSEC, |
2380 | .op_name = "OP_SECINFO_NO_NAME", | 2387 | .op_name = "OP_SECINFO_NO_NAME", |
2381 | .op_rsize_bop = nfsd4_secinfo_rsize, | 2388 | .op_rsize_bop = nfsd4_secinfo_rsize, |
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index aad97b30d5e6..c441f9387a1b 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c | |||
@@ -561,10 +561,8 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c) | |||
561 | c->tmpfile = true; | 561 | c->tmpfile = true; |
562 | err = ovl_copy_up_locked(c); | 562 | err = ovl_copy_up_locked(c); |
563 | } else { | 563 | } else { |
564 | err = -EIO; | 564 | err = ovl_lock_rename_workdir(c->workdir, c->destdir); |
565 | if (lock_rename(c->workdir, c->destdir) != NULL) { | 565 | if (!err) { |
566 | pr_err("overlayfs: failed to lock workdir+upperdir\n"); | ||
567 | } else { | ||
568 | err = ovl_copy_up_locked(c); | 566 | err = ovl_copy_up_locked(c); |
569 | unlock_rename(c->workdir, c->destdir); | 567 | unlock_rename(c->workdir, c->destdir); |
570 | } | 568 | } |
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index 3309b1912241..cc961a3bd3bd 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c | |||
@@ -216,26 +216,6 @@ out_unlock: | |||
216 | return err; | 216 | return err; |
217 | } | 217 | } |
218 | 218 | ||
219 | static int ovl_lock_rename_workdir(struct dentry *workdir, | ||
220 | struct dentry *upperdir) | ||
221 | { | ||
222 | /* Workdir should not be the same as upperdir */ | ||
223 | if (workdir == upperdir) | ||
224 | goto err; | ||
225 | |||
226 | /* Workdir should not be subdir of upperdir and vice versa */ | ||
227 | if (lock_rename(workdir, upperdir) != NULL) | ||
228 | goto err_unlock; | ||
229 | |||
230 | return 0; | ||
231 | |||
232 | err_unlock: | ||
233 | unlock_rename(workdir, upperdir); | ||
234 | err: | ||
235 | pr_err("overlayfs: failed to lock workdir+upperdir\n"); | ||
236 | return -EIO; | ||
237 | } | ||
238 | |||
239 | static struct dentry *ovl_clear_empty(struct dentry *dentry, | 219 | static struct dentry *ovl_clear_empty(struct dentry *dentry, |
240 | struct list_head *list) | 220 | struct list_head *list) |
241 | { | 221 | { |
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index a619addecafc..321511ed8c42 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c | |||
@@ -598,18 +598,30 @@ static bool ovl_verify_inode(struct inode *inode, struct dentry *lowerdentry, | |||
598 | return true; | 598 | return true; |
599 | } | 599 | } |
600 | 600 | ||
601 | struct inode *ovl_get_inode(struct dentry *dentry, struct dentry *upperdentry) | 601 | struct inode *ovl_get_inode(struct dentry *dentry, struct dentry *upperdentry, |
602 | struct dentry *index) | ||
602 | { | 603 | { |
603 | struct dentry *lowerdentry = ovl_dentry_lower(dentry); | 604 | struct dentry *lowerdentry = ovl_dentry_lower(dentry); |
604 | struct inode *realinode = upperdentry ? d_inode(upperdentry) : NULL; | 605 | struct inode *realinode = upperdentry ? d_inode(upperdentry) : NULL; |
605 | struct inode *inode; | 606 | struct inode *inode; |
607 | /* Already indexed or could be indexed on copy up? */ | ||
608 | bool indexed = (index || (ovl_indexdir(dentry->d_sb) && !upperdentry)); | ||
609 | |||
610 | if (WARN_ON(upperdentry && indexed && !lowerdentry)) | ||
611 | return ERR_PTR(-EIO); | ||
606 | 612 | ||
607 | if (!realinode) | 613 | if (!realinode) |
608 | realinode = d_inode(lowerdentry); | 614 | realinode = d_inode(lowerdentry); |
609 | 615 | ||
610 | if (!S_ISDIR(realinode->i_mode) && | 616 | /* |
611 | (upperdentry || (lowerdentry && ovl_indexdir(dentry->d_sb)))) { | 617 | * Copy up origin (lower) may exist for non-indexed upper, but we must |
612 | struct inode *key = d_inode(lowerdentry ?: upperdentry); | 618 | * not use lower as hash key in that case. |
619 | * Hash inodes that are or could be indexed by origin inode and | ||
620 | * non-indexed upper inodes that could be hard linked by upper inode. | ||
621 | */ | ||
622 | if (!S_ISDIR(realinode->i_mode) && (upperdentry || indexed)) { | ||
623 | struct inode *key = d_inode(indexed ? lowerdentry : | ||
624 | upperdentry); | ||
613 | unsigned int nlink; | 625 | unsigned int nlink; |
614 | 626 | ||
615 | inode = iget5_locked(dentry->d_sb, (unsigned long) key, | 627 | inode = iget5_locked(dentry->d_sb, (unsigned long) key, |
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c index c3addd1114f1..a12dc10bf726 100644 --- a/fs/overlayfs/namei.c +++ b/fs/overlayfs/namei.c | |||
@@ -405,14 +405,13 @@ int ovl_verify_index(struct dentry *index, struct path *lowerstack, | |||
405 | * be treated as stale (i.e. after unlink of the overlay inode). | 405 | * be treated as stale (i.e. after unlink of the overlay inode). |
406 | * We don't know the verification rules for directory and whiteout | 406 | * We don't know the verification rules for directory and whiteout |
407 | * index entries, because they have not been implemented yet, so return | 407 | * index entries, because they have not been implemented yet, so return |
408 | * EROFS if those entries are found to avoid corrupting an index that | 408 | * EINVAL if those entries are found to abort the mount to avoid |
409 | * was created by a newer kernel. | 409 | * corrupting an index that was created by a newer kernel. |
410 | */ | 410 | */ |
411 | err = -EROFS; | 411 | err = -EINVAL; |
412 | if (d_is_dir(index) || ovl_is_whiteout(index)) | 412 | if (d_is_dir(index) || ovl_is_whiteout(index)) |
413 | goto fail; | 413 | goto fail; |
414 | 414 | ||
415 | err = -EINVAL; | ||
416 | if (index->d_name.len < sizeof(struct ovl_fh)*2) | 415 | if (index->d_name.len < sizeof(struct ovl_fh)*2) |
417 | goto fail; | 416 | goto fail; |
418 | 417 | ||
@@ -506,6 +505,11 @@ static struct dentry *ovl_lookup_index(struct dentry *dentry, | |||
506 | 505 | ||
507 | index = lookup_one_len_unlocked(name.name, ofs->indexdir, name.len); | 506 | index = lookup_one_len_unlocked(name.name, ofs->indexdir, name.len); |
508 | if (IS_ERR(index)) { | 507 | if (IS_ERR(index)) { |
508 | err = PTR_ERR(index); | ||
509 | if (err == -ENOENT) { | ||
510 | index = NULL; | ||
511 | goto out; | ||
512 | } | ||
509 | pr_warn_ratelimited("overlayfs: failed inode index lookup (ino=%lu, key=%*s, err=%i);\n" | 513 | pr_warn_ratelimited("overlayfs: failed inode index lookup (ino=%lu, key=%*s, err=%i);\n" |
510 | "overlayfs: mount with '-o index=off' to disable inodes index.\n", | 514 | "overlayfs: mount with '-o index=off' to disable inodes index.\n", |
511 | d_inode(origin)->i_ino, name.len, name.name, | 515 | d_inode(origin)->i_ino, name.len, name.name, |
@@ -515,18 +519,9 @@ static struct dentry *ovl_lookup_index(struct dentry *dentry, | |||
515 | 519 | ||
516 | inode = d_inode(index); | 520 | inode = d_inode(index); |
517 | if (d_is_negative(index)) { | 521 | if (d_is_negative(index)) { |
518 | if (upper && d_inode(origin)->i_nlink > 1) { | 522 | goto out_dput; |
519 | pr_warn_ratelimited("overlayfs: hard link with origin but no index (ino=%lu).\n", | ||
520 | d_inode(origin)->i_ino); | ||
521 | goto fail; | ||
522 | } | ||
523 | |||
524 | dput(index); | ||
525 | index = NULL; | ||
526 | } else if (upper && d_inode(upper) != inode) { | 523 | } else if (upper && d_inode(upper) != inode) { |
527 | pr_warn_ratelimited("overlayfs: wrong index found (index=%pd2, ino=%lu, upper ino=%lu).\n", | 524 | goto out_dput; |
528 | index, inode->i_ino, d_inode(upper)->i_ino); | ||
529 | goto fail; | ||
530 | } else if (ovl_dentry_weird(index) || ovl_is_whiteout(index) || | 525 | } else if (ovl_dentry_weird(index) || ovl_is_whiteout(index) || |
531 | ((inode->i_mode ^ d_inode(origin)->i_mode) & S_IFMT)) { | 526 | ((inode->i_mode ^ d_inode(origin)->i_mode) & S_IFMT)) { |
532 | /* | 527 | /* |
@@ -546,6 +541,11 @@ out: | |||
546 | kfree(name.name); | 541 | kfree(name.name); |
547 | return index; | 542 | return index; |
548 | 543 | ||
544 | out_dput: | ||
545 | dput(index); | ||
546 | index = NULL; | ||
547 | goto out; | ||
548 | |||
549 | fail: | 549 | fail: |
550 | dput(index); | 550 | dput(index); |
551 | index = ERR_PTR(-EIO); | 551 | index = ERR_PTR(-EIO); |
@@ -634,6 +634,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, | |||
634 | } | 634 | } |
635 | 635 | ||
636 | if (d.redirect) { | 636 | if (d.redirect) { |
637 | err = -ENOMEM; | ||
637 | upperredirect = kstrdup(d.redirect, GFP_KERNEL); | 638 | upperredirect = kstrdup(d.redirect, GFP_KERNEL); |
638 | if (!upperredirect) | 639 | if (!upperredirect) |
639 | goto out_put_upper; | 640 | goto out_put_upper; |
@@ -708,7 +709,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, | |||
708 | upperdentry = dget(index); | 709 | upperdentry = dget(index); |
709 | 710 | ||
710 | if (upperdentry || ctr) { | 711 | if (upperdentry || ctr) { |
711 | inode = ovl_get_inode(dentry, upperdentry); | 712 | inode = ovl_get_inode(dentry, upperdentry, index); |
712 | err = PTR_ERR(inode); | 713 | err = PTR_ERR(inode); |
713 | if (IS_ERR(inode)) | 714 | if (IS_ERR(inode)) |
714 | goto out_free_oe; | 715 | goto out_free_oe; |
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index d4e8c1a08fb0..d9a0edd4e57e 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h | |||
@@ -235,6 +235,7 @@ bool ovl_inuse_trylock(struct dentry *dentry); | |||
235 | void ovl_inuse_unlock(struct dentry *dentry); | 235 | void ovl_inuse_unlock(struct dentry *dentry); |
236 | int ovl_nlink_start(struct dentry *dentry, bool *locked); | 236 | int ovl_nlink_start(struct dentry *dentry, bool *locked); |
237 | void ovl_nlink_end(struct dentry *dentry, bool locked); | 237 | void ovl_nlink_end(struct dentry *dentry, bool locked); |
238 | int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir); | ||
238 | 239 | ||
239 | static inline bool ovl_is_impuredir(struct dentry *dentry) | 240 | static inline bool ovl_is_impuredir(struct dentry *dentry) |
240 | { | 241 | { |
@@ -285,7 +286,8 @@ int ovl_update_time(struct inode *inode, struct timespec *ts, int flags); | |||
285 | bool ovl_is_private_xattr(const char *name); | 286 | bool ovl_is_private_xattr(const char *name); |
286 | 287 | ||
287 | struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, dev_t rdev); | 288 | struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, dev_t rdev); |
288 | struct inode *ovl_get_inode(struct dentry *dentry, struct dentry *upperdentry); | 289 | struct inode *ovl_get_inode(struct dentry *dentry, struct dentry *upperdentry, |
290 | struct dentry *index); | ||
289 | static inline void ovl_copyattr(struct inode *from, struct inode *to) | 291 | static inline void ovl_copyattr(struct inode *from, struct inode *to) |
290 | { | 292 | { |
291 | to->i_uid = from->i_uid; | 293 | to->i_uid = from->i_uid; |
diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h index 878a750986dd..25d9b5adcd42 100644 --- a/fs/overlayfs/ovl_entry.h +++ b/fs/overlayfs/ovl_entry.h | |||
@@ -37,6 +37,9 @@ struct ovl_fs { | |||
37 | bool noxattr; | 37 | bool noxattr; |
38 | /* sb common to all layers */ | 38 | /* sb common to all layers */ |
39 | struct super_block *same_sb; | 39 | struct super_block *same_sb; |
40 | /* Did we take the inuse lock? */ | ||
41 | bool upperdir_locked; | ||
42 | bool workdir_locked; | ||
40 | }; | 43 | }; |
41 | 44 | ||
42 | /* private information held for every overlayfs dentry */ | 45 | /* private information held for every overlayfs dentry */ |
diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c index 62e9b22a2077..698b74dd750e 100644 --- a/fs/overlayfs/readdir.c +++ b/fs/overlayfs/readdir.c | |||
@@ -988,6 +988,7 @@ int ovl_indexdir_cleanup(struct dentry *dentry, struct vfsmount *mnt, | |||
988 | struct path *lowerstack, unsigned int numlower) | 988 | struct path *lowerstack, unsigned int numlower) |
989 | { | 989 | { |
990 | int err; | 990 | int err; |
991 | struct dentry *index = NULL; | ||
991 | struct inode *dir = dentry->d_inode; | 992 | struct inode *dir = dentry->d_inode; |
992 | struct path path = { .mnt = mnt, .dentry = dentry }; | 993 | struct path path = { .mnt = mnt, .dentry = dentry }; |
993 | LIST_HEAD(list); | 994 | LIST_HEAD(list); |
@@ -1007,8 +1008,6 @@ int ovl_indexdir_cleanup(struct dentry *dentry, struct vfsmount *mnt, | |||
1007 | 1008 | ||
1008 | inode_lock_nested(dir, I_MUTEX_PARENT); | 1009 | inode_lock_nested(dir, I_MUTEX_PARENT); |
1009 | list_for_each_entry(p, &list, l_node) { | 1010 | list_for_each_entry(p, &list, l_node) { |
1010 | struct dentry *index; | ||
1011 | |||
1012 | if (p->name[0] == '.') { | 1011 | if (p->name[0] == '.') { |
1013 | if (p->len == 1) | 1012 | if (p->len == 1) |
1014 | continue; | 1013 | continue; |
@@ -1018,18 +1017,20 @@ int ovl_indexdir_cleanup(struct dentry *dentry, struct vfsmount *mnt, | |||
1018 | index = lookup_one_len(p->name, dentry, p->len); | 1017 | index = lookup_one_len(p->name, dentry, p->len); |
1019 | if (IS_ERR(index)) { | 1018 | if (IS_ERR(index)) { |
1020 | err = PTR_ERR(index); | 1019 | err = PTR_ERR(index); |
1020 | index = NULL; | ||
1021 | break; | 1021 | break; |
1022 | } | 1022 | } |
1023 | err = ovl_verify_index(index, lowerstack, numlower); | 1023 | err = ovl_verify_index(index, lowerstack, numlower); |
1024 | if (err) { | 1024 | /* Cleanup stale and orphan index entries */ |
1025 | if (err == -EROFS) | 1025 | if (err && (err == -ESTALE || err == -ENOENT)) |
1026 | break; | ||
1027 | err = ovl_cleanup(dir, index); | 1026 | err = ovl_cleanup(dir, index); |
1028 | if (err) | 1027 | if (err) |
1029 | break; | 1028 | break; |
1030 | } | 1029 | |
1031 | dput(index); | 1030 | dput(index); |
1031 | index = NULL; | ||
1032 | } | 1032 | } |
1033 | dput(index); | ||
1033 | inode_unlock(dir); | 1034 | inode_unlock(dir); |
1034 | out: | 1035 | out: |
1035 | ovl_cache_free(&list); | 1036 | ovl_cache_free(&list); |
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index fd5ea4facc62..f5738e96a052 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c | |||
@@ -174,6 +174,9 @@ static struct inode *ovl_alloc_inode(struct super_block *sb) | |||
174 | { | 174 | { |
175 | struct ovl_inode *oi = kmem_cache_alloc(ovl_inode_cachep, GFP_KERNEL); | 175 | struct ovl_inode *oi = kmem_cache_alloc(ovl_inode_cachep, GFP_KERNEL); |
176 | 176 | ||
177 | if (!oi) | ||
178 | return NULL; | ||
179 | |||
177 | oi->cache = NULL; | 180 | oi->cache = NULL; |
178 | oi->redirect = NULL; | 181 | oi->redirect = NULL; |
179 | oi->version = 0; | 182 | oi->version = 0; |
@@ -211,9 +214,10 @@ static void ovl_put_super(struct super_block *sb) | |||
211 | 214 | ||
212 | dput(ufs->indexdir); | 215 | dput(ufs->indexdir); |
213 | dput(ufs->workdir); | 216 | dput(ufs->workdir); |
214 | ovl_inuse_unlock(ufs->workbasedir); | 217 | if (ufs->workdir_locked) |
218 | ovl_inuse_unlock(ufs->workbasedir); | ||
215 | dput(ufs->workbasedir); | 219 | dput(ufs->workbasedir); |
216 | if (ufs->upper_mnt) | 220 | if (ufs->upper_mnt && ufs->upperdir_locked) |
217 | ovl_inuse_unlock(ufs->upper_mnt->mnt_root); | 221 | ovl_inuse_unlock(ufs->upper_mnt->mnt_root); |
218 | mntput(ufs->upper_mnt); | 222 | mntput(ufs->upper_mnt); |
219 | for (i = 0; i < ufs->numlower; i++) | 223 | for (i = 0; i < ufs->numlower; i++) |
@@ -881,9 +885,13 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) | |||
881 | goto out_put_upperpath; | 885 | goto out_put_upperpath; |
882 | 886 | ||
883 | err = -EBUSY; | 887 | err = -EBUSY; |
884 | if (!ovl_inuse_trylock(upperpath.dentry)) { | 888 | if (ovl_inuse_trylock(upperpath.dentry)) { |
885 | pr_err("overlayfs: upperdir is in-use by another mount\n"); | 889 | ufs->upperdir_locked = true; |
890 | } else if (ufs->config.index) { | ||
891 | pr_err("overlayfs: upperdir is in-use by another mount, mount with '-o index=off' to override exclusive upperdir protection.\n"); | ||
886 | goto out_put_upperpath; | 892 | goto out_put_upperpath; |
893 | } else { | ||
894 | pr_warn("overlayfs: upperdir is in-use by another mount, accessing files from both mounts will result in undefined behavior.\n"); | ||
887 | } | 895 | } |
888 | 896 | ||
889 | err = ovl_mount_dir(ufs->config.workdir, &workpath); | 897 | err = ovl_mount_dir(ufs->config.workdir, &workpath); |
@@ -901,9 +909,13 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) | |||
901 | } | 909 | } |
902 | 910 | ||
903 | err = -EBUSY; | 911 | err = -EBUSY; |
904 | if (!ovl_inuse_trylock(workpath.dentry)) { | 912 | if (ovl_inuse_trylock(workpath.dentry)) { |
905 | pr_err("overlayfs: workdir is in-use by another mount\n"); | 913 | ufs->workdir_locked = true; |
914 | } else if (ufs->config.index) { | ||
915 | pr_err("overlayfs: workdir is in-use by another mount, mount with '-o index=off' to override exclusive workdir protection.\n"); | ||
906 | goto out_put_workpath; | 916 | goto out_put_workpath; |
917 | } else { | ||
918 | pr_warn("overlayfs: workdir is in-use by another mount, accessing files from both mounts will result in undefined behavior.\n"); | ||
907 | } | 919 | } |
908 | 920 | ||
909 | ufs->workbasedir = workpath.dentry; | 921 | ufs->workbasedir = workpath.dentry; |
@@ -1156,11 +1168,13 @@ out_put_lowerpath: | |||
1156 | out_free_lowertmp: | 1168 | out_free_lowertmp: |
1157 | kfree(lowertmp); | 1169 | kfree(lowertmp); |
1158 | out_unlock_workdentry: | 1170 | out_unlock_workdentry: |
1159 | ovl_inuse_unlock(workpath.dentry); | 1171 | if (ufs->workdir_locked) |
1172 | ovl_inuse_unlock(workpath.dentry); | ||
1160 | out_put_workpath: | 1173 | out_put_workpath: |
1161 | path_put(&workpath); | 1174 | path_put(&workpath); |
1162 | out_unlock_upperdentry: | 1175 | out_unlock_upperdentry: |
1163 | ovl_inuse_unlock(upperpath.dentry); | 1176 | if (ufs->upperdir_locked) |
1177 | ovl_inuse_unlock(upperpath.dentry); | ||
1164 | out_put_upperpath: | 1178 | out_put_upperpath: |
1165 | path_put(&upperpath); | 1179 | path_put(&upperpath); |
1166 | out_free_config: | 1180 | out_free_config: |
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index 117794582f9f..b9b239fa5cfd 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c | |||
@@ -430,7 +430,7 @@ void ovl_inuse_unlock(struct dentry *dentry) | |||
430 | } | 430 | } |
431 | } | 431 | } |
432 | 432 | ||
433 | /* Called must hold OVL_I(inode)->oi_lock */ | 433 | /* Caller must hold OVL_I(inode)->lock */ |
434 | static void ovl_cleanup_index(struct dentry *dentry) | 434 | static void ovl_cleanup_index(struct dentry *dentry) |
435 | { | 435 | { |
436 | struct inode *dir = ovl_indexdir(dentry->d_sb)->d_inode; | 436 | struct inode *dir = ovl_indexdir(dentry->d_sb)->d_inode; |
@@ -469,6 +469,9 @@ static void ovl_cleanup_index(struct dentry *dentry) | |||
469 | err = PTR_ERR(index); | 469 | err = PTR_ERR(index); |
470 | if (!IS_ERR(index)) | 470 | if (!IS_ERR(index)) |
471 | err = ovl_cleanup(dir, index); | 471 | err = ovl_cleanup(dir, index); |
472 | else | ||
473 | index = NULL; | ||
474 | |||
472 | inode_unlock(dir); | 475 | inode_unlock(dir); |
473 | if (err) | 476 | if (err) |
474 | goto fail; | 477 | goto fail; |
@@ -557,3 +560,22 @@ void ovl_nlink_end(struct dentry *dentry, bool locked) | |||
557 | mutex_unlock(&OVL_I(d_inode(dentry))->lock); | 560 | mutex_unlock(&OVL_I(d_inode(dentry))->lock); |
558 | } | 561 | } |
559 | } | 562 | } |
563 | |||
564 | int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir) | ||
565 | { | ||
566 | /* Workdir should not be the same as upperdir */ | ||
567 | if (workdir == upperdir) | ||
568 | goto err; | ||
569 | |||
570 | /* Workdir should not be subdir of upperdir and vice versa */ | ||
571 | if (lock_rename(workdir, upperdir) != NULL) | ||
572 | goto err_unlock; | ||
573 | |||
574 | return 0; | ||
575 | |||
576 | err_unlock: | ||
577 | unlock_rename(workdir, upperdir); | ||
578 | err: | ||
579 | pr_err("overlayfs: failed to lock workdir+upperdir\n"); | ||
580 | return -EIO; | ||
581 | } | ||
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 50b0556a124f..52ad15192e72 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c | |||
@@ -1297,21 +1297,18 @@ static int dquot_add_space(struct dquot *dquot, qsize_t space, | |||
1297 | spin_lock(&dquot->dq_dqb_lock); | 1297 | spin_lock(&dquot->dq_dqb_lock); |
1298 | if (!sb_has_quota_limits_enabled(sb, dquot->dq_id.type) || | 1298 | if (!sb_has_quota_limits_enabled(sb, dquot->dq_id.type) || |
1299 | test_bit(DQ_FAKE_B, &dquot->dq_flags)) | 1299 | test_bit(DQ_FAKE_B, &dquot->dq_flags)) |
1300 | goto add; | 1300 | goto finish; |
1301 | 1301 | ||
1302 | tspace = dquot->dq_dqb.dqb_curspace + dquot->dq_dqb.dqb_rsvspace | 1302 | tspace = dquot->dq_dqb.dqb_curspace + dquot->dq_dqb.dqb_rsvspace |
1303 | + space + rsv_space; | 1303 | + space + rsv_space; |
1304 | 1304 | ||
1305 | if (flags & DQUOT_SPACE_NOFAIL) | ||
1306 | goto add; | ||
1307 | |||
1308 | if (dquot->dq_dqb.dqb_bhardlimit && | 1305 | if (dquot->dq_dqb.dqb_bhardlimit && |
1309 | tspace > dquot->dq_dqb.dqb_bhardlimit && | 1306 | tspace > dquot->dq_dqb.dqb_bhardlimit && |
1310 | !ignore_hardlimit(dquot)) { | 1307 | !ignore_hardlimit(dquot)) { |
1311 | if (flags & DQUOT_SPACE_WARN) | 1308 | if (flags & DQUOT_SPACE_WARN) |
1312 | prepare_warning(warn, dquot, QUOTA_NL_BHARDWARN); | 1309 | prepare_warning(warn, dquot, QUOTA_NL_BHARDWARN); |
1313 | ret = -EDQUOT; | 1310 | ret = -EDQUOT; |
1314 | goto out; | 1311 | goto finish; |
1315 | } | 1312 | } |
1316 | 1313 | ||
1317 | if (dquot->dq_dqb.dqb_bsoftlimit && | 1314 | if (dquot->dq_dqb.dqb_bsoftlimit && |
@@ -1322,7 +1319,7 @@ static int dquot_add_space(struct dquot *dquot, qsize_t space, | |||
1322 | if (flags & DQUOT_SPACE_WARN) | 1319 | if (flags & DQUOT_SPACE_WARN) |
1323 | prepare_warning(warn, dquot, QUOTA_NL_BSOFTLONGWARN); | 1320 | prepare_warning(warn, dquot, QUOTA_NL_BSOFTLONGWARN); |
1324 | ret = -EDQUOT; | 1321 | ret = -EDQUOT; |
1325 | goto out; | 1322 | goto finish; |
1326 | } | 1323 | } |
1327 | 1324 | ||
1328 | if (dquot->dq_dqb.dqb_bsoftlimit && | 1325 | if (dquot->dq_dqb.dqb_bsoftlimit && |
@@ -1338,13 +1335,21 @@ static int dquot_add_space(struct dquot *dquot, qsize_t space, | |||
1338 | * be always printed | 1335 | * be always printed |
1339 | */ | 1336 | */ |
1340 | ret = -EDQUOT; | 1337 | ret = -EDQUOT; |
1341 | goto out; | 1338 | goto finish; |
1342 | } | 1339 | } |
1343 | } | 1340 | } |
1344 | add: | 1341 | finish: |
1345 | dquot->dq_dqb.dqb_rsvspace += rsv_space; | 1342 | /* |
1346 | dquot->dq_dqb.dqb_curspace += space; | 1343 | * We have to be careful and go through warning generation & grace time |
1347 | out: | 1344 | * setting even if DQUOT_SPACE_NOFAIL is set. That's why we check it |
1345 | * only here... | ||
1346 | */ | ||
1347 | if (flags & DQUOT_SPACE_NOFAIL) | ||
1348 | ret = 0; | ||
1349 | if (!ret) { | ||
1350 | dquot->dq_dqb.dqb_rsvspace += rsv_space; | ||
1351 | dquot->dq_dqb.dqb_curspace += space; | ||
1352 | } | ||
1348 | spin_unlock(&dquot->dq_dqb_lock); | 1353 | spin_unlock(&dquot->dq_dqb_lock); |
1349 | return ret; | 1354 | return ret; |
1350 | } | 1355 | } |
diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c index ef4b48d1ea42..1c713fd5b3e6 100644 --- a/fs/userfaultfd.c +++ b/fs/userfaultfd.c | |||
@@ -588,6 +588,12 @@ static void userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx, | |||
588 | break; | 588 | break; |
589 | if (ACCESS_ONCE(ctx->released) || | 589 | if (ACCESS_ONCE(ctx->released) || |
590 | fatal_signal_pending(current)) { | 590 | fatal_signal_pending(current)) { |
591 | /* | ||
592 | * &ewq->wq may be queued in fork_event, but | ||
593 | * __remove_wait_queue ignores the head | ||
594 | * parameter. It would be a problem if it | ||
595 | * didn't. | ||
596 | */ | ||
591 | __remove_wait_queue(&ctx->event_wqh, &ewq->wq); | 597 | __remove_wait_queue(&ctx->event_wqh, &ewq->wq); |
592 | if (ewq->msg.event == UFFD_EVENT_FORK) { | 598 | if (ewq->msg.event == UFFD_EVENT_FORK) { |
593 | struct userfaultfd_ctx *new; | 599 | struct userfaultfd_ctx *new; |
@@ -1061,6 +1067,12 @@ static ssize_t userfaultfd_ctx_read(struct userfaultfd_ctx *ctx, int no_wait, | |||
1061 | (unsigned long) | 1067 | (unsigned long) |
1062 | uwq->msg.arg.reserved.reserved1; | 1068 | uwq->msg.arg.reserved.reserved1; |
1063 | list_move(&uwq->wq.entry, &fork_event); | 1069 | list_move(&uwq->wq.entry, &fork_event); |
1070 | /* | ||
1071 | * fork_nctx can be freed as soon as | ||
1072 | * we drop the lock, unless we take a | ||
1073 | * reference on it. | ||
1074 | */ | ||
1075 | userfaultfd_ctx_get(fork_nctx); | ||
1064 | spin_unlock(&ctx->event_wqh.lock); | 1076 | spin_unlock(&ctx->event_wqh.lock); |
1065 | ret = 0; | 1077 | ret = 0; |
1066 | break; | 1078 | break; |
@@ -1091,19 +1103,53 @@ static ssize_t userfaultfd_ctx_read(struct userfaultfd_ctx *ctx, int no_wait, | |||
1091 | 1103 | ||
1092 | if (!ret && msg->event == UFFD_EVENT_FORK) { | 1104 | if (!ret && msg->event == UFFD_EVENT_FORK) { |
1093 | ret = resolve_userfault_fork(ctx, fork_nctx, msg); | 1105 | ret = resolve_userfault_fork(ctx, fork_nctx, msg); |
1106 | spin_lock(&ctx->event_wqh.lock); | ||
1107 | if (!list_empty(&fork_event)) { | ||
1108 | /* | ||
1109 | * The fork thread didn't abort, so we can | ||
1110 | * drop the temporary refcount. | ||
1111 | */ | ||
1112 | userfaultfd_ctx_put(fork_nctx); | ||
1113 | |||
1114 | uwq = list_first_entry(&fork_event, | ||
1115 | typeof(*uwq), | ||
1116 | wq.entry); | ||
1117 | /* | ||
1118 | * If fork_event list wasn't empty and in turn | ||
1119 | * the event wasn't already released by fork | ||
1120 | * (the event is allocated on fork kernel | ||
1121 | * stack), put the event back to its place in | ||
1122 | * the event_wq. fork_event head will be freed | ||
1123 | * as soon as we return so the event cannot | ||
1124 | * stay queued there no matter the current | ||
1125 | * "ret" value. | ||
1126 | */ | ||
1127 | list_del(&uwq->wq.entry); | ||
1128 | __add_wait_queue(&ctx->event_wqh, &uwq->wq); | ||
1094 | 1129 | ||
1095 | if (!ret) { | 1130 | /* |
1096 | spin_lock(&ctx->event_wqh.lock); | 1131 | * Leave the event in the waitqueue and report |
1097 | if (!list_empty(&fork_event)) { | 1132 | * error to userland if we failed to resolve |
1098 | uwq = list_first_entry(&fork_event, | 1133 | * the userfault fork. |
1099 | typeof(*uwq), | 1134 | */ |
1100 | wq.entry); | 1135 | if (likely(!ret)) |
1101 | list_del(&uwq->wq.entry); | ||
1102 | __add_wait_queue(&ctx->event_wqh, &uwq->wq); | ||
1103 | userfaultfd_event_complete(ctx, uwq); | 1136 | userfaultfd_event_complete(ctx, uwq); |
1104 | } | 1137 | } else { |
1105 | spin_unlock(&ctx->event_wqh.lock); | 1138 | /* |
1139 | * Here the fork thread aborted and the | ||
1140 | * refcount from the fork thread on fork_nctx | ||
1141 | * has already been released. We still hold | ||
1142 | * the reference we took before releasing the | ||
1143 | * lock above. If resolve_userfault_fork | ||
1144 | * failed we've to drop it because the | ||
1145 | * fork_nctx has to be freed in such case. If | ||
1146 | * it succeeded we'll hold it because the new | ||
1147 | * uffd references it. | ||
1148 | */ | ||
1149 | if (ret) | ||
1150 | userfaultfd_ctx_put(fork_nctx); | ||
1106 | } | 1151 | } |
1152 | spin_unlock(&ctx->event_wqh.lock); | ||
1107 | } | 1153 | } |
1108 | 1154 | ||
1109 | return ret; | 1155 | return ret; |
diff --git a/fs/xattr.c b/fs/xattr.c index 4424f7fecf14..61cd28ba25f3 100644 --- a/fs/xattr.c +++ b/fs/xattr.c | |||
@@ -250,7 +250,7 @@ xattr_getsecurity(struct inode *inode, const char *name, void *value, | |||
250 | } | 250 | } |
251 | memcpy(value, buffer, len); | 251 | memcpy(value, buffer, len); |
252 | out: | 252 | out: |
253 | security_release_secctx(buffer, len); | 253 | kfree(buffer); |
254 | out_noalloc: | 254 | out_noalloc: |
255 | return len; | 255 | return len; |
256 | } | 256 | } |
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 744dcaec34cc..f965ce832bc0 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c | |||
@@ -1584,6 +1584,10 @@ xfs_alloc_ag_vextent_small( | |||
1584 | 1584 | ||
1585 | bp = xfs_btree_get_bufs(args->mp, args->tp, | 1585 | bp = xfs_btree_get_bufs(args->mp, args->tp, |
1586 | args->agno, fbno, 0); | 1586 | args->agno, fbno, 0); |
1587 | if (!bp) { | ||
1588 | error = -EFSCORRUPTED; | ||
1589 | goto error0; | ||
1590 | } | ||
1587 | xfs_trans_binval(args->tp, bp); | 1591 | xfs_trans_binval(args->tp, bp); |
1588 | } | 1592 | } |
1589 | args->len = 1; | 1593 | args->len = 1; |
@@ -2141,6 +2145,10 @@ xfs_alloc_fix_freelist( | |||
2141 | if (error) | 2145 | if (error) |
2142 | goto out_agbp_relse; | 2146 | goto out_agbp_relse; |
2143 | bp = xfs_btree_get_bufs(mp, tp, args->agno, bno, 0); | 2147 | bp = xfs_btree_get_bufs(mp, tp, args->agno, bno, 0); |
2148 | if (!bp) { | ||
2149 | error = -EFSCORRUPTED; | ||
2150 | goto out_agbp_relse; | ||
2151 | } | ||
2144 | xfs_trans_binval(tp, bp); | 2152 | xfs_trans_binval(tp, bp); |
2145 | } | 2153 | } |
2146 | 2154 | ||
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 044a363119be..89263797cf32 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c | |||
@@ -1477,14 +1477,14 @@ xfs_bmap_isaeof( | |||
1477 | int is_empty; | 1477 | int is_empty; |
1478 | int error; | 1478 | int error; |
1479 | 1479 | ||
1480 | bma->aeof = 0; | 1480 | bma->aeof = false; |
1481 | error = xfs_bmap_last_extent(NULL, bma->ip, whichfork, &rec, | 1481 | error = xfs_bmap_last_extent(NULL, bma->ip, whichfork, &rec, |
1482 | &is_empty); | 1482 | &is_empty); |
1483 | if (error) | 1483 | if (error) |
1484 | return error; | 1484 | return error; |
1485 | 1485 | ||
1486 | if (is_empty) { | 1486 | if (is_empty) { |
1487 | bma->aeof = 1; | 1487 | bma->aeof = true; |
1488 | return 0; | 1488 | return 0; |
1489 | } | 1489 | } |
1490 | 1490 | ||
@@ -3852,6 +3852,17 @@ xfs_trim_extent( | |||
3852 | } | 3852 | } |
3853 | } | 3853 | } |
3854 | 3854 | ||
3855 | /* trim extent to within eof */ | ||
3856 | void | ||
3857 | xfs_trim_extent_eof( | ||
3858 | struct xfs_bmbt_irec *irec, | ||
3859 | struct xfs_inode *ip) | ||
3860 | |||
3861 | { | ||
3862 | xfs_trim_extent(irec, 0, XFS_B_TO_FSB(ip->i_mount, | ||
3863 | i_size_read(VFS_I(ip)))); | ||
3864 | } | ||
3865 | |||
3855 | /* | 3866 | /* |
3856 | * Trim the returned map to the required bounds | 3867 | * Trim the returned map to the required bounds |
3857 | */ | 3868 | */ |
diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h index 851982a5dfbc..502e0d8fb4ff 100644 --- a/fs/xfs/libxfs/xfs_bmap.h +++ b/fs/xfs/libxfs/xfs_bmap.h | |||
@@ -208,6 +208,7 @@ void xfs_bmap_trace_exlist(struct xfs_inode *ip, xfs_extnum_t cnt, | |||
208 | 208 | ||
209 | void xfs_trim_extent(struct xfs_bmbt_irec *irec, xfs_fileoff_t bno, | 209 | void xfs_trim_extent(struct xfs_bmbt_irec *irec, xfs_fileoff_t bno, |
210 | xfs_filblks_t len); | 210 | xfs_filblks_t len); |
211 | void xfs_trim_extent_eof(struct xfs_bmbt_irec *, struct xfs_inode *); | ||
211 | int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd); | 212 | int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd); |
212 | void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork); | 213 | void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork); |
213 | void xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_defer_ops *dfops, | 214 | void xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_defer_ops *dfops, |
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c index 988bb3f31446..dfd643909f85 100644 --- a/fs/xfs/libxfs/xfs_ialloc.c +++ b/fs/xfs/libxfs/xfs_ialloc.c | |||
@@ -1962,7 +1962,7 @@ xfs_difree_inobt( | |||
1962 | if (!(mp->m_flags & XFS_MOUNT_IKEEP) && | 1962 | if (!(mp->m_flags & XFS_MOUNT_IKEEP) && |
1963 | rec.ir_free == XFS_INOBT_ALL_FREE && | 1963 | rec.ir_free == XFS_INOBT_ALL_FREE && |
1964 | mp->m_sb.sb_inopblock <= XFS_INODES_PER_CHUNK) { | 1964 | mp->m_sb.sb_inopblock <= XFS_INODES_PER_CHUNK) { |
1965 | xic->deleted = 1; | 1965 | xic->deleted = true; |
1966 | xic->first_ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino); | 1966 | xic->first_ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino); |
1967 | xic->alloc = xfs_inobt_irec_to_allocmask(&rec); | 1967 | xic->alloc = xfs_inobt_irec_to_allocmask(&rec); |
1968 | 1968 | ||
@@ -1989,7 +1989,7 @@ xfs_difree_inobt( | |||
1989 | 1989 | ||
1990 | xfs_difree_inode_chunk(mp, agno, &rec, dfops); | 1990 | xfs_difree_inode_chunk(mp, agno, &rec, dfops); |
1991 | } else { | 1991 | } else { |
1992 | xic->deleted = 0; | 1992 | xic->deleted = false; |
1993 | 1993 | ||
1994 | error = xfs_inobt_update(cur, &rec); | 1994 | error = xfs_inobt_update(cur, &rec); |
1995 | if (error) { | 1995 | if (error) { |
diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h index 8372e9bcd7b6..71de185735e0 100644 --- a/fs/xfs/libxfs/xfs_log_format.h +++ b/fs/xfs/libxfs/xfs_log_format.h | |||
@@ -270,6 +270,7 @@ typedef struct xfs_inode_log_format { | |||
270 | uint32_t ilf_fields; /* flags for fields logged */ | 270 | uint32_t ilf_fields; /* flags for fields logged */ |
271 | uint16_t ilf_asize; /* size of attr d/ext/root */ | 271 | uint16_t ilf_asize; /* size of attr d/ext/root */ |
272 | uint16_t ilf_dsize; /* size of data/ext/root */ | 272 | uint16_t ilf_dsize; /* size of data/ext/root */ |
273 | uint32_t ilf_pad; /* pad for 64 bit boundary */ | ||
273 | uint64_t ilf_ino; /* inode number */ | 274 | uint64_t ilf_ino; /* inode number */ |
274 | union { | 275 | union { |
275 | uint32_t ilfu_rdev; /* rdev value for dev inode*/ | 276 | uint32_t ilfu_rdev; /* rdev value for dev inode*/ |
@@ -280,29 +281,17 @@ typedef struct xfs_inode_log_format { | |||
280 | int32_t ilf_boffset; /* off of inode in buffer */ | 281 | int32_t ilf_boffset; /* off of inode in buffer */ |
281 | } xfs_inode_log_format_t; | 282 | } xfs_inode_log_format_t; |
282 | 283 | ||
283 | typedef struct xfs_inode_log_format_32 { | 284 | /* |
284 | uint16_t ilf_type; /* inode log item type */ | 285 | * Old 32 bit systems will log in this format without the 64 bit |
285 | uint16_t ilf_size; /* size of this item */ | 286 | * alignment padding. Recovery will detect this and convert it to the |
286 | uint32_t ilf_fields; /* flags for fields logged */ | 287 | * correct format. |
287 | uint16_t ilf_asize; /* size of attr d/ext/root */ | 288 | */ |
288 | uint16_t ilf_dsize; /* size of data/ext/root */ | 289 | struct xfs_inode_log_format_32 { |
289 | uint64_t ilf_ino; /* inode number */ | ||
290 | union { | ||
291 | uint32_t ilfu_rdev; /* rdev value for dev inode*/ | ||
292 | uuid_t ilfu_uuid; /* mount point value */ | ||
293 | } ilf_u; | ||
294 | int64_t ilf_blkno; /* blkno of inode buffer */ | ||
295 | int32_t ilf_len; /* len of inode buffer */ | ||
296 | int32_t ilf_boffset; /* off of inode in buffer */ | ||
297 | } __attribute__((packed)) xfs_inode_log_format_32_t; | ||
298 | |||
299 | typedef struct xfs_inode_log_format_64 { | ||
300 | uint16_t ilf_type; /* inode log item type */ | 290 | uint16_t ilf_type; /* inode log item type */ |
301 | uint16_t ilf_size; /* size of this item */ | 291 | uint16_t ilf_size; /* size of this item */ |
302 | uint32_t ilf_fields; /* flags for fields logged */ | 292 | uint32_t ilf_fields; /* flags for fields logged */ |
303 | uint16_t ilf_asize; /* size of attr d/ext/root */ | 293 | uint16_t ilf_asize; /* size of attr d/ext/root */ |
304 | uint16_t ilf_dsize; /* size of data/ext/root */ | 294 | uint16_t ilf_dsize; /* size of data/ext/root */ |
305 | uint32_t ilf_pad; /* pad for 64 bit boundary */ | ||
306 | uint64_t ilf_ino; /* inode number */ | 295 | uint64_t ilf_ino; /* inode number */ |
307 | union { | 296 | union { |
308 | uint32_t ilfu_rdev; /* rdev value for dev inode*/ | 297 | uint32_t ilfu_rdev; /* rdev value for dev inode*/ |
@@ -311,7 +300,7 @@ typedef struct xfs_inode_log_format_64 { | |||
311 | int64_t ilf_blkno; /* blkno of inode buffer */ | 300 | int64_t ilf_blkno; /* blkno of inode buffer */ |
312 | int32_t ilf_len; /* len of inode buffer */ | 301 | int32_t ilf_len; /* len of inode buffer */ |
313 | int32_t ilf_boffset; /* off of inode in buffer */ | 302 | int32_t ilf_boffset; /* off of inode in buffer */ |
314 | } xfs_inode_log_format_64_t; | 303 | } __attribute__((packed)); |
315 | 304 | ||
316 | 305 | ||
317 | /* | 306 | /* |
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index 7034e17535de..3354140de07e 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c | |||
@@ -247,6 +247,8 @@ xfs_set_mode(struct inode *inode, umode_t mode) | |||
247 | int | 247 | int |
248 | xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) | 248 | xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) |
249 | { | 249 | { |
250 | umode_t mode; | ||
251 | bool set_mode = false; | ||
250 | int error = 0; | 252 | int error = 0; |
251 | 253 | ||
252 | if (!acl) | 254 | if (!acl) |
@@ -257,16 +259,24 @@ xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) | |||
257 | return error; | 259 | return error; |
258 | 260 | ||
259 | if (type == ACL_TYPE_ACCESS) { | 261 | if (type == ACL_TYPE_ACCESS) { |
260 | umode_t mode; | ||
261 | |||
262 | error = posix_acl_update_mode(inode, &mode, &acl); | 262 | error = posix_acl_update_mode(inode, &mode, &acl); |
263 | if (error) | 263 | if (error) |
264 | return error; | 264 | return error; |
265 | error = xfs_set_mode(inode, mode); | 265 | set_mode = true; |
266 | if (error) | ||
267 | return error; | ||
268 | } | 266 | } |
269 | 267 | ||
270 | set_acl: | 268 | set_acl: |
271 | return __xfs_set_acl(inode, acl, type); | 269 | error = __xfs_set_acl(inode, acl, type); |
270 | if (error) | ||
271 | return error; | ||
272 | |||
273 | /* | ||
274 | * We set the mode after successfully updating the ACL xattr because the | ||
275 | * xattr update can fail at ENOSPC and we don't want to change the mode | ||
276 | * if the ACL update hasn't been applied. | ||
277 | */ | ||
278 | if (set_mode) | ||
279 | error = xfs_set_mode(inode, mode); | ||
280 | |||
281 | return error; | ||
272 | } | 282 | } |
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index f18e5932aec4..a3eeaba156c5 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c | |||
@@ -446,6 +446,19 @@ xfs_imap_valid( | |||
446 | { | 446 | { |
447 | offset >>= inode->i_blkbits; | 447 | offset >>= inode->i_blkbits; |
448 | 448 | ||
449 | /* | ||
450 | * We have to make sure the cached mapping is within EOF to protect | ||
451 | * against eofblocks trimming on file release leaving us with a stale | ||
452 | * mapping. Otherwise, a page for a subsequent file extending buffered | ||
453 | * write could get picked up by this writeback cycle and written to the | ||
454 | * wrong blocks. | ||
455 | * | ||
456 | * Note that what we really want here is a generic mapping invalidation | ||
457 | * mechanism to protect us from arbitrary extent modifying contexts, not | ||
458 | * just eofblocks. | ||
459 | */ | ||
460 | xfs_trim_extent_eof(imap, XFS_I(inode)); | ||
461 | |||
449 | return offset >= imap->br_startoff && | 462 | return offset >= imap->br_startoff && |
450 | offset < imap->br_startoff + imap->br_blockcount; | 463 | offset < imap->br_startoff + imap->br_blockcount; |
451 | } | 464 | } |
@@ -735,6 +748,14 @@ xfs_vm_invalidatepage( | |||
735 | { | 748 | { |
736 | trace_xfs_invalidatepage(page->mapping->host, page, offset, | 749 | trace_xfs_invalidatepage(page->mapping->host, page, offset, |
737 | length); | 750 | length); |
751 | |||
752 | /* | ||
753 | * If we are invalidating the entire page, clear the dirty state from it | ||
754 | * so that we can check for attempts to release dirty cached pages in | ||
755 | * xfs_vm_releasepage(). | ||
756 | */ | ||
757 | if (offset == 0 && length >= PAGE_SIZE) | ||
758 | cancel_dirty_page(page); | ||
738 | block_invalidatepage(page, offset, length); | 759 | block_invalidatepage(page, offset, length); |
739 | } | 760 | } |
740 | 761 | ||
@@ -1190,25 +1211,27 @@ xfs_vm_releasepage( | |||
1190 | * mm accommodates an old ext3 case where clean pages might not have had | 1211 | * mm accommodates an old ext3 case where clean pages might not have had |
1191 | * the dirty bit cleared. Thus, it can send actual dirty pages to | 1212 | * the dirty bit cleared. Thus, it can send actual dirty pages to |
1192 | * ->releasepage() via shrink_active_list(). Conversely, | 1213 | * ->releasepage() via shrink_active_list(). Conversely, |
1193 | * block_invalidatepage() can send pages that are still marked dirty | 1214 | * block_invalidatepage() can send pages that are still marked dirty but |
1194 | * but otherwise have invalidated buffers. | 1215 | * otherwise have invalidated buffers. |
1195 | * | 1216 | * |
1196 | * We want to release the latter to avoid unnecessary buildup of the | 1217 | * We want to release the latter to avoid unnecessary buildup of the |
1197 | * LRU, skip the former and warn if we've left any lingering | 1218 | * LRU, so xfs_vm_invalidatepage() clears the page dirty flag on pages |
1198 | * delalloc/unwritten buffers on clean pages. Skip pages with delalloc | 1219 | * that are entirely invalidated and need to be released. Hence the |
1199 | * or unwritten buffers and warn if the page is not dirty. Otherwise | 1220 | * only time we should get dirty pages here is through |
1200 | * try to release the buffers. | 1221 | * shrink_active_list() and so we can simply skip those now. |
1222 | * | ||
1223 | * warn if we've left any lingering delalloc/unwritten buffers on clean | ||
1224 | * or invalidated pages we are about to release. | ||
1201 | */ | 1225 | */ |
1226 | if (PageDirty(page)) | ||
1227 | return 0; | ||
1228 | |||
1202 | xfs_count_page_state(page, &delalloc, &unwritten); | 1229 | xfs_count_page_state(page, &delalloc, &unwritten); |
1203 | 1230 | ||
1204 | if (delalloc) { | 1231 | if (WARN_ON_ONCE(delalloc)) |
1205 | WARN_ON_ONCE(!PageDirty(page)); | ||
1206 | return 0; | 1232 | return 0; |
1207 | } | 1233 | if (WARN_ON_ONCE(unwritten)) |
1208 | if (unwritten) { | ||
1209 | WARN_ON_ONCE(!PageDirty(page)); | ||
1210 | return 0; | 1234 | return 0; |
1211 | } | ||
1212 | 1235 | ||
1213 | return try_to_free_buffers(page); | 1236 | return try_to_free_buffers(page); |
1214 | } | 1237 | } |
diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c index ebd66b19fbfc..e3a950ed35a8 100644 --- a/fs/xfs/xfs_attr_inactive.c +++ b/fs/xfs/xfs_attr_inactive.c | |||
@@ -302,6 +302,8 @@ xfs_attr3_node_inactive( | |||
302 | &bp, XFS_ATTR_FORK); | 302 | &bp, XFS_ATTR_FORK); |
303 | if (error) | 303 | if (error) |
304 | return error; | 304 | return error; |
305 | node = bp->b_addr; | ||
306 | btree = dp->d_ops->node_tree_p(node); | ||
305 | child_fsb = be32_to_cpu(btree[i + 1].before); | 307 | child_fsb = be32_to_cpu(btree[i + 1].before); |
306 | xfs_trans_brelse(*trans, bp); | 308 | xfs_trans_brelse(*trans, bp); |
307 | } | 309 | } |
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index bc6c6e10a969..6503cfa44262 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c | |||
@@ -84,6 +84,7 @@ xfs_zero_extent( | |||
84 | GFP_NOFS, 0); | 84 | GFP_NOFS, 0); |
85 | } | 85 | } |
86 | 86 | ||
87 | #ifdef CONFIG_XFS_RT | ||
87 | int | 88 | int |
88 | xfs_bmap_rtalloc( | 89 | xfs_bmap_rtalloc( |
89 | struct xfs_bmalloca *ap) /* bmap alloc argument struct */ | 90 | struct xfs_bmalloca *ap) /* bmap alloc argument struct */ |
@@ -190,6 +191,7 @@ xfs_bmap_rtalloc( | |||
190 | } | 191 | } |
191 | return 0; | 192 | return 0; |
192 | } | 193 | } |
194 | #endif /* CONFIG_XFS_RT */ | ||
193 | 195 | ||
194 | /* | 196 | /* |
195 | * Check if the endoff is outside the last extent. If so the caller will grow | 197 | * Check if the endoff is outside the last extent. If so the caller will grow |
@@ -2122,11 +2124,31 @@ xfs_swap_extents( | |||
2122 | ip->i_d.di_flags2 |= tip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK; | 2124 | ip->i_d.di_flags2 |= tip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK; |
2123 | tip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK; | 2125 | tip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK; |
2124 | tip->i_d.di_flags2 |= f & XFS_DIFLAG2_REFLINK; | 2126 | tip->i_d.di_flags2 |= f & XFS_DIFLAG2_REFLINK; |
2127 | } | ||
2128 | |||
2129 | /* Swap the cow forks. */ | ||
2130 | if (xfs_sb_version_hasreflink(&mp->m_sb)) { | ||
2131 | xfs_extnum_t extnum; | ||
2132 | |||
2133 | ASSERT(ip->i_cformat == XFS_DINODE_FMT_EXTENTS); | ||
2134 | ASSERT(tip->i_cformat == XFS_DINODE_FMT_EXTENTS); | ||
2135 | |||
2136 | extnum = ip->i_cnextents; | ||
2137 | ip->i_cnextents = tip->i_cnextents; | ||
2138 | tip->i_cnextents = extnum; | ||
2139 | |||
2125 | cowfp = ip->i_cowfp; | 2140 | cowfp = ip->i_cowfp; |
2126 | ip->i_cowfp = tip->i_cowfp; | 2141 | ip->i_cowfp = tip->i_cowfp; |
2127 | tip->i_cowfp = cowfp; | 2142 | tip->i_cowfp = cowfp; |
2128 | xfs_inode_set_cowblocks_tag(ip); | 2143 | |
2129 | xfs_inode_set_cowblocks_tag(tip); | 2144 | if (ip->i_cowfp && ip->i_cnextents) |
2145 | xfs_inode_set_cowblocks_tag(ip); | ||
2146 | else | ||
2147 | xfs_inode_clear_cowblocks_tag(ip); | ||
2148 | if (tip->i_cowfp && tip->i_cnextents) | ||
2149 | xfs_inode_set_cowblocks_tag(tip); | ||
2150 | else | ||
2151 | xfs_inode_clear_cowblocks_tag(tip); | ||
2130 | } | 2152 | } |
2131 | 2153 | ||
2132 | xfs_trans_log_inode(tp, ip, src_log_flags); | 2154 | xfs_trans_log_inode(tp, ip, src_log_flags); |
diff --git a/fs/xfs/xfs_bmap_util.h b/fs/xfs/xfs_bmap_util.h index 0eaa81dc49be..7d330b3c77c3 100644 --- a/fs/xfs/xfs_bmap_util.h +++ b/fs/xfs/xfs_bmap_util.h | |||
@@ -28,7 +28,20 @@ struct xfs_mount; | |||
28 | struct xfs_trans; | 28 | struct xfs_trans; |
29 | struct xfs_bmalloca; | 29 | struct xfs_bmalloca; |
30 | 30 | ||
31 | #ifdef CONFIG_XFS_RT | ||
31 | int xfs_bmap_rtalloc(struct xfs_bmalloca *ap); | 32 | int xfs_bmap_rtalloc(struct xfs_bmalloca *ap); |
33 | #else /* !CONFIG_XFS_RT */ | ||
34 | /* | ||
35 | * Attempts to allocate RT extents when RT is disable indicates corruption and | ||
36 | * should trigger a shutdown. | ||
37 | */ | ||
38 | static inline int | ||
39 | xfs_bmap_rtalloc(struct xfs_bmalloca *ap) | ||
40 | { | ||
41 | return -EFSCORRUPTED; | ||
42 | } | ||
43 | #endif /* CONFIG_XFS_RT */ | ||
44 | |||
32 | int xfs_bmap_eof(struct xfs_inode *ip, xfs_fileoff_t endoff, | 45 | int xfs_bmap_eof(struct xfs_inode *ip, xfs_fileoff_t endoff, |
33 | int whichfork, int *eof); | 46 | int whichfork, int *eof); |
34 | int xfs_bmap_punch_delalloc_range(struct xfs_inode *ip, | 47 | int xfs_bmap_punch_delalloc_range(struct xfs_inode *ip, |
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 309e26c9dddb..6526ef0e2a23 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
@@ -237,11 +237,13 @@ xfs_file_dax_read( | |||
237 | if (!count) | 237 | if (!count) |
238 | return 0; /* skip atime */ | 238 | return 0; /* skip atime */ |
239 | 239 | ||
240 | if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) { | 240 | if (iocb->ki_flags & IOCB_NOWAIT) { |
241 | if (iocb->ki_flags & IOCB_NOWAIT) | 241 | if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) |
242 | return -EAGAIN; | 242 | return -EAGAIN; |
243 | } else { | ||
243 | xfs_ilock(ip, XFS_IOLOCK_SHARED); | 244 | xfs_ilock(ip, XFS_IOLOCK_SHARED); |
244 | } | 245 | } |
246 | |||
245 | ret = dax_iomap_rw(iocb, to, &xfs_iomap_ops); | 247 | ret = dax_iomap_rw(iocb, to, &xfs_iomap_ops); |
246 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); | 248 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); |
247 | 249 | ||
@@ -259,9 +261,10 @@ xfs_file_buffered_aio_read( | |||
259 | 261 | ||
260 | trace_xfs_file_buffered_read(ip, iov_iter_count(to), iocb->ki_pos); | 262 | trace_xfs_file_buffered_read(ip, iov_iter_count(to), iocb->ki_pos); |
261 | 263 | ||
262 | if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) { | 264 | if (iocb->ki_flags & IOCB_NOWAIT) { |
263 | if (iocb->ki_flags & IOCB_NOWAIT) | 265 | if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) |
264 | return -EAGAIN; | 266 | return -EAGAIN; |
267 | } else { | ||
265 | xfs_ilock(ip, XFS_IOLOCK_SHARED); | 268 | xfs_ilock(ip, XFS_IOLOCK_SHARED); |
266 | } | 269 | } |
267 | ret = generic_file_read_iter(iocb, to); | 270 | ret = generic_file_read_iter(iocb, to); |
@@ -552,9 +555,10 @@ xfs_file_dio_aio_write( | |||
552 | iolock = XFS_IOLOCK_SHARED; | 555 | iolock = XFS_IOLOCK_SHARED; |
553 | } | 556 | } |
554 | 557 | ||
555 | if (!xfs_ilock_nowait(ip, iolock)) { | 558 | if (iocb->ki_flags & IOCB_NOWAIT) { |
556 | if (iocb->ki_flags & IOCB_NOWAIT) | 559 | if (!xfs_ilock_nowait(ip, iolock)) |
557 | return -EAGAIN; | 560 | return -EAGAIN; |
561 | } else { | ||
558 | xfs_ilock(ip, iolock); | 562 | xfs_ilock(ip, iolock); |
559 | } | 563 | } |
560 | 564 | ||
@@ -606,9 +610,10 @@ xfs_file_dax_write( | |||
606 | size_t count; | 610 | size_t count; |
607 | loff_t pos; | 611 | loff_t pos; |
608 | 612 | ||
609 | if (!xfs_ilock_nowait(ip, iolock)) { | 613 | if (iocb->ki_flags & IOCB_NOWAIT) { |
610 | if (iocb->ki_flags & IOCB_NOWAIT) | 614 | if (!xfs_ilock_nowait(ip, iolock)) |
611 | return -EAGAIN; | 615 | return -EAGAIN; |
616 | } else { | ||
612 | xfs_ilock(ip, iolock); | 617 | xfs_ilock(ip, iolock); |
613 | } | 618 | } |
614 | 619 | ||
@@ -764,7 +769,7 @@ xfs_file_fallocate( | |||
764 | enum xfs_prealloc_flags flags = 0; | 769 | enum xfs_prealloc_flags flags = 0; |
765 | uint iolock = XFS_IOLOCK_EXCL; | 770 | uint iolock = XFS_IOLOCK_EXCL; |
766 | loff_t new_size = 0; | 771 | loff_t new_size = 0; |
767 | bool do_file_insert = 0; | 772 | bool do_file_insert = false; |
768 | 773 | ||
769 | if (!S_ISREG(inode->i_mode)) | 774 | if (!S_ISREG(inode->i_mode)) |
770 | return -EINVAL; | 775 | return -EINVAL; |
@@ -825,7 +830,7 @@ xfs_file_fallocate( | |||
825 | error = -EINVAL; | 830 | error = -EINVAL; |
826 | goto out_unlock; | 831 | goto out_unlock; |
827 | } | 832 | } |
828 | do_file_insert = 1; | 833 | do_file_insert = true; |
829 | } else { | 834 | } else { |
830 | flags |= XFS_PREALLOC_SET; | 835 | flags |= XFS_PREALLOC_SET; |
831 | 836 | ||
diff --git a/fs/xfs/xfs_fsmap.c b/fs/xfs/xfs_fsmap.c index 814ed729881d..43cfc07996a4 100644 --- a/fs/xfs/xfs_fsmap.c +++ b/fs/xfs/xfs_fsmap.c | |||
@@ -367,29 +367,6 @@ xfs_getfsmap_datadev_helper( | |||
367 | return xfs_getfsmap_helper(cur->bc_tp, info, rec, rec_daddr); | 367 | return xfs_getfsmap_helper(cur->bc_tp, info, rec, rec_daddr); |
368 | } | 368 | } |
369 | 369 | ||
370 | /* Transform a rtbitmap "record" into a fsmap */ | ||
371 | STATIC int | ||
372 | xfs_getfsmap_rtdev_rtbitmap_helper( | ||
373 | struct xfs_trans *tp, | ||
374 | struct xfs_rtalloc_rec *rec, | ||
375 | void *priv) | ||
376 | { | ||
377 | struct xfs_mount *mp = tp->t_mountp; | ||
378 | struct xfs_getfsmap_info *info = priv; | ||
379 | struct xfs_rmap_irec irec; | ||
380 | xfs_daddr_t rec_daddr; | ||
381 | |||
382 | rec_daddr = XFS_FSB_TO_BB(mp, rec->ar_startblock); | ||
383 | |||
384 | irec.rm_startblock = rec->ar_startblock; | ||
385 | irec.rm_blockcount = rec->ar_blockcount; | ||
386 | irec.rm_owner = XFS_RMAP_OWN_NULL; /* "free" */ | ||
387 | irec.rm_offset = 0; | ||
388 | irec.rm_flags = 0; | ||
389 | |||
390 | return xfs_getfsmap_helper(tp, info, &irec, rec_daddr); | ||
391 | } | ||
392 | |||
393 | /* Transform a bnobt irec into a fsmap */ | 370 | /* Transform a bnobt irec into a fsmap */ |
394 | STATIC int | 371 | STATIC int |
395 | xfs_getfsmap_datadev_bnobt_helper( | 372 | xfs_getfsmap_datadev_bnobt_helper( |
@@ -475,6 +452,30 @@ xfs_getfsmap_logdev( | |||
475 | return xfs_getfsmap_helper(tp, info, &rmap, 0); | 452 | return xfs_getfsmap_helper(tp, info, &rmap, 0); |
476 | } | 453 | } |
477 | 454 | ||
455 | #ifdef CONFIG_XFS_RT | ||
456 | /* Transform a rtbitmap "record" into a fsmap */ | ||
457 | STATIC int | ||
458 | xfs_getfsmap_rtdev_rtbitmap_helper( | ||
459 | struct xfs_trans *tp, | ||
460 | struct xfs_rtalloc_rec *rec, | ||
461 | void *priv) | ||
462 | { | ||
463 | struct xfs_mount *mp = tp->t_mountp; | ||
464 | struct xfs_getfsmap_info *info = priv; | ||
465 | struct xfs_rmap_irec irec; | ||
466 | xfs_daddr_t rec_daddr; | ||
467 | |||
468 | rec_daddr = XFS_FSB_TO_BB(mp, rec->ar_startblock); | ||
469 | |||
470 | irec.rm_startblock = rec->ar_startblock; | ||
471 | irec.rm_blockcount = rec->ar_blockcount; | ||
472 | irec.rm_owner = XFS_RMAP_OWN_NULL; /* "free" */ | ||
473 | irec.rm_offset = 0; | ||
474 | irec.rm_flags = 0; | ||
475 | |||
476 | return xfs_getfsmap_helper(tp, info, &irec, rec_daddr); | ||
477 | } | ||
478 | |||
478 | /* Execute a getfsmap query against the realtime device. */ | 479 | /* Execute a getfsmap query against the realtime device. */ |
479 | STATIC int | 480 | STATIC int |
480 | __xfs_getfsmap_rtdev( | 481 | __xfs_getfsmap_rtdev( |
@@ -561,6 +562,7 @@ xfs_getfsmap_rtdev_rtbitmap( | |||
561 | return __xfs_getfsmap_rtdev(tp, keys, xfs_getfsmap_rtdev_rtbitmap_query, | 562 | return __xfs_getfsmap_rtdev(tp, keys, xfs_getfsmap_rtdev_rtbitmap_query, |
562 | info); | 563 | info); |
563 | } | 564 | } |
565 | #endif /* CONFIG_XFS_RT */ | ||
564 | 566 | ||
565 | /* Execute a getfsmap query against the regular data device. */ | 567 | /* Execute a getfsmap query against the regular data device. */ |
566 | STATIC int | 568 | STATIC int |
@@ -795,7 +797,15 @@ xfs_getfsmap_check_keys( | |||
795 | return false; | 797 | return false; |
796 | } | 798 | } |
797 | 799 | ||
800 | /* | ||
801 | * There are only two devices if we didn't configure RT devices at build time. | ||
802 | */ | ||
803 | #ifdef CONFIG_XFS_RT | ||
798 | #define XFS_GETFSMAP_DEVS 3 | 804 | #define XFS_GETFSMAP_DEVS 3 |
805 | #else | ||
806 | #define XFS_GETFSMAP_DEVS 2 | ||
807 | #endif /* CONFIG_XFS_RT */ | ||
808 | |||
799 | /* | 809 | /* |
800 | * Get filesystem's extents as described in head, and format for | 810 | * Get filesystem's extents as described in head, and format for |
801 | * output. Calls formatter to fill the user's buffer until all | 811 | * output. Calls formatter to fill the user's buffer until all |
@@ -853,10 +863,12 @@ xfs_getfsmap( | |||
853 | handlers[1].dev = new_encode_dev(mp->m_logdev_targp->bt_dev); | 863 | handlers[1].dev = new_encode_dev(mp->m_logdev_targp->bt_dev); |
854 | handlers[1].fn = xfs_getfsmap_logdev; | 864 | handlers[1].fn = xfs_getfsmap_logdev; |
855 | } | 865 | } |
866 | #ifdef CONFIG_XFS_RT | ||
856 | if (mp->m_rtdev_targp) { | 867 | if (mp->m_rtdev_targp) { |
857 | handlers[2].dev = new_encode_dev(mp->m_rtdev_targp->bt_dev); | 868 | handlers[2].dev = new_encode_dev(mp->m_rtdev_targp->bt_dev); |
858 | handlers[2].fn = xfs_getfsmap_rtdev_rtbitmap; | 869 | handlers[2].fn = xfs_getfsmap_rtdev_rtbitmap; |
859 | } | 870 | } |
871 | #endif /* CONFIG_XFS_RT */ | ||
860 | 872 | ||
861 | xfs_sort(handlers, XFS_GETFSMAP_DEVS, sizeof(struct xfs_getfsmap_dev), | 873 | xfs_sort(handlers, XFS_GETFSMAP_DEVS, sizeof(struct xfs_getfsmap_dev), |
862 | xfs_getfsmap_dev_compare); | 874 | xfs_getfsmap_dev_compare); |
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index a705f34b58fa..9bbc2d7cc8cb 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c | |||
@@ -364,6 +364,9 @@ xfs_inode_to_log_dinode( | |||
364 | to->di_dmstate = from->di_dmstate; | 364 | to->di_dmstate = from->di_dmstate; |
365 | to->di_flags = from->di_flags; | 365 | to->di_flags = from->di_flags; |
366 | 366 | ||
367 | /* log a dummy value to ensure log structure is fully initialised */ | ||
368 | to->di_next_unlinked = NULLAGINO; | ||
369 | |||
367 | if (from->di_version == 3) { | 370 | if (from->di_version == 3) { |
368 | to->di_changecount = inode->i_version; | 371 | to->di_changecount = inode->i_version; |
369 | to->di_crtime.t_sec = from->di_crtime.t_sec; | 372 | to->di_crtime.t_sec = from->di_crtime.t_sec; |
@@ -404,6 +407,11 @@ xfs_inode_item_format_core( | |||
404 | * the second with the on-disk inode structure, and a possible third and/or | 407 | * the second with the on-disk inode structure, and a possible third and/or |
405 | * fourth with the inode data/extents/b-tree root and inode attributes | 408 | * fourth with the inode data/extents/b-tree root and inode attributes |
406 | * data/extents/b-tree root. | 409 | * data/extents/b-tree root. |
410 | * | ||
411 | * Note: Always use the 64 bit inode log format structure so we don't | ||
412 | * leave an uninitialised hole in the format item on 64 bit systems. Log | ||
413 | * recovery on 32 bit systems handles this just fine, so there's no reason | ||
414 | * for not using an initialising the properly padded structure all the time. | ||
407 | */ | 415 | */ |
408 | STATIC void | 416 | STATIC void |
409 | xfs_inode_item_format( | 417 | xfs_inode_item_format( |
@@ -412,8 +420,8 @@ xfs_inode_item_format( | |||
412 | { | 420 | { |
413 | struct xfs_inode_log_item *iip = INODE_ITEM(lip); | 421 | struct xfs_inode_log_item *iip = INODE_ITEM(lip); |
414 | struct xfs_inode *ip = iip->ili_inode; | 422 | struct xfs_inode *ip = iip->ili_inode; |
415 | struct xfs_inode_log_format *ilf; | ||
416 | struct xfs_log_iovec *vecp = NULL; | 423 | struct xfs_log_iovec *vecp = NULL; |
424 | struct xfs_inode_log_format *ilf; | ||
417 | 425 | ||
418 | ASSERT(ip->i_d.di_version > 1); | 426 | ASSERT(ip->i_d.di_version > 1); |
419 | 427 | ||
@@ -425,7 +433,17 @@ xfs_inode_item_format( | |||
425 | ilf->ilf_boffset = ip->i_imap.im_boffset; | 433 | ilf->ilf_boffset = ip->i_imap.im_boffset; |
426 | ilf->ilf_fields = XFS_ILOG_CORE; | 434 | ilf->ilf_fields = XFS_ILOG_CORE; |
427 | ilf->ilf_size = 2; /* format + core */ | 435 | ilf->ilf_size = 2; /* format + core */ |
428 | xlog_finish_iovec(lv, vecp, sizeof(struct xfs_inode_log_format)); | 436 | |
437 | /* | ||
438 | * make sure we don't leak uninitialised data into the log in the case | ||
439 | * when we don't log every field in the inode. | ||
440 | */ | ||
441 | ilf->ilf_dsize = 0; | ||
442 | ilf->ilf_asize = 0; | ||
443 | ilf->ilf_pad = 0; | ||
444 | uuid_copy(&ilf->ilf_u.ilfu_uuid, &uuid_null); | ||
445 | |||
446 | xlog_finish_iovec(lv, vecp, sizeof(*ilf)); | ||
429 | 447 | ||
430 | xfs_inode_item_format_core(ip, lv, &vecp); | 448 | xfs_inode_item_format_core(ip, lv, &vecp); |
431 | xfs_inode_item_format_data_fork(iip, ilf, lv, &vecp); | 449 | xfs_inode_item_format_data_fork(iip, ilf, lv, &vecp); |
@@ -855,44 +873,29 @@ xfs_istale_done( | |||
855 | } | 873 | } |
856 | 874 | ||
857 | /* | 875 | /* |
858 | * convert an xfs_inode_log_format struct from either 32 or 64 bit versions | 876 | * convert an xfs_inode_log_format struct from the old 32 bit version |
859 | * (which can have different field alignments) to the native version | 877 | * (which can have different field alignments) to the native 64 bit version |
860 | */ | 878 | */ |
861 | int | 879 | int |
862 | xfs_inode_item_format_convert( | 880 | xfs_inode_item_format_convert( |
863 | xfs_log_iovec_t *buf, | 881 | struct xfs_log_iovec *buf, |
864 | xfs_inode_log_format_t *in_f) | 882 | struct xfs_inode_log_format *in_f) |
865 | { | 883 | { |
866 | if (buf->i_len == sizeof(xfs_inode_log_format_32_t)) { | 884 | struct xfs_inode_log_format_32 *in_f32 = buf->i_addr; |
867 | xfs_inode_log_format_32_t *in_f32 = buf->i_addr; | 885 | |
868 | 886 | if (buf->i_len != sizeof(*in_f32)) | |
869 | in_f->ilf_type = in_f32->ilf_type; | 887 | return -EFSCORRUPTED; |
870 | in_f->ilf_size = in_f32->ilf_size; | 888 | |
871 | in_f->ilf_fields = in_f32->ilf_fields; | 889 | in_f->ilf_type = in_f32->ilf_type; |
872 | in_f->ilf_asize = in_f32->ilf_asize; | 890 | in_f->ilf_size = in_f32->ilf_size; |
873 | in_f->ilf_dsize = in_f32->ilf_dsize; | 891 | in_f->ilf_fields = in_f32->ilf_fields; |
874 | in_f->ilf_ino = in_f32->ilf_ino; | 892 | in_f->ilf_asize = in_f32->ilf_asize; |
875 | /* copy biggest field of ilf_u */ | 893 | in_f->ilf_dsize = in_f32->ilf_dsize; |
876 | uuid_copy(&in_f->ilf_u.ilfu_uuid, &in_f32->ilf_u.ilfu_uuid); | 894 | in_f->ilf_ino = in_f32->ilf_ino; |
877 | in_f->ilf_blkno = in_f32->ilf_blkno; | 895 | /* copy biggest field of ilf_u */ |
878 | in_f->ilf_len = in_f32->ilf_len; | 896 | uuid_copy(&in_f->ilf_u.ilfu_uuid, &in_f32->ilf_u.ilfu_uuid); |
879 | in_f->ilf_boffset = in_f32->ilf_boffset; | 897 | in_f->ilf_blkno = in_f32->ilf_blkno; |
880 | return 0; | 898 | in_f->ilf_len = in_f32->ilf_len; |
881 | } else if (buf->i_len == sizeof(xfs_inode_log_format_64_t)){ | 899 | in_f->ilf_boffset = in_f32->ilf_boffset; |
882 | xfs_inode_log_format_64_t *in_f64 = buf->i_addr; | 900 | return 0; |
883 | |||
884 | in_f->ilf_type = in_f64->ilf_type; | ||
885 | in_f->ilf_size = in_f64->ilf_size; | ||
886 | in_f->ilf_fields = in_f64->ilf_fields; | ||
887 | in_f->ilf_asize = in_f64->ilf_asize; | ||
888 | in_f->ilf_dsize = in_f64->ilf_dsize; | ||
889 | in_f->ilf_ino = in_f64->ilf_ino; | ||
890 | /* copy biggest field of ilf_u */ | ||
891 | uuid_copy(&in_f->ilf_u.ilfu_uuid, &in_f64->ilf_u.ilfu_uuid); | ||
892 | in_f->ilf_blkno = in_f64->ilf_blkno; | ||
893 | in_f->ilf_len = in_f64->ilf_len; | ||
894 | in_f->ilf_boffset = in_f64->ilf_boffset; | ||
895 | return 0; | ||
896 | } | ||
897 | return -EFSCORRUPTED; | ||
898 | } | 901 | } |
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index c5107c7bc4bf..dc95a49d62e7 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
@@ -2515,7 +2515,7 @@ next_lv: | |||
2515 | if (lv) | 2515 | if (lv) |
2516 | vecp = lv->lv_iovecp; | 2516 | vecp = lv->lv_iovecp; |
2517 | } | 2517 | } |
2518 | if (record_cnt == 0 && ordered == false) { | 2518 | if (record_cnt == 0 && !ordered) { |
2519 | if (!lv) | 2519 | if (!lv) |
2520 | return 0; | 2520 | return 0; |
2521 | break; | 2521 | break; |
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index ea7d4b4e50d0..e9727d0a541a 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -704,7 +704,7 @@ xfs_mountfs( | |||
704 | xfs_set_maxicount(mp); | 704 | xfs_set_maxicount(mp); |
705 | 705 | ||
706 | /* enable fail_at_unmount as default */ | 706 | /* enable fail_at_unmount as default */ |
707 | mp->m_fail_unmount = 1; | 707 | mp->m_fail_unmount = true; |
708 | 708 | ||
709 | error = xfs_sysfs_init(&mp->m_kobj, &xfs_mp_ktype, NULL, mp->m_fsname); | 709 | error = xfs_sysfs_init(&mp->m_kobj, &xfs_mp_ktype, NULL, mp->m_fsname); |
710 | if (error) | 710 | if (error) |
diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h index 0c381d71b242..0492436a053f 100644 --- a/fs/xfs/xfs_ondisk.h +++ b/fs/xfs/xfs_ondisk.h | |||
@@ -134,7 +134,7 @@ xfs_check_ondisk_structs(void) | |||
134 | XFS_CHECK_STRUCT_SIZE(struct xfs_icreate_log, 28); | 134 | XFS_CHECK_STRUCT_SIZE(struct xfs_icreate_log, 28); |
135 | XFS_CHECK_STRUCT_SIZE(struct xfs_ictimestamp, 8); | 135 | XFS_CHECK_STRUCT_SIZE(struct xfs_ictimestamp, 8); |
136 | XFS_CHECK_STRUCT_SIZE(struct xfs_inode_log_format_32, 52); | 136 | XFS_CHECK_STRUCT_SIZE(struct xfs_inode_log_format_32, 52); |
137 | XFS_CHECK_STRUCT_SIZE(struct xfs_inode_log_format_64, 56); | 137 | XFS_CHECK_STRUCT_SIZE(struct xfs_inode_log_format, 56); |
138 | XFS_CHECK_STRUCT_SIZE(struct xfs_qoff_logformat, 20); | 138 | XFS_CHECK_STRUCT_SIZE(struct xfs_qoff_logformat, 20); |
139 | XFS_CHECK_STRUCT_SIZE(struct xfs_trans_header, 16); | 139 | XFS_CHECK_STRUCT_SIZE(struct xfs_trans_header, 16); |
140 | } | 140 | } |
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index 3246815c24d6..37e603bf1591 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c | |||
@@ -736,7 +736,13 @@ xfs_reflink_end_cow( | |||
736 | /* If there is a hole at end_fsb - 1 go to the previous extent */ | 736 | /* If there is a hole at end_fsb - 1 go to the previous extent */ |
737 | if (!xfs_iext_lookup_extent(ip, ifp, end_fsb - 1, &idx, &got) || | 737 | if (!xfs_iext_lookup_extent(ip, ifp, end_fsb - 1, &idx, &got) || |
738 | got.br_startoff > end_fsb) { | 738 | got.br_startoff > end_fsb) { |
739 | ASSERT(idx > 0); | 739 | /* |
740 | * In case of racing, overlapping AIO writes no COW extents | ||
741 | * might be left by the time I/O completes for the loser of | ||
742 | * the race. In that case we are done. | ||
743 | */ | ||
744 | if (idx <= 0) | ||
745 | goto out_cancel; | ||
740 | xfs_iext_get_extent(ifp, --idx, &got); | 746 | xfs_iext_get_extent(ifp, --idx, &got); |
741 | } | 747 | } |
742 | 748 | ||
@@ -809,6 +815,7 @@ next_extent: | |||
809 | 815 | ||
810 | out_defer: | 816 | out_defer: |
811 | xfs_defer_cancel(&dfops); | 817 | xfs_defer_cancel(&dfops); |
818 | out_cancel: | ||
812 | xfs_trans_cancel(tp); | 819 | xfs_trans_cancel(tp); |
813 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 820 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
814 | out: | 821 | out: |
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 584cf2d573ba..f663022353c0 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c | |||
@@ -1637,7 +1637,7 @@ xfs_fs_fill_super( | |||
1637 | 1637 | ||
1638 | /* version 5 superblocks support inode version counters. */ | 1638 | /* version 5 superblocks support inode version counters. */ |
1639 | if (XFS_SB_VERSION_NUM(&mp->m_sb) == XFS_SB_VERSION_5) | 1639 | if (XFS_SB_VERSION_NUM(&mp->m_sb) == XFS_SB_VERSION_5) |
1640 | sb->s_flags |= MS_I_VERSION; | 1640 | sb->s_flags |= SB_I_VERSION; |
1641 | 1641 | ||
1642 | if (mp->m_flags & XFS_MOUNT_DAX) { | 1642 | if (mp->m_flags & XFS_MOUNT_DAX) { |
1643 | xfs_warn(mp, | 1643 | xfs_warn(mp, |