mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 21:33:00 +00:00
File locking changes for v6.2.
-----BEGIN PGP SIGNATURE----- iQJHBAABCAAxFiEES8DXskRxsqGE6vXTAA5oQRlWghUFAmOPOjwTHGpsYXl0b25A a2VybmVsLm9yZwAKCRAADmhBGVaCFZ/jEADDZ1RlXCwuozDzAXFzzsR+kmKJJfXG ff3ejXHhyJdYH8kh1IldTCR4RGblTH7dM/gO/ApJlSLbEglQm9AIjZ2lpVstqtzQ lnZir+bA6uzOyYMRVXJ+0oDZuv3Gca3W8IhFHCqD7K9oQQbn+c/ZmEWrvNJJXN1j Ogi1SXHUNfrFgSbgBKjc2VqewuiTc2I8tZAQyezYoGXKn6LtAgMJhQIS4eWjqjju 38aageni9doKPnAmMOq+vBcw2bWV5mYijz/pObfsaDlAgFdr9rKjNP5+F4fBply1 SDW2T1ge8jWYegq39EcDKxd/raSOET/p9vQu6rHniXKfvMQ6Ywbr7qji1a7yTZ+i MkuOToNZy/+TTEvFQm48Fa25tcKjjl/uuk5Ugojf/hSWOsNkW1Cy4S33eUzDZiSO wox5EFVhFpf8Q8L3dUQY0sZazCyoEftw+bq2cKGHJYfUhBD7u6yLG7EKqYiqpepX SSPxuh3GC65xl33hYJL2V+5cgXAV23kSGCdNqDUvYZgJfjhDjQnyoSTcuBjh67kv chmSoeUaIkS4yFqsH9kRINMSef2M5LXYbfxTnftokX0cvV6RqQndZl43X5LEBgQL GRIxyxPkkKaqFjkqyFzBD0dkVGyjyUmkioy/1xON3pLWz3Sk77U38pEQ7NeUl2Lc bK5uysBuvDnCpg== =XMv7 -----END PGP SIGNATURE----- Merge tag 'locks-v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/jlayton/linux Pull file locking updates from Jeff Layton: "The main change here is to add the new locks_inode_context helper, and convert all of the places that dereference inode->i_flctx directly to use that instead. There is a new helper to indicate whether any locks are held on an inode. This is mostly for Ceph but may be usable elsewhere too. Andi Kleen requested that we print the PID when the LOCK_MAND warning fires, to help track down applications trying to use it. Finally, we added some new warnings to some of the file locking functions that fire when the ->fl_file and filp arguments differ. This helped us find some long-standing bugs in lockd. Patches for those are in Chuck Lever's tree and should be in his v6.2 PR. After that patch, people using NFSv2/v3 locking may see some warnings fire until those go in. Happy Holidays!" * tag 'locks-v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/jlayton/linux: Add process name and pid to locks warning nfsd: use locks_inode_context helper nfs: use locks_inode_context helper lockd: use locks_inode_context helper ksmbd: use locks_inode_context helper cifs: use locks_inode_context helper ceph: use locks_inode_context helper filelock: add a new locks_inode_context accessor function filelock: new helper: vfs_inode_has_locks filelock: WARN_ON_ONCE when ->fl_file and filp don't match
This commit is contained in:
commit
73fa58dca8
@ -364,7 +364,7 @@ void ceph_count_locks(struct inode *inode, int *fcntl_count, int *flock_count)
|
||||
*fcntl_count = 0;
|
||||
*flock_count = 0;
|
||||
|
||||
ctx = inode->i_flctx;
|
||||
ctx = locks_inode_context(inode);
|
||||
if (ctx) {
|
||||
spin_lock(&ctx->flc_lock);
|
||||
list_for_each_entry(lock, &ctx->flc_posix, fl_list)
|
||||
@ -418,7 +418,7 @@ int ceph_encode_locks_to_buffer(struct inode *inode,
|
||||
int num_fcntl_locks, int num_flock_locks)
|
||||
{
|
||||
struct file_lock *lock;
|
||||
struct file_lock_context *ctx = inode->i_flctx;
|
||||
struct file_lock_context *ctx = locks_inode_context(inode);
|
||||
int err = 0;
|
||||
int seen_fcntl = 0;
|
||||
int seen_flock = 0;
|
||||
|
@ -1413,7 +1413,7 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile)
|
||||
struct inode *inode = d_inode(cfile->dentry);
|
||||
struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
|
||||
struct file_lock *flock;
|
||||
struct file_lock_context *flctx = inode->i_flctx;
|
||||
struct file_lock_context *flctx = locks_inode_context(inode);
|
||||
unsigned int count = 0, i;
|
||||
int rc = 0, xid, type;
|
||||
struct list_head locks_to_send, *el;
|
||||
|
@ -321,7 +321,7 @@ static int check_lock_range(struct file *filp, loff_t start, loff_t end,
|
||||
unsigned char type)
|
||||
{
|
||||
struct file_lock *flock;
|
||||
struct file_lock_context *ctx = file_inode(filp)->i_flctx;
|
||||
struct file_lock_context *ctx = locks_inode_context(file_inode(filp));
|
||||
int error = 0;
|
||||
|
||||
if (!ctx || list_empty_careful(&ctx->flc_posix))
|
||||
|
@ -207,7 +207,7 @@ nlm_traverse_locks(struct nlm_host *host, struct nlm_file *file,
|
||||
{
|
||||
struct inode *inode = nlmsvc_file_inode(file);
|
||||
struct file_lock *fl;
|
||||
struct file_lock_context *flctx = inode->i_flctx;
|
||||
struct file_lock_context *flctx = locks_inode_context(inode);
|
||||
struct nlm_host *lockhost;
|
||||
|
||||
if (!flctx || list_empty_careful(&flctx->flc_posix))
|
||||
@ -262,7 +262,7 @@ nlm_file_inuse(struct nlm_file *file)
|
||||
{
|
||||
struct inode *inode = nlmsvc_file_inode(file);
|
||||
struct file_lock *fl;
|
||||
struct file_lock_context *flctx = inode->i_flctx;
|
||||
struct file_lock_context *flctx = locks_inode_context(inode);
|
||||
|
||||
if (file->f_count || !list_empty(&file->f_blocks) || file->f_shares)
|
||||
return 1;
|
||||
|
50
fs/locks.c
50
fs/locks.c
@ -175,7 +175,7 @@ locks_get_lock_context(struct inode *inode, int type)
|
||||
struct file_lock_context *ctx;
|
||||
|
||||
/* paired with cmpxchg() below */
|
||||
ctx = smp_load_acquire(&inode->i_flctx);
|
||||
ctx = locks_inode_context(inode);
|
||||
if (likely(ctx) || type == F_UNLCK)
|
||||
goto out;
|
||||
|
||||
@ -194,7 +194,7 @@ locks_get_lock_context(struct inode *inode, int type)
|
||||
*/
|
||||
if (cmpxchg(&inode->i_flctx, NULL, ctx)) {
|
||||
kmem_cache_free(flctx_cache, ctx);
|
||||
ctx = smp_load_acquire(&inode->i_flctx);
|
||||
ctx = locks_inode_context(inode);
|
||||
}
|
||||
out:
|
||||
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
|
||||
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)) {
|
||||
locks_check_ctx_lists(inode);
|
||||
@ -891,7 +891,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl)
|
||||
void *owner;
|
||||
void (*func)(void);
|
||||
|
||||
ctx = smp_load_acquire(&inode->i_flctx);
|
||||
ctx = locks_inode_context(inode);
|
||||
if (!ctx || list_empty_careful(&ctx->flc_posix)) {
|
||||
fl->fl_type = F_UNLCK;
|
||||
return;
|
||||
@ -1483,7 +1483,7 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
|
||||
new_fl->fl_flags = type;
|
||||
|
||||
/* 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) {
|
||||
WARN_ON_ONCE(1);
|
||||
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 *fl;
|
||||
|
||||
ctx = smp_load_acquire(&inode->i_flctx);
|
||||
ctx = locks_inode_context(inode);
|
||||
if (ctx && !list_empty_careful(&ctx->flc_lease)) {
|
||||
spin_lock(&ctx->flc_lock);
|
||||
fl = list_first_entry_or_null(&ctx->flc_lease,
|
||||
@ -1634,7 +1634,7 @@ int fcntl_getlease(struct file *filp)
|
||||
int type = F_UNLCK;
|
||||
LIST_HEAD(dispose);
|
||||
|
||||
ctx = smp_load_acquire(&inode->i_flctx);
|
||||
ctx = locks_inode_context(inode);
|
||||
if (ctx && !list_empty_careful(&ctx->flc_lease)) {
|
||||
percpu_down_read(&file_rwsem);
|
||||
spin_lock(&ctx->flc_lock);
|
||||
@ -1823,7 +1823,7 @@ static int generic_delete_lease(struct file *filp, void *owner)
|
||||
struct file_lock_context *ctx;
|
||||
LIST_HEAD(dispose);
|
||||
|
||||
ctx = smp_load_acquire(&inode->i_flctx);
|
||||
ctx = locks_inode_context(inode);
|
||||
if (!ctx) {
|
||||
trace_generic_delete_lease(inode, NULL);
|
||||
return error;
|
||||
@ -2096,7 +2096,7 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
|
||||
* throw a warning to let people know that they don't actually work.
|
||||
*/
|
||||
if (cmd & LOCK_MAND) {
|
||||
pr_warn_once("Attempt to set a LOCK_MAND lock via flock(2). This support has been removed and the request ignored.\n");
|
||||
pr_warn_once("%s(%d): Attempt to set a LOCK_MAND lock via flock(2). This support has been removed and the request ignored.\n", current->comm, current->pid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2146,6 +2146,7 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
|
||||
*/
|
||||
int vfs_test_lock(struct file *filp, struct file_lock *fl)
|
||||
{
|
||||
WARN_ON_ONCE(filp != fl->fl_file);
|
||||
if (filp->f_op->lock)
|
||||
return filp->f_op->lock(filp, F_GETLK, fl);
|
||||
posix_test_lock(filp, fl);
|
||||
@ -2295,6 +2296,7 @@ out:
|
||||
*/
|
||||
int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf)
|
||||
{
|
||||
WARN_ON_ONCE(filp != fl->fl_file);
|
||||
if (filp->f_op->lock)
|
||||
return filp->f_op->lock(filp, cmd, fl);
|
||||
else
|
||||
@ -2561,7 +2563,7 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)
|
||||
* 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.
|
||||
*/
|
||||
ctx = smp_load_acquire(&inode->i_flctx);
|
||||
ctx = locks_inode_context(inode);
|
||||
if (!ctx || list_empty(&ctx->flc_posix))
|
||||
return;
|
||||
|
||||
@ -2634,7 +2636,7 @@ void locks_remove_file(struct file *filp)
|
||||
{
|
||||
struct file_lock_context *ctx;
|
||||
|
||||
ctx = smp_load_acquire(&locks_inode(filp)->i_flctx);
|
||||
ctx = locks_inode_context(locks_inode(filp));
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
@ -2663,12 +2665,36 @@ void locks_remove_file(struct file *filp)
|
||||
*/
|
||||
int vfs_cancel_lock(struct file *filp, struct file_lock *fl)
|
||||
{
|
||||
WARN_ON_ONCE(filp != fl->fl_file);
|
||||
if (filp->f_op->lock)
|
||||
return filp->f_op->lock(filp, F_CANCELLK, fl);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vfs_cancel_lock);
|
||||
|
||||
/**
|
||||
* vfs_inode_has_locks - are any file locks held on @inode?
|
||||
* @inode: inode to check for locks
|
||||
*
|
||||
* Return true if there are any FL_POSIX or FL_FLOCK locks currently
|
||||
* set on @inode.
|
||||
*/
|
||||
bool vfs_inode_has_locks(struct inode *inode)
|
||||
{
|
||||
struct file_lock_context *ctx;
|
||||
bool ret;
|
||||
|
||||
ctx = locks_inode_context(inode);
|
||||
if (!ctx)
|
||||
return false;
|
||||
|
||||
spin_lock(&ctx->flc_lock);
|
||||
ret = !list_empty(&ctx->flc_posix) || !list_empty(&ctx->flc_flock);
|
||||
spin_unlock(&ctx->flc_lock);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vfs_inode_has_locks);
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
@ -2839,7 +2865,7 @@ void show_fd_locks(struct seq_file *f,
|
||||
struct file_lock_context *ctx;
|
||||
int id = 0;
|
||||
|
||||
ctx = smp_load_acquire(&inode->i_flctx);
|
||||
ctx = locks_inode_context(inode);
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
|
@ -146,7 +146,7 @@ static int nfs_delegation_claim_locks(struct nfs4_state *state, const nfs4_state
|
||||
{
|
||||
struct inode *inode = state->inode;
|
||||
struct file_lock *fl;
|
||||
struct file_lock_context *flctx = inode->i_flctx;
|
||||
struct file_lock_context *flctx = locks_inode_context(inode);
|
||||
struct list_head *list;
|
||||
int status = 0;
|
||||
|
||||
|
@ -1501,7 +1501,7 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_
|
||||
struct file_lock *fl;
|
||||
struct nfs4_lock_state *lsp;
|
||||
int status = 0;
|
||||
struct file_lock_context *flctx = inode->i_flctx;
|
||||
struct file_lock_context *flctx = locks_inode_context(inode);
|
||||
struct list_head *list;
|
||||
|
||||
if (flctx == NULL)
|
||||
|
@ -1055,7 +1055,7 @@ static unsigned int nfs_coalesce_size(struct nfs_page *prev,
|
||||
if (prev) {
|
||||
if (!nfs_match_open_context(nfs_req_openctx(req), nfs_req_openctx(prev)))
|
||||
return 0;
|
||||
flctx = d_inode(nfs_req_openctx(req)->dentry)->i_flctx;
|
||||
flctx = locks_inode_context(d_inode(nfs_req_openctx(req)->dentry));
|
||||
if (flctx != NULL &&
|
||||
!(list_empty_careful(&flctx->flc_posix) &&
|
||||
list_empty_careful(&flctx->flc_flock)) &&
|
||||
|
@ -1185,7 +1185,7 @@ int nfs_flush_incompatible(struct file *file, struct page *page)
|
||||
{
|
||||
struct nfs_open_context *ctx = nfs_file_open_context(file);
|
||||
struct nfs_lock_context *l_ctx;
|
||||
struct file_lock_context *flctx = file_inode(file)->i_flctx;
|
||||
struct file_lock_context *flctx = locks_inode_context(file_inode(file));
|
||||
struct nfs_page *req;
|
||||
int do_flush, status;
|
||||
/*
|
||||
@ -1321,7 +1321,7 @@ static int nfs_can_extend_write(struct file *file, struct page *page,
|
||||
struct inode *inode, unsigned int pagelen)
|
||||
{
|
||||
int ret;
|
||||
struct file_lock_context *flctx = inode->i_flctx;
|
||||
struct file_lock_context *flctx = locks_inode_context(inode);
|
||||
struct file_lock *fl;
|
||||
|
||||
if (file->f_flags & O_DSYNC)
|
||||
|
@ -4758,7 +4758,7 @@ nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
|
||||
|
||||
static bool nfsd4_deleg_present(const struct inode *inode)
|
||||
{
|
||||
struct file_lock_context *ctx = smp_load_acquire(&inode->i_flctx);
|
||||
struct file_lock_context *ctx = locks_inode_context(inode);
|
||||
|
||||
return ctx && !list_empty_careful(&ctx->flc_lease);
|
||||
}
|
||||
@ -5897,7 +5897,7 @@ nfs4_lockowner_has_blockers(struct nfs4_lockowner *lo)
|
||||
|
||||
list_for_each_entry(stp, &lo->lo_owner.so_stateids, st_perstateowner) {
|
||||
nf = stp->st_stid.sc_file;
|
||||
ctx = nf->fi_inode->i_flctx;
|
||||
ctx = locks_inode_context(nf->fi_inode);
|
||||
if (!ctx)
|
||||
continue;
|
||||
if (locks_owner_has_blockers(ctx, lo))
|
||||
@ -7713,7 +7713,7 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner)
|
||||
}
|
||||
|
||||
inode = locks_inode(nf->nf_file);
|
||||
flctx = inode->i_flctx;
|
||||
flctx = locks_inode_context(inode);
|
||||
|
||||
if (flctx && !list_empty_careful(&flctx->flc_posix)) {
|
||||
spin_lock(&flctx->flc_lock);
|
||||
|
@ -1170,6 +1170,7 @@ extern int locks_delete_block(struct file_lock *);
|
||||
extern int vfs_test_lock(struct file *, struct file_lock *);
|
||||
extern int vfs_lock_file(struct file *, unsigned int, struct file_lock *, struct file_lock *);
|
||||
extern int vfs_cancel_lock(struct file *filp, struct file_lock *fl);
|
||||
bool vfs_inode_has_locks(struct inode *inode);
|
||||
extern int locks_lock_inode_wait(struct inode *inode, struct file_lock *fl);
|
||||
extern int __break_lease(struct inode *inode, unsigned int flags, unsigned int type);
|
||||
extern void lease_get_mtime(struct inode *, struct timespec64 *time);
|
||||
@ -1186,6 +1187,13 @@ extern void show_fd_locks(struct seq_file *f,
|
||||
struct file *filp, struct files_struct *files);
|
||||
extern bool locks_owner_has_blockers(struct file_lock_context *flctx,
|
||||
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 */
|
||||
static inline int fcntl_getlk(struct file *file, unsigned int cmd,
|
||||
struct flock __user *user)
|
||||
@ -1284,6 +1292,11 @@ static inline int vfs_cancel_lock(struct file *filp, struct file_lock *fl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool vfs_inode_has_locks(struct inode *inode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int locks_lock_inode_wait(struct inode *inode, struct file_lock *fl)
|
||||
{
|
||||
return -ENOLCK;
|
||||
@ -1326,6 +1339,13 @@ static inline bool locks_owner_has_blockers(struct file_lock_context *flctx,
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline struct file_lock_context *
|
||||
locks_inode_context(const struct inode *inode)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_FILE_LOCKING */
|
||||
|
||||
static inline struct inode *file_inode(const struct file *f)
|
||||
|
Loading…
Reference in New Issue
Block a user