diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/extent-tree.c | 3 | ||||
-rw-r--r-- | fs/btrfs/extent_io.c | 8 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 13 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 5 | ||||
-rw-r--r-- | fs/btrfs/relocation.c | 9 | ||||
-rw-r--r-- | fs/nfsd/netns.h | 5 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 38 | ||||
-rw-r--r-- | fs/overlayfs/copy_up.c | 2 | ||||
-rw-r--r-- | fs/overlayfs/inode.c | 3 | ||||
-rw-r--r-- | fs/overlayfs/super.c | 15 |
10 files changed, 70 insertions, 31 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 210c94ac8818..4607af38c72e 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -2647,7 +2647,10 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, | |||
2647 | 2647 | ||
2648 | btrfs_free_delayed_extent_op(extent_op); | 2648 | btrfs_free_delayed_extent_op(extent_op); |
2649 | if (ret) { | 2649 | if (ret) { |
2650 | spin_lock(&delayed_refs->lock); | ||
2650 | locked_ref->processing = 0; | 2651 | locked_ref->processing = 0; |
2652 | delayed_refs->num_heads_ready++; | ||
2653 | spin_unlock(&delayed_refs->lock); | ||
2651 | btrfs_delayed_ref_unlock(locked_ref); | 2654 | btrfs_delayed_ref_unlock(locked_ref); |
2652 | btrfs_put_delayed_ref(ref); | 2655 | btrfs_put_delayed_ref(ref); |
2653 | btrfs_debug(fs_info, "run_one_delayed_ref returned %d", | 2656 | btrfs_debug(fs_info, "run_one_delayed_ref returned %d", |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 66a755150056..8ed05d95584a 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -5569,7 +5569,7 @@ void le_bitmap_set(u8 *map, unsigned int start, int len) | |||
5569 | *p |= mask_to_set; | 5569 | *p |= mask_to_set; |
5570 | len -= bits_to_set; | 5570 | len -= bits_to_set; |
5571 | bits_to_set = BITS_PER_BYTE; | 5571 | bits_to_set = BITS_PER_BYTE; |
5572 | mask_to_set = ~(u8)0; | 5572 | mask_to_set = ~0; |
5573 | p++; | 5573 | p++; |
5574 | } | 5574 | } |
5575 | if (len) { | 5575 | if (len) { |
@@ -5589,7 +5589,7 @@ void le_bitmap_clear(u8 *map, unsigned int start, int len) | |||
5589 | *p &= ~mask_to_clear; | 5589 | *p &= ~mask_to_clear; |
5590 | len -= bits_to_clear; | 5590 | len -= bits_to_clear; |
5591 | bits_to_clear = BITS_PER_BYTE; | 5591 | bits_to_clear = BITS_PER_BYTE; |
5592 | mask_to_clear = ~(u8)0; | 5592 | mask_to_clear = ~0; |
5593 | p++; | 5593 | p++; |
5594 | } | 5594 | } |
5595 | if (len) { | 5595 | if (len) { |
@@ -5679,7 +5679,7 @@ void extent_buffer_bitmap_set(struct extent_buffer *eb, unsigned long start, | |||
5679 | kaddr[offset] |= mask_to_set; | 5679 | kaddr[offset] |= mask_to_set; |
5680 | len -= bits_to_set; | 5680 | len -= bits_to_set; |
5681 | bits_to_set = BITS_PER_BYTE; | 5681 | bits_to_set = BITS_PER_BYTE; |
5682 | mask_to_set = ~(u8)0; | 5682 | mask_to_set = ~0; |
5683 | if (++offset >= PAGE_SIZE && len > 0) { | 5683 | if (++offset >= PAGE_SIZE && len > 0) { |
5684 | offset = 0; | 5684 | offset = 0; |
5685 | page = eb->pages[++i]; | 5685 | page = eb->pages[++i]; |
@@ -5721,7 +5721,7 @@ void extent_buffer_bitmap_clear(struct extent_buffer *eb, unsigned long start, | |||
5721 | kaddr[offset] &= ~mask_to_clear; | 5721 | kaddr[offset] &= ~mask_to_clear; |
5722 | len -= bits_to_clear; | 5722 | len -= bits_to_clear; |
5723 | bits_to_clear = BITS_PER_BYTE; | 5723 | bits_to_clear = BITS_PER_BYTE; |
5724 | mask_to_clear = ~(u8)0; | 5724 | mask_to_clear = ~0; |
5725 | if (++offset >= PAGE_SIZE && len > 0) { | 5725 | if (++offset >= PAGE_SIZE && len > 0) { |
5726 | offset = 0; | 5726 | offset = 0; |
5727 | page = eb->pages[++i]; | 5727 | page = eb->pages[++i]; |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 2b790bda7998..8e3a5a266917 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -4605,8 +4605,8 @@ delete: | |||
4605 | BUG_ON(ret); | 4605 | BUG_ON(ret); |
4606 | if (btrfs_should_throttle_delayed_refs(trans, root)) | 4606 | if (btrfs_should_throttle_delayed_refs(trans, root)) |
4607 | btrfs_async_run_delayed_refs(root, | 4607 | btrfs_async_run_delayed_refs(root, |
4608 | trans->transid, | 4608 | trans->delayed_ref_updates * 2, |
4609 | trans->delayed_ref_updates * 2, 0); | 4609 | trans->transid, 0); |
4610 | if (be_nice) { | 4610 | if (be_nice) { |
4611 | if (truncate_space_check(trans, root, | 4611 | if (truncate_space_check(trans, root, |
4612 | extent_num_bytes)) { | 4612 | extent_num_bytes)) { |
@@ -8931,9 +8931,14 @@ again: | |||
8931 | * So even we call qgroup_free_data(), it won't decrease reserved | 8931 | * So even we call qgroup_free_data(), it won't decrease reserved |
8932 | * space. | 8932 | * space. |
8933 | * 2) Not written to disk | 8933 | * 2) Not written to disk |
8934 | * This means the reserved space should be freed here. | 8934 | * This means the reserved space should be freed here. However, |
8935 | * if a truncate invalidates the page (by clearing PageDirty) | ||
8936 | * and the page is accounted for while allocating extent | ||
8937 | * in btrfs_check_data_free_space() we let delayed_ref to | ||
8938 | * free the entire extent. | ||
8935 | */ | 8939 | */ |
8936 | btrfs_qgroup_free_data(inode, page_start, PAGE_SIZE); | 8940 | if (PageDirty(page)) |
8941 | btrfs_qgroup_free_data(inode, page_start, PAGE_SIZE); | ||
8937 | if (!inode_evicting) { | 8942 | if (!inode_evicting) { |
8938 | clear_extent_bit(tree, page_start, page_end, | 8943 | clear_extent_bit(tree, page_start, page_end, |
8939 | EXTENT_LOCKED | EXTENT_DIRTY | | 8944 | EXTENT_LOCKED | EXTENT_DIRTY | |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 18e1aa0f85f5..7acbd2cf6192 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -3814,6 +3814,11 @@ process_slot: | |||
3814 | } | 3814 | } |
3815 | btrfs_release_path(path); | 3815 | btrfs_release_path(path); |
3816 | key.offset = next_key_min_offset; | 3816 | key.offset = next_key_min_offset; |
3817 | |||
3818 | if (fatal_signal_pending(current)) { | ||
3819 | ret = -EINTR; | ||
3820 | goto out; | ||
3821 | } | ||
3817 | } | 3822 | } |
3818 | ret = 0; | 3823 | ret = 0; |
3819 | 3824 | ||
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 0ec8ffa37ab0..c4af0cdb783d 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
@@ -2728,7 +2728,14 @@ static int do_relocation(struct btrfs_trans_handle *trans, | |||
2728 | 2728 | ||
2729 | bytenr = btrfs_node_blockptr(upper->eb, slot); | 2729 | bytenr = btrfs_node_blockptr(upper->eb, slot); |
2730 | if (lowest) { | 2730 | if (lowest) { |
2731 | BUG_ON(bytenr != node->bytenr); | 2731 | if (bytenr != node->bytenr) { |
2732 | btrfs_err(root->fs_info, | ||
2733 | "lowest leaf/node mismatch: bytenr %llu node->bytenr %llu slot %d upper %llu", | ||
2734 | bytenr, node->bytenr, slot, | ||
2735 | upper->eb->start); | ||
2736 | err = -EIO; | ||
2737 | goto next; | ||
2738 | } | ||
2732 | } else { | 2739 | } else { |
2733 | if (node->eb->start == bytenr) | 2740 | if (node->eb->start == bytenr) |
2734 | goto next; | 2741 | goto next; |
diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h index b10d557f9c9e..ee36efd5aece 100644 --- a/fs/nfsd/netns.h +++ b/fs/nfsd/netns.h | |||
@@ -84,6 +84,8 @@ struct nfsd_net { | |||
84 | struct list_head client_lru; | 84 | struct list_head client_lru; |
85 | struct list_head close_lru; | 85 | struct list_head close_lru; |
86 | struct list_head del_recall_lru; | 86 | struct list_head del_recall_lru; |
87 | |||
88 | /* protected by blocked_locks_lock */ | ||
87 | struct list_head blocked_locks_lru; | 89 | struct list_head blocked_locks_lru; |
88 | 90 | ||
89 | struct delayed_work laundromat_work; | 91 | struct delayed_work laundromat_work; |
@@ -91,6 +93,9 @@ struct nfsd_net { | |||
91 | /* client_lock protects the client lru list and session hash table */ | 93 | /* client_lock protects the client lru list and session hash table */ |
92 | spinlock_t client_lock; | 94 | spinlock_t client_lock; |
93 | 95 | ||
96 | /* protects blocked_locks_lru */ | ||
97 | spinlock_t blocked_locks_lock; | ||
98 | |||
94 | struct file *rec_file; | 99 | struct file *rec_file; |
95 | bool in_grace; | 100 | bool in_grace; |
96 | const struct nfsd4_client_tracking_ops *client_tracking_ops; | 101 | const struct nfsd4_client_tracking_ops *client_tracking_ops; |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 9752beb78659..4b4beaaa4eaa 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -217,7 +217,7 @@ find_blocked_lock(struct nfs4_lockowner *lo, struct knfsd_fh *fh, | |||
217 | { | 217 | { |
218 | struct nfsd4_blocked_lock *cur, *found = NULL; | 218 | struct nfsd4_blocked_lock *cur, *found = NULL; |
219 | 219 | ||
220 | spin_lock(&nn->client_lock); | 220 | spin_lock(&nn->blocked_locks_lock); |
221 | list_for_each_entry(cur, &lo->lo_blocked, nbl_list) { | 221 | list_for_each_entry(cur, &lo->lo_blocked, nbl_list) { |
222 | if (fh_match(fh, &cur->nbl_fh)) { | 222 | if (fh_match(fh, &cur->nbl_fh)) { |
223 | list_del_init(&cur->nbl_list); | 223 | list_del_init(&cur->nbl_list); |
@@ -226,7 +226,7 @@ find_blocked_lock(struct nfs4_lockowner *lo, struct knfsd_fh *fh, | |||
226 | break; | 226 | break; |
227 | } | 227 | } |
228 | } | 228 | } |
229 | spin_unlock(&nn->client_lock); | 229 | spin_unlock(&nn->blocked_locks_lock); |
230 | if (found) | 230 | if (found) |
231 | posix_unblock_lock(&found->nbl_lock); | 231 | posix_unblock_lock(&found->nbl_lock); |
232 | return found; | 232 | return found; |
@@ -1227,9 +1227,7 @@ static void put_ol_stateid_locked(struct nfs4_ol_stateid *stp, | |||
1227 | 1227 | ||
1228 | static bool unhash_lock_stateid(struct nfs4_ol_stateid *stp) | 1228 | static bool unhash_lock_stateid(struct nfs4_ol_stateid *stp) |
1229 | { | 1229 | { |
1230 | struct nfs4_openowner *oo = openowner(stp->st_openstp->st_stateowner); | 1230 | lockdep_assert_held(&stp->st_stid.sc_client->cl_lock); |
1231 | |||
1232 | lockdep_assert_held(&oo->oo_owner.so_client->cl_lock); | ||
1233 | 1231 | ||
1234 | list_del_init(&stp->st_locks); | 1232 | list_del_init(&stp->st_locks); |
1235 | nfs4_unhash_stid(&stp->st_stid); | 1233 | nfs4_unhash_stid(&stp->st_stid); |
@@ -1238,12 +1236,12 @@ static bool unhash_lock_stateid(struct nfs4_ol_stateid *stp) | |||
1238 | 1236 | ||
1239 | static void release_lock_stateid(struct nfs4_ol_stateid *stp) | 1237 | static void release_lock_stateid(struct nfs4_ol_stateid *stp) |
1240 | { | 1238 | { |
1241 | struct nfs4_openowner *oo = openowner(stp->st_openstp->st_stateowner); | 1239 | struct nfs4_client *clp = stp->st_stid.sc_client; |
1242 | bool unhashed; | 1240 | bool unhashed; |
1243 | 1241 | ||
1244 | spin_lock(&oo->oo_owner.so_client->cl_lock); | 1242 | spin_lock(&clp->cl_lock); |
1245 | unhashed = unhash_lock_stateid(stp); | 1243 | unhashed = unhash_lock_stateid(stp); |
1246 | spin_unlock(&oo->oo_owner.so_client->cl_lock); | 1244 | spin_unlock(&clp->cl_lock); |
1247 | if (unhashed) | 1245 | if (unhashed) |
1248 | nfs4_put_stid(&stp->st_stid); | 1246 | nfs4_put_stid(&stp->st_stid); |
1249 | } | 1247 | } |
@@ -4665,7 +4663,7 @@ nfs4_laundromat(struct nfsd_net *nn) | |||
4665 | * indefinitely once the lock does become free. | 4663 | * indefinitely once the lock does become free. |
4666 | */ | 4664 | */ |
4667 | BUG_ON(!list_empty(&reaplist)); | 4665 | BUG_ON(!list_empty(&reaplist)); |
4668 | spin_lock(&nn->client_lock); | 4666 | spin_lock(&nn->blocked_locks_lock); |
4669 | while (!list_empty(&nn->blocked_locks_lru)) { | 4667 | while (!list_empty(&nn->blocked_locks_lru)) { |
4670 | nbl = list_first_entry(&nn->blocked_locks_lru, | 4668 | nbl = list_first_entry(&nn->blocked_locks_lru, |
4671 | struct nfsd4_blocked_lock, nbl_lru); | 4669 | struct nfsd4_blocked_lock, nbl_lru); |
@@ -4678,7 +4676,7 @@ nfs4_laundromat(struct nfsd_net *nn) | |||
4678 | list_move(&nbl->nbl_lru, &reaplist); | 4676 | list_move(&nbl->nbl_lru, &reaplist); |
4679 | list_del_init(&nbl->nbl_list); | 4677 | list_del_init(&nbl->nbl_list); |
4680 | } | 4678 | } |
4681 | spin_unlock(&nn->client_lock); | 4679 | spin_unlock(&nn->blocked_locks_lock); |
4682 | 4680 | ||
4683 | while (!list_empty(&reaplist)) { | 4681 | while (!list_empty(&reaplist)) { |
4684 | nbl = list_first_entry(&nn->blocked_locks_lru, | 4682 | nbl = list_first_entry(&nn->blocked_locks_lru, |
@@ -5439,13 +5437,13 @@ nfsd4_lm_notify(struct file_lock *fl) | |||
5439 | bool queue = false; | 5437 | bool queue = false; |
5440 | 5438 | ||
5441 | /* An empty list means that something else is going to be using it */ | 5439 | /* An empty list means that something else is going to be using it */ |
5442 | spin_lock(&nn->client_lock); | 5440 | spin_lock(&nn->blocked_locks_lock); |
5443 | if (!list_empty(&nbl->nbl_list)) { | 5441 | if (!list_empty(&nbl->nbl_list)) { |
5444 | list_del_init(&nbl->nbl_list); | 5442 | list_del_init(&nbl->nbl_list); |
5445 | list_del_init(&nbl->nbl_lru); | 5443 | list_del_init(&nbl->nbl_lru); |
5446 | queue = true; | 5444 | queue = true; |
5447 | } | 5445 | } |
5448 | spin_unlock(&nn->client_lock); | 5446 | spin_unlock(&nn->blocked_locks_lock); |
5449 | 5447 | ||
5450 | if (queue) | 5448 | if (queue) |
5451 | nfsd4_run_cb(&nbl->nbl_cb); | 5449 | nfsd4_run_cb(&nbl->nbl_cb); |
@@ -5868,10 +5866,10 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
5868 | 5866 | ||
5869 | if (fl_flags & FL_SLEEP) { | 5867 | if (fl_flags & FL_SLEEP) { |
5870 | nbl->nbl_time = jiffies; | 5868 | nbl->nbl_time = jiffies; |
5871 | spin_lock(&nn->client_lock); | 5869 | spin_lock(&nn->blocked_locks_lock); |
5872 | list_add_tail(&nbl->nbl_list, &lock_sop->lo_blocked); | 5870 | list_add_tail(&nbl->nbl_list, &lock_sop->lo_blocked); |
5873 | list_add_tail(&nbl->nbl_lru, &nn->blocked_locks_lru); | 5871 | list_add_tail(&nbl->nbl_lru, &nn->blocked_locks_lru); |
5874 | spin_unlock(&nn->client_lock); | 5872 | spin_unlock(&nn->blocked_locks_lock); |
5875 | } | 5873 | } |
5876 | 5874 | ||
5877 | err = vfs_lock_file(filp, F_SETLK, file_lock, conflock); | 5875 | err = vfs_lock_file(filp, F_SETLK, file_lock, conflock); |
@@ -5900,10 +5898,10 @@ out: | |||
5900 | if (nbl) { | 5898 | if (nbl) { |
5901 | /* dequeue it if we queued it before */ | 5899 | /* dequeue it if we queued it before */ |
5902 | if (fl_flags & FL_SLEEP) { | 5900 | if (fl_flags & FL_SLEEP) { |
5903 | spin_lock(&nn->client_lock); | 5901 | spin_lock(&nn->blocked_locks_lock); |
5904 | list_del_init(&nbl->nbl_list); | 5902 | list_del_init(&nbl->nbl_list); |
5905 | list_del_init(&nbl->nbl_lru); | 5903 | list_del_init(&nbl->nbl_lru); |
5906 | spin_unlock(&nn->client_lock); | 5904 | spin_unlock(&nn->blocked_locks_lock); |
5907 | } | 5905 | } |
5908 | free_blocked_lock(nbl); | 5906 | free_blocked_lock(nbl); |
5909 | } | 5907 | } |
@@ -6943,9 +6941,11 @@ static int nfs4_state_create_net(struct net *net) | |||
6943 | INIT_LIST_HEAD(&nn->client_lru); | 6941 | INIT_LIST_HEAD(&nn->client_lru); |
6944 | INIT_LIST_HEAD(&nn->close_lru); | 6942 | INIT_LIST_HEAD(&nn->close_lru); |
6945 | INIT_LIST_HEAD(&nn->del_recall_lru); | 6943 | INIT_LIST_HEAD(&nn->del_recall_lru); |
6946 | INIT_LIST_HEAD(&nn->blocked_locks_lru); | ||
6947 | spin_lock_init(&nn->client_lock); | 6944 | spin_lock_init(&nn->client_lock); |
6948 | 6945 | ||
6946 | spin_lock_init(&nn->blocked_locks_lock); | ||
6947 | INIT_LIST_HEAD(&nn->blocked_locks_lru); | ||
6948 | |||
6949 | INIT_DELAYED_WORK(&nn->laundromat_work, laundromat_main); | 6949 | INIT_DELAYED_WORK(&nn->laundromat_work, laundromat_main); |
6950 | get_net(net); | 6950 | get_net(net); |
6951 | 6951 | ||
@@ -7063,14 +7063,14 @@ nfs4_state_shutdown_net(struct net *net) | |||
7063 | } | 7063 | } |
7064 | 7064 | ||
7065 | BUG_ON(!list_empty(&reaplist)); | 7065 | BUG_ON(!list_empty(&reaplist)); |
7066 | spin_lock(&nn->client_lock); | 7066 | spin_lock(&nn->blocked_locks_lock); |
7067 | while (!list_empty(&nn->blocked_locks_lru)) { | 7067 | while (!list_empty(&nn->blocked_locks_lru)) { |
7068 | nbl = list_first_entry(&nn->blocked_locks_lru, | 7068 | nbl = list_first_entry(&nn->blocked_locks_lru, |
7069 | struct nfsd4_blocked_lock, nbl_lru); | 7069 | struct nfsd4_blocked_lock, nbl_lru); |
7070 | list_move(&nbl->nbl_lru, &reaplist); | 7070 | list_move(&nbl->nbl_lru, &reaplist); |
7071 | list_del_init(&nbl->nbl_list); | 7071 | list_del_init(&nbl->nbl_list); |
7072 | } | 7072 | } |
7073 | spin_unlock(&nn->client_lock); | 7073 | spin_unlock(&nn->blocked_locks_lock); |
7074 | 7074 | ||
7075 | while (!list_empty(&reaplist)) { | 7075 | while (!list_empty(&reaplist)) { |
7076 | nbl = list_first_entry(&nn->blocked_locks_lru, | 7076 | nbl = list_first_entry(&nn->blocked_locks_lru, |
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index aeb60f791418..36795eed40b0 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c | |||
@@ -178,6 +178,8 @@ static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len) | |||
178 | len -= bytes; | 178 | len -= bytes; |
179 | } | 179 | } |
180 | 180 | ||
181 | if (!error) | ||
182 | error = vfs_fsync(new_file, 0); | ||
181 | fput(new_file); | 183 | fput(new_file); |
182 | out_fput: | 184 | out_fput: |
183 | fput(old_file); | 185 | fput(old_file); |
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index c58f01babf30..7fb53d055537 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c | |||
@@ -270,9 +270,6 @@ struct posix_acl *ovl_get_acl(struct inode *inode, int type) | |||
270 | if (!IS_ENABLED(CONFIG_FS_POSIX_ACL) || !IS_POSIXACL(realinode)) | 270 | if (!IS_ENABLED(CONFIG_FS_POSIX_ACL) || !IS_POSIXACL(realinode)) |
271 | return NULL; | 271 | return NULL; |
272 | 272 | ||
273 | if (!realinode->i_op->get_acl) | ||
274 | return NULL; | ||
275 | |||
276 | old_cred = ovl_override_creds(inode->i_sb); | 273 | old_cred = ovl_override_creds(inode->i_sb); |
277 | acl = get_acl(realinode, type); | 274 | acl = get_acl(realinode, type); |
278 | revert_creds(old_cred); | 275 | revert_creds(old_cred); |
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index bcf3965be819..edd46a0e951d 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c | |||
@@ -1037,6 +1037,21 @@ ovl_posix_acl_xattr_set(const struct xattr_handler *handler, | |||
1037 | 1037 | ||
1038 | posix_acl_release(acl); | 1038 | posix_acl_release(acl); |
1039 | 1039 | ||
1040 | /* | ||
1041 | * Check if sgid bit needs to be cleared (actual setacl operation will | ||
1042 | * be done with mounter's capabilities and so that won't do it for us). | ||
1043 | */ | ||
1044 | if (unlikely(inode->i_mode & S_ISGID) && | ||
1045 | handler->flags == ACL_TYPE_ACCESS && | ||
1046 | !in_group_p(inode->i_gid) && | ||
1047 | !capable_wrt_inode_uidgid(inode, CAP_FSETID)) { | ||
1048 | struct iattr iattr = { .ia_valid = ATTR_KILL_SGID }; | ||
1049 | |||
1050 | err = ovl_setattr(dentry, &iattr); | ||
1051 | if (err) | ||
1052 | return err; | ||
1053 | } | ||
1054 | |||
1040 | err = ovl_xattr_set(dentry, handler->name, value, size, flags); | 1055 | err = ovl_xattr_set(dentry, handler->name, value, size, flags); |
1041 | if (!err) | 1056 | if (!err) |
1042 | ovl_copyattr(ovl_inode_real(inode, NULL), inode); | 1057 | ovl_copyattr(ovl_inode_real(inode, NULL), inode); |