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.c220
1 files changed, 80 insertions, 140 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 6bbefd06f10d..1143cfb64549 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1088,7 +1088,7 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
1088 sop->so_seqid = open->op_seqid; 1088 sop->so_seqid = open->op_seqid;
1089 sop->so_confirmed = 0; 1089 sop->so_confirmed = 0;
1090 rp = &sop->so_replay; 1090 rp = &sop->so_replay;
1091 rp->rp_status = NFSERR_SERVERFAULT; 1091 rp->rp_status = nfserr_serverfault;
1092 rp->rp_buflen = 0; 1092 rp->rp_buflen = 0;
1093 rp->rp_buf = rp->rp_ibuf; 1093 rp->rp_buf = rp->rp_ibuf;
1094 return sop; 1094 return sop;
@@ -1178,7 +1178,6 @@ release_stateid(struct nfs4_stateid *stp, int flags)
1178 locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner); 1178 locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner);
1179 put_nfs4_file(stp->st_file); 1179 put_nfs4_file(stp->st_file);
1180 kmem_cache_free(stateid_slab, stp); 1180 kmem_cache_free(stateid_slab, stp);
1181 stp = NULL;
1182} 1181}
1183 1182
1184static void 1183static void
@@ -1191,22 +1190,6 @@ move_to_close_lru(struct nfs4_stateowner *sop)
1191 sop->so_time = get_seconds(); 1190 sop->so_time = get_seconds();
1192} 1191}
1193 1192
1194static void
1195release_state_owner(struct nfs4_stateid *stp, int flag)
1196{
1197 struct nfs4_stateowner *sop = stp->st_stateowner;
1198
1199 dprintk("NFSD: release_state_owner\n");
1200 release_stateid(stp, flag);
1201
1202 /* place unused nfs4_stateowners on so_close_lru list to be
1203 * released by the laundromat service after the lease period
1204 * to enable us to handle CLOSE replay
1205 */
1206 if (sop->so_confirmed && list_empty(&sop->so_stateids))
1207 move_to_close_lru(sop);
1208}
1209
1210static int 1193static int
1211cmp_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner, clientid_t *clid) { 1194cmp_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner, clientid_t *clid) {
1212 return ((sop->so_owner.len == owner->len) && 1195 return ((sop->so_owner.len == owner->len) &&
@@ -1446,92 +1429,61 @@ static struct lock_manager_operations nfsd_lease_mng_ops = {
1446}; 1429};
1447 1430
1448 1431
1449/*
1450 * nfsd4_process_open1()
1451 * lookup stateowner.
1452 * found:
1453 * check confirmed
1454 * confirmed:
1455 * check seqid
1456 * not confirmed:
1457 * delete owner
1458 * create new owner
1459 * notfound:
1460 * verify clientid
1461 * create new owner
1462 *
1463 * called with nfs4_lock_state() held.
1464 */
1465int 1432int
1466nfsd4_process_open1(struct nfsd4_open *open) 1433nfsd4_process_open1(struct nfsd4_open *open)
1467{ 1434{
1468 int status;
1469 clientid_t *clientid = &open->op_clientid; 1435 clientid_t *clientid = &open->op_clientid;
1470 struct nfs4_client *clp = NULL; 1436 struct nfs4_client *clp = NULL;
1471 unsigned int strhashval; 1437 unsigned int strhashval;
1472 struct nfs4_stateowner *sop = NULL; 1438 struct nfs4_stateowner *sop = NULL;
1473 1439
1474 status = nfserr_inval;
1475 if (!check_name(open->op_owner)) 1440 if (!check_name(open->op_owner))
1476 goto out; 1441 return nfserr_inval;
1477 1442
1478 if (STALE_CLIENTID(&open->op_clientid)) 1443 if (STALE_CLIENTID(&open->op_clientid))
1479 return nfserr_stale_clientid; 1444 return nfserr_stale_clientid;
1480 1445
1481 strhashval = ownerstr_hashval(clientid->cl_id, open->op_owner); 1446 strhashval = ownerstr_hashval(clientid->cl_id, open->op_owner);
1482 sop = find_openstateowner_str(strhashval, open); 1447 sop = find_openstateowner_str(strhashval, open);
1483 if (sop) { 1448 open->op_stateowner = sop;
1484 open->op_stateowner = sop; 1449 if (!sop) {
1485 /* check for replay */ 1450 /* Make sure the client's lease hasn't expired. */
1486 if (open->op_seqid == sop->so_seqid - 1){
1487 if (sop->so_replay.rp_buflen)
1488 return NFSERR_REPLAY_ME;
1489 else {
1490 /* The original OPEN failed so spectacularly
1491 * that we don't even have replay data saved!
1492 * Therefore, we have no choice but to continue
1493 * processing this OPEN; presumably, we'll
1494 * fail again for the same reason.
1495 */
1496 dprintk("nfsd4_process_open1:"
1497 " replay with no replay cache\n");
1498 goto renew;
1499 }
1500 } else if (sop->so_confirmed) {
1501 if (open->op_seqid == sop->so_seqid)
1502 goto renew;
1503 status = nfserr_bad_seqid;
1504 goto out;
1505 } else {
1506 /* If we get here, we received an OPEN for an
1507 * unconfirmed nfs4_stateowner. Since the seqid's are
1508 * different, purge the existing nfs4_stateowner, and
1509 * instantiate a new one.
1510 */
1511 clp = sop->so_client;
1512 release_stateowner(sop);
1513 }
1514 } else {
1515 /* nfs4_stateowner not found.
1516 * Verify clientid and instantiate new nfs4_stateowner.
1517 * If verify fails this is presumably the result of the
1518 * client's lease expiring.
1519 */
1520 status = nfserr_expired;
1521 clp = find_confirmed_client(clientid); 1451 clp = find_confirmed_client(clientid);
1522 if (clp == NULL) 1452 if (clp == NULL)
1523 goto out; 1453 return nfserr_expired;
1454 goto renew;
1524 } 1455 }
1525 status = nfserr_resource; 1456 if (!sop->so_confirmed) {
1526 sop = alloc_init_open_stateowner(strhashval, clp, open); 1457 /* Replace unconfirmed owners without checking for replay. */
1527 if (sop == NULL) 1458 clp = sop->so_client;
1528 goto out; 1459 release_stateowner(sop);
1529 open->op_stateowner = sop; 1460 open->op_stateowner = NULL;
1461 goto renew;
1462 }
1463 if (open->op_seqid == sop->so_seqid - 1) {
1464 if (sop->so_replay.rp_buflen)
1465 return NFSERR_REPLAY_ME;
1466 /* The original OPEN failed so spectacularly
1467 * that we don't even have replay data saved!
1468 * Therefore, we have no choice but to continue
1469 * processing this OPEN; presumably, we'll
1470 * fail again for the same reason.
1471 */
1472 dprintk("nfsd4_process_open1: replay with no replay cache\n");
1473 goto renew;
1474 }
1475 if (open->op_seqid != sop->so_seqid)
1476 return nfserr_bad_seqid;
1530renew: 1477renew:
1531 status = nfs_ok; 1478 if (open->op_stateowner == NULL) {
1479 sop = alloc_init_open_stateowner(strhashval, clp, open);
1480 if (sop == NULL)
1481 return nfserr_resource;
1482 open->op_stateowner = sop;
1483 }
1484 list_del_init(&sop->so_close_lru);
1532 renew_client(sop->so_client); 1485 renew_client(sop->so_client);
1533out: 1486 return nfs_ok;
1534 return status;
1535} 1487}
1536 1488
1537static inline int 1489static inline int
@@ -1648,7 +1600,7 @@ nfsd4_truncate(struct svc_rqst *rqstp, struct svc_fh *fh,
1648 if (!open->op_truncate) 1600 if (!open->op_truncate)
1649 return 0; 1601 return 0;
1650 if (!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE)) 1602 if (!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
1651 return -EINVAL; 1603 return nfserr_inval;
1652 return nfsd_setattr(rqstp, fh, &iattr, 0, (time_t)0); 1604 return nfsd_setattr(rqstp, fh, &iattr, 0, (time_t)0);
1653} 1605}
1654 1606
@@ -1657,26 +1609,26 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_sta
1657{ 1609{
1658 struct file *filp = stp->st_vfs_file; 1610 struct file *filp = stp->st_vfs_file;
1659 struct inode *inode = filp->f_dentry->d_inode; 1611 struct inode *inode = filp->f_dentry->d_inode;
1660 unsigned int share_access; 1612 unsigned int share_access, new_writer;
1661 int status; 1613 int status;
1662 1614
1663 set_access(&share_access, stp->st_access_bmap); 1615 set_access(&share_access, stp->st_access_bmap);
1664 share_access = ~share_access; 1616 new_writer = (~share_access) & open->op_share_access
1665 share_access &= open->op_share_access; 1617 & NFS4_SHARE_ACCESS_WRITE;
1666
1667 if (!(share_access & NFS4_SHARE_ACCESS_WRITE))
1668 return nfsd4_truncate(rqstp, cur_fh, open);
1669 1618
1670 status = get_write_access(inode); 1619 if (new_writer) {
1671 if (status) 1620 status = get_write_access(inode);
1672 return nfserrno(status); 1621 if (status)
1622 return nfserrno(status);
1623 }
1673 status = nfsd4_truncate(rqstp, cur_fh, open); 1624 status = nfsd4_truncate(rqstp, cur_fh, open);
1674 if (status) { 1625 if (status) {
1675 put_write_access(inode); 1626 if (new_writer)
1627 put_write_access(inode);
1676 return status; 1628 return status;
1677 } 1629 }
1678 /* remember the open */ 1630 /* remember the open */
1679 filp->f_mode = (filp->f_mode | FMODE_WRITE) & ~FMODE_READ; 1631 filp->f_mode |= open->op_share_access;
1680 set_bit(open->op_share_access, &stp->st_access_bmap); 1632 set_bit(open->op_share_access, &stp->st_access_bmap);
1681 set_bit(open->op_share_deny, &stp->st_deny_bmap); 1633 set_bit(open->op_share_deny, &stp->st_deny_bmap);
1682 1634
@@ -1780,12 +1732,6 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
1780 struct nfs4_delegation *dp = NULL; 1732 struct nfs4_delegation *dp = NULL;
1781 int status; 1733 int status;
1782 1734
1783 if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
1784 return nfserr_grace;
1785
1786 if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
1787 return nfserr_no_grace;
1788
1789 status = nfserr_inval; 1735 status = nfserr_inval;
1790 if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny)) 1736 if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny))
1791 goto out; 1737 goto out;
@@ -2423,15 +2369,19 @@ nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_clos
2423 CHECK_FH | OPEN_STATE | CLOSE_STATE, 2369 CHECK_FH | OPEN_STATE | CLOSE_STATE,
2424 &close->cl_stateowner, &stp, NULL))) 2370 &close->cl_stateowner, &stp, NULL)))
2425 goto out; 2371 goto out;
2426 /*
2427 * Return success, but first update the stateid.
2428 */
2429 status = nfs_ok; 2372 status = nfs_ok;
2430 update_stateid(&stp->st_stateid); 2373 update_stateid(&stp->st_stateid);
2431 memcpy(&close->cl_stateid, &stp->st_stateid, sizeof(stateid_t)); 2374 memcpy(&close->cl_stateid, &stp->st_stateid, sizeof(stateid_t));
2432 2375
2433 /* release_state_owner() calls nfsd_close() if needed */ 2376 /* release_stateid() calls nfsd_close() if needed */
2434 release_state_owner(stp, OPEN_STATE); 2377 release_stateid(stp, OPEN_STATE);
2378
2379 /* place unused nfs4_stateowners on so_close_lru list to be
2380 * released by the laundromat service after the lease period
2381 * to enable us to handle CLOSE replay
2382 */
2383 if (list_empty(&close->cl_stateowner->so_stateids))
2384 move_to_close_lru(close->cl_stateowner);
2435out: 2385out:
2436 if (close->cl_stateowner) { 2386 if (close->cl_stateowner) {
2437 nfs4_get_stateowner(close->cl_stateowner); 2387 nfs4_get_stateowner(close->cl_stateowner);
@@ -2633,7 +2583,7 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
2633 sop->so_seqid = lock->lk_new_lock_seqid + 1; 2583 sop->so_seqid = lock->lk_new_lock_seqid + 1;
2634 sop->so_confirmed = 1; 2584 sop->so_confirmed = 1;
2635 rp = &sop->so_replay; 2585 rp = &sop->so_replay;
2636 rp->rp_status = NFSERR_SERVERFAULT; 2586 rp->rp_status = nfserr_serverfault;
2637 rp->rp_buflen = 0; 2587 rp->rp_buflen = 0;
2638 rp->rp_buf = rp->rp_ibuf; 2588 rp->rp_buf = rp->rp_ibuf;
2639 return sop; 2589 return sop;
@@ -2700,6 +2650,11 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2700 if (check_lock_length(lock->lk_offset, lock->lk_length)) 2650 if (check_lock_length(lock->lk_offset, lock->lk_length))
2701 return nfserr_inval; 2651 return nfserr_inval;
2702 2652
2653 if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) {
2654 dprintk("NFSD: nfsd4_lock: permission denied!\n");
2655 return status;
2656 }
2657
2703 nfs4_lock_state(); 2658 nfs4_lock_state();
2704 2659
2705 if (lock->lk_is_new) { 2660 if (lock->lk_is_new) {
@@ -2720,11 +2675,11 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2720 lock->lk_new_open_seqid, 2675 lock->lk_new_open_seqid,
2721 &lock->lk_new_open_stateid, 2676 &lock->lk_new_open_stateid,
2722 CHECK_FH | OPEN_STATE, 2677 CHECK_FH | OPEN_STATE,
2723 &lock->lk_stateowner, &open_stp, 2678 &lock->lk_replay_owner, &open_stp,
2724 lock); 2679 lock);
2725 if (status) 2680 if (status)
2726 goto out; 2681 goto out;
2727 open_sop = lock->lk_stateowner; 2682 open_sop = lock->lk_replay_owner;
2728 /* create lockowner and lock stateid */ 2683 /* create lockowner and lock stateid */
2729 fp = open_stp->st_file; 2684 fp = open_stp->st_file;
2730 strhashval = lock_ownerstr_hashval(fp->fi_inode, 2685 strhashval = lock_ownerstr_hashval(fp->fi_inode,
@@ -2739,29 +2694,22 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2739 if (lock_sop == NULL) 2694 if (lock_sop == NULL)
2740 goto out; 2695 goto out;
2741 lock_stp = alloc_init_lock_stateid(lock_sop, fp, open_stp); 2696 lock_stp = alloc_init_lock_stateid(lock_sop, fp, open_stp);
2742 if (lock_stp == NULL) { 2697 if (lock_stp == NULL)
2743 release_stateowner(lock_sop);
2744 goto out; 2698 goto out;
2745 }
2746 } else { 2699 } else {
2747 /* lock (lock owner + lock stateid) already exists */ 2700 /* lock (lock owner + lock stateid) already exists */
2748 status = nfs4_preprocess_seqid_op(current_fh, 2701 status = nfs4_preprocess_seqid_op(current_fh,
2749 lock->lk_old_lock_seqid, 2702 lock->lk_old_lock_seqid,
2750 &lock->lk_old_lock_stateid, 2703 &lock->lk_old_lock_stateid,
2751 CHECK_FH | LOCK_STATE, 2704 CHECK_FH | LOCK_STATE,
2752 &lock->lk_stateowner, &lock_stp, lock); 2705 &lock->lk_replay_owner, &lock_stp, lock);
2753 if (status) 2706 if (status)
2754 goto out; 2707 goto out;
2755 lock_sop = lock->lk_stateowner; 2708 lock_sop = lock->lk_replay_owner;
2756 } 2709 }
2757 /* lock->lk_stateowner and lock_stp have been created or found */ 2710 /* lock->lk_replay_owner and lock_stp have been created or found */
2758 filp = lock_stp->st_vfs_file; 2711 filp = lock_stp->st_vfs_file;
2759 2712
2760 if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) {
2761 dprintk("NFSD: nfsd4_lock: permission denied!\n");
2762 goto out;
2763 }
2764
2765 status = nfserr_grace; 2713 status = nfserr_grace;
2766 if (nfs4_in_grace() && !lock->lk_reclaim) 2714 if (nfs4_in_grace() && !lock->lk_reclaim)
2767 goto out; 2715 goto out;
@@ -2802,8 +2750,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2802 */ 2750 */
2803 2751
2804 status = posix_lock_file(filp, &file_lock); 2752 status = posix_lock_file(filp, &file_lock);
2805 if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
2806 file_lock.fl_ops->fl_release_private(&file_lock);
2807 dprintk("NFSD: nfsd4_lock: posix_lock_file status %d\n",status); 2753 dprintk("NFSD: nfsd4_lock: posix_lock_file status %d\n",status);
2808 switch (-status) { 2754 switch (-status) {
2809 case 0: /* success! */ 2755 case 0: /* success! */
@@ -2815,9 +2761,12 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2815 goto conflicting_lock; 2761 goto conflicting_lock;
2816 case (EDEADLK): 2762 case (EDEADLK):
2817 status = nfserr_deadlock; 2763 status = nfserr_deadlock;
2764 dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status);
2765 goto out;
2818 default: 2766 default:
2767 status = nfserrno(status);
2819 dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status); 2768 dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status);
2820 goto out_destroy_new_stateid; 2769 goto out;
2821 } 2770 }
2822 2771
2823conflicting_lock: 2772conflicting_lock:
@@ -2831,20 +2780,12 @@ conflicting_lock:
2831 goto out; 2780 goto out;
2832 } 2781 }
2833 nfs4_set_lock_denied(conflock, &lock->lk_denied); 2782 nfs4_set_lock_denied(conflock, &lock->lk_denied);
2834
2835out_destroy_new_stateid:
2836 if (lock->lk_is_new) {
2837 dprintk("NFSD: nfsd4_lock: destroy new stateid!\n");
2838 /*
2839 * An error encountered after instantiation of the new
2840 * stateid has forced us to destroy it.
2841 */
2842 release_state_owner(lock_stp, LOCK_STATE);
2843 }
2844out: 2783out:
2845 if (lock->lk_stateowner) { 2784 if (status && lock->lk_is_new && lock_sop)
2846 nfs4_get_stateowner(lock->lk_stateowner); 2785 release_stateowner(lock_sop);
2847 *replay_owner = lock->lk_stateowner; 2786 if (lock->lk_replay_owner) {
2787 nfs4_get_stateowner(lock->lk_replay_owner);
2788 *replay_owner = lock->lk_replay_owner;
2848 } 2789 }
2849 nfs4_unlock_state(); 2790 nfs4_unlock_state();
2850 return status; 2791 return status;
@@ -2977,8 +2918,6 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2977 * Try to unlock the file in the VFS. 2918 * Try to unlock the file in the VFS.
2978 */ 2919 */
2979 status = posix_lock_file(filp, &file_lock); 2920 status = posix_lock_file(filp, &file_lock);
2980 if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
2981 file_lock.fl_ops->fl_release_private(&file_lock);
2982 if (status) { 2921 if (status) {
2983 dprintk("NFSD: nfs4_locku: posix_lock_file failed!\n"); 2922 dprintk("NFSD: nfs4_locku: posix_lock_file failed!\n");
2984 goto out_nfserr; 2923 goto out_nfserr;
@@ -3016,9 +2955,10 @@ check_for_locks(struct file *filp, struct nfs4_stateowner *lowner)
3016 2955
3017 lock_kernel(); 2956 lock_kernel();
3018 for (flpp = &inode->i_flock; *flpp != NULL; flpp = &(*flpp)->fl_next) { 2957 for (flpp = &inode->i_flock; *flpp != NULL; flpp = &(*flpp)->fl_next) {
3019 if ((*flpp)->fl_owner == (fl_owner_t)lowner) 2958 if ((*flpp)->fl_owner == (fl_owner_t)lowner) {
3020 status = 1; 2959 status = 1;
3021 goto out; 2960 goto out;
2961 }
3022 } 2962 }
3023out: 2963out:
3024 unlock_kernel(); 2964 unlock_kernel();