Lines Matching +full:force +full:- +full:m1
1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
40 * - I think a false hit is more serious than a false miss
41 * - A false hit for an RPC that has Op(s) that order via seqid# must be
43 * - A valid hit will probably happen a long time after the original reply
47 * - The mechanism will satisfy the requirements of ordering Ops with seqid#s
48 * in them as well as minimizing the risk of redoing retried non-idempotent
55 * - Null RPCs bypass the cache and are just done
57 * - key on <xid, NFS version> (as noted above, there can be several
61 * - if RPC# != OR request_size !=
62 * - not a match with this one
63 * - if NFSv4 and received on same TCP socket OR
66 * - not a match with this one
68 * - calculate checksum on first N bytes of NFS XDR
69 * - if checksum !=
70 * - not a match for this one
73 * - not a match (go do RPC, using new cache entry)
75 * - a hit (reply from cache)
77 * - miss (go do RPC, using new cache entry)
80 * - set a flag when a non-idempotent Op is processed
81 * - when an Op that uses a seqid# (Open,...) is processed
82 * - if same seqid# as referenced entry in cache
83 * - free new cache entry
84 * - reply from referenced cache entry
86 * - free referenced cache entry
87 * - increment seqid_refcnt on new cache entry
88 * - set pointer from Openowner/Lockowner to
91 * - increment seqid_refcnt on new cache entry
92 * - set pointer from Openowner/Lockowner to
96 * - if seqid_refcnt > 0 OR flagged non-idempotent on new
98 * - save reply in cache entry
99 * - calculate checksum on first N bytes of NFS XDR
101 * - note op and length of XDR request (in bytes)
102 * - timestamp it
104 * - free new cache entry
105 * - Send reply (noting info for socket activity check, below)
108 * - if saved since seqid_refcnt was > 0
109 * - free when seqid_refcnt decrements to 0
112 * else { non-idempotent Op(s) }
113 * - free when
114 * - some further activity observed on same
122 * - when very old (hours, days, weeks?)
125 * - key on <xid, NFS version, RPC#, Client host ip#>
129 * - if a match with entry via key
130 * - if RPC marked In_progress
131 * - discard request (don't send reply)
133 * - reply from cache
134 * - timestamp cache entry
136 * - add entry to cache, marked In_progress
137 * - do RPC
138 * - when RPC done
139 * - if RPC# non-idempotent
140 * - mark entry Done (not In_progress)
141 * - save reply
142 * - timestamp cache entry
144 * - free cache entry
145 * - send reply
151 * pages 53-63. San Diego, February 1989.
155 * hit. For V4, the non-idempotent Op will return NFSERR_RESOURCE in
181 if (error != 0 || req->newptr == NULL) in sysctl_tcphighwater()
278 (((rp)->rc_flag & RC_INETIPV6) ? AF_INET6 : AF_INET)
287 static int nfsrc_getlenandcksum(struct mbuf *m1, u_int16_t *cksum);
297 if ((rp->rc_flag & RC_UDP) != 0) in nfsrc_cachemutex()
299 return (&NFSD_VNET(nfsrchash_table)[nfsrc_hash(rp->rc_xid)].mtx); in nfsrc_cachemutex()
342 if (nd->nd_procnum == NFSPROC_NULL) in nfsrvd_getcache()
347 if (nd->nd_flag & ND_NFSV4) in nfsrvd_getcache()
348 newrp->rc_flag = RC_NFSV4; in nfsrvd_getcache()
349 else if (nd->nd_flag & ND_NFSV3) in nfsrvd_getcache()
350 newrp->rc_flag = RC_NFSV3; in nfsrvd_getcache()
352 newrp->rc_flag = RC_NFSV2; in nfsrvd_getcache()
353 newrp->rc_xid = nd->nd_retxid; in nfsrvd_getcache()
354 newrp->rc_proc = nd->nd_procnum; in nfsrvd_getcache()
355 newrp->rc_sockref = nd->nd_sockref; in nfsrvd_getcache()
356 newrp->rc_cachetime = nd->nd_tcpconntime; in nfsrvd_getcache()
357 if (nd->nd_flag & ND_SAMETCPCONN) in nfsrvd_getcache()
358 newrp->rc_flag |= RC_SAMETCPCONN; in nfsrvd_getcache()
359 if (nd->nd_nam2 != NULL) { in nfsrvd_getcache()
360 newrp->rc_flag |= RC_UDP; in nfsrvd_getcache()
371 * - key on <xid, NFS version, RPC#, Client host ip#>
385 hp = NFSRCUDPHASH(newrp->rc_xid); in nfsrc_getudp()
389 if (newrp->rc_xid == rp->rc_xid && in nfsrc_getudp()
390 newrp->rc_proc == rp->rc_proc && in nfsrc_getudp()
391 (newrp->rc_flag & rp->rc_flag & RC_NFSVERS) && in nfsrc_getudp()
392 nfsaddr_match(NETFAMILY(rp), &rp->rc_haddr, nd->nd_nam)) { in nfsrc_getudp()
393 if ((rp->rc_flag & RC_LOCKED) != 0) { in nfsrc_getudp()
394 rp->rc_flag |= RC_WANTED; in nfsrc_getudp()
395 (void)mtx_sleep(rp, mutex, (PZERO - 1) | PDROP, in nfsrc_getudp()
399 if (rp->rc_flag == 0) in nfsrc_getudp()
401 rp->rc_flag |= RC_LOCKED; in nfsrc_getudp()
404 if (rp->rc_flag & RC_INPROG) { in nfsrc_getudp()
405 NFSD_VNET(nfsstatsv1_p)->srvcache_inproghits++; in nfsrc_getudp()
408 } else if (rp->rc_flag & RC_REPSTATUS) { in nfsrc_getudp()
412 NFSD_VNET(nfsstatsv1_p)->srvcache_nonidemdonehits++; in nfsrc_getudp()
415 *(nd->nd_errp) = rp->rc_status; in nfsrc_getudp()
417 rp->rc_timestamp = NFSD_MONOSEC + in nfsrc_getudp()
419 } else if (rp->rc_flag & RC_REPMBUF) { in nfsrc_getudp()
420 NFSD_VNET(nfsstatsv1_p)->srvcache_nonidemdonehits++; in nfsrc_getudp()
422 nd->nd_mreq = m_copym(rp->rc_reply, 0, in nfsrc_getudp()
425 rp->rc_timestamp = NFSD_MONOSEC + in nfsrc_getudp()
435 NFSD_VNET(nfsstatsv1_p)->srvcache_misses++; in nfsrc_getudp()
436 atomic_add_int(&NFSD_VNET(nfsstatsv1_p)->srvcache_size, 1); in nfsrc_getudp()
439 newrp->rc_flag |= RC_INPROG; in nfsrc_getudp()
440 saddr = NFSSOCKADDR(nd->nd_nam, struct sockaddr_in *); in nfsrc_getudp()
441 if (saddr->sin_family == AF_INET) in nfsrc_getudp()
442 newrp->rc_inet = saddr->sin_addr.s_addr; in nfsrc_getudp()
443 else if (saddr->sin_family == AF_INET6) { in nfsrc_getudp()
445 NFSBCOPY((caddr_t)&saddr6->sin6_addr, (caddr_t)&newrp->rc_inet6, in nfsrc_getudp()
447 newrp->rc_flag |= RC_INETIPV6; in nfsrc_getudp()
452 nd->nd_rp = newrp; in nfsrc_getudp()
471 rp = nd->nd_rp; in nfsrvd_updatecache()
474 nd->nd_rp = NULL; in nfsrvd_updatecache()
478 if (!(rp->rc_flag & RC_INPROG)) in nfsrvd_updatecache()
480 rp->rc_flag &= ~RC_INPROG; in nfsrvd_updatecache()
481 if (rp->rc_flag & RC_UDP) { in nfsrvd_updatecache()
489 if (nd->nd_repstat == NFSERR_REPLYFROMCACHE) { in nfsrvd_updatecache()
490 NFSD_VNET(nfsstatsv1_p)->srvcache_nonidemdonehits++; in nfsrvd_updatecache()
492 nd->nd_repstat = 0; in nfsrvd_updatecache()
493 if (nd->nd_mreq) in nfsrvd_updatecache()
494 m_freem(nd->nd_mreq); in nfsrvd_updatecache()
495 if (!(rp->rc_flag & RC_REPMBUF)) in nfsrvd_updatecache()
497 nd->nd_mreq = m_copym(rp->rc_reply, 0, in nfsrvd_updatecache()
499 rp->rc_timestamp = NFSD_MONOSEC + nfsrc_tcptimeout; in nfsrvd_updatecache()
509 if (nd->nd_repstat != NFSERR_DONTREPLY && in nfsrvd_updatecache()
510 (rp->rc_refcnt > 0 || in nfsrvd_updatecache()
511 ((nd->nd_flag & ND_SAVEREPLY) && (rp->rc_flag & RC_UDP)) || in nfsrvd_updatecache()
512 ((nd->nd_flag & ND_SAVEREPLY) && !(rp->rc_flag & RC_UDP) && in nfsrvd_updatecache()
515 if (rp->rc_refcnt > 0) { in nfsrvd_updatecache()
516 if (!(rp->rc_flag & RC_NFSV4)) in nfsrvd_updatecache()
518 rp->rc_flag |= RC_REFCNT; in nfsrvd_updatecache()
520 if ((nd->nd_flag & ND_NFSV2) && in nfsrvd_updatecache()
521 nfsv2_repstat[newnfsv2_procid[nd->nd_procnum]]) { in nfsrvd_updatecache()
522 rp->rc_status = nd->nd_repstat; in nfsrvd_updatecache()
523 rp->rc_flag |= RC_REPSTATUS; in nfsrvd_updatecache()
526 if (!(rp->rc_flag & RC_UDP)) { in nfsrvd_updatecache()
530 NFSD_VNET(nfsstatsv1_p)->srvcache_tcppeak) in nfsrvd_updatecache()
531 NFSD_VNET(nfsstatsv1_p)->srvcache_tcppeak = in nfsrvd_updatecache()
535 m = m_copym(nd->nd_mreq, 0, M_COPYALL, M_WAITOK); in nfsrvd_updatecache()
537 rp->rc_reply = m; in nfsrvd_updatecache()
538 rp->rc_flag |= RC_REPMBUF; in nfsrvd_updatecache()
541 if (rp->rc_flag & RC_UDP) { in nfsrvd_updatecache()
542 rp->rc_timestamp = NFSD_MONOSEC + in nfsrvd_updatecache()
546 rp->rc_timestamp = NFSD_MONOSEC + nfsrc_tcptimeout; in nfsrvd_updatecache()
547 if (rp->rc_refcnt > 0) in nfsrvd_updatecache()
572 if (!(rp->rc_flag & RC_INPROG)) in nfsrvd_delcache()
575 rp->rc_flag &= ~RC_INPROG; in nfsrvd_delcache()
576 if (rp->rc_refcnt == 0 && !(rp->rc_flag & RC_LOCKED)) in nfsrvd_delcache()
591 KASSERT(rp->rc_flag & RC_LOCKED, ("nfsrvd_sentcache not locked")); in nfsrvd_sentcache()
593 hbp = NFSRCAHASH(rp->rc_sockref); in nfsrvd_sentcache()
594 mtx_lock(&hbp->mtx); in nfsrvd_sentcache()
595 rp->rc_tcpseq = seq; in nfsrvd_sentcache()
596 if (rp->rc_acked != RC_NO_ACK) in nfsrvd_sentcache()
597 LIST_INSERT_HEAD(&hbp->tbl, rp, rc_ahash); in nfsrvd_sentcache()
598 rp->rc_acked = RC_NO_ACK; in nfsrvd_sentcache()
599 mtx_unlock(&hbp->mtx); in nfsrvd_sentcache()
606 * - key on <xid, nfs version>
620 hp = NFSRCHASH(newrp->rc_xid); in nfsrc_gettcp()
621 newrp->rc_reqlen = nfsrc_getlenandcksum(nd->nd_mrep, &newrp->rc_cksum); in nfsrc_gettcp()
632 if (newrp->rc_xid == rp->rc_xid && in nfsrc_gettcp()
633 (!(rp->rc_flag & RC_INPROG) || in nfsrc_gettcp()
634 ((newrp->rc_flag & RC_SAMETCPCONN) && in nfsrc_gettcp()
635 newrp->rc_sockref == rp->rc_sockref)) && in nfsrc_gettcp()
636 (newrp->rc_flag & rp->rc_flag & RC_NFSVERS) && in nfsrc_gettcp()
637 newrp->rc_proc == rp->rc_proc && in nfsrc_gettcp()
638 ((newrp->rc_flag & RC_NFSV4) && in nfsrc_gettcp()
639 newrp->rc_sockref != rp->rc_sockref && in nfsrc_gettcp()
640 newrp->rc_cachetime >= rp->rc_cachetime) in nfsrc_gettcp()
641 && newrp->rc_reqlen == rp->rc_reqlen && in nfsrc_gettcp()
642 newrp->rc_cksum == rp->rc_cksum) { in nfsrc_gettcp()
655 if (rp->rc_refcnt > 0) { in nfsrc_gettcp()
679 if ((rp->rc_flag & RC_LOCKED) != 0) { in nfsrc_gettcp()
680 rp->rc_flag |= RC_WANTED; in nfsrc_gettcp()
681 (void)mtx_sleep(rp, mutex, (PZERO - 1) | PDROP, in nfsrc_gettcp()
685 if (rp->rc_flag == 0) in nfsrc_gettcp()
687 rp->rc_flag |= RC_LOCKED; in nfsrc_gettcp()
688 if (rp->rc_flag & RC_INPROG) { in nfsrc_gettcp()
689 NFSD_VNET(nfsstatsv1_p)->srvcache_inproghits++; in nfsrc_gettcp()
691 if (newrp->rc_sockref == rp->rc_sockref) in nfsrc_gettcp()
692 nfsrc_marksametcpconn(rp->rc_sockref); in nfsrc_gettcp()
694 } else if (rp->rc_flag & RC_REPSTATUS) { in nfsrc_gettcp()
698 NFSD_VNET(nfsstatsv1_p)->srvcache_nonidemdonehits++; in nfsrc_gettcp()
700 if (newrp->rc_sockref == rp->rc_sockref) in nfsrc_gettcp()
701 nfsrc_marksametcpconn(rp->rc_sockref); in nfsrc_gettcp()
704 *(nd->nd_errp) = rp->rc_status; in nfsrc_gettcp()
705 rp->rc_timestamp = NFSD_MONOSEC + nfsrc_tcptimeout; in nfsrc_gettcp()
706 } else if (rp->rc_flag & RC_REPMBUF) { in nfsrc_gettcp()
707 NFSD_VNET(nfsstatsv1_p)->srvcache_nonidemdonehits++; in nfsrc_gettcp()
709 if (newrp->rc_sockref == rp->rc_sockref) in nfsrc_gettcp()
710 nfsrc_marksametcpconn(rp->rc_sockref); in nfsrc_gettcp()
712 nd->nd_mreq = m_copym(rp->rc_reply, 0, in nfsrc_gettcp()
714 rp->rc_timestamp = NFSD_MONOSEC + nfsrc_tcptimeout; in nfsrc_gettcp()
722 NFSD_VNET(nfsstatsv1_p)->srvcache_misses++; in nfsrc_gettcp()
723 atomic_add_int(&NFSD_VNET(nfsstatsv1_p)->srvcache_size, 1); in nfsrc_gettcp()
729 newrp->rc_cachetime = NFSD_MONOSEC; in nfsrc_gettcp()
730 newrp->rc_flag |= RC_INPROG; in nfsrc_gettcp()
733 nd->nd_rp = newrp; in nfsrc_gettcp()
751 while ((rp->rc_flag & RC_LOCKED) != 0) { in nfsrc_lock()
752 rp->rc_flag |= RC_WANTED; in nfsrc_lock()
753 (void)mtx_sleep(rp, mutex, PZERO - 1, "nfsrc", 0); in nfsrc_lock()
755 rp->rc_flag |= RC_LOCKED; in nfsrc_lock()
768 rp->rc_flag &= ~RC_LOCKED; in nfsrc_unlock()
779 if (rp->rc_flag & RC_WANTED) { in nfsrc_wanted()
780 rp->rc_flag &= ~RC_WANTED; in nfsrc_wanted()
795 if (rp->rc_flag & RC_UDP) { in nfsrc_freecache()
797 NFSD_VNET(nfsrc_udpcachesize)--; in nfsrc_freecache()
798 } else if (rp->rc_acked != RC_NO_SEQ) { in nfsrc_freecache()
799 hbp = NFSRCAHASH(rp->rc_sockref); in nfsrc_freecache()
800 mtx_lock(&hbp->mtx); in nfsrc_freecache()
801 if (rp->rc_acked == RC_NO_ACK) in nfsrc_freecache()
803 mtx_unlock(&hbp->mtx); in nfsrc_freecache()
806 if (rp->rc_flag & RC_REPMBUF) { in nfsrc_freecache()
807 m_freem(rp->rc_reply); in nfsrc_freecache()
808 if (!(rp->rc_flag & RC_UDP)) in nfsrc_freecache()
809 atomic_add_int(&NFSD_VNET(nfsrc_tcpsavedreplies), -1); in nfsrc_freecache()
812 atomic_add_int(&NFSD_VNET(nfsstatsv1_p)->srvcache_size, -1); in nfsrc_freecache()
835 NFSD_VNET(nfsstatsv1_p)->srvcache_size = 0; in nfsrvd_cleancache()
848 int force, lastslot, i, j, k, tto, time_histo[HISTSIZE]; in nfsrc_trimcache() local
855 mtx_lock(&hbp->mtx); in nfsrc_trimcache()
856 LIST_FOREACH_SAFE(rp, &hbp->tbl, rc_ahash, nextrp) { in nfsrc_trimcache()
857 if (sockref == rp->rc_sockref) { in nfsrc_trimcache()
858 if (SEQ_GEQ(snd_una, rp->rc_tcpseq)) { in nfsrc_trimcache()
859 rp->rc_acked = RC_ACK; in nfsrc_trimcache()
862 rp->rc_acked = RC_NACK; in nfsrc_trimcache()
867 mtx_unlock(&hbp->mtx); in nfsrc_trimcache()
879 if (!(rp->rc_flag & (RC_INPROG|RC_LOCKED|RC_WANTED)) in nfsrc_trimcache()
880 && rp->rc_refcnt == 0 in nfsrc_trimcache()
881 && ((rp->rc_flag & RC_REFCNT) || in nfsrc_trimcache()
882 udp_lasttrim > rp->rc_timestamp || in nfsrc_trimcache()
891 force = nfsrc_tcphighwater / 4; in nfsrc_trimcache()
892 if (force > 0 && in nfsrc_trimcache()
893 NFSD_VNET(nfsrc_tcpsavedreplies) + force >= in nfsrc_trimcache()
898 lastslot = NFSRVCACHE_HASHSIZE - 1; in nfsrc_trimcache()
900 force = 0; in nfsrc_trimcache()
903 lastslot = NFSRVCACHE_HASHSIZE - 1; in nfsrc_trimcache()
917 if (!(rp->rc_flag & in nfsrc_trimcache()
919 && rp->rc_refcnt == 0) { in nfsrc_trimcache()
920 if ((rp->rc_flag & RC_REFCNT) || in nfsrc_trimcache()
921 tcp_lasttrim > rp->rc_timestamp || in nfsrc_trimcache()
922 rp->rc_acked == RC_ACK) { in nfsrc_trimcache()
927 if (force == 0) in nfsrc_trimcache()
935 j = rp->rc_timestamp - tcp_lasttrim; in nfsrc_trimcache()
937 j = HISTSIZE - 1; in nfsrc_trimcache()
947 if (force) { in nfsrc_trimcache()
954 for (i = 0; i < (HISTSIZE - 2); i++) { in nfsrc_trimcache()
956 if (k > force) in nfsrc_trimcache()
968 if (!(rp->rc_flag & in nfsrc_trimcache()
970 && rp->rc_refcnt == 0 in nfsrc_trimcache()
971 && ((rp->rc_flag & RC_REFCNT) || in nfsrc_trimcache()
972 thisstamp > rp->rc_timestamp || in nfsrc_trimcache()
973 rp->rc_acked == RC_ACK)) in nfsrc_trimcache()
996 if (rp->rc_refcnt < 0) in nfsrvd_refcache()
998 rp->rc_refcnt++; in nfsrvd_refcache()
1012 if (rp->rc_refcnt <= 0) in nfsrvd_derefcache()
1014 rp->rc_refcnt--; in nfsrvd_derefcache()
1015 if (rp->rc_refcnt == 0 && !(rp->rc_flag & (RC_LOCKED | RC_INPROG))) in nfsrvd_derefcache()
1025 nfsrc_getlenandcksum(struct mbuf *m1, u_int16_t *cksum) in nfsrc_getlenandcksum() argument
1030 m = m1; in nfsrc_getlenandcksum()
1032 len += m->m_len; in nfsrc_getlenandcksum()
1033 m = m->m_next; in nfsrc_getlenandcksum()
1036 *cksum = in_cksum(m1, cklen); in nfsrc_getlenandcksum()