diff options
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index e5cba833613f..edcced18caa8 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -194,8 +194,15 @@ static void nfs4_file_put_fd(struct nfs4_file *fp, int oflag) | |||
194 | static void __nfs4_file_put_access(struct nfs4_file *fp, int oflag) | 194 | static void __nfs4_file_put_access(struct nfs4_file *fp, int oflag) |
195 | { | 195 | { |
196 | if (atomic_dec_and_test(&fp->fi_access[oflag])) { | 196 | if (atomic_dec_and_test(&fp->fi_access[oflag])) { |
197 | nfs4_file_put_fd(fp, O_RDWR); | ||
198 | nfs4_file_put_fd(fp, oflag); | 197 | nfs4_file_put_fd(fp, oflag); |
198 | /* | ||
199 | * It's also safe to get rid of the RDWR open *if* | ||
200 | * we no longer have need of the other kind of access | ||
201 | * or if we already have the other kind of open: | ||
202 | */ | ||
203 | if (fp->fi_fds[1-oflag] | ||
204 | || atomic_read(&fp->fi_access[1 - oflag]) == 0) | ||
205 | nfs4_file_put_fd(fp, O_RDWR); | ||
199 | } | 206 | } |
200 | } | 207 | } |
201 | 208 | ||
@@ -3500,8 +3507,9 @@ static inline void nfs4_file_downgrade(struct nfs4_ol_stateid *stp, unsigned int | |||
3500 | int i; | 3507 | int i; |
3501 | 3508 | ||
3502 | for (i = 1; i < 4; i++) { | 3509 | for (i = 1; i < 4; i++) { |
3503 | if (test_bit(i, &stp->st_access_bmap) && !(i & to_access)) { | 3510 | if (test_bit(i, &stp->st_access_bmap) |
3504 | nfs4_file_put_access(stp->st_file, i); | 3511 | && ((i & to_access) != i)) { |
3512 | nfs4_file_put_access(stp->st_file, nfs4_access_to_omode(i)); | ||
3505 | __clear_bit(i, &stp->st_access_bmap); | 3513 | __clear_bit(i, &stp->st_access_bmap); |
3506 | } | 3514 | } |
3507 | } | 3515 | } |