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 --- |