Commit 6f2e64d3e1f661095e274c9d9d47e3f39a6cf1c0

Authored by Trond Myklebust
1 parent 275a5d24bf

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>

Showing 2 changed files with 21 additions and 2 deletions Side-by-side Diff

... ... @@ -83,6 +83,7 @@
83 83 struct nfs4_state_owner {
84 84 struct nfs_unique_id so_owner_id;
85 85 struct nfs_client *so_client;
  86 + struct nfs_server *so_server;
86 87 struct rb_node so_client_node;
87 88  
88 89 struct rpc_cred *so_cred; /* Associated cred */
... ... @@ -156,8 +156,9 @@
156 156 }
157 157  
158 158 static struct nfs4_state_owner *
159   -nfs4_find_state_owner(struct nfs_client *clp, struct rpc_cred *cred)
  159 +nfs4_find_state_owner(struct nfs_server *server, struct rpc_cred *cred)
160 160 {
  161 + struct nfs_client *clp = server->nfs_client;
161 162 struct rb_node **p = &clp->cl_state_owners.rb_node,
162 163 *parent = NULL;
163 164 struct nfs4_state_owner *sp, *res = NULL;
... ... @@ -166,6 +167,14 @@
166 167 parent = *p;
167 168 sp = rb_entry(parent, struct nfs4_state_owner, so_client_node);
168 169  
  170 + if (server < sp->so_server) {
  171 + p = &parent->rb_left;
  172 + continue;
  173 + }
  174 + if (server > sp->so_server) {
  175 + p = &parent->rb_right;
  176 + continue;
  177 + }
169 178 if (cred < sp->so_cred)
170 179 p = &parent->rb_left;
171 180 else if (cred > sp->so_cred)
... ... @@ -190,6 +199,14 @@
190 199 parent = *p;
191 200 sp = rb_entry(parent, struct nfs4_state_owner, so_client_node);
192 201  
  202 + if (new->so_server < sp->so_server) {
  203 + p = &parent->rb_left;
  204 + continue;
  205 + }
  206 + if (new->so_server > sp->so_server) {
  207 + p = &parent->rb_right;
  208 + continue;
  209 + }
193 210 if (new->so_cred < sp->so_cred)
194 211 p = &parent->rb_left;
195 212 else if (new->so_cred > sp->so_cred)
... ... @@ -260,7 +277,7 @@
260 277 struct nfs4_state_owner *sp, *new;
261 278  
262 279 spin_lock(&clp->cl_lock);
263   - sp = nfs4_find_state_owner(clp, cred);
  280 + sp = nfs4_find_state_owner(server, cred);
264 281 spin_unlock(&clp->cl_lock);
265 282 if (sp != NULL)
266 283 return sp;
... ... @@ -268,6 +285,7 @@
268 285 if (new == NULL)
269 286 return NULL;
270 287 new->so_client = clp;
  288 + new->so_server = server;
271 289 new->so_cred = cred;
272 290 spin_lock(&clp->cl_lock);
273 291 sp = nfs4_insert_state_owner(clp, new);