]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/nfs/nfs_srvcache.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / bsd / nfs / nfs_srvcache.c
index db1c6e6a7deacd5188d8b1ca3f2ca7baab2850b7..a934d4d078082bd83d1f8efd2c03896b4fcfe100 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 2000-2009 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2010 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * unlawful or unlicensed copies of an Apple operating system, or to
  * circumvent, violate, or enable the circumvention or violation of, any
  * terms of an Apple operating system software license agreement.
- * 
+ *
  * Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
@@ -22,7 +22,7 @@
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
@@ -65,7 +65,9 @@
  * FreeBSD-Id: nfs_srvcache.c,v 1.15 1997/10/12 20:25:46 phk Exp $
  */
 
-#if NFSSERVER
+#include <nfs/nfs_conf.h>
+#if CONFIG_NFS_SERVER
+
 /*
  * Reference: Chet Juszczak, "Improving the Performance and Correctness
  *             of an NFS Server", in Proc. Winter 1989 USENIX Conference,
@@ -92,14 +94,14 @@ extern int nfsv2_procid[NFS_NPROCS];
 static int nfsrv_reqcache_count;
 int nfsrv_reqcache_size = NFSRVCACHESIZ;
 
-#define        NFSRCHASH(xid) \
+#define NFSRCHASH(xid) \
        (&nfsrv_reqcache_hashtbl[((xid) + ((xid) >> 24)) & nfsrv_reqcache_hash])
-LIST_HEAD(nfsrv_reqcache_hash, nfsrvcache) *nfsrv_reqcache_hashtbl;
+LIST_HEAD(nfsrv_reqcache_hash, nfsrvcache) * nfsrv_reqcache_hashtbl;
 TAILQ_HEAD(nfsrv_reqcache_lru, nfsrvcache) nfsrv_reqcache_lruhead;
 u_long nfsrv_reqcache_hash;
 
-lck_grp_t *nfsrv_reqcache_lck_grp;
-lck_mtx_t *nfsrv_reqcache_mutex;
+static LCK_GRP_DECLARE(nfsrv_reqcache_lck_grp, "nfsrv_reqcache");
+LCK_MTX_DECLARE(nfsrv_reqcache_mutex, &nfsrv_reqcache_lck_grp);
 
 /*
  * Static array that defines which nfs rpc's are nonidempotent
@@ -158,14 +160,15 @@ static int nfsv2_repstat[NFS_NPROCS] = {
 void
 nfsrv_initcache(void)
 {
-       if (nfsrv_reqcache_size <= 0)
+       if (nfsrv_reqcache_size <= 0) {
                return;
+       }
 
-       lck_mtx_lock(nfsrv_reqcache_mutex);
+       lck_mtx_lock(&nfsrv_reqcache_mutex);
        /* init nfs server request cache hash table */
        nfsrv_reqcache_hashtbl = hashinit(nfsrv_reqcache_size, M_NFSD, &nfsrv_reqcache_hash);
        TAILQ_INIT(&nfsrv_reqcache_lruhead);
-       lck_mtx_unlock(nfsrv_reqcache_mutex);
+       lck_mtx_unlock(&nfsrv_reqcache_mutex);
 }
 
 /*
@@ -174,6 +177,7 @@ nfsrv_initcache(void)
  * If there is any doubt, return FALSE.
  * The AF_INET family is handled as a special case so that address mbufs
  * don't need to be saved to store "struct in_addr", which is only 4 bytes.
+ * Ditto for AF_INET6 which is only 16 bytes.
  */
 static int
 netaddr_match(
@@ -182,18 +186,25 @@ netaddr_match(
        mbuf_t nam)
 {
        struct sockaddr_in *inetaddr;
+       struct sockaddr_in6 *inet6addr;
 
        switch (family) {
        case AF_INET:
                inetaddr = mbuf_data(nam);
-               if (inetaddr->sin_family == AF_INET &&
-                   inetaddr->sin_addr.s_addr == haddr->had_inetaddr)
-                       return (1);
+               if ((inetaddr->sin_family == AF_INET) &&
+                   (inetaddr->sin_addr.s_addr == haddr->had_inetaddr)) {
+                       return 1;
+               }
                break;
-       default:
+       case AF_INET6:
+               inet6addr = mbuf_data(nam);
+               if ((inet6addr->sin6_family == AF_INET6) &&
+                   !bcmp(&inet6addr->sin6_addr, &haddr->had_inet6addr, sizeof(inet6addr->sin6_addr))) {
+                       return 1;
+               }
                break;
-       };
-       return (0);
+       }
+       return 0;
 }
 
 /*
@@ -218,24 +229,25 @@ nfsrv_getcache(
 {
        struct nfsrvcache *rp;
        struct nfsm_chain nmrep;
-       struct sockaddr_in *saddr;
+       struct sockaddr *saddr;
        int ret, error;
 
        /*
         * Don't cache recent requests for reliable transport protocols.
         * (Maybe we should for the case of a reconnect, but..)
         */
-       if (!nd->nd_nam2)
-               return (RC_DOIT);
-       lck_mtx_lock(nfsrv_reqcache_mutex);
+       if (!nd->nd_nam2) {
+               return RC_DOIT;
+       }
+       lck_mtx_lock(&nfsrv_reqcache_mutex);
 loop:
        for (rp = NFSRCHASH(nd->nd_retxid)->lh_first; rp != 0;
            rp = rp->rc_hash.le_next) {
-           if (nd->nd_retxid == rp->rc_xid && nd->nd_procnum == rp->rc_proc &&
-               netaddr_match(AF_INET, &rp->rc_haddr, nd->nd_nam)) {
+               if (nd->nd_retxid == rp->rc_xid && nd->nd_procnum == rp->rc_proc &&
+                   netaddr_match(rp->rc_family, &rp->rc_haddr, nd->nd_nam)) {
                        if ((rp->rc_flag & RC_LOCKED) != 0) {
                                rp->rc_flag |= RC_WANTED;
-                               msleep(rp, nfsrv_reqcache_mutex, PZERO-1, "nfsrc", NULL);
+                               msleep(rp, &nfsrv_reqcache_mutex, PZERO - 1, "nfsrc", NULL);
                                goto loop;
                        }
                        rp->rc_flag |= RC_LOCKED;
@@ -244,13 +256,14 @@ loop:
                                TAILQ_REMOVE(&nfsrv_reqcache_lruhead, rp, rc_lru);
                                TAILQ_INSERT_TAIL(&nfsrv_reqcache_lruhead, rp, rc_lru);
                        }
-                       if (rp->rc_state == RC_UNUSED)
+                       if (rp->rc_state == RC_UNUSED) {
                                panic("nfsrv cache");
+                       }
                        if (rp->rc_state == RC_INPROG) {
-                               OSAddAtomic(1, &nfsstats.srvcache_inproghits);
+                               OSAddAtomic64(1, &nfsstats.srvcache_inproghits);
                                ret = RC_DROPIT;
                        } else if (rp->rc_flag & RC_REPSTATUS) {
-                               OSAddAtomic(1, &nfsstats.srvcache_nonidemdonehits);
+                               OSAddAtomic64(1, &nfsstats.srvcache_nonidemdonehits);
                                nd->nd_repstat = rp->rc_status;
                                error = nfsrv_rephead(nd, slp, &nmrep, 0);
                                if (error) {
@@ -262,7 +275,7 @@ loop:
                                        *mrepp = nmrep.nmc_mhead;
                                }
                        } else if (rp->rc_flag & RC_REPMBUF) {
-                               OSAddAtomic(1, &nfsstats.srvcache_nonidemdonehits);
+                               OSAddAtomic64(1, &nfsstats.srvcache_nonidemdonehits);
                                error = mbuf_copym(rp->rc_reply, 0, MBUF_COPYALL, MBUF_WAITOK, mrepp);
                                if (error) {
                                        printf("nfsrv cache: reply copym failed for nonidem request hit\n");
@@ -271,7 +284,7 @@ loop:
                                        ret = RC_REPLY;
                                }
                        } else {
-                               OSAddAtomic(1, &nfsstats.srvcache_idemdonehits);
+                               OSAddAtomic64(1, &nfsstats.srvcache_idemdonehits);
                                rp->rc_state = RC_INPROG;
                                ret = RC_DOIT;
                        }
@@ -280,11 +293,11 @@ loop:
                                rp->rc_flag &= ~RC_WANTED;
                                wakeup(rp);
                        }
-                       lck_mtx_unlock(nfsrv_reqcache_mutex);
-                       return (ret);
+                       lck_mtx_unlock(&nfsrv_reqcache_mutex);
+                       return ret;
                }
        }
-       OSAddAtomic(1, &nfsstats.srvcache_misses);
+       OSAddAtomic64(1, &nfsstats.srvcache_misses);
        if (nfsrv_reqcache_count < nfsrv_reqcache_size) {
                /* try to allocate a new entry */
                MALLOC(rp, struct nfsrvcache *, sizeof *rp, M_NFSD, M_WAITOK);
@@ -302,40 +315,49 @@ loop:
                if (!rp) {
                        /* no entry to reuse? */
                        /* OK, we just won't be able to cache this request */
-                       lck_mtx_unlock(nfsrv_reqcache_mutex);
-                       return (RC_DOIT);
+                       lck_mtx_unlock(&nfsrv_reqcache_mutex);
+                       return RC_DOIT;
                }
                while ((rp->rc_flag & RC_LOCKED) != 0) {
                        rp->rc_flag |= RC_WANTED;
-                       msleep(rp, nfsrv_reqcache_mutex, PZERO-1, "nfsrc", NULL);
+                       msleep(rp, &nfsrv_reqcache_mutex, PZERO - 1, "nfsrc", NULL);
                        rp = nfsrv_reqcache_lruhead.tqh_first;
                }
                rp->rc_flag |= RC_LOCKED;
                LIST_REMOVE(rp, rc_hash);
                TAILQ_REMOVE(&nfsrv_reqcache_lruhead, rp, rc_lru);
-               if (rp->rc_flag & RC_REPMBUF)
+               if (rp->rc_flag & RC_REPMBUF) {
                        mbuf_freem(rp->rc_reply);
-               if (rp->rc_flag & RC_NAM)
+               }
+               if (rp->rc_flag & RC_NAM) {
                        mbuf_freem(rp->rc_nam);
+               }
                rp->rc_flag &= (RC_LOCKED | RC_WANTED);
        }
        TAILQ_INSERT_TAIL(&nfsrv_reqcache_lruhead, rp, rc_lru);
        rp->rc_state = RC_INPROG;
        rp->rc_xid = nd->nd_retxid;
        saddr = mbuf_data(nd->nd_nam);
-       switch (saddr->sin_family) {
+       rp->rc_family = saddr->sa_family;
+       switch (saddr->sa_family) {
        case AF_INET:
                rp->rc_flag |= RC_INETADDR;
-               rp->rc_inetaddr = saddr->sin_addr.s_addr;
+               rp->rc_inetaddr = ((struct sockaddr_in*)saddr)->sin_addr.s_addr;
+               break;
+       case AF_INET6:
+               rp->rc_flag |= RC_INETADDR;
+               rp->rc_inet6addr = ((struct sockaddr_in6*)saddr)->sin6_addr;
                break;
        default:
                error = mbuf_copym(nd->nd_nam, 0, MBUF_COPYALL, MBUF_WAITOK, &rp->rc_nam);
-               if (error)
+               if (error) {
                        printf("nfsrv cache: nam copym failed\n");
-               else
+               } else {
                        rp->rc_flag |= RC_NAM;
+               }
                break;
-       };
+       }
+       ;
        rp->rc_proc = nd->nd_procnum;
        LIST_INSERT_HEAD(NFSRCHASH(nd->nd_retxid), rp, rc_hash);
        rp->rc_flag &= ~RC_LOCKED;
@@ -343,8 +365,8 @@ loop:
                rp->rc_flag &= ~RC_WANTED;
                wakeup(rp);
        }
-       lck_mtx_unlock(nfsrv_reqcache_mutex);
-       return (RC_DOIT);
+       lck_mtx_unlock(&nfsrv_reqcache_mutex);
+       return RC_DOIT;
 }
 
 /*
@@ -359,31 +381,32 @@ nfsrv_updatecache(
        struct nfsrvcache *rp;
        int error;
 
-       if (!nd->nd_nam2)
+       if (!nd->nd_nam2) {
                return;
-       lck_mtx_lock(nfsrv_reqcache_mutex);
+       }
+       lck_mtx_lock(&nfsrv_reqcache_mutex);
 loop:
        for (rp = NFSRCHASH(nd->nd_retxid)->lh_first; rp != 0;
            rp = rp->rc_hash.le_next) {
-           if (nd->nd_retxid == rp->rc_xid && nd->nd_procnum == rp->rc_proc &&
-               netaddr_match(AF_INET, &rp->rc_haddr, nd->nd_nam)) {
+               if (nd->nd_retxid == rp->rc_xid && nd->nd_procnum == rp->rc_proc &&
+                   netaddr_match(rp->rc_family, &rp->rc_haddr, nd->nd_nam)) {
                        if ((rp->rc_flag & RC_LOCKED) != 0) {
                                rp->rc_flag |= RC_WANTED;
-                               msleep(rp, nfsrv_reqcache_mutex, PZERO-1, "nfsrc", NULL);
+                               msleep(rp, &nfsrv_reqcache_mutex, PZERO - 1, "nfsrc", NULL);
                                goto loop;
                        }
                        rp->rc_flag |= RC_LOCKED;
-                        if (rp->rc_state == RC_DONE) {
-                                /*
-                                 * This can occur if the cache is too small.
-                                 * Retransmits of the same request aren't
-                                 * dropped so we may see the operation
-                                 * complete more then once.
-                                 */
-                                if (rp->rc_flag & RC_REPMBUF) {
-                                        mbuf_freem(rp->rc_reply);
-                                        rp->rc_flag &= ~RC_REPMBUF;
-                                }
+                       if (rp->rc_state == RC_DONE) {
+                               /*
+                                * This can occur if the cache is too small.
+                                * Retransmits of the same request aren't
+                                * dropped so we may see the operation
+                                * complete more then once.
+                                */
+                               if (rp->rc_flag & RC_REPMBUF) {
+                                       mbuf_freem(rp->rc_reply);
+                                       rp->rc_flag &= ~RC_REPMBUF;
+                               }
                        }
                        rp->rc_state = RC_DONE;
                        /*
@@ -392,13 +415,14 @@ loop:
                         */
                        if (repvalid && nonidempotent[nd->nd_procnum]) {
                                if ((nd->nd_vers == NFS_VER2) &&
-                                 nfsv2_repstat[nfsv2_procid[nd->nd_procnum]]) {
+                                   nfsv2_repstat[nfsv2_procid[nd->nd_procnum]]) {
                                        rp->rc_status = nd->nd_repstat;
                                        rp->rc_flag |= RC_REPSTATUS;
                                } else {
                                        error = mbuf_copym(repmbuf, 0, MBUF_COPYALL, MBUF_WAITOK, &rp->rc_reply);
-                                       if (!error)
+                                       if (!error) {
                                                rp->rc_flag |= RC_REPMBUF;
+                                       }
                                }
                        }
                        rp->rc_flag &= ~RC_LOCKED;
@@ -406,11 +430,11 @@ loop:
                                rp->rc_flag &= ~RC_WANTED;
                                wakeup(rp);
                        }
-                       lck_mtx_unlock(nfsrv_reqcache_mutex);
+                       lck_mtx_unlock(&nfsrv_reqcache_mutex);
                        return;
                }
        }
-       lck_mtx_unlock(nfsrv_reqcache_mutex);
+       lck_mtx_unlock(&nfsrv_reqcache_mutex);
 }
 
 /*
@@ -421,7 +445,7 @@ nfsrv_cleancache(void)
 {
        struct nfsrvcache *rp, *nextrp;
 
-       lck_mtx_lock(nfsrv_reqcache_mutex);
+       lck_mtx_lock(&nfsrv_reqcache_mutex);
        for (rp = nfsrv_reqcache_lruhead.tqh_first; rp != 0; rp = nextrp) {
                nextrp = rp->rc_lru.tqe_next;
                LIST_REMOVE(rp, rc_hash);
@@ -430,7 +454,7 @@ nfsrv_cleancache(void)
        }
        nfsrv_reqcache_count = 0;
        FREE(nfsrv_reqcache_hashtbl, M_TEMP);
-       lck_mtx_unlock(nfsrv_reqcache_mutex);
+       lck_mtx_unlock(&nfsrv_reqcache_mutex);
 }
 
-#endif /* NFSSERVER */
+#endif /* CONFIG_NFS_SERVER */