Skip to content

Commit

Permalink
NFSv4: Make the NFS state model work with the nosharedcache mount option
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Trond Myklebust authored and Trond Myklebust committed Jul 11, 2007
1 parent 275a5d2 commit 6f2e64d
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 2 deletions.
1 change: 1 addition & 0 deletions fs/nfs/nfs4_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ struct nfs_unique_id {
struct nfs4_state_owner {
struct nfs_unique_id so_owner_id;
struct nfs_client *so_client;
struct nfs_server *so_server;
struct rb_node so_client_node;

struct rpc_cred *so_cred; /* Associated cred */
Expand Down
22 changes: 20 additions & 2 deletions fs/nfs/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,9 @@ static void nfs_free_unique_id(struct rb_root *root, struct nfs_unique_id *id)
}

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,
*parent = NULL;
struct nfs4_state_owner *sp, *res = NULL;
Expand All @@ -166,6 +167,14 @@ nfs4_find_state_owner(struct nfs_client *clp, struct rpc_cred *cred)
parent = *p;
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)
p = &parent->rb_left;
else if (cred > sp->so_cred)
Expand All @@ -190,6 +199,14 @@ nfs4_insert_state_owner(struct nfs_client *clp, struct nfs4_state_owner *new)
parent = *p;
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)
p = &parent->rb_left;
else if (new->so_cred > sp->so_cred)
Expand Down Expand Up @@ -260,14 +277,15 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct
struct nfs4_state_owner *sp, *new;

spin_lock(&clp->cl_lock);
sp = nfs4_find_state_owner(clp, cred);
sp = nfs4_find_state_owner(server, cred);
spin_unlock(&clp->cl_lock);
if (sp != NULL)
return sp;
new = nfs4_alloc_state_owner();
if (new == NULL)
return NULL;
new->so_client = clp;
new->so_server = server;
new->so_cred = cred;
spin_lock(&clp->cl_lock);
sp = nfs4_insert_state_owner(clp, new);
Expand Down

0 comments on commit 6f2e64d

Please sign in to comment.