aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4state.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r--fs/nfsd/nfs4state.c49
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 */
1176static void 1194static void
1177set_access(unsigned int *access, unsigned long bmap) { 1195set_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 */
3252static void 3278static void
3253nfs4_set_recdir(char *recdir) 3279nfs4_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
3305char *
3306nfs4_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 */
3290void 3323void
3291nfs4_reset_lease(time_t leasetime) 3324nfs4_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}