Deleted Added
sdiff udiff text old ( 194117 ) new ( 195510 )
full compact
1/*-
2 * Copyright (c) 2009 Rick Macklem, University of Guelph
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 12 unchanged lines hidden (view full) ---

21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD: head/sys/fs/nfsclient/nfs_clstate.c 194117 2009-06-13 15:35:22Z jamie $");
30
31/*
32 * These functions implement the client side state handling for NFSv4.
33 * NFSv4 state handling:
34 * - A lockowner is used to determine lock contention, so it
35 * corresponds directly to a Posix pid. (1 to 1 mapping)
36 * - The correct granularity of an OpenOwner is not nearly so
37 * obvious. An OpenOwner does the following:

--- 407 unchanged lines hidden (view full) ---

445 */
446APPLESTATIC int
447nfscl_getstateid(vnode_t vp, u_int8_t *nfhp, int fhlen, u_int32_t mode,
448 struct ucred *cred, NFSPROC_T *p, nfsv4stateid_t *stateidp,
449 void **lckpp)
450{
451 struct nfsclclient *clp;
452 struct nfsclowner *owp;
453 struct nfsclopen *op;
454 struct nfscllockowner *lp;
455 struct nfscldeleg *dp;
456 struct nfsnode *np;
457 u_int8_t own[NFSV4CL_LOCKNAMELEN];
458 int error, done;
459
460 *lckpp = NULL;
461 /*

--- 45 unchanged lines hidden (view full) ---

507 if (p != NULL) {
508 /*
509 * If p != NULL, we want to search the parentage tree
510 * for a matching OpenOwner and use that.
511 */
512 nfscl_filllockowner(p, own);
513 error = nfscl_getopen(&clp->nfsc_owner, nfhp, fhlen, NULL, p,
514 mode, NULL, &op);
515 if (error) {
516 NFSUNLOCKCLSTATE();
517 return (error);
518 }
519
520 /* now look for a lockowner */
521 LIST_FOREACH(lp, &op->nfso_lock, nfsl_list) {
522 if (!NFSBCMP(lp->nfsl_owner, own, NFSV4CL_LOCKNAMELEN)) {
523 stateidp->seqid = lp->nfsl_stateid.seqid;
524 stateidp->other[0] = lp->nfsl_stateid.other[0];
525 stateidp->other[1] = lp->nfsl_stateid.other[1];
526 stateidp->other[2] = lp->nfsl_stateid.other[2];
527 NFSUNLOCKCLSTATE();
528 return (0);
529 }
530 }
531 } else {
532 /*
533 * If p == NULL, it is a read ahead or write behind,
534 * so just look for any OpenOwner that will work.
535 */
536 done = 0;
537 owp = LIST_FIRST(&clp->nfsc_owner);
538 while (!done && owp != NULL) {
539 LIST_FOREACH(op, &owp->nfsow_open, nfso_list) {
540 if (op->nfso_fhlen == fhlen &&
541 !NFSBCMP(op->nfso_fh, nfhp, fhlen) &&
542 (mode & op->nfso_mode) == mode) {
543 done = 1;
544 break;
545 }
546 }
547 if (!done)
548 owp = LIST_NEXT(owp, nfsow_list);
549 }
550 if (!done) {
551 NFSUNLOCKCLSTATE();
552 return (ENOENT);
553 }
554 /* for read aheads or write behinds, use the open cred */
555 newnfs_copycred(&op->nfso_cred, cred);
556 }

--- 2190 unchanged lines hidden (view full) ---

2747 }
2748 }
2749 NFSUNLOCKCLSTATE();
2750}
2751
2752/*
2753 * During close, find an open that needs to be dereferenced and
2754 * dereference it. If there are no more opens for this file,
2755 * return the list of opens, so they can be closed on the
2756 * server. As such, opens aren't closed on the server until
2757 * all the opens for the file are closed off.
2758 * This is the safe way, since it is difficult to identify
2759 * which open the close is for.
2760 * If it returns 0 for success, there will be a referenced
2761 * clp returned via clpp and a list of opens to close/free
2762 * on ohp.
2763 */
2764APPLESTATIC int
2765nfscl_getclose(vnode_t vp, struct nfsclclient **clpp,
2766 struct nfsclopenhead *ohp)
2767{
2768 struct nfsclclient *clp;
2769 struct nfsclowner *owp, *nowp;
2770 struct nfsclopen *op, *nop;
2771 struct nfscldeleg *dp;
2772 struct nfsfh *nfhp;
2773 int error, notdecr, candelete;
2774
2775 error = nfscl_getcl(vp, NULL, NULL, &clp);
2776 if (error)
2777 return (error);
2778 *clpp = clp;
2779
2780 if (ohp != NULL)
2781 LIST_INIT(ohp);
2782 nfhp = VTONFS(vp)->n_fhp;
2783 notdecr = 1;
2784 NFSLOCKCLSTATE();
2785 /*
2786 * First, look for one under a delegation that was locally issued
2787 * and just decrement the opencnt for it. Since all my Opens against
2788 * the server are DENY_NONE, I don't see a problem with hanging
2789 * onto them. (It is much easier to use one of the extant Opens
2790 * that I already have on the server when a Delegation is recalled
2791 * than to do fresh Opens.) Someday, I might need to rethink this, but..
2792 */
2793 dp = nfscl_finddeleg(clp, nfhp->nfh_fh, nfhp->nfh_len);
2794 if (dp != NULL) {
2795 LIST_FOREACH(owp, &dp->nfsdl_owner, nfsow_list) {
2796 op = LIST_FIRST(&owp->nfsow_open);
2797 if (op != NULL) {
2798 /*
2799 * Since a delegation is for a file, there

--- 8 unchanged lines hidden (view full) ---

2808 break;
2809 }
2810 }
2811 }
2812 }
2813
2814 /* Now process the opens against the server. */
2815 LIST_FOREACH(owp, &clp->nfsc_owner, nfsow_list) {
2816 op = LIST_FIRST(&owp->nfsow_open);
2817 while (op != NULL) {
2818 nop = LIST_NEXT(op, nfso_list);
2819 if (op->nfso_fhlen == nfhp->nfh_len &&
2820 !NFSBCMP(op->nfso_fh, nfhp->nfh_fh,
2821 nfhp->nfh_len)) {
2822 /* Found an open, decrement cnt if possible */
2823 if (notdecr && op->nfso_opencnt > 0) {
2824 notdecr = 0;
2825 op->nfso_opencnt--;
2826 }
2827 /*
2828 * There are more opens, so just return after
2829 * putting any opens already found back in the
2830 * state list.
2831 */
2832 if (op->nfso_opencnt > 0) {
2833 if (ohp != NULL) {
2834 /* Reattach open until later */
2835 op = LIST_FIRST(ohp);
2836 while (op != NULL) {
2837 nop = LIST_NEXT(op, nfso_list);
2838 LIST_REMOVE(op, nfso_list);
2839 LIST_INSERT_HEAD(
2840 &op->nfso_own->nfsow_open,
2841 op, nfso_list);
2842 op = nop;
2843 }
2844 LIST_INIT(ohp);
2845 }
2846 NFSUNLOCKCLSTATE();
2847 return (0);
2848 }
2849
2850 /*
2851 * Move this entry to the list of opens to be
2852 * returned. (If we find other open(s) still in
2853 * use, it will be put back in the state list
2854 * in the code just above.)
2855 */
2856 if (ohp != NULL) {
2857 LIST_REMOVE(op, nfso_list);
2858 LIST_INSERT_HEAD(ohp, op, nfso_list);
2859 }
2860 }
2861 op = nop;
2862 }
2863 }
2864
2865 if (dp != NULL && ohp != NULL) {
2866 /*
2867 * If we are flushing all writes against the server for this
2868 * file upon close, we do not need to keep the local opens
2869 * (against the delegation) if they all have an opencnt == 0,
2870 * since there are now no opens on the file and no dirty blocks.
2871 * If the writes aren't being flushed upon close,
2872 * a test for "no dirty blocks to write back" would have to
2873 * be added to this code.
2874 */
2875 candelete = 1;
2876 LIST_FOREACH(owp, &dp->nfsdl_owner, nfsow_list) {
2877 op = LIST_FIRST(&owp->nfsow_open);
2878 if (op != NULL && op->nfso_opencnt > 0) {
2879 candelete = 0;
2880 break;
2881 }
2882 }
2883 if (candelete) {
2884 LIST_FOREACH_SAFE(owp, &dp->nfsdl_owner, nfsow_list,
2885 nowp) {
2886 op = LIST_FIRST(&owp->nfsow_open);
2887 if (op != NULL)
2888 nfscl_freeopen(op, 1);
2889 nfscl_freeopenowner(owp, 1);
2890 }
2891 }
2892 }
2893 NFSUNLOCKCLSTATE();
2894 if (notdecr && ohp == NULL)
2895 printf("nfscl: never fnd open\n");
2896 return (0);
2897}
2898
2899/*
2900 * Return all delegations on this client.
2901 * (Must be called with client sleep lock.)
2902 */
2903static void

--- 1252 unchanged lines hidden ---