* [PATCH 0/4] locks: locks related cleanups for v4.1
@ 2015-03-07 16:09 Jeff Layton
2015-03-07 16:09 ` [PATCH 1/4] locks: don't allocate a lock context for an F_UNLCK request Jeff Layton
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Jeff Layton @ 2015-03-07 16:09 UTC (permalink / raw)
To: linux-fsdevel; +Cc: bfields, linux-kernel
Nothing terribly earth-shattering here. Just a few locking-related
cleanup patches that I'm planning to queue up for v4.1. The only one
that really warrants close attention is the 4th one that gets rid of the
i_lock protection around the i_flctx pointer.
One of the earlier patchsets that added the i_flctx field used cmpxchg
to assign it, but I ended up taking that out due to a problem that Sasha
Levin reported. I now think that I misunderstood the problem and that
using cmpxchg for that should be ok.
Jeff Layton (4):
locks: don't allocate a lock context for an F_UNLCK request
locks: change lm_get_owner and lm_put_owner prototypes
locks: get rid of WE_CAN_BREAK_LSLK_NOW dead code
locks: use cmpxchg to assign i_flctx pointer
fs/locks.c | 45 +++++++++++++++++++--------------------------
fs/nfsd/nfs4state.c | 18 ++++++++++--------
include/linux/fs.h | 4 ++--
3 files changed, 31 insertions(+), 36 deletions(-)
--
2.1.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/4] locks: don't allocate a lock context for an F_UNLCK request
2015-03-07 16:09 [PATCH 0/4] locks: locks related cleanups for v4.1 Jeff Layton
@ 2015-03-07 16:09 ` Jeff Layton
2015-03-07 16:09 ` [PATCH 2/4] locks: change lm_get_owner and lm_put_owner prototypes Jeff Layton
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Jeff Layton @ 2015-03-07 16:09 UTC (permalink / raw)
To: linux-fsdevel; +Cc: bfields, linux-kernel
In the event that we get an F_UNLCK request on an inode that has no lock
context, there is no reason to allocate one. Change
locks_get_lock_context to take a "type" pointer and avoid allocating a
new context if it's F_UNLCK.
Then, fix the callers to return appropriately if that function returns
NULL.
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
---
fs/locks.c | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)
diff --git a/fs/locks.c b/fs/locks.c
index 0915a3ead897..7be49ad1c902 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -203,11 +203,11 @@ static struct kmem_cache *flctx_cache __read_mostly;
static struct kmem_cache *filelock_cache __read_mostly;
static struct file_lock_context *
-locks_get_lock_context(struct inode *inode)
+locks_get_lock_context(struct inode *inode, int type)
{
struct file_lock_context *new;
- if (likely(inode->i_flctx))
+ if (likely(inode->i_flctx) || type == F_UNLCK)
goto out;
new = kmem_cache_alloc(flctx_cache, GFP_KERNEL);
@@ -877,9 +877,12 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
bool found = false;
LIST_HEAD(dispose);
- ctx = locks_get_lock_context(inode);
- if (!ctx)
- return -ENOMEM;
+ ctx = locks_get_lock_context(inode, request->fl_type);
+ if (!ctx) {
+ if (request->fl_type != F_UNLCK)
+ return -ENOMEM;
+ return (request->fl_flags & FL_EXISTS) ? -ENOENT : 0;
+ }
if (!(request->fl_flags & FL_ACCESS) && (request->fl_type != F_UNLCK)) {
new_fl = locks_alloc_lock();
@@ -945,9 +948,9 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
bool added = false;
LIST_HEAD(dispose);
- ctx = locks_get_lock_context(inode);
+ ctx = locks_get_lock_context(inode, request->fl_type);
if (!ctx)
- return -ENOMEM;
+ return (request->fl_type == F_UNLCK) ? 0 : -ENOMEM;
/*
* We may need two file_lock structures for this operation,
@@ -1610,9 +1613,9 @@ generic_add_lease(struct file *filp, long arg, struct file_lock **flp, void **pr
lease = *flp;
trace_generic_add_lease(inode, lease);
- ctx = locks_get_lock_context(inode);
+ ctx = locks_get_lock_context(inode, arg);
if (!ctx)
- return -ENOMEM;
+ return (arg == F_UNLCK) ? 0 : -ENOMEM;
/*
* In the delegation case we need mutual exclusion with
--
2.1.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/4] locks: change lm_get_owner and lm_put_owner prototypes
2015-03-07 16:09 [PATCH 0/4] locks: locks related cleanups for v4.1 Jeff Layton
2015-03-07 16:09 ` [PATCH 1/4] locks: don't allocate a lock context for an F_UNLCK request Jeff Layton
@ 2015-03-07 16:09 ` Jeff Layton
2015-03-07 16:09 ` [PATCH 3/4] locks: get rid of WE_CAN_BREAK_LSLK_NOW dead code Jeff Layton
2015-03-07 16:09 ` [PATCH 4/4] locks: use cmpxchg to assign i_flctx pointer Jeff Layton
3 siblings, 0 replies; 5+ messages in thread
From: Jeff Layton @ 2015-03-07 16:09 UTC (permalink / raw)
To: linux-fsdevel; +Cc: bfields, linux-kernel
The current prototypes for these operations are somewhat awkward as they
deal with fl_owners but take struct file_lock arguments. In the future,
we'll want to be able to take references without necessarily dealing
with a struct file_lock.
Change them to take fl_owner_t arguments instead and have the callers
deal with assigning the values to the file_lock structs.
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
---
fs/locks.c | 8 +++++---
fs/nfsd/nfs4state.c | 18 ++++++++++--------
include/linux/fs.h | 4 ++--
3 files changed, 17 insertions(+), 13 deletions(-)
diff --git a/fs/locks.c b/fs/locks.c
index 7be49ad1c902..49d240874d4e 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -276,8 +276,10 @@ void locks_release_private(struct file_lock *fl)
}
if (fl->fl_lmops) {
- if (fl->fl_lmops->lm_put_owner)
- fl->fl_lmops->lm_put_owner(fl);
+ if (fl->fl_lmops->lm_put_owner) {
+ fl->fl_lmops->lm_put_owner(fl->fl_owner);
+ fl->fl_owner = NULL;
+ }
fl->fl_lmops = NULL;
}
}
@@ -333,7 +335,7 @@ void locks_copy_conflock(struct file_lock *new, struct file_lock *fl)
if (fl->fl_lmops) {
if (fl->fl_lmops->lm_get_owner)
- fl->fl_lmops->lm_get_owner(new, fl);
+ fl->fl_lmops->lm_get_owner(fl->fl_owner);
}
}
EXPORT_SYMBOL(locks_copy_conflock);
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index d2f2c37dc2db..132a0270dff3 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -4932,20 +4932,22 @@ nfs4_transform_lock_offset(struct file_lock *lock)
lock->fl_end = OFFSET_MAX;
}
-static void nfsd4_fl_get_owner(struct file_lock *dst, struct file_lock *src)
+static fl_owner_t
+nfsd4_fl_get_owner(fl_owner_t owner)
{
- struct nfs4_lockowner *lo = (struct nfs4_lockowner *)src->fl_owner;
- dst->fl_owner = (fl_owner_t)lockowner(nfs4_get_stateowner(&lo->lo_owner));
+ struct nfs4_lockowner *lo = (struct nfs4_lockowner *)owner;
+
+ nfs4_get_stateowner(&lo->lo_owner);
+ return owner;
}
-static void nfsd4_fl_put_owner(struct file_lock *fl)
+static void
+nfsd4_fl_put_owner(fl_owner_t owner)
{
- struct nfs4_lockowner *lo = (struct nfs4_lockowner *)fl->fl_owner;
+ struct nfs4_lockowner *lo = (struct nfs4_lockowner *)owner;
- if (lo) {
+ if (lo)
nfs4_put_stateowner(&lo->lo_owner);
- fl->fl_owner = NULL;
- }
}
static const struct lock_manager_operations nfsd_posix_mng_ops = {
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b4d71b5e1ff2..fe1cef7bb677 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -892,8 +892,8 @@ struct file_lock_operations {
struct lock_manager_operations {
int (*lm_compare_owner)(struct file_lock *, struct file_lock *);
unsigned long (*lm_owner_key)(struct file_lock *);
- void (*lm_get_owner)(struct file_lock *, struct file_lock *);
- void (*lm_put_owner)(struct file_lock *);
+ fl_owner_t (*lm_get_owner)(fl_owner_t);
+ void (*lm_put_owner)(fl_owner_t);
void (*lm_notify)(struct file_lock *); /* unblock callback */
int (*lm_grant)(struct file_lock *, int);
bool (*lm_break)(struct file_lock *);
--
2.1.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 3/4] locks: get rid of WE_CAN_BREAK_LSLK_NOW dead code
2015-03-07 16:09 [PATCH 0/4] locks: locks related cleanups for v4.1 Jeff Layton
2015-03-07 16:09 ` [PATCH 1/4] locks: don't allocate a lock context for an F_UNLCK request Jeff Layton
2015-03-07 16:09 ` [PATCH 2/4] locks: change lm_get_owner and lm_put_owner prototypes Jeff Layton
@ 2015-03-07 16:09 ` Jeff Layton
2015-03-07 16:09 ` [PATCH 4/4] locks: use cmpxchg to assign i_flctx pointer Jeff Layton
3 siblings, 0 replies; 5+ messages in thread
From: Jeff Layton @ 2015-03-07 16:09 UTC (permalink / raw)
To: linux-fsdevel; +Cc: bfields, linux-kernel
As Bruce points out, there's no compelling reason to change /proc/locks
output at this point. If we did want to do this, then we'd almost
certainly want to introduce a new file to display this info (maybe via
debugfs?).
Let's remove the dead WE_CAN_BREAK_LSLK_NOW ifdef here and just plan to
stay with the legacy format.
Signed-off-by: Jeff Layton <jeff.layton@primarydata.com>
---
fs/locks.c | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/fs/locks.c b/fs/locks.c
index 49d240874d4e..4347f3dc17cc 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -2565,15 +2565,10 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl,
: (fl->fl_type == F_WRLCK) ? "WRITE" : "READ ");
}
if (inode) {
-#ifdef WE_CAN_BREAK_LSLK_NOW
- seq_printf(f, "%d %s:%ld ", fl_pid,
- inode->i_sb->s_id, inode->i_ino);
-#else
- /* userspace relies on this representation of dev_t ;-( */
+ /* userspace relies on this representation of dev_t */
seq_printf(f, "%d %02x:%02x:%ld ", fl_pid,
MAJOR(inode->i_sb->s_dev),
MINOR(inode->i_sb->s_dev), inode->i_ino);
-#endif
} else {
seq_printf(f, "%d <none>:0 ", fl_pid);
}
--
2.1.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 4/4] locks: use cmpxchg to assign i_flctx pointer
2015-03-07 16:09 [PATCH 0/4] locks: locks related cleanups for v4.1 Jeff Layton
` (2 preceding siblings ...)
2015-03-07 16:09 ` [PATCH 3/4] locks: get rid of WE_CAN_BREAK_LSLK_NOW dead code Jeff Layton
@ 2015-03-07 16:09 ` Jeff Layton
3 siblings, 0 replies; 5+ messages in thread
From: Jeff Layton @ 2015-03-07 16:09 UTC (permalink / raw)
To: linux-fsdevel; +Cc: bfields, linux-kernel
During the v3.20/v4.0 cycle, I had originally had the code manage the
inode->i_flctx pointer using a compare-and-swap operation instead of
the i_lock.
Sasha Levin though hit a problem while testing trinity that made me
believe that that wasn't safe. I now think though that I completely
misread the problem, even though it seemed like it went away when
we started using the i_lock to protect this pointer.
The issue was likely the same race that Kirill Shutemov hit while
testing the pre-rc1 v4.0 kernel and that Linus spotted. Due to the
way that the spinlock was dropped in the middle of flock_lock_file,
you could end up with multiple flock locks for the same struct file
on the inode.
Reinstate the use of a CAS operation to assign this pointer since it's
likely to be more efficient and gets the i_lock completely out of the
file locking business.
Signed-off-by: Jeff Layton <jeff.layton@primarydata.com>
---
fs/locks.c | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/fs/locks.c b/fs/locks.c
index 4347f3dc17cc..22c0785c00ed 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -223,14 +223,7 @@ locks_get_lock_context(struct inode *inode, int type)
* Assign the pointer if it's not already assigned. If it is, then
* free the context we just allocated.
*/
- spin_lock(&inode->i_lock);
- if (likely(!inode->i_flctx)) {
- inode->i_flctx = new;
- new = NULL;
- }
- spin_unlock(&inode->i_lock);
-
- if (new)
+ if (cmpxchg(&inode->i_flctx, NULL, new))
kmem_cache_free(flctx_cache, new);
out:
return inode->i_flctx;
--
2.1.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2015-03-07 16:09 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-03-07 16:09 [PATCH 0/4] locks: locks related cleanups for v4.1 Jeff Layton
2015-03-07 16:09 ` [PATCH 1/4] locks: don't allocate a lock context for an F_UNLCK request Jeff Layton
2015-03-07 16:09 ` [PATCH 2/4] locks: change lm_get_owner and lm_put_owner prototypes Jeff Layton
2015-03-07 16:09 ` [PATCH 3/4] locks: get rid of WE_CAN_BREAK_LSLK_NOW dead code Jeff Layton
2015-03-07 16:09 ` [PATCH 4/4] locks: use cmpxchg to assign i_flctx pointer Jeff Layton
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).