Deleted Added
full compact
nfs_clstate.c (194117) nfs_clstate.c (195510)
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>
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 $");
29__FBSDID("$FreeBSD: head/sys/fs/nfsclient/nfs_clstate.c 195510 2009-07-09 19:00:29Z rmacklem $");
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;
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;
453 struct nfsclopen *op = NULL;
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);
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);
515 if (error == 0) {
516 /* now look for a lockowner */
517 LIST_FOREACH(lp, &op->nfso_lock, nfsl_list) {
518 if (!NFSBCMP(lp->nfsl_owner, own,
519 NFSV4CL_LOCKNAMELEN)) {
520 stateidp->seqid =
521 lp->nfsl_stateid.seqid;
522 stateidp->other[0] =
523 lp->nfsl_stateid.other[0];
524 stateidp->other[1] =
525 lp->nfsl_stateid.other[1];
526 stateidp->other[2] =
527 lp->nfsl_stateid.other[2];
528 NFSUNLOCKCLSTATE();
529 return (0);
530 }
531 }
518 }
532 }
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 */
533 }
534 if (op == NULL) {
535 /* If not found, just look for any OpenOwner that will work. */
536 done = 0;
537 owp = LIST_FIRST(&clp->nfsc_owner);
538 while (!done && owp != NULL) {
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;
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 }
545 }
546 }
546 }
547 if (!done)
548 owp = LIST_NEXT(owp, nfsow_list);
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,
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.
2755 * log a message to that effect.
2756 * Opens aren't actually Close'd until VOP_INACTIVE() is performed
2757 * on the file's vnode.
2758 * This is the safe way, since it is difficult to identify
2758 * This is the safe way, since it is difficult to identify
2759 * which open the close is for.
2759 * which open the close is for and I/O can be performed after the
2760 * close(2) system call when a file is mmap'd.
2760 * If it returns 0 for success, there will be a referenced
2761 * 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.
2762 * clp returned via clpp.
2763 */
2764APPLESTATIC int
2763 */
2764APPLESTATIC int
2765nfscl_getclose(vnode_t vp, struct nfsclclient **clpp,
2766 struct nfsclopenhead *ohp)
2765nfscl_getclose(vnode_t vp, struct nfsclclient **clpp)
2767{
2768 struct nfsclclient *clp;
2766{
2767 struct nfsclclient *clp;
2769 struct nfsclowner *owp, *nowp;
2770 struct nfsclopen *op, *nop;
2768 struct nfsclowner *owp;
2769 struct nfsclopen *op;
2771 struct nfscldeleg *dp;
2772 struct nfsfh *nfhp;
2770 struct nfscldeleg *dp;
2771 struct nfsfh *nfhp;
2773 int error, notdecr, candelete;
2772 int error, notdecr;
2774
2775 error = nfscl_getcl(vp, NULL, NULL, &clp);
2776 if (error)
2777 return (error);
2778 *clpp = clp;
2779
2773
2774 error = nfscl_getcl(vp, NULL, NULL, &clp);
2775 if (error)
2776 return (error);
2777 *clpp = clp;
2778
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
2779 nfhp = VTONFS(vp)->n_fhp;
2780 notdecr = 1;
2781 NFSLOCKCLSTATE();
2782 /*
2783 * First, look for one under a delegation that was locally issued
2784 * and just decrement the opencnt for it. Since all my Opens against
2785 * the server are DENY_NONE, I don't see a problem with hanging
2786 * onto them. (It is much easier to use one of the extant Opens
2787 * 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..
2788 * 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) {
2789 */
2790 dp = nfscl_finddeleg(clp, nfhp->nfh_fh, nfhp->nfh_len);
2791 if (dp != NULL) {
2792 LIST_FOREACH(owp, &dp->nfsdl_owner, nfsow_list) {
2793 op = LIST_FIRST(&owp->nfsow_open);
2794 if (op != NULL) {
2795 /*
2796 * Since a delegation is for a file, there

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

2805 break;
2806 }
2807 }
2808 }
2809 }
2810
2811 /* Now process the opens against the server. */
2812 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);
2813 LIST_FOREACH(op, &owp->nfsow_open, 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 /*
2814 if (op->nfso_fhlen == nfhp->nfh_len &&
2815 !NFSBCMP(op->nfso_fh, nfhp->nfh_fh,
2816 nfhp->nfh_len)) {
2817 /* Found an open, decrement cnt if possible */
2818 if (notdecr && op->nfso_opencnt > 0) {
2819 notdecr = 0;
2820 op->nfso_opencnt--;
2821 }
2822 /*
2828 * There are more opens, so just return after
2829 * putting any opens already found back in the
2830 * state list.
2823 * There are more opens, so just return.
2831 */
2832 if (op->nfso_opencnt > 0) {
2824 */
2825 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 }
2826 NFSUNLOCKCLSTATE();
2827 return (0);
2828 }
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 }
2829 }
2861 op = nop;
2862 }
2863 }
2830 }
2831 }
2832 NFSUNLOCKCLSTATE();
2833 if (notdecr)
2834 printf("nfscl: never fnd open\n");
2835 return (0);
2836}
2864
2837
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) {
2838APPLESTATIC int
2839nfscl_doclose(vnode_t vp, struct nfsclclient **clpp, NFSPROC_T *p)
2840{
2841 struct nfsclclient *clp;
2842 struct nfsclowner *owp, *nowp;
2843 struct nfsclopen *op;
2844 struct nfscldeleg *dp;
2845 struct nfsfh *nfhp;
2846 int error;
2847
2848 error = nfscl_getcl(vp, NULL, NULL, &clp);
2849 if (error)
2850 return (error);
2851 *clpp = clp;
2852
2853 nfhp = VTONFS(vp)->n_fhp;
2854 NFSLOCKCLSTATE();
2855 /*
2856 * First get rid of the local Open structures, which should be no
2857 * longer in use.
2858 */
2859 dp = nfscl_finddeleg(clp, nfhp->nfh_fh, nfhp->nfh_len);
2860 if (dp != NULL) {
2861 LIST_FOREACH_SAFE(owp, &dp->nfsdl_owner, nfsow_list, nowp) {
2877 op = LIST_FIRST(&owp->nfsow_open);
2862 op = LIST_FIRST(&owp->nfsow_open);
2878 if (op != NULL && op->nfso_opencnt > 0) {
2879 candelete = 0;
2880 break;
2863 if (op != NULL) {
2864 KASSERT((op->nfso_opencnt == 0),
2865 ("nfscl: bad open cnt on deleg"));
2866 nfscl_freeopen(op, 1);
2881 }
2867 }
2868 nfscl_freeopenowner(owp, 1);
2882 }
2869 }
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);
2870 }
2871
2872 /* Now process the opens against the server. */
2873lookformore:
2874 LIST_FOREACH(owp, &clp->nfsc_owner, nfsow_list) {
2875 op = LIST_FIRST(&owp->nfsow_open);
2876 while (op != NULL) {
2877 if (op->nfso_fhlen == nfhp->nfh_len &&
2878 !NFSBCMP(op->nfso_fh, nfhp->nfh_fh,
2879 nfhp->nfh_len)) {
2880 /* Found an open, close it. */
2881 KASSERT((op->nfso_opencnt == 0),
2882 ("nfscl: bad open cnt on server"));
2883 NFSUNLOCKCLSTATE();
2884 nfsrpc_doclose(VFSTONFS(vnode_mount(vp)), op,
2885 p);
2886 NFSLOCKCLSTATE();
2887 goto lookformore;
2890 }
2888 }
2889 op = LIST_NEXT(op, nfso_list);
2891 }
2892 }
2893 NFSUNLOCKCLSTATE();
2890 }
2891 }
2892 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 ---
2893 return (0);
2894}
2895
2896/*
2897 * Return all delegations on this client.
2898 * (Must be called with client sleep lock.)
2899 */
2900static void

--- 1252 unchanged lines hidden ---