aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2007-07-06 10:53:21 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-07-10 23:40:48 -0400
commit6f2e64d3e1f661095e274c9d9d47e3f39a6cf1c0 (patch)
tree59bb802bfe2df34ef5666a3d9b7a8f7c21b7247b
parent275a5d24bf56b2d9dd4644c54a56366b89a028f1 (diff)
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>
-rw-r--r--fs/nfs/nfs4_fs.h1
-rw-r--r--fs/nfs/nfs4state.c22
2 files changed, 21 insertions, 2 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index dd1aa2b598ce..6c028e734fe6 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -83,6 +83,7 @@ struct nfs_unique_id {
83struct nfs4_state_owner { 83struct nfs4_state_owner {
84 struct nfs_unique_id so_owner_id; 84 struct nfs_unique_id so_owner_id;
85 struct nfs_client *so_client; 85 struct nfs_client *so_client;
86 struct nfs_server *so_server;
86 struct rb_node so_client_node; 87 struct rb_node so_client_node;
87 88
88 struct rpc_cred *so_cred; /* Associated cred */ 89 struct rpc_cred *so_cred; /* Associated cred */
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 523cc2cbb5e1..e9662ba81d86 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -156,8 +156,9 @@ static void nfs_free_unique_id(struct rb_root *root, struct nfs_unique_id *id)
156} 156}
157 157
158static struct nfs4_state_owner * 158static struct nfs4_state_owner *
159nfs4_find_state_owner(struct nfs_client *clp, struct rpc_cred *cred) 159nfs4_find_state_owner(struct nfs_server *server, struct rpc_cred *cred)
160{ 160{
161 struct nfs_client *clp = server->nfs_client;
161 struct rb_node **p = &clp->cl_state_owners.rb_node, 162 struct rb_node **p = &clp->cl_state_owners.rb_node,
162 *parent = NULL; 163 *parent = NULL;
163 struct nfs4_state_owner *sp, *res = NULL; 164 struct nfs4_state_owner *sp, *res = NULL;
@@ -166,6 +167,14 @@ nfs4_find_state_owner(struct nfs_client *clp, struct rpc_cred *cred)
166 parent = *p; 167 parent = *p;
167 sp = rb_entry(parent, struct nfs4_state_owner, so_client_node); 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 if (cred < sp->so_cred) 178 if (cred < sp->so_cred)
170 p = &parent->rb_left; 179 p = &parent->rb_left;
171 else if (cred > sp->so_cred) 180 else if (cred > sp->so_cred)
@@ -190,6 +199,14 @@ nfs4_insert_state_owner(struct nfs_client *clp, struct nfs4_state_owner *new)
190 parent = *p; 199 parent = *p;
191 sp = rb_entry(parent, struct nfs4_state_owner, so_client_node); 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 if (new->so_cred < sp->so_cred) 210 if (new->so_cred < sp->so_cred)
194 p = &parent->rb_left; 211 p = &parent->rb_left;
195 else if (new->so_cred > sp->so_cred) 212 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
260 struct nfs4_state_owner *sp, *new; 277 struct nfs4_state_owner *sp, *new;
261 278
262 spin_lock(&clp->cl_lock); 279 spin_lock(&clp->cl_lock);
263 sp = nfs4_find_state_owner(clp, cred); 280 sp = nfs4_find_state_owner(server, cred);
264 spin_unlock(&clp->cl_lock); 281 spin_unlock(&clp->cl_lock);
265 if (sp != NULL) 282 if (sp != NULL)
266 return sp; 283 return sp;
@@ -268,6 +285,7 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct
268 if (new == NULL) 285 if (new == NULL)
269 return NULL; 286 return NULL;
270 new->so_client = clp; 287 new->so_client = clp;
288 new->so_server = server;
271 new->so_cred = cred; 289 new->so_cred = cred;
272 spin_lock(&clp->cl_lock); 290 spin_lock(&clp->cl_lock);
273 sp = nfs4_insert_state_owner(clp, new); 291 sp = nfs4_insert_state_owner(clp, new);