* [PATCH 0/3] nfs4: file locking fixes and cleanups
@ 2014-04-23 18:24 Jeff Layton
2014-04-23 18:24 ` [PATCH 1/3] nfs4: treat lock owners as opaque values Jeff Layton
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Jeff Layton @ 2014-04-23 18:24 UTC (permalink / raw)
To: trond.myklebust; +Cc: linux-nfs
The impetus for this set was a bug report in Fedora about "sleeping in
atomic context" warning that patch #2 fixes. While looking at that, I
noticed that a LOCKU wasn't being sent in the reproducer provided so I
tracked down and fixed that bug as well.
These are only lightly tested, and could probably use some soak time in
linux-next. Also, I'm not 100% thrilled with queueing the
free_lock_state job submission to a workqueue, but I don't see a better
way to handle it so far.
Jeff Layton (3):
nfs4: treat lock owners as opaque values
nfs4: queue free_lock_state job submission to nfsiod
nfs4: turn free_lock_state into a void return operation
fs/nfs/nfs4_fs.h | 26 +++++++--------------
fs/nfs/nfs4proc.c | 14 ++++++------
fs/nfs/nfs4state.c | 67 ++++++++++++++++++++++--------------------------------
3 files changed, 42 insertions(+), 65 deletions(-)
--
1.9.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/3] nfs4: treat lock owners as opaque values
2014-04-23 18:24 [PATCH 0/3] nfs4: file locking fixes and cleanups Jeff Layton
@ 2014-04-23 18:24 ` Jeff Layton
2014-04-23 18:48 ` Trond Myklebust
2014-04-23 18:24 ` [PATCH 2/3] nfs4: queue free_lock_state job submission to nfsiod Jeff Layton
2014-04-23 18:25 ` [PATCH 3/3] nfs4: turn free_lock_state into a void return operation Jeff Layton
2 siblings, 1 reply; 7+ messages in thread
From: Jeff Layton @ 2014-04-23 18:24 UTC (permalink / raw)
To: trond.myklebust; +Cc: linux-nfs
Do the following set of ops with a file on a NFSv4 mount:
exec 3>>$1
flock -x 3
exec 3>&-
You'll see the LOCK request go across the wire, but no LOCKU when the
file is closed. This leads to
What happens is that the fd is passed across a fork, and the final close
is done in a different process than the opener. That makes
__nfs4_find_lock_state miss finding the correct lock state because it
uses the fl_pid as a search key. A new one is created, and the locking
code treats it as a delegation stateid (because NFS_LOCK_INITIALIZED
isn't set).
The root cause of this breakage seems to be commit 77041ed9b49a9e
(NFSv4: Ensure the lockowners are labelled using the fl_owner and/or
fl_pid).
That changed it so that flock lockowners are allocated based on the
fl_pid. I think this is incorrect. flock locks should be "owned" by the
struct file, and that is already accounted for in the fl_owner field of
the lock request when the vfs layer passes it down.
This patch basically reverts the above commit and with it, a LOCKU is
sent in the above reproducer.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/nfs/nfs4_fs.h | 13 +------------
fs/nfs/nfs4state.c | 43 +++++++++----------------------------------
2 files changed, 10 insertions(+), 46 deletions(-)
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index e1d1badbe53c..3888dd0b43a1 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -129,17 +129,6 @@ enum {
* LOCK: one nfs4_state (LOCK) to hold the lock stateid nfs4_state(OPEN)
*/
-struct nfs4_lock_owner {
- unsigned int lo_type;
-#define NFS4_ANY_LOCK_TYPE (0U)
-#define NFS4_FLOCK_LOCK_TYPE (1U << 0)
-#define NFS4_POSIX_LOCK_TYPE (1U << 1)
- union {
- fl_owner_t posix_owner;
- pid_t flock_owner;
- } lo_u;
-};
-
struct nfs4_lock_state {
struct list_head ls_locks; /* Other lock stateids */
struct nfs4_state * ls_state; /* Pointer to open state */
@@ -149,7 +138,7 @@ struct nfs4_lock_state {
struct nfs_seqid_counter ls_seqid;
nfs4_stateid ls_stateid;
atomic_t ls_count;
- struct nfs4_lock_owner ls_owner;
+ fl_owner_t ls_owner;
};
/* bits for nfs4_state->flags */
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 2349518eef2c..102cd4b4f07e 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -787,21 +787,12 @@ void nfs4_close_sync(struct nfs4_state *state, fmode_t fmode)
* that is compatible with current->files
*/
static struct nfs4_lock_state *
-__nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_pid, unsigned int type)
+__nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_pid)
{
struct nfs4_lock_state *pos;
list_for_each_entry(pos, &state->lock_states, ls_locks) {
- if (type != NFS4_ANY_LOCK_TYPE && pos->ls_owner.lo_type != type)
+ if (pos->ls_owner != fl_owner)
continue;
- switch (pos->ls_owner.lo_type) {
- case NFS4_POSIX_LOCK_TYPE:
- if (pos->ls_owner.lo_u.posix_owner != fl_owner)
- continue;
- break;
- case NFS4_FLOCK_LOCK_TYPE:
- if (pos->ls_owner.lo_u.flock_owner != fl_pid)
- continue;
- }
atomic_inc(&pos->ls_count);
return pos;
}
@@ -813,7 +804,7 @@ __nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_p
* exists, return an uninitialized one.
*
*/
-static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_pid, unsigned int type)
+static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_pid)
{
struct nfs4_lock_state *lsp;
struct nfs_server *server = state->owner->so_server;
@@ -824,17 +815,7 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f
nfs4_init_seqid_counter(&lsp->ls_seqid);
atomic_set(&lsp->ls_count, 1);
lsp->ls_state = state;
- lsp->ls_owner.lo_type = type;
- switch (lsp->ls_owner.lo_type) {
- case NFS4_FLOCK_LOCK_TYPE:
- lsp->ls_owner.lo_u.flock_owner = fl_pid;
- break;
- case NFS4_POSIX_LOCK_TYPE:
- lsp->ls_owner.lo_u.posix_owner = fl_owner;
- break;
- default:
- goto out_free;
- }
+ lsp->ls_owner = fl_owner;
lsp->ls_seqid.owner_id = ida_simple_get(&server->lockowner_id, 0, 0, GFP_NOFS);
if (lsp->ls_seqid.owner_id < 0)
goto out_free;
@@ -857,13 +838,13 @@ void nfs4_free_lock_state(struct nfs_server *server, struct nfs4_lock_state *lsp
* exists, return an uninitialized one.
*
*/
-static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner, pid_t pid, unsigned int type)
+static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner, pid_t pid)
{
struct nfs4_lock_state *lsp, *new = NULL;
for(;;) {
spin_lock(&state->state_lock);
- lsp = __nfs4_find_lock_state(state, owner, pid, type);
+ lsp = __nfs4_find_lock_state(state, owner, pid);
if (lsp != NULL)
break;
if (new != NULL) {
@@ -874,7 +855,7 @@ static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_
break;
}
spin_unlock(&state->state_lock);
- new = nfs4_alloc_lock_state(state, owner, pid, type);
+ new = nfs4_alloc_lock_state(state, owner, pid);
if (new == NULL)
return NULL;
}
@@ -935,13 +916,7 @@ int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl)
if (fl->fl_ops != NULL)
return 0;
- if (fl->fl_flags & FL_POSIX)
- lsp = nfs4_get_lock_state(state, fl->fl_owner, 0, NFS4_POSIX_LOCK_TYPE);
- else if (fl->fl_flags & FL_FLOCK)
- lsp = nfs4_get_lock_state(state, NULL, fl->fl_pid,
- NFS4_FLOCK_LOCK_TYPE);
- else
- return -EINVAL;
+ lsp = nfs4_get_lock_state(state, fl->fl_owner, 0);
if (lsp == NULL)
return -ENOMEM;
fl->fl_u.nfs4_fl.owner = lsp;
@@ -968,7 +943,7 @@ static int nfs4_copy_lock_stateid(nfs4_stateid *dst,
fl_owner = lockowner->l_owner;
fl_pid = lockowner->l_pid;
spin_lock(&state->state_lock);
- lsp = __nfs4_find_lock_state(state, fl_owner, fl_pid, NFS4_ANY_LOCK_TYPE);
+ lsp = __nfs4_find_lock_state(state, fl_owner, fl_pid);
if (lsp && test_bit(NFS_LOCK_LOST, &lsp->ls_flags))
ret = -EIO;
else if (lsp != NULL && test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) != 0) {
--
1.9.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/3] nfs4: queue free_lock_state job submission to nfsiod
2014-04-23 18:24 [PATCH 0/3] nfs4: file locking fixes and cleanups Jeff Layton
2014-04-23 18:24 ` [PATCH 1/3] nfs4: treat lock owners as opaque values Jeff Layton
@ 2014-04-23 18:24 ` Jeff Layton
2014-04-23 18:25 ` [PATCH 3/3] nfs4: turn free_lock_state into a void return operation Jeff Layton
2 siblings, 0 replies; 7+ messages in thread
From: Jeff Layton @ 2014-04-23 18:24 UTC (permalink / raw)
To: trond.myklebust; +Cc: linux-nfs
We got a report of the following warning in Fedora:
BUG: sleeping function called from invalid context at mm/slub.c:969
in_atomic(): 1, irqs_disabled(): 0, pid: 533, name: bash
3 locks held by bash/533:
#0: (&sp->so_delegreturn_mutex){+.+...}, at: [<ffffffffa033da62>] nfs4_proc_lock+0x262/0x910 [nfsv4]
#1: (&nfsi->rwsem){.+.+.+}, at: [<ffffffffa033da6a>] nfs4_proc_lock+0x26a/0x910 [nfsv4]
#2: (&sb->s_type->i_lock_key#23){+.+...}, at: [<ffffffff812998dc>] flock_lock_file_wait+0x8c/0x3a0
CPU: 0 PID: 533 Comm: bash Not tainted 3.15.0-0.rc1.git1.1.fc21.x86_64 #1
Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
0000000000000000 00000000d664ff3c ffff880078b69a70 ffffffff817e82e0
0000000000000000 ffff880078b69a98 ffffffff810cf1a4 0000000000000050
0000000000000050 ffff88007cc01a00 ffff880078b69ad8 ffffffff8121449e
Call Trace:
[<ffffffff817e82e0>] dump_stack+0x4d/0x66
[<ffffffff810cf1a4>] __might_sleep+0x184/0x240
[<ffffffff8121449e>] kmem_cache_alloc_trace+0x4e/0x330
[<ffffffffa0331124>] ? nfs4_release_lockowner+0x74/0x110 [nfsv4]
[<ffffffffa0331124>] nfs4_release_lockowner+0x74/0x110 [nfsv4]
[<ffffffffa0352340>] nfs4_put_lock_state+0x90/0xb0 [nfsv4]
[<ffffffffa0352375>] nfs4_fl_release_lock+0x15/0x20 [nfsv4]
[<ffffffff81297515>] locks_free_lock+0x45/0x90
[<ffffffff8129996c>] flock_lock_file_wait+0x11c/0x3a0
[<ffffffffa033da6a>] ? nfs4_proc_lock+0x26a/0x910 [nfsv4]
[<ffffffffa033301e>] do_vfs_lock+0x1e/0x30 [nfsv4]
[<ffffffffa033da79>] nfs4_proc_lock+0x279/0x910 [nfsv4]
[<ffffffff810dbb26>] ? local_clock+0x16/0x30
[<ffffffff810f5a3f>] ? lock_release_holdtime.part.28+0xf/0x200
[<ffffffffa02f820c>] do_unlk+0x8c/0xc0 [nfs]
[<ffffffffa02f85c5>] nfs_flock+0xa5/0xf0 [nfs]
[<ffffffff8129a6f6>] locks_remove_file+0xb6/0x1e0
[<ffffffff812159d8>] ? kfree+0xd8/0x2d0
[<ffffffff8123bc63>] __fput+0xd3/0x210
[<ffffffff8123bdee>] ____fput+0xe/0x10
[<ffffffff810bfb6d>] task_work_run+0xcd/0xf0
[<ffffffff81019cd1>] do_notify_resume+0x61/0x90
[<ffffffff817fbea2>] int_signal+0x12/0x17
The problem is that NFSv4 is trying to do an allocation from
fl_release_private (in order to send a RELEASE_LOCKOWNER call). That
function can be called while holding the inode->i_lock, and it's
currently set up to do __GFP_WAIT allocations. v4.1 code has a
similar problem.
This patch adds a work_struct to the nfs4_lock_state and has the code
queue the free_lock_state operation to nfsiod.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/nfs/nfs4_fs.h | 13 +++++++------
fs/nfs/nfs4state.c | 24 ++++++++++++++++++------
2 files changed, 25 insertions(+), 12 deletions(-)
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 3888dd0b43a1..75aadf8c0429 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -130,15 +130,16 @@ enum {
*/
struct nfs4_lock_state {
- struct list_head ls_locks; /* Other lock stateids */
- struct nfs4_state * ls_state; /* Pointer to open state */
+ struct list_head ls_locks; /* Other lock stateids */
+ struct nfs4_state * ls_state; /* Pointer to open state */
#define NFS_LOCK_INITIALIZED 0
#define NFS_LOCK_LOST 1
- unsigned long ls_flags;
+ unsigned long ls_flags;
struct nfs_seqid_counter ls_seqid;
- nfs4_stateid ls_stateid;
- atomic_t ls_count;
- fl_owner_t ls_owner;
+ nfs4_stateid ls_stateid;
+ atomic_t ls_count;
+ fl_owner_t ls_owner;
+ struct work_struct ls_release;
};
/* bits for nfs4_state->flags */
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 102cd4b4f07e..7b0b113e3c37 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -799,6 +799,18 @@ __nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_p
return NULL;
}
+static void
+free_lock_state_work(struct work_struct *work)
+{
+ struct nfs4_lock_state *lsp = container_of(work,
+ struct nfs4_lock_state, ls_release);
+ struct nfs4_state *state = lsp->ls_state;
+ struct nfs_server *server = state->owner->so_server;
+ struct nfs_client *clp = server->nfs_client;
+
+ clp->cl_mvops->free_lock_state(server, lsp);
+}
+
/*
* Return a compatible lock_state. If no initialized lock_state structure
* exists, return an uninitialized one.
@@ -820,6 +832,7 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f
if (lsp->ls_seqid.owner_id < 0)
goto out_free;
INIT_LIST_HEAD(&lsp->ls_locks);
+ INIT_WORK(&lsp->ls_release, free_lock_state_work);
return lsp;
out_free:
kfree(lsp);
@@ -883,13 +896,12 @@ void nfs4_put_lock_state(struct nfs4_lock_state *lsp)
if (list_empty(&state->lock_states))
clear_bit(LK_STATE_IN_USE, &state->flags);
spin_unlock(&state->state_lock);
- server = state->owner->so_server;
- if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) {
- struct nfs_client *clp = server->nfs_client;
-
- clp->cl_mvops->free_lock_state(server, lsp);
- } else
+ if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags))
+ queue_work(nfsiod_workqueue, &lsp->ls_release);
+ else {
+ server = state->owner->so_server;
nfs4_free_lock_state(server, lsp);
+ }
}
static void nfs4_fl_copy_lock(struct file_lock *dst, struct file_lock *src)
--
1.9.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/3] nfs4: turn free_lock_state into a void return operation
2014-04-23 18:24 [PATCH 0/3] nfs4: file locking fixes and cleanups Jeff Layton
2014-04-23 18:24 ` [PATCH 1/3] nfs4: treat lock owners as opaque values Jeff Layton
2014-04-23 18:24 ` [PATCH 2/3] nfs4: queue free_lock_state job submission to nfsiod Jeff Layton
@ 2014-04-23 18:25 ` Jeff Layton
2 siblings, 0 replies; 7+ messages in thread
From: Jeff Layton @ 2014-04-23 18:25 UTC (permalink / raw)
To: trond.myklebust; +Cc: linux-nfs
Nothing checks its return value, and these calls are generally
best-effort anyway.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
fs/nfs/nfs4_fs.h | 2 +-
fs/nfs/nfs4proc.c | 14 +++++++-------
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 75aadf8c0429..f495ff306c4f 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -54,7 +54,7 @@ struct nfs4_minor_version_ops {
const nfs4_stateid *);
int (*find_root_sec)(struct nfs_server *, struct nfs_fh *,
struct nfs_fsinfo *);
- int (*free_lock_state)(struct nfs_server *,
+ void (*free_lock_state)(struct nfs_server *,
struct nfs4_lock_state *);
const struct rpc_call_ops *call_sync_ops;
const struct nfs4_state_recovery_ops *reboot_recovery_ops;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index cc6c3fe3e060..06c1e9e777ab 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -5915,7 +5915,8 @@ static const struct rpc_call_ops nfs4_release_lockowner_ops = {
.rpc_release = nfs4_release_lockowner_release,
};
-static int nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_state *lsp)
+static void
+nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_state *lsp)
{
struct nfs_release_lockowner_data *data;
struct rpc_message msg = {
@@ -5923,11 +5924,11 @@ static int nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_st
};
if (server->nfs_client->cl_mvops->minor_version != 0)
- return -EINVAL;
+ return;
data = kmalloc(sizeof(*data), GFP_NOFS);
if (!data)
- return -ENOMEM;
+ return;
data->lsp = lsp;
data->server = server;
data->args.lock_owner.clientid = server->nfs_client->cl_clientid;
@@ -5938,7 +5939,6 @@ static int nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_st
msg.rpc_resp = &data->res;
nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0);
rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, data);
- return 0;
}
#define XATTR_NAME_NFSV4_ACL "system.nfs4_acl"
@@ -8225,7 +8225,8 @@ static int nfs41_free_stateid(struct nfs_server *server,
return ret;
}
-static int nfs41_free_lock_state(struct nfs_server *server, struct nfs4_lock_state *lsp)
+static void
+nfs41_free_lock_state(struct nfs_server *server, struct nfs4_lock_state *lsp)
{
struct rpc_task *task;
struct rpc_cred *cred = lsp->ls_state->owner->so_cred;
@@ -8233,9 +8234,8 @@ static int nfs41_free_lock_state(struct nfs_server *server, struct nfs4_lock_sta
task = _nfs41_free_stateid(server, &lsp->ls_stateid, cred, false);
nfs4_free_lock_state(server, lsp);
if (IS_ERR(task))
- return PTR_ERR(task);
+ return;
rpc_put_task(task);
- return 0;
}
static bool nfs41_match_stateid(const nfs4_stateid *s1,
--
1.9.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 1/3] nfs4: treat lock owners as opaque values
2014-04-23 18:24 ` [PATCH 1/3] nfs4: treat lock owners as opaque values Jeff Layton
@ 2014-04-23 18:48 ` Trond Myklebust
2014-04-23 19:00 ` Jeff Layton
0 siblings, 1 reply; 7+ messages in thread
From: Trond Myklebust @ 2014-04-23 18:48 UTC (permalink / raw)
To: Layton Jeff; +Cc: linux-nfs
On Apr 23, 2014, at 14:24, Jeff Layton <jlayton@redhat.com> wrote:
> Do the following set of ops with a file on a NFSv4 mount:
>
> exec 3>>$1
> flock -x 3
> exec 3>&-
>
> You'll see the LOCK request go across the wire, but no LOCKU when the
> file is closed. This leads to
>
> What happens is that the fd is passed across a fork, and the final close
> is done in a different process than the opener. That makes
> __nfs4_find_lock_state miss finding the correct lock state because it
> uses the fl_pid as a search key. A new one is created, and the locking
> code treats it as a delegation stateid (because NFS_LOCK_INITIALIZED
> isn't set).
>
> The root cause of this breakage seems to be commit 77041ed9b49a9e
> (NFSv4: Ensure the lockowners are labelled using the fl_owner and/or
> fl_pid).
>
> That changed it so that flock lockowners are allocated based on the
> fl_pid. I think this is incorrect. flock locks should be "owned" by the
> struct file, and that is already accounted for in the fl_owner field of
> the lock request when the vfs layer passes it down.
NACKed for now.
I'll grant you that there are several nice potential cleanups here, but as far as I can tell, flock_make_lock() never sets fl_owner, and neither does anything else in sys_flock().
_________________________________
Trond Myklebust
Linux NFS client maintainer, PrimaryData
trond.myklebust@primarydata.com
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/3] nfs4: treat lock owners as opaque values
2014-04-23 18:48 ` Trond Myklebust
@ 2014-04-23 19:00 ` Jeff Layton
2014-04-24 14:25 ` Jeff Layton
0 siblings, 1 reply; 7+ messages in thread
From: Jeff Layton @ 2014-04-23 19:00 UTC (permalink / raw)
To: Trond Myklebust; +Cc: linux-nfs
On Wed, 23 Apr 2014 14:48:08 -0400
Trond Myklebust <trond.myklebust@primarydata.com> wrote:
>
> On Apr 23, 2014, at 14:24, Jeff Layton <jlayton@redhat.com> wrote:
>
> > Do the following set of ops with a file on a NFSv4 mount:
> >
> > exec 3>>$1
> > flock -x 3
> > exec 3>&-
> >
> > You'll see the LOCK request go across the wire, but no LOCKU when the
> > file is closed. This leads to
> >
> > What happens is that the fd is passed across a fork, and the final close
> > is done in a different process than the opener. That makes
> > __nfs4_find_lock_state miss finding the correct lock state because it
> > uses the fl_pid as a search key. A new one is created, and the locking
> > code treats it as a delegation stateid (because NFS_LOCK_INITIALIZED
> > isn't set).
> >
> > The root cause of this breakage seems to be commit 77041ed9b49a9e
> > (NFSv4: Ensure the lockowners are labelled using the fl_owner and/or
> > fl_pid).
> >
> > That changed it so that flock lockowners are allocated based on the
> > fl_pid. I think this is incorrect. flock locks should be "owned" by the
> > struct file, and that is already accounted for in the fl_owner field of
> > the lock request when the vfs layer passes it down.
>
> NACKed for now.
>
> I'll grant you that there are several nice potential cleanups here, but as far as I can tell, flock_make_lock() never sets fl_owner, and neither does anything else in sys_flock().
>
Ahh right...nfs_flock is what sets that currently. So this patch *does*
work, but I think you're right that we ought to have the generic flock
codepath universally set fl_owner instead.
I'll see if I can make that a bit more consistent for v3.16 and then we
can revisit this one.
Thanks,
--
Jeff Layton <jlayton@redhat.com>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/3] nfs4: treat lock owners as opaque values
2014-04-23 19:00 ` Jeff Layton
@ 2014-04-24 14:25 ` Jeff Layton
0 siblings, 0 replies; 7+ messages in thread
From: Jeff Layton @ 2014-04-24 14:25 UTC (permalink / raw)
To: Trond Myklebust; +Cc: linux-nfs
On Wed, 23 Apr 2014 15:00:23 -0400
Jeff Layton <jlayton@redhat.com> wrote:
> On Wed, 23 Apr 2014 14:48:08 -0400
> Trond Myklebust <trond.myklebust@primarydata.com> wrote:
>
> >
> > On Apr 23, 2014, at 14:24, Jeff Layton <jlayton@redhat.com> wrote:
> >
> > > Do the following set of ops with a file on a NFSv4 mount:
> > >
> > > exec 3>>$1
> > > flock -x 3
> > > exec 3>&-
> > >
> > > You'll see the LOCK request go across the wire, but no LOCKU when the
> > > file is closed. This leads to
> > >
> > > What happens is that the fd is passed across a fork, and the final close
> > > is done in a different process than the opener. That makes
> > > __nfs4_find_lock_state miss finding the correct lock state because it
> > > uses the fl_pid as a search key. A new one is created, and the locking
> > > code treats it as a delegation stateid (because NFS_LOCK_INITIALIZED
> > > isn't set).
> > >
> > > The root cause of this breakage seems to be commit 77041ed9b49a9e
> > > (NFSv4: Ensure the lockowners are labelled using the fl_owner and/or
> > > fl_pid).
> > >
> > > That changed it so that flock lockowners are allocated based on the
> > > fl_pid. I think this is incorrect. flock locks should be "owned" by the
> > > struct file, and that is already accounted for in the fl_owner field of
> > > the lock request when the vfs layer passes it down.
> >
> > NACKed for now.
> >
> > I'll grant you that there are several nice potential cleanups here, but as far as I can tell, flock_make_lock() never sets fl_owner, and neither does anything else in sys_flock().
> >
>
> Ahh right...nfs_flock is what sets that currently. So this patch *does*
> work, but I think you're right that we ought to have the generic flock
> codepath universally set fl_owner instead.
>
> I'll see if I can make that a bit more consistent for v3.16 and then we
> can revisit this one.
>
BTW, any thoughts on the second patch in this series? It's not really
dependent on the first, and it does fix a bug where we're trying to do
a __GFP_WAIT allocation under a spinlock.
Thanks,
--
Jeff Layton <jlayton@poochiereds.net>
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2014-04-24 14:33 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-04-23 18:24 [PATCH 0/3] nfs4: file locking fixes and cleanups Jeff Layton
2014-04-23 18:24 ` [PATCH 1/3] nfs4: treat lock owners as opaque values Jeff Layton
2014-04-23 18:48 ` Trond Myklebust
2014-04-23 19:00 ` Jeff Layton
2014-04-24 14:25 ` Jeff Layton
2014-04-23 18:24 ` [PATCH 2/3] nfs4: queue free_lock_state job submission to nfsiod Jeff Layton
2014-04-23 18:25 ` [PATCH 3/3] nfs4: turn free_lock_state into a void return operation 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).