filelock: add a new locks_inode_context accessor function
[ Upstream commit 401a8b8fd5acd51582b15238d72a8d0edd580e9f ] 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 <hch@lst.de> Signed-off-by: Jeff Layton <jlayton@kernel.org> Stable-dep-of: 77c67530e1f9 ("nfsd: use locks_inode_context helper") Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
6b12589f61
commit
1f76cb66ff
24
fs/locks.c
24
fs/locks.c
@ -175,7 +175,7 @@ locks_get_lock_context(struct inode *inode, int type)
|
|||||||
struct file_lock_context *ctx;
|
struct file_lock_context *ctx;
|
||||||
|
|
||||||
/* paired with cmpxchg() below */
|
/* paired with cmpxchg() below */
|
||||||
ctx = smp_load_acquire(&inode->i_flctx);
|
ctx = locks_inode_context(inode);
|
||||||
if (likely(ctx) || type == F_UNLCK)
|
if (likely(ctx) || type == F_UNLCK)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -194,7 +194,7 @@ locks_get_lock_context(struct inode *inode, int type)
|
|||||||
*/
|
*/
|
||||||
if (cmpxchg(&inode->i_flctx, NULL, ctx)) {
|
if (cmpxchg(&inode->i_flctx, NULL, ctx)) {
|
||||||
kmem_cache_free(flctx_cache, ctx);
|
kmem_cache_free(flctx_cache, ctx);
|
||||||
ctx = smp_load_acquire(&inode->i_flctx);
|
ctx = locks_inode_context(inode);
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
trace_locks_get_lock_context(inode, type, ctx);
|
trace_locks_get_lock_context(inode, type, ctx);
|
||||||
@ -247,7 +247,7 @@ locks_check_ctx_file_list(struct file *filp, struct list_head *list,
|
|||||||
void
|
void
|
||||||
locks_free_lock_context(struct inode *inode)
|
locks_free_lock_context(struct inode *inode)
|
||||||
{
|
{
|
||||||
struct file_lock_context *ctx = inode->i_flctx;
|
struct file_lock_context *ctx = locks_inode_context(inode);
|
||||||
|
|
||||||
if (unlikely(ctx)) {
|
if (unlikely(ctx)) {
|
||||||
locks_check_ctx_lists(inode);
|
locks_check_ctx_lists(inode);
|
||||||
@ -891,7 +891,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl)
|
|||||||
void *owner;
|
void *owner;
|
||||||
void (*func)(void);
|
void (*func)(void);
|
||||||
|
|
||||||
ctx = smp_load_acquire(&inode->i_flctx);
|
ctx = locks_inode_context(inode);
|
||||||
if (!ctx || list_empty_careful(&ctx->flc_posix)) {
|
if (!ctx || list_empty_careful(&ctx->flc_posix)) {
|
||||||
fl->fl_type = F_UNLCK;
|
fl->fl_type = F_UNLCK;
|
||||||
return;
|
return;
|
||||||
@ -1483,7 +1483,7 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
|
|||||||
new_fl->fl_flags = type;
|
new_fl->fl_flags = type;
|
||||||
|
|
||||||
/* typically we will check that ctx is non-NULL before calling */
|
/* typically we will check that ctx is non-NULL before calling */
|
||||||
ctx = smp_load_acquire(&inode->i_flctx);
|
ctx = locks_inode_context(inode);
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
WARN_ON_ONCE(1);
|
WARN_ON_ONCE(1);
|
||||||
goto free_lock;
|
goto free_lock;
|
||||||
@ -1588,7 +1588,7 @@ void lease_get_mtime(struct inode *inode, struct timespec64 *time)
|
|||||||
struct file_lock_context *ctx;
|
struct file_lock_context *ctx;
|
||||||
struct file_lock *fl;
|
struct file_lock *fl;
|
||||||
|
|
||||||
ctx = smp_load_acquire(&inode->i_flctx);
|
ctx = locks_inode_context(inode);
|
||||||
if (ctx && !list_empty_careful(&ctx->flc_lease)) {
|
if (ctx && !list_empty_careful(&ctx->flc_lease)) {
|
||||||
spin_lock(&ctx->flc_lock);
|
spin_lock(&ctx->flc_lock);
|
||||||
fl = list_first_entry_or_null(&ctx->flc_lease,
|
fl = list_first_entry_or_null(&ctx->flc_lease,
|
||||||
@ -1634,7 +1634,7 @@ int fcntl_getlease(struct file *filp)
|
|||||||
int type = F_UNLCK;
|
int type = F_UNLCK;
|
||||||
LIST_HEAD(dispose);
|
LIST_HEAD(dispose);
|
||||||
|
|
||||||
ctx = smp_load_acquire(&inode->i_flctx);
|
ctx = locks_inode_context(inode);
|
||||||
if (ctx && !list_empty_careful(&ctx->flc_lease)) {
|
if (ctx && !list_empty_careful(&ctx->flc_lease)) {
|
||||||
percpu_down_read(&file_rwsem);
|
percpu_down_read(&file_rwsem);
|
||||||
spin_lock(&ctx->flc_lock);
|
spin_lock(&ctx->flc_lock);
|
||||||
@ -1823,7 +1823,7 @@ static int generic_delete_lease(struct file *filp, void *owner)
|
|||||||
struct file_lock_context *ctx;
|
struct file_lock_context *ctx;
|
||||||
LIST_HEAD(dispose);
|
LIST_HEAD(dispose);
|
||||||
|
|
||||||
ctx = smp_load_acquire(&inode->i_flctx);
|
ctx = locks_inode_context(inode);
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
trace_generic_delete_lease(inode, NULL);
|
trace_generic_delete_lease(inode, NULL);
|
||||||
return error;
|
return error;
|
||||||
@ -2562,7 +2562,7 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)
|
|||||||
* posix_lock_file(). Another process could be setting a lock on this
|
* posix_lock_file(). Another process could be setting a lock on this
|
||||||
* file at the same time, but we wouldn't remove that lock anyway.
|
* file at the same time, but we wouldn't remove that lock anyway.
|
||||||
*/
|
*/
|
||||||
ctx = smp_load_acquire(&inode->i_flctx);
|
ctx = locks_inode_context(inode);
|
||||||
if (!ctx || list_empty(&ctx->flc_posix))
|
if (!ctx || list_empty(&ctx->flc_posix))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -2635,7 +2635,7 @@ void locks_remove_file(struct file *filp)
|
|||||||
{
|
{
|
||||||
struct file_lock_context *ctx;
|
struct file_lock_context *ctx;
|
||||||
|
|
||||||
ctx = smp_load_acquire(&locks_inode(filp)->i_flctx);
|
ctx = locks_inode_context(locks_inode(filp));
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -2682,7 +2682,7 @@ bool vfs_inode_has_locks(struct inode *inode)
|
|||||||
struct file_lock_context *ctx;
|
struct file_lock_context *ctx;
|
||||||
bool ret;
|
bool ret;
|
||||||
|
|
||||||
ctx = smp_load_acquire(&inode->i_flctx);
|
ctx = locks_inode_context(inode);
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -2863,7 +2863,7 @@ void show_fd_locks(struct seq_file *f,
|
|||||||
struct file_lock_context *ctx;
|
struct file_lock_context *ctx;
|
||||||
int id = 0;
|
int id = 0;
|
||||||
|
|
||||||
ctx = smp_load_acquire(&inode->i_flctx);
|
ctx = locks_inode_context(inode);
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1189,6 +1189,13 @@ extern void show_fd_locks(struct seq_file *f,
|
|||||||
struct file *filp, struct files_struct *files);
|
struct file *filp, struct files_struct *files);
|
||||||
extern bool locks_owner_has_blockers(struct file_lock_context *flctx,
|
extern bool locks_owner_has_blockers(struct file_lock_context *flctx,
|
||||||
fl_owner_t owner);
|
fl_owner_t owner);
|
||||||
|
|
||||||
|
static inline struct file_lock_context *
|
||||||
|
locks_inode_context(const struct inode *inode)
|
||||||
|
{
|
||||||
|
return smp_load_acquire(&inode->i_flctx);
|
||||||
|
}
|
||||||
|
|
||||||
#else /* !CONFIG_FILE_LOCKING */
|
#else /* !CONFIG_FILE_LOCKING */
|
||||||
static inline int fcntl_getlk(struct file *file, unsigned int cmd,
|
static inline int fcntl_getlk(struct file *file, unsigned int cmd,
|
||||||
struct flock __user *user)
|
struct flock __user *user)
|
||||||
@ -1334,6 +1341,13 @@ static inline bool locks_owner_has_blockers(struct file_lock_context *flctx,
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline struct file_lock_context *
|
||||||
|
locks_inode_context(const struct inode *inode)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* !CONFIG_FILE_LOCKING */
|
#endif /* !CONFIG_FILE_LOCKING */
|
||||||
|
|
||||||
static inline struct inode *file_inode(const struct file *f)
|
static inline struct inode *file_inode(const struct file *f)
|
||||||
|
Loading…
Reference in New Issue
Block a user