1 From 11111ab9e11b05b76ef1d82199a846d59c06b2f6 Mon Sep 17 00:00:00 2001
2 From: Sasha Levin <sashal@kernel.org>
3 Date: Wed, 16 Nov 2022 09:02:30 -0500
4 Subject: filelock: add a new locks_inode_context accessor function
6 From: Jeff Layton <jlayton@kernel.org>
8 [ Upstream commit 401a8b8fd5acd51582b15238d72a8d0edd580e9f ]
10 There are a number of places in the kernel that are accessing the
11 inode->i_flctx field without smp_load_acquire. This is required to
12 ensure that the caller doesn't see a partially-initialized structure.
14 Add a new accessor function for it to make this clear and convert all of
15 the relevant accesses in locks.c to use it. Also, convert
16 locks_free_lock_context to use the helper as well instead of just doing
19 Reviewed-by: Christoph Hellwig <hch@lst.de>
20 Signed-off-by: Jeff Layton <jlayton@kernel.org>
21 Stable-dep-of: 77c67530e1f9 ("nfsd: use locks_inode_context helper")
22 Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
24 fs/locks.c | 24 ++++++++++++------------
25 include/linux/fs.h | 14 ++++++++++++++
26 2 files changed, 26 insertions(+), 12 deletions(-)
28 diff --git a/fs/locks.c b/fs/locks.c
29 index 317c2ec17b943..77781b71bcaab 100644
32 @@ -251,7 +251,7 @@ locks_get_lock_context(struct inode *inode, int type)
33 struct file_lock_context *ctx;
35 /* paired with cmpxchg() below */
36 - ctx = smp_load_acquire(&inode->i_flctx);
37 + ctx = locks_inode_context(inode);
38 if (likely(ctx) || type == F_UNLCK)
41 @@ -270,7 +270,7 @@ locks_get_lock_context(struct inode *inode, int type)
43 if (cmpxchg(&inode->i_flctx, NULL, ctx)) {
44 kmem_cache_free(flctx_cache, ctx);
45 - ctx = smp_load_acquire(&inode->i_flctx);
46 + ctx = locks_inode_context(inode);
49 trace_locks_get_lock_context(inode, type, ctx);
50 @@ -323,7 +323,7 @@ locks_check_ctx_file_list(struct file *filp, struct list_head *list,
52 locks_free_lock_context(struct inode *inode)
54 - struct file_lock_context *ctx = inode->i_flctx;
55 + struct file_lock_context *ctx = locks_inode_context(inode);
58 locks_check_ctx_lists(inode);
59 @@ -985,7 +985,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl)
63 - ctx = smp_load_acquire(&inode->i_flctx);
64 + ctx = locks_inode_context(inode);
65 if (!ctx || list_empty_careful(&ctx->flc_posix)) {
66 fl->fl_type = F_UNLCK;
68 @@ -1577,7 +1577,7 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
69 new_fl->fl_flags = type;
71 /* typically we will check that ctx is non-NULL before calling */
72 - ctx = smp_load_acquire(&inode->i_flctx);
73 + ctx = locks_inode_context(inode);
77 @@ -1682,7 +1682,7 @@ void lease_get_mtime(struct inode *inode, struct timespec64 *time)
78 struct file_lock_context *ctx;
81 - ctx = smp_load_acquire(&inode->i_flctx);
82 + ctx = locks_inode_context(inode);
83 if (ctx && !list_empty_careful(&ctx->flc_lease)) {
84 spin_lock(&ctx->flc_lock);
85 fl = list_first_entry_or_null(&ctx->flc_lease,
86 @@ -1728,7 +1728,7 @@ int fcntl_getlease(struct file *filp)
90 - ctx = smp_load_acquire(&inode->i_flctx);
91 + ctx = locks_inode_context(inode);
92 if (ctx && !list_empty_careful(&ctx->flc_lease)) {
93 percpu_down_read(&file_rwsem);
94 spin_lock(&ctx->flc_lock);
95 @@ -1917,7 +1917,7 @@ static int generic_delete_lease(struct file *filp, void *owner)
96 struct file_lock_context *ctx;
99 - ctx = smp_load_acquire(&inode->i_flctx);
100 + ctx = locks_inode_context(inode);
102 trace_generic_delete_lease(inode, NULL);
104 @@ -2651,7 +2651,7 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)
105 * posix_lock_file(). Another process could be setting a lock on this
106 * file at the same time, but we wouldn't remove that lock anyway.
108 - ctx = smp_load_acquire(&inode->i_flctx);
109 + ctx = locks_inode_context(inode);
110 if (!ctx || list_empty(&ctx->flc_posix))
113 @@ -2724,7 +2724,7 @@ void locks_remove_file(struct file *filp)
115 struct file_lock_context *ctx;
117 - ctx = smp_load_acquire(&locks_inode(filp)->i_flctx);
118 + ctx = locks_inode_context(locks_inode(filp));
122 @@ -2771,7 +2771,7 @@ bool vfs_inode_has_locks(struct inode *inode)
123 struct file_lock_context *ctx;
126 - ctx = smp_load_acquire(&inode->i_flctx);
127 + ctx = locks_inode_context(inode);
131 @@ -2962,7 +2962,7 @@ void show_fd_locks(struct seq_file *f,
132 struct file_lock_context *ctx;
135 - ctx = smp_load_acquire(&inode->i_flctx);
136 + ctx = locks_inode_context(inode);
140 diff --git a/include/linux/fs.h b/include/linux/fs.h
141 index ef5a04d626953..61e86502fe65e 100644
142 --- a/include/linux/fs.h
143 +++ b/include/linux/fs.h
144 @@ -1217,6 +1217,13 @@ extern void show_fd_locks(struct seq_file *f,
145 struct file *filp, struct files_struct *files);
146 extern bool locks_owner_has_blockers(struct file_lock_context *flctx,
149 +static inline struct file_lock_context *
150 +locks_inode_context(const struct inode *inode)
152 + return smp_load_acquire(&inode->i_flctx);
155 #else /* !CONFIG_FILE_LOCKING */
156 static inline int fcntl_getlk(struct file *file, unsigned int cmd,
157 struct flock __user *user)
158 @@ -1362,6 +1369,13 @@ static inline bool locks_owner_has_blockers(struct file_lock_context *flctx,
163 +static inline struct file_lock_context *
164 +locks_inode_context(const struct inode *inode)
169 #endif /* !CONFIG_FILE_LOCKING */
171 static inline struct inode *file_inode(const struct file *f)