Annotation of Net2/nfs/nfs_srvcache.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1989 The Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * This code is derived from software contributed to Berkeley by
                      6:  * Rick Macklem at The University of Guelph.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *     This product includes software developed by the University of
                     19:  *     California, Berkeley and its contributors.
                     20:  * 4. Neither the name of the University nor the names of its contributors
                     21:  *    may be used to endorse or promote products derived from this software
                     22:  *    without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     34:  * SUCH DAMAGE.
                     35:  *
                     36:  *     @(#)nfs_srvcache.c      7.11 (Berkeley) 4/16/91
                     37:  */
                     38: 
                     39: /*
                     40:  * Reference: Chet Juszczak, "Improving the Performance and Correctness
                     41:  *            of an NFS Server", in Proc. Winter 1989 USENIX Conference,
                     42:  *            pages 53-63. San Diego, February 1989.
                     43:  */
                     44: 
                     45: #include "param.h"
                     46: #include "namei.h"
                     47: #include "vnode.h"
                     48: #include "mount.h"
                     49: #include "kernel.h"
                     50: #include "systm.h"
                     51: #include "mbuf.h"
                     52: #include "socket.h"
                     53: #include "socketvar.h"
                     54: 
                     55: #include "../netinet/in.h"
                     56: 
                     57: #include "nfsm_subs.h"
                     58: #include "nfsv2.h"
                     59: #include "nfsrvcache.h"
                     60: #include "nfs.h"
                     61: 
                     62: #if    ((NFSRCHSZ&(NFSRCHSZ-1)) == 0)
                     63: #define        NFSRCHASH(xid)          (((xid)+((xid)>>16))&(NFSRCHSZ-1))
                     64: #else
                     65: #define        NFSRCHASH(xid)          (((unsigned)((xid)+((xid)>>16)))%NFSRCHSZ)
                     66: #endif
                     67: 
                     68: union rhead {
                     69:        union  rhead *rh_head[2];
                     70:        struct nfsrvcache *rh_chain[2];
                     71: } rhead[NFSRCHSZ];
                     72: 
                     73: static struct nfsrvcache nfsrvcachehead;
                     74: static struct nfsrvcache nfsrvcache[NFSRVCACHESIZ];
                     75: 
                     76: #define TRUE   1
                     77: #define        FALSE   0
                     78: 
                     79: /*
                     80:  * Static array that defines which nfs rpc's are nonidempotent
                     81:  */
                     82: int nonidempotent[NFS_NPROCS] = {
                     83:        FALSE,
                     84:        FALSE,
                     85:        TRUE,
                     86:        FALSE,
                     87:        FALSE,
                     88:        FALSE,
                     89:        FALSE,
                     90:        FALSE,
                     91:        TRUE,
                     92:        TRUE,
                     93:        TRUE,
                     94:        TRUE,
                     95:        TRUE,
                     96:        TRUE,
                     97:        TRUE,
                     98:        TRUE,
                     99:        FALSE,
                    100:        FALSE,
                    101: };
                    102: 
                    103: /* True iff the rpc reply is an nfs status ONLY! */
                    104: static int repliesstatus[NFS_NPROCS] = {
                    105:        FALSE,
                    106:        FALSE,
                    107:        FALSE,
                    108:        FALSE,
                    109:        FALSE,
                    110:        FALSE,
                    111:        FALSE,
                    112:        FALSE,
                    113:        FALSE,
                    114:        FALSE,
                    115:        TRUE,
                    116:        TRUE,
                    117:        TRUE,
                    118:        TRUE,
                    119:        FALSE,
                    120:        TRUE,
                    121:        FALSE,
                    122:        FALSE,
                    123: };
                    124: 
                    125: /*
                    126:  * Initialize the server request cache list
                    127:  */
                    128: nfsrv_initcache()
                    129: {
                    130:        register int i;
                    131:        register struct nfsrvcache *rp = nfsrvcache;
                    132:        register struct nfsrvcache *hp = &nfsrvcachehead;
                    133:        register union  rhead *rh = rhead;
                    134: 
                    135:        for (i = NFSRCHSZ; --i >= 0; rh++) {
                    136:                rh->rh_head[0] = rh;
                    137:                rh->rh_head[1] = rh;
                    138:        }
                    139:        hp->rc_next = hp->rc_prev = hp;
                    140:        for (i = NFSRVCACHESIZ; i-- > 0; ) {
                    141:                rp->rc_state = RC_UNUSED;
                    142:                rp->rc_flag = 0;
                    143:                rp->rc_forw = rp;
                    144:                rp->rc_back = rp;
                    145:                rp->rc_next = hp->rc_next;
                    146:                hp->rc_next->rc_prev = rp;
                    147:                rp->rc_prev = hp;
                    148:                hp->rc_next = rp;
                    149:                rp++;
                    150:        }
                    151: }
                    152: 
                    153: /*
                    154:  * Look for the request in the cache
                    155:  * If found then
                    156:  *    return action and optionally reply
                    157:  * else
                    158:  *    insert it in the cache
                    159:  *
                    160:  * The rules are as follows:
                    161:  * - if in progress, return DROP request
                    162:  * - if completed within DELAY of the current time, return DROP it
                    163:  * - if completed a longer time ago return REPLY if the reply was cached or
                    164:  *   return DOIT
                    165:  * Update/add new request at end of lru list
                    166:  */
                    167: nfsrv_getcache(nam, xid, proc, repp)
                    168:        struct mbuf *nam;
                    169:        u_long xid;
                    170:        int proc;
                    171:        struct mbuf **repp;
                    172: {
                    173:        register struct nfsrvcache *rp;
                    174:        register union  rhead *rh;
                    175:        struct mbuf *mb;
                    176:        caddr_t bpos;
                    177:        int ret;
                    178: 
                    179:        rh = &rhead[NFSRCHASH(xid)];
                    180: loop:
                    181:        for (rp = rh->rh_chain[0]; rp != (struct nfsrvcache *)rh; rp = rp->rc_forw) {
                    182:                if (xid == rp->rc_xid && proc == rp->rc_proc &&
                    183:                    nfs_netaddr_match(nam, &rp->rc_nam)) {
                    184:                        if ((rp->rc_flag & RC_LOCKED) != 0) {
                    185:                                rp->rc_flag |= RC_WANTED;
                    186:                                (void) tsleep((caddr_t)rp, PZERO-1, "nfsrc", 0);
                    187:                                goto loop;
                    188:                        }
                    189:                        rp->rc_flag |= RC_LOCKED;
                    190:                        put_at_head(rp);
                    191:                        if (rp->rc_state == RC_UNUSED)
                    192:                                panic("nfsrv cache");
                    193:                        if (rp->rc_state == RC_INPROG ||
                    194:                           (time.tv_sec - rp->rc_timestamp) < RC_DELAY) {
                    195:                                nfsstats.srvcache_inproghits++;
                    196:                                ret = RC_DROPIT;
                    197:                        } else if (rp->rc_flag & RC_REPSTATUS) {
                    198:                                nfsstats.srvcache_idemdonehits++;
                    199:                                nfs_rephead(0, xid, rp->rc_status, repp, &mb,
                    200:                                        &bpos);
                    201:                                rp->rc_timestamp = time.tv_sec;
                    202:                                ret = RC_REPLY;
                    203:                        } else if (rp->rc_flag & RC_REPMBUF) {
                    204:                                nfsstats.srvcache_idemdonehits++;
                    205:                                *repp = m_copym(rp->rc_reply, 0, M_COPYALL,
                    206:                                                M_WAIT);
                    207:                                rp->rc_timestamp = time.tv_sec;
                    208:                                ret = RC_REPLY;
                    209:                        } else {
                    210:                                nfsstats.srvcache_nonidemdonehits++;
                    211:                                rp->rc_state = RC_INPROG;
                    212:                                ret = RC_DOIT;
                    213:                        }
                    214:                        rp->rc_flag &= ~RC_LOCKED;
                    215:                        if (rp->rc_flag & RC_WANTED) {
                    216:                                rp->rc_flag &= ~RC_WANTED;
                    217:                                wakeup((caddr_t)rp);
                    218:                        }
                    219:                        return (ret);
                    220:                }
                    221:        }
                    222:        nfsstats.srvcache_misses++;
                    223:        rp = nfsrvcachehead.rc_prev;
                    224:        while ((rp->rc_flag & RC_LOCKED) != 0) {
                    225:                rp->rc_flag |= RC_WANTED;
                    226:                (void) tsleep((caddr_t)rp, PZERO-1, "nfsrc", 0);
                    227:        }
                    228:        remque(rp);
                    229:        put_at_head(rp);
                    230:        if (rp->rc_flag & RC_REPMBUF)
                    231:                mb = rp->rc_reply;
                    232:        else
                    233:                mb = (struct mbuf *)0;
                    234:        rp->rc_flag = 0;
                    235:        rp->rc_state = RC_INPROG;
                    236:        rp->rc_xid = xid;
                    237:        bcopy((caddr_t)nam, (caddr_t)&rp->rc_nam, sizeof (struct mbuf));
                    238:        rp->rc_proc = proc;
                    239:        insque(rp, rh);
                    240:        if (mb)
                    241:                m_freem(mb);
                    242:        return (RC_DOIT);
                    243: }
                    244: 
                    245: /*
                    246:  * Update a request cache entry after the rpc has been done
                    247:  */
                    248: nfsrv_updatecache(nam, xid, proc, repvalid, repstat, repmbuf)
                    249:        struct mbuf *nam;
                    250:        u_long xid;
                    251:        int proc;
                    252:        int repvalid;
                    253:        int repstat;
                    254:        struct mbuf *repmbuf;
                    255: {
                    256:        register struct nfsrvcache *rp;
                    257:        register union  rhead *rh;
                    258: 
                    259:        rh = &rhead[NFSRCHASH(xid)];
                    260: loop:
                    261:        for (rp = rh->rh_chain[0]; rp != (struct nfsrvcache *)rh; rp = rp->rc_forw) {
                    262:                if (xid == rp->rc_xid && proc == rp->rc_proc &&
                    263:                    nfs_netaddr_match(nam, &rp->rc_nam)) {
                    264:                        if ((rp->rc_flag & RC_LOCKED) != 0) {
                    265:                                rp->rc_flag |= RC_WANTED;
                    266:                                (void) tsleep((caddr_t)rp, PZERO-1, "nfsrc", 0);
                    267:                                goto loop;
                    268:                        }
                    269:                        rp->rc_flag |= RC_LOCKED;
                    270:                        rp->rc_state = RC_DONE;
                    271:                        /*
                    272:                         * If we have a valid reply update status and save
                    273:                         * the reply for non-idempotent rpc's.
                    274:                         * Otherwise invalidate entry by setting the timestamp
                    275:                         * to nil.
                    276:                         */
                    277:                        if (repvalid) {
                    278:                                rp->rc_timestamp = time.tv_sec;
                    279:                                if (nonidempotent[proc]) {
                    280:                                        if (repliesstatus[proc]) {
                    281:                                                rp->rc_status = repstat;
                    282:                                                rp->rc_flag |= RC_REPSTATUS;
                    283:                                        } else {
                    284:                                                rp->rc_reply = m_copym(repmbuf,
                    285:                                                        0, M_COPYALL, M_WAIT);
                    286:                                                rp->rc_flag |= RC_REPMBUF;
                    287:                                        }
                    288:                                }
                    289:                        } else {
                    290:                                rp->rc_timestamp = 0;
                    291:                        }
                    292:                        rp->rc_flag &= ~RC_LOCKED;
                    293:                        if (rp->rc_flag & RC_WANTED) {
                    294:                                rp->rc_flag &= ~RC_WANTED;
                    295:                                wakeup((caddr_t)rp);
                    296:                        }
                    297:                        return;
                    298:                }
                    299:        }
                    300: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.