diff options
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 49 |
1 files changed, 40 insertions, 9 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 8799b8708188..1578d7a2667e 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -1173,6 +1173,24 @@ static inline int deny_valid(u32 x) | |||
1173 | return x <= NFS4_SHARE_DENY_BOTH; | 1173 | return x <= NFS4_SHARE_DENY_BOTH; |
1174 | } | 1174 | } |
1175 | 1175 | ||
1176 | /* | ||
1177 | * We store the NONE, READ, WRITE, and BOTH bits separately in the | ||
1178 | * st_{access,deny}_bmap field of the stateid, in order to track not | ||
1179 | * only what share bits are currently in force, but also what | ||
1180 | * combinations of share bits previous opens have used. This allows us | ||
1181 | * to enforce the recommendation of rfc 3530 14.2.19 that the server | ||
1182 | * return an error if the client attempt to downgrade to a combination | ||
1183 | * of share bits not explicable by closing some of its previous opens. | ||
1184 | * | ||
1185 | * XXX: This enforcement is actually incomplete, since we don't keep | ||
1186 | * track of access/deny bit combinations; so, e.g., we allow: | ||
1187 | * | ||
1188 | * OPEN allow read, deny write | ||
1189 | * OPEN allow both, deny none | ||
1190 | * DOWNGRADE allow read, deny none | ||
1191 | * | ||
1192 | * which we should reject. | ||
1193 | */ | ||
1176 | static void | 1194 | static void |
1177 | set_access(unsigned int *access, unsigned long bmap) { | 1195 | set_access(unsigned int *access, unsigned long bmap) { |
1178 | int i; | 1196 | int i; |
@@ -1570,6 +1588,10 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_sta | |||
1570 | int err = get_write_access(inode); | 1588 | int err = get_write_access(inode); |
1571 | if (err) | 1589 | if (err) |
1572 | return nfserrno(err); | 1590 | return nfserrno(err); |
1591 | err = mnt_want_write(cur_fh->fh_export->ex_path.mnt); | ||
1592 | if (err) | ||
1593 | return nfserrno(err); | ||
1594 | file_take_write(filp); | ||
1573 | } | 1595 | } |
1574 | status = nfsd4_truncate(rqstp, cur_fh, open); | 1596 | status = nfsd4_truncate(rqstp, cur_fh, open); |
1575 | if (status) { | 1597 | if (status) { |
@@ -1579,8 +1601,8 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_sta | |||
1579 | } | 1601 | } |
1580 | /* remember the open */ | 1602 | /* remember the open */ |
1581 | filp->f_mode |= open->op_share_access; | 1603 | filp->f_mode |= open->op_share_access; |
1582 | set_bit(open->op_share_access, &stp->st_access_bmap); | 1604 | __set_bit(open->op_share_access, &stp->st_access_bmap); |
1583 | set_bit(open->op_share_deny, &stp->st_deny_bmap); | 1605 | __set_bit(open->op_share_deny, &stp->st_deny_bmap); |
1584 | 1606 | ||
1585 | return nfs_ok; | 1607 | return nfs_ok; |
1586 | } | 1608 | } |
@@ -1722,9 +1744,9 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf | |||
1722 | /* Stateid was not found, this is a new OPEN */ | 1744 | /* Stateid was not found, this is a new OPEN */ |
1723 | int flags = 0; | 1745 | int flags = 0; |
1724 | if (open->op_share_access & NFS4_SHARE_ACCESS_READ) | 1746 | if (open->op_share_access & NFS4_SHARE_ACCESS_READ) |
1725 | flags |= MAY_READ; | 1747 | flags |= NFSD_MAY_READ; |
1726 | if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) | 1748 | if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) |
1727 | flags |= MAY_WRITE; | 1749 | flags |= NFSD_MAY_WRITE; |
1728 | status = nfs4_new_open(rqstp, &stp, dp, current_fh, flags); | 1750 | status = nfs4_new_open(rqstp, &stp, dp, current_fh, flags); |
1729 | if (status) | 1751 | if (status) |
1730 | goto out; | 1752 | goto out; |
@@ -2610,7 +2632,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
2610 | return nfserr_inval; | 2632 | return nfserr_inval; |
2611 | 2633 | ||
2612 | if ((status = fh_verify(rqstp, &cstate->current_fh, | 2634 | if ((status = fh_verify(rqstp, &cstate->current_fh, |
2613 | S_IFREG, MAY_LOCK))) { | 2635 | S_IFREG, NFSD_MAY_LOCK))) { |
2614 | dprintk("NFSD: nfsd4_lock: permission denied!\n"); | 2636 | dprintk("NFSD: nfsd4_lock: permission denied!\n"); |
2615 | return status; | 2637 | return status; |
2616 | } | 2638 | } |
@@ -3249,12 +3271,14 @@ nfs4_state_shutdown(void) | |||
3249 | nfs4_unlock_state(); | 3271 | nfs4_unlock_state(); |
3250 | } | 3272 | } |
3251 | 3273 | ||
3274 | /* | ||
3275 | * user_recovery_dirname is protected by the nfsd_mutex since it's only | ||
3276 | * accessed when nfsd is starting. | ||
3277 | */ | ||
3252 | static void | 3278 | static void |
3253 | nfs4_set_recdir(char *recdir) | 3279 | nfs4_set_recdir(char *recdir) |
3254 | { | 3280 | { |
3255 | nfs4_lock_state(); | ||
3256 | strcpy(user_recovery_dirname, recdir); | 3281 | strcpy(user_recovery_dirname, recdir); |
3257 | nfs4_unlock_state(); | ||
3258 | } | 3282 | } |
3259 | 3283 | ||
3260 | /* | 3284 | /* |
@@ -3278,6 +3302,12 @@ nfs4_reset_recoverydir(char *recdir) | |||
3278 | return status; | 3302 | return status; |
3279 | } | 3303 | } |
3280 | 3304 | ||
3305 | char * | ||
3306 | nfs4_recoverydir(void) | ||
3307 | { | ||
3308 | return user_recovery_dirname; | ||
3309 | } | ||
3310 | |||
3281 | /* | 3311 | /* |
3282 | * Called when leasetime is changed. | 3312 | * Called when leasetime is changed. |
3283 | * | 3313 | * |
@@ -3286,11 +3316,12 @@ nfs4_reset_recoverydir(char *recdir) | |||
3286 | * we start to register any changes in lease time. If the administrator | 3316 | * we start to register any changes in lease time. If the administrator |
3287 | * really wants to change the lease time *now*, they can go ahead and bring | 3317 | * really wants to change the lease time *now*, they can go ahead and bring |
3288 | * nfsd down and then back up again after changing the lease time. | 3318 | * nfsd down and then back up again after changing the lease time. |
3319 | * | ||
3320 | * user_lease_time is protected by nfsd_mutex since it's only really accessed | ||
3321 | * when nfsd is starting | ||
3289 | */ | 3322 | */ |
3290 | void | 3323 | void |
3291 | nfs4_reset_lease(time_t leasetime) | 3324 | nfs4_reset_lease(time_t leasetime) |
3292 | { | 3325 | { |
3293 | lock_kernel(); | ||
3294 | user_lease_time = leasetime; | 3326 | user_lease_time = leasetime; |
3295 | unlock_kernel(); | ||
3296 | } | 3327 | } |