NFSv4: Make the NFS state model work with the nosharedcache mount option
Consider the case where the user has mounted the remote filesystem server:/foo on the two local directories /bar and /baz using the nosharedcache mount option. The files /bar/file and /baz/file are represented by different inodes in the local namespace, but refer to the same file /foo/file on the server. Consider the case where a process opens both /bar/file and /baz/file, then closes /bar/file: because the nfs4_state is not shared between /bar/file and /baz/file, the kernel will see that the nfs4_state for /bar/file is no longer referenced, so it will send off a CLOSE rpc call. Unless the open_owners differ, then that CLOSE call will invalidate the open state on /baz/file too. Conclusion: we cannot share open state owners between two different non-shared mount instances of the same filesystem. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
parent
275a5d24bf
commit
6f2e64d3e1
@ -83,6 +83,7 @@ struct nfs_unique_id {
|
|||||||
struct nfs4_state_owner {
|
struct nfs4_state_owner {
|
||||||
struct nfs_unique_id so_owner_id;
|
struct nfs_unique_id so_owner_id;
|
||||||
struct nfs_client *so_client;
|
struct nfs_client *so_client;
|
||||||
|
struct nfs_server *so_server;
|
||||||
struct rb_node so_client_node;
|
struct rb_node so_client_node;
|
||||||
|
|
||||||
struct rpc_cred *so_cred; /* Associated cred */
|
struct rpc_cred *so_cred; /* Associated cred */
|
||||||
|
@ -156,8 +156,9 @@ static void nfs_free_unique_id(struct rb_root *root, struct nfs_unique_id *id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct nfs4_state_owner *
|
static struct nfs4_state_owner *
|
||||||
nfs4_find_state_owner(struct nfs_client *clp, struct rpc_cred *cred)
|
nfs4_find_state_owner(struct nfs_server *server, struct rpc_cred *cred)
|
||||||
{
|
{
|
||||||
|
struct nfs_client *clp = server->nfs_client;
|
||||||
struct rb_node **p = &clp->cl_state_owners.rb_node,
|
struct rb_node **p = &clp->cl_state_owners.rb_node,
|
||||||
*parent = NULL;
|
*parent = NULL;
|
||||||
struct nfs4_state_owner *sp, *res = NULL;
|
struct nfs4_state_owner *sp, *res = NULL;
|
||||||
@ -166,6 +167,14 @@ nfs4_find_state_owner(struct nfs_client *clp, struct rpc_cred *cred)
|
|||||||
parent = *p;
|
parent = *p;
|
||||||
sp = rb_entry(parent, struct nfs4_state_owner, so_client_node);
|
sp = rb_entry(parent, struct nfs4_state_owner, so_client_node);
|
||||||
|
|
||||||
|
if (server < sp->so_server) {
|
||||||
|
p = &parent->rb_left;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (server > sp->so_server) {
|
||||||
|
p = &parent->rb_right;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (cred < sp->so_cred)
|
if (cred < sp->so_cred)
|
||||||
p = &parent->rb_left;
|
p = &parent->rb_left;
|
||||||
else if (cred > sp->so_cred)
|
else if (cred > sp->so_cred)
|
||||||
@ -190,6 +199,14 @@ nfs4_insert_state_owner(struct nfs_client *clp, struct nfs4_state_owner *new)
|
|||||||
parent = *p;
|
parent = *p;
|
||||||
sp = rb_entry(parent, struct nfs4_state_owner, so_client_node);
|
sp = rb_entry(parent, struct nfs4_state_owner, so_client_node);
|
||||||
|
|
||||||
|
if (new->so_server < sp->so_server) {
|
||||||
|
p = &parent->rb_left;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (new->so_server > sp->so_server) {
|
||||||
|
p = &parent->rb_right;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (new->so_cred < sp->so_cred)
|
if (new->so_cred < sp->so_cred)
|
||||||
p = &parent->rb_left;
|
p = &parent->rb_left;
|
||||||
else if (new->so_cred > sp->so_cred)
|
else if (new->so_cred > sp->so_cred)
|
||||||
@ -260,7 +277,7 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct
|
|||||||
struct nfs4_state_owner *sp, *new;
|
struct nfs4_state_owner *sp, *new;
|
||||||
|
|
||||||
spin_lock(&clp->cl_lock);
|
spin_lock(&clp->cl_lock);
|
||||||
sp = nfs4_find_state_owner(clp, cred);
|
sp = nfs4_find_state_owner(server, cred);
|
||||||
spin_unlock(&clp->cl_lock);
|
spin_unlock(&clp->cl_lock);
|
||||||
if (sp != NULL)
|
if (sp != NULL)
|
||||||
return sp;
|
return sp;
|
||||||
@ -268,6 +285,7 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct
|
|||||||
if (new == NULL)
|
if (new == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
new->so_client = clp;
|
new->so_client = clp;
|
||||||
|
new->so_server = server;
|
||||||
new->so_cred = cred;
|
new->so_cred = cred;
|
||||||
spin_lock(&clp->cl_lock);
|
spin_lock(&clp->cl_lock);
|
||||||
sp = nfs4_insert_state_owner(clp, new);
|
sp = nfs4_insert_state_owner(clp, new);
|
||||||
|
Loading…
Reference in New Issue
Block a user