diff options
author | J. Bruce Fields <bfields@citi.umich.edu> | 2010-07-08 11:02:09 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2010-07-29 18:19:23 -0400 |
commit | f9d7562fdb9dc0ada3a7aba5dbbe9d965e2a105d (patch) | |
tree | bbeb32b2cc49b6c6dafae57331a680b906017b6e /fs/nfsd/state.h | |
parent | 02921914170e3b7fea1cd82dac9713685d2de5e2 (diff) |
nfsd4: share file descriptors between stateid's
The vfs doesn't really allow us to "upgrade" a file descriptor from
read-only to read-write, and our attempt to do so in nfs4_upgrade_open
is ugly and incomplete.
Move to a different scheme where we keep multiple opens, shared between
open stateid's, in the nfs4_file struct. Each file will be opened at
most 3 times (for read, write, and read-write), and those opens will be
shared between all clients and openers. On upgrade we will do another
open if necessary instead of attempting to upgrade an existing open.
We keep count of the number of readers and writers so we know when to
close the shared files.
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'fs/nfsd/state.h')
-rw-r--r-- | fs/nfsd/state.h | 40 |
1 files changed, 38 insertions, 2 deletions
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 006c84230c7c..7731a75971dd 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h | |||
@@ -88,7 +88,6 @@ struct nfs4_delegation { | |||
88 | struct nfs4_client *dl_client; | 88 | struct nfs4_client *dl_client; |
89 | struct nfs4_file *dl_file; | 89 | struct nfs4_file *dl_file; |
90 | struct file_lock *dl_flock; | 90 | struct file_lock *dl_flock; |
91 | struct file *dl_vfs_file; | ||
92 | u32 dl_type; | 91 | u32 dl_type; |
93 | time_t dl_time; | 92 | time_t dl_time; |
94 | /* For recall: */ | 93 | /* For recall: */ |
@@ -342,12 +341,50 @@ struct nfs4_file { | |||
342 | struct list_head fi_hash; /* hash by "struct inode *" */ | 341 | struct list_head fi_hash; /* hash by "struct inode *" */ |
343 | struct list_head fi_stateids; | 342 | struct list_head fi_stateids; |
344 | struct list_head fi_delegations; | 343 | struct list_head fi_delegations; |
344 | /* One each for O_RDONLY, O_WRONLY, O_RDWR: */ | ||
345 | struct file * fi_fds[3]; | ||
346 | /* One each for O_RDONLY, O_WRONLY: */ | ||
347 | atomic_t fi_access[2]; | ||
348 | /* | ||
349 | * Each open stateid contributes 1 to either fi_readers or | ||
350 | * fi_writers, or both, depending on the open mode. A | ||
351 | * delegation also takes an fi_readers reference. Lock | ||
352 | * stateid's take none. | ||
353 | */ | ||
354 | atomic_t fi_readers; | ||
355 | atomic_t fi_writers; | ||
345 | struct inode *fi_inode; | 356 | struct inode *fi_inode; |
346 | u32 fi_id; /* used with stateowner->so_id | 357 | u32 fi_id; /* used with stateowner->so_id |
347 | * for stateid_hashtbl hash */ | 358 | * for stateid_hashtbl hash */ |
348 | bool fi_had_conflict; | 359 | bool fi_had_conflict; |
349 | }; | 360 | }; |
350 | 361 | ||
362 | /* XXX: for first cut may fall back on returning file that doesn't work | ||
363 | * at all? */ | ||
364 | static inline struct file *find_writeable_file(struct nfs4_file *f) | ||
365 | { | ||
366 | if (f->fi_fds[O_RDWR]) | ||
367 | return f->fi_fds[O_RDWR]; | ||
368 | return f->fi_fds[O_WRONLY]; | ||
369 | } | ||
370 | |||
371 | static inline struct file *find_readable_file(struct nfs4_file *f) | ||
372 | { | ||
373 | if (f->fi_fds[O_RDWR]) | ||
374 | return f->fi_fds[O_RDWR]; | ||
375 | return f->fi_fds[O_RDONLY]; | ||
376 | } | ||
377 | |||
378 | static inline struct file *find_any_file(struct nfs4_file *f) | ||
379 | { | ||
380 | if (f->fi_fds[O_RDWR]) | ||
381 | return f->fi_fds[O_RDWR]; | ||
382 | else if (f->fi_fds[O_RDWR]) | ||
383 | return f->fi_fds[O_WRONLY]; | ||
384 | else | ||
385 | return f->fi_fds[O_RDONLY]; | ||
386 | } | ||
387 | |||
351 | /* | 388 | /* |
352 | * nfs4_stateid can either be an open stateid or (eventually) a lock stateid | 389 | * nfs4_stateid can either be an open stateid or (eventually) a lock stateid |
353 | * | 390 | * |
@@ -373,7 +410,6 @@ struct nfs4_stateid { | |||
373 | struct nfs4_stateowner * st_stateowner; | 410 | struct nfs4_stateowner * st_stateowner; |
374 | struct nfs4_file * st_file; | 411 | struct nfs4_file * st_file; |
375 | stateid_t st_stateid; | 412 | stateid_t st_stateid; |
376 | struct file * st_vfs_file; | ||
377 | unsigned long st_access_bmap; | 413 | unsigned long st_access_bmap; |
378 | unsigned long st_deny_bmap; | 414 | unsigned long st_deny_bmap; |
379 | struct nfs4_stateid * st_openstp; | 415 | struct nfs4_stateid * st_openstp; |