Skip to content

Commit 401a8b8

Browse files
committed
filelock: add a new locks_inode_context accessor function
There are a number of places in the kernel that are accessing the inode->i_flctx field without smp_load_acquire. This is required to ensure that the caller doesn't see a partially-initialized structure. Add a new accessor function for it to make this clear and convert all of the relevant accesses in locks.c to use it. Also, convert locks_free_lock_context to use the helper as well instead of just doing a "bare" assignment. Reviewed-by: Christoph Hellwig <[email protected]> Signed-off-by: Jeff Layton <[email protected]>
1 parent ab1ddef commit 401a8b8

File tree

2 files changed

+26
-12
lines changed

2 files changed

+26
-12
lines changed

fs/locks.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ locks_get_lock_context(struct inode *inode, int type)
175175
struct file_lock_context *ctx;
176176

177177
/* paired with cmpxchg() below */
178-
ctx = smp_load_acquire(&inode->i_flctx);
178+
ctx = locks_inode_context(inode);
179179
if (likely(ctx) || type == F_UNLCK)
180180
goto out;
181181

@@ -194,7 +194,7 @@ locks_get_lock_context(struct inode *inode, int type)
194194
*/
195195
if (cmpxchg(&inode->i_flctx, NULL, ctx)) {
196196
kmem_cache_free(flctx_cache, ctx);
197-
ctx = smp_load_acquire(&inode->i_flctx);
197+
ctx = locks_inode_context(inode);
198198
}
199199
out:
200200
trace_locks_get_lock_context(inode, type, ctx);
@@ -247,7 +247,7 @@ locks_check_ctx_file_list(struct file *filp, struct list_head *list,
247247
void
248248
locks_free_lock_context(struct inode *inode)
249249
{
250-
struct file_lock_context *ctx = inode->i_flctx;
250+
struct file_lock_context *ctx = locks_inode_context(inode);
251251

252252
if (unlikely(ctx)) {
253253
locks_check_ctx_lists(inode);
@@ -891,7 +891,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl)
891891
void *owner;
892892
void (*func)(void);
893893

894-
ctx = smp_load_acquire(&inode->i_flctx);
894+
ctx = locks_inode_context(inode);
895895
if (!ctx || list_empty_careful(&ctx->flc_posix)) {
896896
fl->fl_type = F_UNLCK;
897897
return;
@@ -1483,7 +1483,7 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
14831483
new_fl->fl_flags = type;
14841484

14851485
/* typically we will check that ctx is non-NULL before calling */
1486-
ctx = smp_load_acquire(&inode->i_flctx);
1486+
ctx = locks_inode_context(inode);
14871487
if (!ctx) {
14881488
WARN_ON_ONCE(1);
14891489
goto free_lock;
@@ -1588,7 +1588,7 @@ void lease_get_mtime(struct inode *inode, struct timespec64 *time)
15881588
struct file_lock_context *ctx;
15891589
struct file_lock *fl;
15901590

1591-
ctx = smp_load_acquire(&inode->i_flctx);
1591+
ctx = locks_inode_context(inode);
15921592
if (ctx && !list_empty_careful(&ctx->flc_lease)) {
15931593
spin_lock(&ctx->flc_lock);
15941594
fl = list_first_entry_or_null(&ctx->flc_lease,
@@ -1634,7 +1634,7 @@ int fcntl_getlease(struct file *filp)
16341634
int type = F_UNLCK;
16351635
LIST_HEAD(dispose);
16361636

1637-
ctx = smp_load_acquire(&inode->i_flctx);
1637+
ctx = locks_inode_context(inode);
16381638
if (ctx && !list_empty_careful(&ctx->flc_lease)) {
16391639
percpu_down_read(&file_rwsem);
16401640
spin_lock(&ctx->flc_lock);
@@ -1823,7 +1823,7 @@ static int generic_delete_lease(struct file *filp, void *owner)
18231823
struct file_lock_context *ctx;
18241824
LIST_HEAD(dispose);
18251825

1826-
ctx = smp_load_acquire(&inode->i_flctx);
1826+
ctx = locks_inode_context(inode);
18271827
if (!ctx) {
18281828
trace_generic_delete_lease(inode, NULL);
18291829
return error;
@@ -2563,7 +2563,7 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)
25632563
* posix_lock_file(). Another process could be setting a lock on this
25642564
* file at the same time, but we wouldn't remove that lock anyway.
25652565
*/
2566-
ctx = smp_load_acquire(&inode->i_flctx);
2566+
ctx = locks_inode_context(inode);
25672567
if (!ctx || list_empty(&ctx->flc_posix))
25682568
return;
25692569

@@ -2636,7 +2636,7 @@ void locks_remove_file(struct file *filp)
26362636
{
26372637
struct file_lock_context *ctx;
26382638

2639-
ctx = smp_load_acquire(&locks_inode(filp)->i_flctx);
2639+
ctx = locks_inode_context(locks_inode(filp));
26402640
if (!ctx)
26412641
return;
26422642

@@ -2684,7 +2684,7 @@ bool vfs_inode_has_locks(struct inode *inode)
26842684
struct file_lock_context *ctx;
26852685
bool ret;
26862686

2687-
ctx = smp_load_acquire(&inode->i_flctx);
2687+
ctx = locks_inode_context(inode);
26882688
if (!ctx)
26892689
return false;
26902690

@@ -2865,7 +2865,7 @@ void show_fd_locks(struct seq_file *f,
28652865
struct file_lock_context *ctx;
28662866
int id = 0;
28672867

2868-
ctx = smp_load_acquire(&inode->i_flctx);
2868+
ctx = locks_inode_context(inode);
28692869
if (!ctx)
28702870
return;
28712871

include/linux/fs.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,6 +1187,13 @@ extern void show_fd_locks(struct seq_file *f,
11871187
struct file *filp, struct files_struct *files);
11881188
extern bool locks_owner_has_blockers(struct file_lock_context *flctx,
11891189
fl_owner_t owner);
1190+
1191+
static inline struct file_lock_context *
1192+
locks_inode_context(const struct inode *inode)
1193+
{
1194+
return smp_load_acquire(&inode->i_flctx);
1195+
}
1196+
11901197
#else /* !CONFIG_FILE_LOCKING */
11911198
static inline int fcntl_getlk(struct file *file, unsigned int cmd,
11921199
struct flock __user *user)
@@ -1332,6 +1339,13 @@ static inline bool locks_owner_has_blockers(struct file_lock_context *flctx,
13321339
{
13331340
return false;
13341341
}
1342+
1343+
static inline struct file_lock_context *
1344+
locks_inode_context(const struct inode *inode)
1345+
{
1346+
return NULL;
1347+
}
1348+
13351349
#endif /* !CONFIG_FILE_LOCKING */
13361350

13371351
static inline struct inode *file_inode(const struct file *f)

0 commit comments

Comments
 (0)