17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM * CDDL HEADER START
37836SJohn.Forte@Sun.COM *
47836SJohn.Forte@Sun.COM * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM *
87836SJohn.Forte@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM * and limitations under the License.
127836SJohn.Forte@Sun.COM *
137836SJohn.Forte@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM *
197836SJohn.Forte@Sun.COM * CDDL HEADER END
207836SJohn.Forte@Sun.COM */
217836SJohn.Forte@Sun.COM /*
22*9093SRamana.Srikanth@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
237836SJohn.Forte@Sun.COM * Use is subject to license terms.
247836SJohn.Forte@Sun.COM */
257836SJohn.Forte@Sun.COM
267836SJohn.Forte@Sun.COM #include <sys/types.h>
277836SJohn.Forte@Sun.COM #include <sys/ksynch.h>
287836SJohn.Forte@Sun.COM #include <sys/cmn_err.h>
297836SJohn.Forte@Sun.COM #include <sys/kmem.h>
307836SJohn.Forte@Sun.COM #include <sys/stat.h>
317836SJohn.Forte@Sun.COM #include <sys/errno.h>
327836SJohn.Forte@Sun.COM
337836SJohn.Forte@Sun.COM #include "../solaris/nsc_thread.h"
347836SJohn.Forte@Sun.COM #ifdef DS_DDICT
357836SJohn.Forte@Sun.COM #include "../contract.h"
367836SJohn.Forte@Sun.COM #endif
377836SJohn.Forte@Sun.COM #include <sys/nsctl/nsctl.h>
387836SJohn.Forte@Sun.COM
397836SJohn.Forte@Sun.COM #include <sys/kmem.h>
407836SJohn.Forte@Sun.COM #include <sys/ddi.h>
417836SJohn.Forte@Sun.COM
427836SJohn.Forte@Sun.COM #include <sys/sdt.h> /* dtrace is S10 or later */
437836SJohn.Forte@Sun.COM
447836SJohn.Forte@Sun.COM #include "rdc_io.h"
457836SJohn.Forte@Sun.COM #include "rdc_bitmap.h"
467836SJohn.Forte@Sun.COM #include "rdc_diskq.h"
477836SJohn.Forte@Sun.COM #include "rdc_clnt.h"
487836SJohn.Forte@Sun.COM
497836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s.h>
507836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s_k.h>
517836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_errors.h>
527836SJohn.Forte@Sun.COM
537836SJohn.Forte@Sun.COM extern nsc_io_t *_rdc_io_hc;
547836SJohn.Forte@Sun.COM
557836SJohn.Forte@Sun.COM int rdc_diskq_coalesce = 0;
567836SJohn.Forte@Sun.COM
577836SJohn.Forte@Sun.COM int
_rdc_rsrv_diskq(rdc_group_t * group)587836SJohn.Forte@Sun.COM _rdc_rsrv_diskq(rdc_group_t *group)
597836SJohn.Forte@Sun.COM {
607836SJohn.Forte@Sun.COM int rc = 0;
617836SJohn.Forte@Sun.COM
627836SJohn.Forte@Sun.COM mutex_enter(&group->diskqmutex);
637836SJohn.Forte@Sun.COM if (group->diskqfd == NULL) {
647836SJohn.Forte@Sun.COM mutex_exit(&group->diskqmutex);
657836SJohn.Forte@Sun.COM return (EIO);
667836SJohn.Forte@Sun.COM } else if ((group->diskqrsrv == 0) &&
677836SJohn.Forte@Sun.COM (rc = nsc_reserve(group->diskqfd, 0)) != 0) {
687836SJohn.Forte@Sun.COM cmn_err(CE_WARN,
69*9093SRamana.Srikanth@Sun.COM "!rdc: nsc_reserve(%s) failed %d\n",
707836SJohn.Forte@Sun.COM nsc_pathname(group->diskqfd), rc);
717836SJohn.Forte@Sun.COM } else {
727836SJohn.Forte@Sun.COM group->diskqrsrv++;
737836SJohn.Forte@Sun.COM }
747836SJohn.Forte@Sun.COM
757836SJohn.Forte@Sun.COM mutex_exit(&group->diskqmutex);
767836SJohn.Forte@Sun.COM return (rc);
777836SJohn.Forte@Sun.COM }
787836SJohn.Forte@Sun.COM
797836SJohn.Forte@Sun.COM void
_rdc_rlse_diskq(rdc_group_t * group)807836SJohn.Forte@Sun.COM _rdc_rlse_diskq(rdc_group_t *group)
817836SJohn.Forte@Sun.COM {
827836SJohn.Forte@Sun.COM mutex_enter(&group->diskqmutex);
837836SJohn.Forte@Sun.COM if (group->diskqrsrv > 0 && --group->diskqrsrv == 0) {
847836SJohn.Forte@Sun.COM nsc_release(group->diskqfd);
857836SJohn.Forte@Sun.COM }
867836SJohn.Forte@Sun.COM mutex_exit(&group->diskqmutex);
877836SJohn.Forte@Sun.COM }
887836SJohn.Forte@Sun.COM
897836SJohn.Forte@Sun.COM void
rdc_wait_qbusy(disk_queue * q)907836SJohn.Forte@Sun.COM rdc_wait_qbusy(disk_queue *q)
917836SJohn.Forte@Sun.COM {
927836SJohn.Forte@Sun.COM ASSERT(MUTEX_HELD(QLOCK(q)));
937836SJohn.Forte@Sun.COM while (q->busycnt > 0)
947836SJohn.Forte@Sun.COM cv_wait(&q->busycv, QLOCK(q));
957836SJohn.Forte@Sun.COM }
967836SJohn.Forte@Sun.COM
977836SJohn.Forte@Sun.COM void
rdc_set_qbusy(disk_queue * q)987836SJohn.Forte@Sun.COM rdc_set_qbusy(disk_queue *q)
997836SJohn.Forte@Sun.COM {
1007836SJohn.Forte@Sun.COM ASSERT(MUTEX_HELD(QLOCK(q)));
1017836SJohn.Forte@Sun.COM q->busycnt++;
1027836SJohn.Forte@Sun.COM }
1037836SJohn.Forte@Sun.COM
1047836SJohn.Forte@Sun.COM void
rdc_clr_qbusy(disk_queue * q)1057836SJohn.Forte@Sun.COM rdc_clr_qbusy(disk_queue *q)
1067836SJohn.Forte@Sun.COM {
1077836SJohn.Forte@Sun.COM ASSERT(MUTEX_HELD(QLOCK(q)));
1087836SJohn.Forte@Sun.COM q->busycnt--;
1097836SJohn.Forte@Sun.COM if (q->busycnt == 0)
1107836SJohn.Forte@Sun.COM cv_broadcast(&q->busycv);
1117836SJohn.Forte@Sun.COM }
1127836SJohn.Forte@Sun.COM
1137836SJohn.Forte@Sun.COM int
rdc_lookup_diskq(char * pathname)1147836SJohn.Forte@Sun.COM rdc_lookup_diskq(char *pathname)
1157836SJohn.Forte@Sun.COM {
1167836SJohn.Forte@Sun.COM rdc_u_info_t *urdc;
1177836SJohn.Forte@Sun.COM #ifdef DEBUG
1187836SJohn.Forte@Sun.COM rdc_k_info_t *krdc;
1197836SJohn.Forte@Sun.COM #endif
1207836SJohn.Forte@Sun.COM int index;
1217836SJohn.Forte@Sun.COM
1227836SJohn.Forte@Sun.COM for (index = 0; index < rdc_max_sets; index++) {
1237836SJohn.Forte@Sun.COM urdc = &rdc_u_info[index];
1247836SJohn.Forte@Sun.COM #ifdef DEBUG
1257836SJohn.Forte@Sun.COM krdc = &rdc_k_info[index];
1267836SJohn.Forte@Sun.COM #endif
1277836SJohn.Forte@Sun.COM ASSERT(krdc->index == index);
1287836SJohn.Forte@Sun.COM ASSERT(urdc->index == index);
1297836SJohn.Forte@Sun.COM if (!IS_ENABLED(urdc))
1307836SJohn.Forte@Sun.COM continue;
1317836SJohn.Forte@Sun.COM
1327836SJohn.Forte@Sun.COM if (strncmp(pathname, urdc->disk_queue,
1337836SJohn.Forte@Sun.COM NSC_MAXPATH) == 0)
1347836SJohn.Forte@Sun.COM return (index);
1357836SJohn.Forte@Sun.COM }
1367836SJohn.Forte@Sun.COM
1377836SJohn.Forte@Sun.COM return (-1);
1387836SJohn.Forte@Sun.COM }
1397836SJohn.Forte@Sun.COM
1407836SJohn.Forte@Sun.COM void
rdc_unintercept_diskq(rdc_group_t * grp)1417836SJohn.Forte@Sun.COM rdc_unintercept_diskq(rdc_group_t *grp)
1427836SJohn.Forte@Sun.COM {
1437836SJohn.Forte@Sun.COM if (!RDC_IS_DISKQ(grp))
1447836SJohn.Forte@Sun.COM return;
1457836SJohn.Forte@Sun.COM if (grp->q_tok)
1467836SJohn.Forte@Sun.COM (void) nsc_unregister_path(grp->q_tok, 0);
1477836SJohn.Forte@Sun.COM grp->q_tok = NULL;
1487836SJohn.Forte@Sun.COM }
1497836SJohn.Forte@Sun.COM
1507836SJohn.Forte@Sun.COM void
rdc_close_diskq(rdc_group_t * grp)1517836SJohn.Forte@Sun.COM rdc_close_diskq(rdc_group_t *grp)
1527836SJohn.Forte@Sun.COM {
1537836SJohn.Forte@Sun.COM
1547836SJohn.Forte@Sun.COM if (grp == NULL) {
1557836SJohn.Forte@Sun.COM #ifdef DEBUG
156*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!rdc_close_diskq: NULL group!");
1577836SJohn.Forte@Sun.COM #endif
1587836SJohn.Forte@Sun.COM return;
1597836SJohn.Forte@Sun.COM }
1607836SJohn.Forte@Sun.COM
1617836SJohn.Forte@Sun.COM if (grp->diskqfd) {
1627836SJohn.Forte@Sun.COM if (nsc_close(grp->diskqfd) != 0) {
1637836SJohn.Forte@Sun.COM #ifdef DEBUG
164*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!nsc_close on diskq failed");
1657836SJohn.Forte@Sun.COM #else
1667836SJohn.Forte@Sun.COM ;
1677836SJohn.Forte@Sun.COM /*EMPTY*/
1687836SJohn.Forte@Sun.COM #endif
1697836SJohn.Forte@Sun.COM }
1707836SJohn.Forte@Sun.COM grp->diskqfd = 0;
1717836SJohn.Forte@Sun.COM grp->diskqrsrv = 0;
1727836SJohn.Forte@Sun.COM }
1737836SJohn.Forte@Sun.COM bzero(&grp->diskq.disk_hdr, sizeof (diskq_header));
1747836SJohn.Forte@Sun.COM }
1757836SJohn.Forte@Sun.COM
1767836SJohn.Forte@Sun.COM /*
1777836SJohn.Forte@Sun.COM * nsc_open the diskq and attach
1787836SJohn.Forte@Sun.COM * the nsc_fd to krdc->diskqfd
1797836SJohn.Forte@Sun.COM */
1807836SJohn.Forte@Sun.COM int
rdc_open_diskq(rdc_k_info_t * krdc)1817836SJohn.Forte@Sun.COM rdc_open_diskq(rdc_k_info_t *krdc)
1827836SJohn.Forte@Sun.COM {
1837836SJohn.Forte@Sun.COM rdc_u_info_t *urdc;
1847836SJohn.Forte@Sun.COM rdc_group_t *grp;
1857836SJohn.Forte@Sun.COM int sts;
1867836SJohn.Forte@Sun.COM nsc_size_t size;
1877836SJohn.Forte@Sun.COM char *diskqname;
1887836SJohn.Forte@Sun.COM int mutexheld = 0;
1897836SJohn.Forte@Sun.COM
1907836SJohn.Forte@Sun.COM grp = krdc->group;
1917836SJohn.Forte@Sun.COM urdc = &rdc_u_info[krdc->index];
1927836SJohn.Forte@Sun.COM
1937836SJohn.Forte@Sun.COM mutex_enter(&grp->diskqmutex);
1947836SJohn.Forte@Sun.COM mutexheld++;
1957836SJohn.Forte@Sun.COM if (&urdc->disk_queue[0] == '\0') {
1967836SJohn.Forte@Sun.COM goto fail;
1977836SJohn.Forte@Sun.COM }
1987836SJohn.Forte@Sun.COM
1997836SJohn.Forte@Sun.COM diskqname = &urdc->disk_queue[0];
2007836SJohn.Forte@Sun.COM
2017836SJohn.Forte@Sun.COM if (grp->diskqfd == NULL) {
2027836SJohn.Forte@Sun.COM grp->diskqfd = nsc_open(diskqname,
2037836SJohn.Forte@Sun.COM NSC_RDCHR_ID|NSC_DEVICE|NSC_WRITE, 0, 0, 0);
2047836SJohn.Forte@Sun.COM if (grp->diskqfd == NULL) {
205*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!rdc_open_diskq: Unable to open %s",
2067836SJohn.Forte@Sun.COM diskqname);
2077836SJohn.Forte@Sun.COM goto fail;
2087836SJohn.Forte@Sun.COM }
2097836SJohn.Forte@Sun.COM }
2107836SJohn.Forte@Sun.COM if (!grp->q_tok)
2117836SJohn.Forte@Sun.COM grp->q_tok = nsc_register_path(urdc->disk_queue,
2127836SJohn.Forte@Sun.COM NSC_DEVICE | NSC_CACHE, _rdc_io_hc);
2137836SJohn.Forte@Sun.COM
2147836SJohn.Forte@Sun.COM grp->diskqrsrv = 0; /* init reserve count */
2157836SJohn.Forte@Sun.COM
2167836SJohn.Forte@Sun.COM mutex_exit(&grp->diskqmutex);
2177836SJohn.Forte@Sun.COM mutexheld--;
2187836SJohn.Forte@Sun.COM /* just test a reserve release */
2197836SJohn.Forte@Sun.COM sts = _rdc_rsrv_diskq(grp);
2207836SJohn.Forte@Sun.COM if (!RDC_SUCCESS(sts)) {
221*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!rdc_open_diskq: Reserve failed for %s",
2227836SJohn.Forte@Sun.COM diskqname);
2237836SJohn.Forte@Sun.COM goto fail;
2247836SJohn.Forte@Sun.COM }
2257836SJohn.Forte@Sun.COM sts = nsc_partsize(grp->diskqfd, &size);
2267836SJohn.Forte@Sun.COM _rdc_rlse_diskq(grp);
2277836SJohn.Forte@Sun.COM
2287836SJohn.Forte@Sun.COM if ((sts == 0) && (size < 1)) {
2297836SJohn.Forte@Sun.COM rdc_unintercept_diskq(grp);
2307836SJohn.Forte@Sun.COM rdc_close_diskq(grp);
2317836SJohn.Forte@Sun.COM goto fail;
2327836SJohn.Forte@Sun.COM }
2337836SJohn.Forte@Sun.COM
2347836SJohn.Forte@Sun.COM return (0);
2357836SJohn.Forte@Sun.COM
2367836SJohn.Forte@Sun.COM fail:
2377836SJohn.Forte@Sun.COM bzero(&urdc->disk_queue, NSC_MAXPATH);
2387836SJohn.Forte@Sun.COM if (mutexheld)
2397836SJohn.Forte@Sun.COM mutex_exit(&grp->diskqmutex);
2407836SJohn.Forte@Sun.COM return (-1);
2417836SJohn.Forte@Sun.COM
2427836SJohn.Forte@Sun.COM }
2437836SJohn.Forte@Sun.COM
2447836SJohn.Forte@Sun.COM /*
2457836SJohn.Forte@Sun.COM * rdc_count_vecs
2467836SJohn.Forte@Sun.COM * simply vec++'s until sb_addr is null
2477836SJohn.Forte@Sun.COM * returns number of vectors encountered
2487836SJohn.Forte@Sun.COM */
2497836SJohn.Forte@Sun.COM int
rdc_count_vecs(nsc_vec_t * vec)2507836SJohn.Forte@Sun.COM rdc_count_vecs(nsc_vec_t *vec)
2517836SJohn.Forte@Sun.COM {
2527836SJohn.Forte@Sun.COM nsc_vec_t *vecp;
2537836SJohn.Forte@Sun.COM int i = 0;
2547836SJohn.Forte@Sun.COM vecp = vec;
2557836SJohn.Forte@Sun.COM while (vecp->sv_addr) {
2567836SJohn.Forte@Sun.COM vecp++;
2577836SJohn.Forte@Sun.COM i++;
2587836SJohn.Forte@Sun.COM }
2597836SJohn.Forte@Sun.COM return (i+1);
2607836SJohn.Forte@Sun.COM }
2617836SJohn.Forte@Sun.COM /*
2627836SJohn.Forte@Sun.COM * rdc_setid2idx
2637836SJohn.Forte@Sun.COM * given setid, return index
2647836SJohn.Forte@Sun.COM */
2657836SJohn.Forte@Sun.COM int
rdc_setid2idx(int setid)2667836SJohn.Forte@Sun.COM rdc_setid2idx(int setid) {
2677836SJohn.Forte@Sun.COM
2687836SJohn.Forte@Sun.COM int index = 0;
2697836SJohn.Forte@Sun.COM
2707836SJohn.Forte@Sun.COM for (index = 0; index < rdc_max_sets; index++) {
2717836SJohn.Forte@Sun.COM if (rdc_u_info[index].setid == setid)
2727836SJohn.Forte@Sun.COM break;
2737836SJohn.Forte@Sun.COM }
2747836SJohn.Forte@Sun.COM if (index >= rdc_max_sets)
2757836SJohn.Forte@Sun.COM index = -1;
2767836SJohn.Forte@Sun.COM return (index);
2777836SJohn.Forte@Sun.COM }
2787836SJohn.Forte@Sun.COM
2797836SJohn.Forte@Sun.COM /*
2807836SJohn.Forte@Sun.COM * rdc_idx2setid
2817836SJohn.Forte@Sun.COM * given an index, return its setid
2827836SJohn.Forte@Sun.COM */
2837836SJohn.Forte@Sun.COM int
rdc_idx2setid(int index)2847836SJohn.Forte@Sun.COM rdc_idx2setid(int index)
2857836SJohn.Forte@Sun.COM {
2867836SJohn.Forte@Sun.COM return (rdc_u_info[index].setid);
2877836SJohn.Forte@Sun.COM }
2887836SJohn.Forte@Sun.COM
2897836SJohn.Forte@Sun.COM /*
2907836SJohn.Forte@Sun.COM * rdc_fill_ioheader
2917836SJohn.Forte@Sun.COM * fill in all the stuff you want to save on disk
2927836SJohn.Forte@Sun.COM * at the beginnig of each queued write
2937836SJohn.Forte@Sun.COM */
2947836SJohn.Forte@Sun.COM void
rdc_fill_ioheader(rdc_aio_t * aio,io_hdr * hd,int qpos)2957836SJohn.Forte@Sun.COM rdc_fill_ioheader(rdc_aio_t *aio, io_hdr *hd, int qpos)
2967836SJohn.Forte@Sun.COM {
2977836SJohn.Forte@Sun.COM ASSERT(MUTEX_HELD(&rdc_k_info[aio->index].group->diskq.disk_qlock));
2987836SJohn.Forte@Sun.COM
2997836SJohn.Forte@Sun.COM hd->dat.magic = RDC_IOHDR_MAGIC;
3007836SJohn.Forte@Sun.COM hd->dat.type = RDC_QUEUEIO;
3017836SJohn.Forte@Sun.COM hd->dat.pos = aio->pos;
3027836SJohn.Forte@Sun.COM hd->dat.hpos = aio->pos;
3037836SJohn.Forte@Sun.COM hd->dat.qpos = qpos;
3047836SJohn.Forte@Sun.COM hd->dat.len = aio->len;
3057836SJohn.Forte@Sun.COM hd->dat.flag = aio->flag;
3067836SJohn.Forte@Sun.COM hd->dat.iostatus = aio->iostatus;
3077836SJohn.Forte@Sun.COM hd->dat.setid = rdc_idx2setid(aio->index);
3087836SJohn.Forte@Sun.COM hd->dat.time = nsc_time();
3097836SJohn.Forte@Sun.COM if (!aio->handle)
3107836SJohn.Forte@Sun.COM hd->dat.flag |= RDC_NULL_BUF; /* no real data to queue */
3117836SJohn.Forte@Sun.COM }
3127836SJohn.Forte@Sun.COM
3137836SJohn.Forte@Sun.COM /*
3147836SJohn.Forte@Sun.COM * rdc_dump_iohdrs
3157836SJohn.Forte@Sun.COM * give back the iohdr list
3167836SJohn.Forte@Sun.COM * and clear out q->lastio
3177836SJohn.Forte@Sun.COM */
3187836SJohn.Forte@Sun.COM void
rdc_dump_iohdrs(disk_queue * q)3197836SJohn.Forte@Sun.COM rdc_dump_iohdrs(disk_queue *q)
3207836SJohn.Forte@Sun.COM {
3217836SJohn.Forte@Sun.COM io_hdr *p, *r;
3227836SJohn.Forte@Sun.COM
3237836SJohn.Forte@Sun.COM ASSERT(MUTEX_HELD(QLOCK(q)));
3247836SJohn.Forte@Sun.COM
3257836SJohn.Forte@Sun.COM p = q->iohdrs;
3267836SJohn.Forte@Sun.COM while (p) {
3277836SJohn.Forte@Sun.COM r = p->dat.next;
3287836SJohn.Forte@Sun.COM kmem_free(p, sizeof (*p));
3297836SJohn.Forte@Sun.COM q->hdrcnt--;
3307836SJohn.Forte@Sun.COM p = r;
3317836SJohn.Forte@Sun.COM }
3327836SJohn.Forte@Sun.COM q->iohdrs = q->hdr_last = NULL;
3337836SJohn.Forte@Sun.COM q->hdrcnt = 0;
3347836SJohn.Forte@Sun.COM if (q->lastio->handle)
3357836SJohn.Forte@Sun.COM (void) nsc_free_buf(q->lastio->handle);
3367836SJohn.Forte@Sun.COM bzero(&(*q->lastio), sizeof (*q->lastio));
3377836SJohn.Forte@Sun.COM }
3387836SJohn.Forte@Sun.COM
3397836SJohn.Forte@Sun.COM /*
3407836SJohn.Forte@Sun.COM * rdc_fail_diskq
3417836SJohn.Forte@Sun.COM * set flags, throw away q info
3427836SJohn.Forte@Sun.COM * clean up what you can
3437836SJohn.Forte@Sun.COM * wait for flusher threads to stop (taking into account this may be one)
3447836SJohn.Forte@Sun.COM * takes group_lock, so conf, many, and bitmap may not be held
3457836SJohn.Forte@Sun.COM */
3467836SJohn.Forte@Sun.COM void
rdc_fail_diskq(rdc_k_info_t * krdc,int wait,int flag)3477836SJohn.Forte@Sun.COM rdc_fail_diskq(rdc_k_info_t *krdc, int wait, int flag)
3487836SJohn.Forte@Sun.COM {
3497836SJohn.Forte@Sun.COM rdc_k_info_t *p;
3507836SJohn.Forte@Sun.COM rdc_u_info_t *q = &rdc_u_info[krdc->index];
3517836SJohn.Forte@Sun.COM rdc_group_t *group = krdc->group;
3527836SJohn.Forte@Sun.COM disk_queue *dq = &krdc->group->diskq;
3537836SJohn.Forte@Sun.COM
3547836SJohn.Forte@Sun.COM if (IS_STATE(q, RDC_DISKQ_FAILED))
3557836SJohn.Forte@Sun.COM return;
3567836SJohn.Forte@Sun.COM
3577836SJohn.Forte@Sun.COM if (!(flag & RDC_NOFAIL))
358*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!disk queue %s failure", q->disk_queue);
3597836SJohn.Forte@Sun.COM
3607836SJohn.Forte@Sun.COM if (flag & RDC_DOLOG) {
3617836SJohn.Forte@Sun.COM rdc_group_enter(krdc);
3627836SJohn.Forte@Sun.COM rdc_group_log(krdc, RDC_NOFLUSH | RDC_ALLREMOTE,
363*9093SRamana.Srikanth@Sun.COM "disk queue failed");
3647836SJohn.Forte@Sun.COM rdc_group_exit(krdc);
3657836SJohn.Forte@Sun.COM }
3667836SJohn.Forte@Sun.COM mutex_enter(QHEADLOCK(dq));
3677836SJohn.Forte@Sun.COM mutex_enter(QLOCK(dq));
3687836SJohn.Forte@Sun.COM /*
3697836SJohn.Forte@Sun.COM * quick stop of the flushers
3707836SJohn.Forte@Sun.COM * other cleanup is done on the un-failing of the diskq
3717836SJohn.Forte@Sun.COM */
3727836SJohn.Forte@Sun.COM SET_QHEAD(dq, RDC_DISKQ_DATA_OFF);
3737836SJohn.Forte@Sun.COM SET_QTAIL(dq, RDC_DISKQ_DATA_OFF);
3747836SJohn.Forte@Sun.COM SET_QNXTIO(dq, RDC_DISKQ_DATA_OFF);
3757836SJohn.Forte@Sun.COM SET_LASTQTAIL(dq, 0);
3767836SJohn.Forte@Sun.COM
3777836SJohn.Forte@Sun.COM rdc_dump_iohdrs(dq);
3787836SJohn.Forte@Sun.COM
3797836SJohn.Forte@Sun.COM mutex_exit(QLOCK(dq));
3807836SJohn.Forte@Sun.COM mutex_exit(QHEADLOCK(dq));
3817836SJohn.Forte@Sun.COM
3827836SJohn.Forte@Sun.COM bzero(krdc->bitmap_ref, krdc->bitmap_size * BITS_IN_BYTE *
3837836SJohn.Forte@Sun.COM BMAP_REF_PREF_SIZE);
3847836SJohn.Forte@Sun.COM
3857836SJohn.Forte@Sun.COM if (flag & RDC_DOLOG) /* otherwise, we already have the conf lock */
3867836SJohn.Forte@Sun.COM rdc_group_enter(krdc);
3877836SJohn.Forte@Sun.COM
3887836SJohn.Forte@Sun.COM else if (!(flag & RDC_GROUP_LOCKED))
3897836SJohn.Forte@Sun.COM ASSERT(MUTEX_HELD(&rdc_conf_lock));
3907836SJohn.Forte@Sun.COM
3917836SJohn.Forte@Sun.COM if (!(flag & RDC_NOFAIL)) {
3927836SJohn.Forte@Sun.COM rdc_set_flags(q, RDC_DISKQ_FAILED);
3937836SJohn.Forte@Sun.COM }
3947836SJohn.Forte@Sun.COM rdc_clr_flags(q, RDC_QUEUING);
3957836SJohn.Forte@Sun.COM
3967836SJohn.Forte@Sun.COM for (p = krdc->group_next; p != krdc; p = p->group_next) {
3977836SJohn.Forte@Sun.COM q = &rdc_u_info[p->index];
3987836SJohn.Forte@Sun.COM if (!IS_ENABLED(q))
3997836SJohn.Forte@Sun.COM continue;
4007836SJohn.Forte@Sun.COM if (!(flag & RDC_NOFAIL)) {
4017836SJohn.Forte@Sun.COM rdc_set_flags(q, RDC_DISKQ_FAILED);
4027836SJohn.Forte@Sun.COM }
4037836SJohn.Forte@Sun.COM rdc_clr_flags(q, RDC_QUEUING);
4047836SJohn.Forte@Sun.COM bzero(p->bitmap_ref, p->bitmap_size * BITS_IN_BYTE *
4057836SJohn.Forte@Sun.COM BMAP_REF_PREF_SIZE);
4067836SJohn.Forte@Sun.COM /* RDC_QUEUING is cleared in group_log() */
4077836SJohn.Forte@Sun.COM }
4087836SJohn.Forte@Sun.COM
4097836SJohn.Forte@Sun.COM if (flag & RDC_DOLOG)
4107836SJohn.Forte@Sun.COM rdc_group_exit(krdc);
4117836SJohn.Forte@Sun.COM
4127836SJohn.Forte@Sun.COM /* can't wait for myself to go away, I'm a flusher */
4137836SJohn.Forte@Sun.COM if (wait & RDC_WAIT)
4147836SJohn.Forte@Sun.COM while (group->rdc_thrnum)
4157836SJohn.Forte@Sun.COM delay(2);
4167836SJohn.Forte@Sun.COM
4177836SJohn.Forte@Sun.COM }
4187836SJohn.Forte@Sun.COM
4197836SJohn.Forte@Sun.COM /*
4207836SJohn.Forte@Sun.COM * rdc_stamp_diskq
4217836SJohn.Forte@Sun.COM * write out diskq header info
4227836SJohn.Forte@Sun.COM * must have disk_qlock held
4237836SJohn.Forte@Sun.COM * if rsrvd flag is 0, the nsc_reserve is done
4247836SJohn.Forte@Sun.COM */
4257836SJohn.Forte@Sun.COM int
rdc_stamp_diskq(rdc_k_info_t * krdc,int rsrvd,int failflags)4267836SJohn.Forte@Sun.COM rdc_stamp_diskq(rdc_k_info_t *krdc, int rsrvd, int failflags)
4277836SJohn.Forte@Sun.COM {
4287836SJohn.Forte@Sun.COM nsc_vec_t vec[2];
4297836SJohn.Forte@Sun.COM nsc_buf_t *head = NULL;
4307836SJohn.Forte@Sun.COM rdc_group_t *grp;
4317836SJohn.Forte@Sun.COM rdc_u_info_t *urdc;
4327836SJohn.Forte@Sun.COM disk_queue *q;
4337836SJohn.Forte@Sun.COM int rc, flags;
4347836SJohn.Forte@Sun.COM
4357836SJohn.Forte@Sun.COM grp = krdc->group;
4367836SJohn.Forte@Sun.COM q = &krdc->group->diskq;
4377836SJohn.Forte@Sun.COM
4387836SJohn.Forte@Sun.COM ASSERT(MUTEX_HELD(&q->disk_qlock));
4397836SJohn.Forte@Sun.COM
4407836SJohn.Forte@Sun.COM urdc = &rdc_u_info[krdc->index];
4417836SJohn.Forte@Sun.COM
4427836SJohn.Forte@Sun.COM if (!rsrvd && _rdc_rsrv_diskq(grp)) {
443*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!rdc_stamp_diskq: %s reserve failed",
4447836SJohn.Forte@Sun.COM urdc->disk_queue);
4457836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
4467836SJohn.Forte@Sun.COM rdc_fail_diskq(krdc, RDC_NOWAIT, failflags);
4477836SJohn.Forte@Sun.COM mutex_enter(QLOCK(q));
4487836SJohn.Forte@Sun.COM return (-1);
4497836SJohn.Forte@Sun.COM }
4507836SJohn.Forte@Sun.COM flags = NSC_WRITE | NSC_NOCACHE | NSC_NODATA;
4517836SJohn.Forte@Sun.COM rc = nsc_alloc_buf(grp->diskqfd, 0, 1, flags, &head);
4527836SJohn.Forte@Sun.COM
4537836SJohn.Forte@Sun.COM if (!RDC_SUCCESS(rc)) {
454*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!Alloc buf failed for disk queue %s",
4557836SJohn.Forte@Sun.COM &urdc->disk_queue[0]);
4567836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
4577836SJohn.Forte@Sun.COM rdc_fail_diskq(krdc, RDC_NOWAIT, failflags);
4587836SJohn.Forte@Sun.COM mutex_enter(QLOCK(q));
4597836SJohn.Forte@Sun.COM return (-1);
4607836SJohn.Forte@Sun.COM }
4617836SJohn.Forte@Sun.COM vec[0].sv_len = FBA_SIZE(1);
4627836SJohn.Forte@Sun.COM vec[0].sv_addr = (uchar_t *)&q->disk_hdr;
4637836SJohn.Forte@Sun.COM vec[1].sv_len = 0;
4647836SJohn.Forte@Sun.COM vec[1].sv_addr = NULL;
4657836SJohn.Forte@Sun.COM
4667836SJohn.Forte@Sun.COM head->sb_vec = &vec[0];
4677836SJohn.Forte@Sun.COM
4687836SJohn.Forte@Sun.COM #ifdef DEBUG_DISKQ
469*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!rdc_stamp_diskq: hdr: %p magic: %x state: "
4707836SJohn.Forte@Sun.COM "%x head: %d tail: %d size: %d nitems: %d blocks: %d",
4717836SJohn.Forte@Sun.COM q, QMAGIC(q), QSTATE(q), QHEAD(q),
4727836SJohn.Forte@Sun.COM QTAIL(q), QSIZE(q), QNITEMS(q), QBLOCKS(q));
4737836SJohn.Forte@Sun.COM #endif
4747836SJohn.Forte@Sun.COM
4757836SJohn.Forte@Sun.COM rc = nsc_write(head, 0, 1, 0);
4767836SJohn.Forte@Sun.COM
4777836SJohn.Forte@Sun.COM if (!RDC_SUCCESS(rc)) {
4787836SJohn.Forte@Sun.COM if (!rsrvd)
4797836SJohn.Forte@Sun.COM _rdc_rlse_diskq(grp);
480*9093SRamana.Srikanth@Sun.COM cmn_err(CE_CONT, "!disk queue %s failed rc %d",
4817836SJohn.Forte@Sun.COM &urdc->disk_queue[0], rc);
4827836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
4837836SJohn.Forte@Sun.COM rdc_fail_diskq(krdc, RDC_NOWAIT, failflags);
4847836SJohn.Forte@Sun.COM mutex_enter(QLOCK(q));
4857836SJohn.Forte@Sun.COM return (-1);
4867836SJohn.Forte@Sun.COM }
4877836SJohn.Forte@Sun.COM
4887836SJohn.Forte@Sun.COM (void) nsc_free_buf(head);
4897836SJohn.Forte@Sun.COM if (!rsrvd)
4907836SJohn.Forte@Sun.COM _rdc_rlse_diskq(grp);
4917836SJohn.Forte@Sun.COM
4927836SJohn.Forte@Sun.COM return (0);
4937836SJohn.Forte@Sun.COM }
4947836SJohn.Forte@Sun.COM
4957836SJohn.Forte@Sun.COM /*
4967836SJohn.Forte@Sun.COM * rdc_init_diskq_header
4977836SJohn.Forte@Sun.COM * load initial values into the header
4987836SJohn.Forte@Sun.COM */
4997836SJohn.Forte@Sun.COM void
rdc_init_diskq_header(rdc_group_t * grp,dqheader * header)5007836SJohn.Forte@Sun.COM rdc_init_diskq_header(rdc_group_t *grp, dqheader *header)
5017836SJohn.Forte@Sun.COM {
5027836SJohn.Forte@Sun.COM int rc;
5037836SJohn.Forte@Sun.COM int type = 0;
5047836SJohn.Forte@Sun.COM disk_queue *q = &grp->diskq;
5057836SJohn.Forte@Sun.COM
5067836SJohn.Forte@Sun.COM ASSERT(MUTEX_HELD(QLOCK(q)));
5077836SJohn.Forte@Sun.COM
5087836SJohn.Forte@Sun.COM /* save q type if this is a failure */
5097836SJohn.Forte@Sun.COM if (QSTATE(q) & RDC_QNOBLOCK)
5107836SJohn.Forte@Sun.COM type = RDC_QNOBLOCK;
5117836SJohn.Forte@Sun.COM bzero(header, sizeof (*header));
5127836SJohn.Forte@Sun.COM header->h.magic = RDC_DISKQ_MAGIC;
5137836SJohn.Forte@Sun.COM header->h.vers = RDC_DISKQ_VERS;
5147836SJohn.Forte@Sun.COM header->h.state |= (RDC_SHUTDOWN_BAD|type); /* SHUTDOWN_OK on suspend */
5157836SJohn.Forte@Sun.COM header->h.head_offset = RDC_DISKQ_DATA_OFF;
5167836SJohn.Forte@Sun.COM header->h.tail_offset = RDC_DISKQ_DATA_OFF;
5177836SJohn.Forte@Sun.COM header->h.nitems = 0;
5187836SJohn.Forte@Sun.COM header->h.blocks = 0;
5197836SJohn.Forte@Sun.COM header->h.qwrap = 0;
5207836SJohn.Forte@Sun.COM SET_QNXTIO(q, QHEAD(q));
5217836SJohn.Forte@Sun.COM SET_QCOALBOUNDS(q, RDC_DISKQ_DATA_OFF);
5227836SJohn.Forte@Sun.COM
5237836SJohn.Forte@Sun.COM /* do this last, as this might be a failure. get the kernel state ok */
5247836SJohn.Forte@Sun.COM rc = _rdc_rsrv_diskq(grp);
5257836SJohn.Forte@Sun.COM if (!RDC_SUCCESS(rc)) {
526*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!init_diskq_hdr: Reserve failed for queue");
5277836SJohn.Forte@Sun.COM return;
5287836SJohn.Forte@Sun.COM }
5297836SJohn.Forte@Sun.COM (void) nsc_partsize(grp->diskqfd, &header->h.disk_size);
5307836SJohn.Forte@Sun.COM _rdc_rlse_diskq(grp);
5317836SJohn.Forte@Sun.COM
5327836SJohn.Forte@Sun.COM }
5337836SJohn.Forte@Sun.COM
5347836SJohn.Forte@Sun.COM /*
5357836SJohn.Forte@Sun.COM * rdc_unfail_diskq
5367836SJohn.Forte@Sun.COM * the diskq failed for some reason, lets try and re-start it
5377836SJohn.Forte@Sun.COM * the old stuff has already been thrown away
5387836SJohn.Forte@Sun.COM * should just be called from rdc_sync
5397836SJohn.Forte@Sun.COM */
5407836SJohn.Forte@Sun.COM void
rdc_unfail_diskq(rdc_k_info_t * krdc)5417836SJohn.Forte@Sun.COM rdc_unfail_diskq(rdc_k_info_t *krdc)
5427836SJohn.Forte@Sun.COM {
5437836SJohn.Forte@Sun.COM rdc_k_info_t *p;
5447836SJohn.Forte@Sun.COM rdc_u_info_t *q = &rdc_u_info[krdc->index];
5457836SJohn.Forte@Sun.COM rdc_group_t *group = krdc->group;
5467836SJohn.Forte@Sun.COM disk_queue *dq = &group->diskq;
5477836SJohn.Forte@Sun.COM
5487836SJohn.Forte@Sun.COM rdc_group_enter(krdc);
5497836SJohn.Forte@Sun.COM rdc_clr_flags(q, RDC_ASYNC);
5507836SJohn.Forte@Sun.COM /* someone else won the race... */
5517836SJohn.Forte@Sun.COM if (!IS_STATE(q, RDC_DISKQ_FAILED)) {
5527836SJohn.Forte@Sun.COM rdc_group_exit(krdc);
5537836SJohn.Forte@Sun.COM return;
5547836SJohn.Forte@Sun.COM }
5557836SJohn.Forte@Sun.COM rdc_clr_flags(q, RDC_DISKQ_FAILED);
5567836SJohn.Forte@Sun.COM for (p = krdc->group_next; p != krdc; p = p->group_next) {
5577836SJohn.Forte@Sun.COM q = &rdc_u_info[p->index];
5587836SJohn.Forte@Sun.COM if (!IS_ENABLED(q))
5597836SJohn.Forte@Sun.COM continue;
5607836SJohn.Forte@Sun.COM rdc_clr_flags(q, RDC_DISKQ_FAILED);
5617836SJohn.Forte@Sun.COM rdc_clr_flags(q, RDC_ASYNC);
5627836SJohn.Forte@Sun.COM if (IS_STATE(q, RDC_QUEUING))
5637836SJohn.Forte@Sun.COM rdc_clr_flags(q, RDC_QUEUING);
5647836SJohn.Forte@Sun.COM }
5657836SJohn.Forte@Sun.COM rdc_group_exit(krdc);
5667836SJohn.Forte@Sun.COM
5677836SJohn.Forte@Sun.COM mutex_enter(QLOCK(dq));
5687836SJohn.Forte@Sun.COM
5697836SJohn.Forte@Sun.COM rdc_init_diskq_header(group, &group->diskq.disk_hdr);
5707836SJohn.Forte@Sun.COM /* real i/o to the queue */
5717836SJohn.Forte@Sun.COM /* clear RDC_AUXSYNCIP because we cannot halt a sync that's not here */
5727836SJohn.Forte@Sun.COM krdc->aux_state &= ~RDC_AUXSYNCIP;
5737836SJohn.Forte@Sun.COM if (rdc_stamp_diskq(krdc, 0, RDC_GROUP_LOCKED | RDC_DOLOG) < 0) {
5747836SJohn.Forte@Sun.COM mutex_exit(QLOCK(dq));
5757836SJohn.Forte@Sun.COM goto fail;
5767836SJohn.Forte@Sun.COM }
5777836SJohn.Forte@Sun.COM
5787836SJohn.Forte@Sun.COM SET_QNXTIO(dq, QHEAD(dq));
5797836SJohn.Forte@Sun.COM SET_QHDRCNT(dq, 0);
5807836SJohn.Forte@Sun.COM SET_QSTATE(dq, RDC_SHUTDOWN_BAD); /* only suspend can write good */
5817836SJohn.Forte@Sun.COM dq->iohdrs = NULL;
5827836SJohn.Forte@Sun.COM dq->hdr_last = NULL;
5837836SJohn.Forte@Sun.COM
5847836SJohn.Forte@Sun.COM /* should be none, but.. */
5857836SJohn.Forte@Sun.COM rdc_dump_iohdrs(dq);
5867836SJohn.Forte@Sun.COM
5877836SJohn.Forte@Sun.COM mutex_exit(QLOCK(dq));
5887836SJohn.Forte@Sun.COM
5897836SJohn.Forte@Sun.COM
5907836SJohn.Forte@Sun.COM fail:
5917836SJohn.Forte@Sun.COM krdc->aux_state |= RDC_AUXSYNCIP;
5927836SJohn.Forte@Sun.COM return;
5937836SJohn.Forte@Sun.COM
5947836SJohn.Forte@Sun.COM }
5957836SJohn.Forte@Sun.COM
5967836SJohn.Forte@Sun.COM int
rdc_read_diskq_header(rdc_k_info_t * krdc)5977836SJohn.Forte@Sun.COM rdc_read_diskq_header(rdc_k_info_t *krdc)
5987836SJohn.Forte@Sun.COM {
5997836SJohn.Forte@Sun.COM int rc;
6007836SJohn.Forte@Sun.COM diskq_header *header;
6017836SJohn.Forte@Sun.COM rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
6027836SJohn.Forte@Sun.COM
6037836SJohn.Forte@Sun.COM if (krdc->group->diskqfd == NULL) {
6047836SJohn.Forte@Sun.COM char buf[NSC_MAXPATH];
6057836SJohn.Forte@Sun.COM (void) snprintf(buf, NSC_MAXPATH, "%s:%s", urdc->secondary.intf,
6067836SJohn.Forte@Sun.COM &urdc->secondary.intf[0]);
607*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!Disk Queue Header read failed for %s",
6087836SJohn.Forte@Sun.COM &urdc->group_name[0] == '\0' ? buf:
6097836SJohn.Forte@Sun.COM &urdc->group_name[0]);
6107836SJohn.Forte@Sun.COM return (-1);
6117836SJohn.Forte@Sun.COM }
6127836SJohn.Forte@Sun.COM
6137836SJohn.Forte@Sun.COM header = &krdc->group->diskq.disk_hdr.h;
6147836SJohn.Forte@Sun.COM if (_rdc_rsrv_diskq(krdc->group)) {
6157836SJohn.Forte@Sun.COM return (-1);
6167836SJohn.Forte@Sun.COM }
6177836SJohn.Forte@Sun.COM
6187836SJohn.Forte@Sun.COM rc = rdc_ns_io(krdc->group->diskqfd, NSC_RDBUF, 0,
6197836SJohn.Forte@Sun.COM (uchar_t *)header, sizeof (diskq_header));
6207836SJohn.Forte@Sun.COM
6217836SJohn.Forte@Sun.COM _rdc_rlse_diskq(krdc->group);
6227836SJohn.Forte@Sun.COM
6237836SJohn.Forte@Sun.COM if (!RDC_SUCCESS(rc)) {
6247836SJohn.Forte@Sun.COM char buf[NSC_MAXPATH];
6257836SJohn.Forte@Sun.COM (void) snprintf(buf, NSC_MAXPATH, "%s:%s", urdc->secondary.intf,
6267836SJohn.Forte@Sun.COM &urdc->secondary.file[0]);
627*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!Disk Queue Header read failed(%d) for %s",
6287836SJohn.Forte@Sun.COM rc, &urdc->group_name[0] == '\0' ? buf :
6297836SJohn.Forte@Sun.COM &urdc->group_name[0]);
6307836SJohn.Forte@Sun.COM return (-1);
6317836SJohn.Forte@Sun.COM }
6327836SJohn.Forte@Sun.COM return (0);
6337836SJohn.Forte@Sun.COM }
6347836SJohn.Forte@Sun.COM
6357836SJohn.Forte@Sun.COM /*
6367836SJohn.Forte@Sun.COM * rdc_stop_diskq_flusher
6377836SJohn.Forte@Sun.COM */
6387836SJohn.Forte@Sun.COM void
rdc_stop_diskq_flusher(rdc_k_info_t * krdc)6397836SJohn.Forte@Sun.COM rdc_stop_diskq_flusher(rdc_k_info_t *krdc)
6407836SJohn.Forte@Sun.COM {
6417836SJohn.Forte@Sun.COM disk_queue q, *qp;
6427836SJohn.Forte@Sun.COM rdc_group_t *group;
6437836SJohn.Forte@Sun.COM #ifdef DEBUG
644*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!stopping flusher threads");
6457836SJohn.Forte@Sun.COM #endif
6467836SJohn.Forte@Sun.COM group = krdc->group;
6477836SJohn.Forte@Sun.COM qp = &krdc->group->diskq;
6487836SJohn.Forte@Sun.COM
6497836SJohn.Forte@Sun.COM /* save the queue info */
6507836SJohn.Forte@Sun.COM q = *qp;
6517836SJohn.Forte@Sun.COM
6527836SJohn.Forte@Sun.COM /* lie a little */
6537836SJohn.Forte@Sun.COM SET_QTAIL(qp, RDC_DISKQ_DATA_OFF);
6547836SJohn.Forte@Sun.COM SET_QHEAD(qp, RDC_DISKQ_DATA_OFF);
6557836SJohn.Forte@Sun.COM SET_QSTATE(qp, RDC_QDISABLEPEND);
6567836SJohn.Forte@Sun.COM SET_QSTATE(qp, RDC_STOPPINGFLUSH);
6577836SJohn.Forte@Sun.COM
6587836SJohn.Forte@Sun.COM /* drop locks to allow flushers to die */
6597836SJohn.Forte@Sun.COM mutex_exit(QLOCK(qp));
6607836SJohn.Forte@Sun.COM mutex_exit(QHEADLOCK(qp));
6617836SJohn.Forte@Sun.COM rdc_group_exit(krdc);
6627836SJohn.Forte@Sun.COM
6637836SJohn.Forte@Sun.COM while (group->rdc_thrnum)
6647836SJohn.Forte@Sun.COM delay(2);
6657836SJohn.Forte@Sun.COM
6667836SJohn.Forte@Sun.COM rdc_group_enter(krdc);
6677836SJohn.Forte@Sun.COM mutex_enter(QHEADLOCK(qp));
6687836SJohn.Forte@Sun.COM mutex_enter(QLOCK(qp));
6697836SJohn.Forte@Sun.COM
6707836SJohn.Forte@Sun.COM CLR_QSTATE(qp, RDC_STOPPINGFLUSH);
6717836SJohn.Forte@Sun.COM *qp = q;
6727836SJohn.Forte@Sun.COM }
6737836SJohn.Forte@Sun.COM
6747836SJohn.Forte@Sun.COM /*
6757836SJohn.Forte@Sun.COM * rdc_enable_diskq
6767836SJohn.Forte@Sun.COM * open the diskq
6777836SJohn.Forte@Sun.COM * and stamp the header onto it.
6787836SJohn.Forte@Sun.COM */
6797836SJohn.Forte@Sun.COM int
rdc_enable_diskq(rdc_k_info_t * krdc)6807836SJohn.Forte@Sun.COM rdc_enable_diskq(rdc_k_info_t *krdc)
6817836SJohn.Forte@Sun.COM {
6827836SJohn.Forte@Sun.COM rdc_group_t *group;
6837836SJohn.Forte@Sun.COM disk_queue *q;
6847836SJohn.Forte@Sun.COM
6857836SJohn.Forte@Sun.COM group = krdc->group;
6867836SJohn.Forte@Sun.COM q = &group->diskq;
6877836SJohn.Forte@Sun.COM
6887836SJohn.Forte@Sun.COM if (rdc_open_diskq(krdc) < 0)
6897836SJohn.Forte@Sun.COM goto fail;
6907836SJohn.Forte@Sun.COM
6917836SJohn.Forte@Sun.COM mutex_enter(QLOCK(q));
6927836SJohn.Forte@Sun.COM rdc_init_diskq_header(group, &group->diskq.disk_hdr);
6937836SJohn.Forte@Sun.COM
6947836SJohn.Forte@Sun.COM if (rdc_stamp_diskq(krdc, 0, RDC_NOLOG) < 0) {
6957836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
6967836SJohn.Forte@Sun.COM goto fail;
6977836SJohn.Forte@Sun.COM }
6987836SJohn.Forte@Sun.COM
6997836SJohn.Forte@Sun.COM SET_QNXTIO(q, QHEAD(q));
7007836SJohn.Forte@Sun.COM
7017836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
7027836SJohn.Forte@Sun.COM return (0);
7037836SJohn.Forte@Sun.COM
7047836SJohn.Forte@Sun.COM fail:
7057836SJohn.Forte@Sun.COM mutex_enter(&group->diskqmutex);
7067836SJohn.Forte@Sun.COM rdc_close_diskq(group);
7077836SJohn.Forte@Sun.COM mutex_exit(&group->diskqmutex);
7087836SJohn.Forte@Sun.COM
7097836SJohn.Forte@Sun.COM /* caller has to fail diskq after dropping conf & many locks */
7107836SJohn.Forte@Sun.COM return (RDC_EQNOADD);
7117836SJohn.Forte@Sun.COM }
7127836SJohn.Forte@Sun.COM
7137836SJohn.Forte@Sun.COM /*
7147836SJohn.Forte@Sun.COM * rdc_resume_diskq
7157836SJohn.Forte@Sun.COM * open the diskq and read the header
7167836SJohn.Forte@Sun.COM */
7177836SJohn.Forte@Sun.COM int
rdc_resume_diskq(rdc_k_info_t * krdc)7187836SJohn.Forte@Sun.COM rdc_resume_diskq(rdc_k_info_t *krdc)
7197836SJohn.Forte@Sun.COM {
7207836SJohn.Forte@Sun.COM rdc_u_info_t *urdc;
7217836SJohn.Forte@Sun.COM rdc_group_t *group;
7227836SJohn.Forte@Sun.COM disk_queue *q;
7237836SJohn.Forte@Sun.COM int rc = 0;
7247836SJohn.Forte@Sun.COM
7257836SJohn.Forte@Sun.COM urdc = &rdc_u_info[krdc->index];
7267836SJohn.Forte@Sun.COM group = krdc->group;
7277836SJohn.Forte@Sun.COM q = &group->diskq;
7287836SJohn.Forte@Sun.COM
7297836SJohn.Forte@Sun.COM if (rdc_open_diskq(krdc) < 0) {
7307836SJohn.Forte@Sun.COM rc = RDC_EQNOADD;
7317836SJohn.Forte@Sun.COM goto fail;
7327836SJohn.Forte@Sun.COM }
7337836SJohn.Forte@Sun.COM
7347836SJohn.Forte@Sun.COM mutex_enter(QLOCK(q));
7357836SJohn.Forte@Sun.COM
7367836SJohn.Forte@Sun.COM rdc_init_diskq_header(group, &group->diskq.disk_hdr);
7377836SJohn.Forte@Sun.COM
7387836SJohn.Forte@Sun.COM if (rdc_read_diskq_header(krdc) < 0) {
7397836SJohn.Forte@Sun.COM SET_QSTATE(q, RDC_QBADRESUME);
7407836SJohn.Forte@Sun.COM rc = RDC_EQNOADD;
7417836SJohn.Forte@Sun.COM }
7427836SJohn.Forte@Sun.COM
7437836SJohn.Forte@Sun.COM /* check diskq magic number */
7447836SJohn.Forte@Sun.COM if (QMAGIC(q) != RDC_DISKQ_MAGIC) {
745*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!SNDR: unable to resume diskq %s,"
7467836SJohn.Forte@Sun.COM " incorrect magic number in header", urdc->disk_queue);
7477836SJohn.Forte@Sun.COM rdc_init_diskq_header(group, &group->diskq.disk_hdr);
7487836SJohn.Forte@Sun.COM SET_QSTATE(q, RDC_QBADRESUME);
7497836SJohn.Forte@Sun.COM rc = RDC_EQNOADD;
7507836SJohn.Forte@Sun.COM } else switch (QVERS(q)) {
7517836SJohn.Forte@Sun.COM diskq_header1 h1; /* version 1 header */
7527836SJohn.Forte@Sun.COM diskq_header *hc; /* current header */
7537836SJohn.Forte@Sun.COM
7547836SJohn.Forte@Sun.COM #ifdef NSC_MULTI_TERABYTE
7557836SJohn.Forte@Sun.COM case RDC_DISKQ_VER_ORIG:
7567836SJohn.Forte@Sun.COM /* version 1 diskq header, upgrade to 64bit version */
7577836SJohn.Forte@Sun.COM h1 = *(diskq_header1 *)(&group->diskq.disk_hdr.h);
7587836SJohn.Forte@Sun.COM hc = &group->diskq.disk_hdr.h;
7597836SJohn.Forte@Sun.COM
760*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!SNDR: old version header for diskq %s,"
7617836SJohn.Forte@Sun.COM " upgrading to current version", urdc->disk_queue);
7627836SJohn.Forte@Sun.COM hc->vers = RDC_DISKQ_VERS;
7637836SJohn.Forte@Sun.COM hc->state = h1.state;
7647836SJohn.Forte@Sun.COM hc->head_offset = h1.head_offset;
7657836SJohn.Forte@Sun.COM hc->tail_offset = h1.tail_offset;
7667836SJohn.Forte@Sun.COM hc->disk_size = h1.disk_size;
7677836SJohn.Forte@Sun.COM hc->nitems = h1.nitems;
7687836SJohn.Forte@Sun.COM hc->blocks = h1.blocks;
7697836SJohn.Forte@Sun.COM hc->qwrap = h1.qwrap;
7707836SJohn.Forte@Sun.COM hc->auxqwrap = h1.auxqwrap;
7717836SJohn.Forte@Sun.COM hc->seq_last = h1.seq_last;
7727836SJohn.Forte@Sun.COM hc->ack_last = h1.ack_last;
7737836SJohn.Forte@Sun.COM
7747836SJohn.Forte@Sun.COM if (hc->nitems > 0) {
775*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!SNDR: unable to resume diskq %s,"
7767836SJohn.Forte@Sun.COM " old version Q contains data", urdc->disk_queue);
7777836SJohn.Forte@Sun.COM rdc_init_diskq_header(group, &group->diskq.disk_hdr);
7787836SJohn.Forte@Sun.COM SET_QSTATE(q, RDC_QBADRESUME);
7797836SJohn.Forte@Sun.COM rc = RDC_EQNOADD;
7807836SJohn.Forte@Sun.COM }
7817836SJohn.Forte@Sun.COM break;
7827836SJohn.Forte@Sun.COM #else
7837836SJohn.Forte@Sun.COM case RDC_DISKQ_VER_64BIT:
784*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!SNDR: unable to resume diskq %s,"
7857836SJohn.Forte@Sun.COM " diskq header newer than current version",
7867836SJohn.Forte@Sun.COM urdc->disk_queue);
7877836SJohn.Forte@Sun.COM rdc_init_diskq_header(group, &group->diskq.disk_hdr);
7887836SJohn.Forte@Sun.COM SET_QSTATE(q, RDC_QBADRESUME);
7897836SJohn.Forte@Sun.COM rc = RDC_EQNOADD;
7907836SJohn.Forte@Sun.COM break;
7917836SJohn.Forte@Sun.COM #endif
7927836SJohn.Forte@Sun.COM case RDC_DISKQ_VERS:
7937836SJohn.Forte@Sun.COM /* okay, current version diskq */
7947836SJohn.Forte@Sun.COM break;
7957836SJohn.Forte@Sun.COM default:
796*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!SNDR: unable to resume diskq %s,"
7977836SJohn.Forte@Sun.COM " unknown diskq header version", urdc->disk_queue);
7987836SJohn.Forte@Sun.COM rdc_init_diskq_header(group, &group->diskq.disk_hdr);
7997836SJohn.Forte@Sun.COM SET_QSTATE(q, RDC_QBADRESUME);
8007836SJohn.Forte@Sun.COM rc = RDC_EQNOADD;
8017836SJohn.Forte@Sun.COM break;
8027836SJohn.Forte@Sun.COM }
8037836SJohn.Forte@Sun.COM if (IS_QSTATE(q, RDC_SHUTDOWN_BAD)) {
804*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!SNDR: unable to resume diskq %s,"
8057836SJohn.Forte@Sun.COM " unsafe shutdown", urdc->disk_queue);
8067836SJohn.Forte@Sun.COM rdc_init_diskq_header(group, &group->diskq.disk_hdr);
8077836SJohn.Forte@Sun.COM SET_QSTATE(q, RDC_QBADRESUME);
8087836SJohn.Forte@Sun.COM rc = RDC_EQNOADD;
8097836SJohn.Forte@Sun.COM }
8107836SJohn.Forte@Sun.COM
8117836SJohn.Forte@Sun.COM CLR_QSTATE(q, RDC_SHUTDOWN_OK);
8127836SJohn.Forte@Sun.COM SET_QSTATE(q, RDC_SHUTDOWN_BAD);
8137836SJohn.Forte@Sun.COM
8147836SJohn.Forte@Sun.COM /* bad, until proven not bad */
8157836SJohn.Forte@Sun.COM if (rdc_stamp_diskq(krdc, 0, RDC_NOLOG) < 0) {
8167836SJohn.Forte@Sun.COM rdc_fail_diskq(krdc, RDC_NOWAIT, RDC_NOLOG);
8177836SJohn.Forte@Sun.COM rc = RDC_EQNOADD;
8187836SJohn.Forte@Sun.COM }
8197836SJohn.Forte@Sun.COM
8207836SJohn.Forte@Sun.COM SET_QNXTIO(q, QHEAD(q));
8217836SJohn.Forte@Sun.COM group->diskq.nitems_hwm = QNITEMS(q);
8227836SJohn.Forte@Sun.COM group->diskq.blocks_hwm = QBLOCKS(q);
8237836SJohn.Forte@Sun.COM
8247836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
8257836SJohn.Forte@Sun.COM
8267836SJohn.Forte@Sun.COM #ifdef DEBUG
827*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!rdc_resume_diskq: resuming diskq %s \n",
8287836SJohn.Forte@Sun.COM urdc->disk_queue);
829*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!qinfo: " QDISPLAY(q));
8307836SJohn.Forte@Sun.COM #endif
8317836SJohn.Forte@Sun.COM if (rc == 0)
8327836SJohn.Forte@Sun.COM return (0);
8337836SJohn.Forte@Sun.COM
8347836SJohn.Forte@Sun.COM fail:
8357836SJohn.Forte@Sun.COM
8367836SJohn.Forte@Sun.COM /* caller has to set the diskq failed after dropping it's locks */
8377836SJohn.Forte@Sun.COM return (rc);
8387836SJohn.Forte@Sun.COM
8397836SJohn.Forte@Sun.COM }
8407836SJohn.Forte@Sun.COM
8417836SJohn.Forte@Sun.COM int
rdc_suspend_diskq(rdc_k_info_t * krdc)8427836SJohn.Forte@Sun.COM rdc_suspend_diskq(rdc_k_info_t *krdc)
8437836SJohn.Forte@Sun.COM {
8447836SJohn.Forte@Sun.COM int rc;
8457836SJohn.Forte@Sun.COM rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
8467836SJohn.Forte@Sun.COM disk_queue *q;
8477836SJohn.Forte@Sun.COM
8487836SJohn.Forte@Sun.COM q = &krdc->group->diskq;
8497836SJohn.Forte@Sun.COM
8507836SJohn.Forte@Sun.COM /* grab both diskq locks as we are going to kill the flusher */
8517836SJohn.Forte@Sun.COM mutex_enter(QHEADLOCK(q));
8527836SJohn.Forte@Sun.COM mutex_enter(QLOCK(q));
8537836SJohn.Forte@Sun.COM
8547836SJohn.Forte@Sun.COM if ((krdc->group->rdc_thrnum) && (!IS_QSTATE(q, RDC_STOPPINGFLUSH))) {
8557836SJohn.Forte@Sun.COM SET_QSTATE(q, RDC_STOPPINGFLUSH);
8567836SJohn.Forte@Sun.COM rdc_stop_diskq_flusher(krdc);
8577836SJohn.Forte@Sun.COM CLR_QSTATE(q, RDC_STOPPINGFLUSH);
8587836SJohn.Forte@Sun.COM }
8597836SJohn.Forte@Sun.COM
8607836SJohn.Forte@Sun.COM krdc->group->diskq.disk_hdr.h.state &= ~RDC_SHUTDOWN_BAD;
8617836SJohn.Forte@Sun.COM krdc->group->diskq.disk_hdr.h.state |= RDC_SHUTDOWN_OK;
8627836SJohn.Forte@Sun.COM krdc->group->diskq.disk_hdr.h.state &= ~RDC_QBADRESUME;
8637836SJohn.Forte@Sun.COM
8647836SJohn.Forte@Sun.COM /* let's make sure that the flusher has stopped.. */
8657836SJohn.Forte@Sun.COM if (krdc->group->rdc_thrnum) {
8667836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
8677836SJohn.Forte@Sun.COM mutex_exit(QHEADLOCK(q));
8687836SJohn.Forte@Sun.COM rdc_group_exit(krdc);
8697836SJohn.Forte@Sun.COM
8707836SJohn.Forte@Sun.COM while (krdc->group->rdc_thrnum)
8717836SJohn.Forte@Sun.COM delay(5);
8727836SJohn.Forte@Sun.COM
8737836SJohn.Forte@Sun.COM rdc_group_enter(krdc);
8747836SJohn.Forte@Sun.COM mutex_enter(QLOCK(q));
8757836SJohn.Forte@Sun.COM mutex_enter(QHEADLOCK(q));
8767836SJohn.Forte@Sun.COM }
8777836SJohn.Forte@Sun.COM /* write refcount to the bitmap */
8787836SJohn.Forte@Sun.COM if ((rc = rdc_write_refcount(krdc)) < 0) {
8797836SJohn.Forte@Sun.COM rdc_group_exit(krdc);
8807836SJohn.Forte@Sun.COM goto fail;
8817836SJohn.Forte@Sun.COM }
8827836SJohn.Forte@Sun.COM
8837836SJohn.Forte@Sun.COM if (!QEMPTY(q)) {
8847836SJohn.Forte@Sun.COM rdc_set_flags(urdc, RDC_QUEUING);
8857836SJohn.Forte@Sun.COM } else {
8867836SJohn.Forte@Sun.COM rdc_clr_flags(urdc, RDC_QUEUING);
8877836SJohn.Forte@Sun.COM }
8887836SJohn.Forte@Sun.COM
8897836SJohn.Forte@Sun.COM /* fill in diskq header info */
8907836SJohn.Forte@Sun.COM krdc->group->diskq.disk_hdr.h.state &= ~RDC_QDISABLEPEND;
8917836SJohn.Forte@Sun.COM
8927836SJohn.Forte@Sun.COM #ifdef DEBUG
893*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!suspending disk queue\n" QDISPLAY(q));
8947836SJohn.Forte@Sun.COM #endif
8957836SJohn.Forte@Sun.COM
8967836SJohn.Forte@Sun.COM /* to avoid a possible deadlock, release in order, and reacquire */
8977836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
8987836SJohn.Forte@Sun.COM mutex_exit(QHEADLOCK(q));
8997836SJohn.Forte@Sun.COM
9007836SJohn.Forte@Sun.COM if (krdc->group->count > 1) {
9017836SJohn.Forte@Sun.COM rdc_group_exit(krdc);
9027836SJohn.Forte@Sun.COM goto fail; /* just stamp on the last suspend */
9037836SJohn.Forte@Sun.COM }
9047836SJohn.Forte@Sun.COM rdc_group_exit(krdc); /* in case this stamp fails */
9057836SJohn.Forte@Sun.COM mutex_enter(QLOCK(q));
9067836SJohn.Forte@Sun.COM
9077836SJohn.Forte@Sun.COM rc = rdc_stamp_diskq(krdc, 0, RDC_NOLOG);
9087836SJohn.Forte@Sun.COM
9097836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
9107836SJohn.Forte@Sun.COM
9117836SJohn.Forte@Sun.COM fail:
9127836SJohn.Forte@Sun.COM rdc_group_enter(krdc);
9137836SJohn.Forte@Sun.COM
9147836SJohn.Forte@Sun.COM /* diskq already failed if stamp failed */
9157836SJohn.Forte@Sun.COM
9167836SJohn.Forte@Sun.COM return (rc);
9177836SJohn.Forte@Sun.COM }
9187836SJohn.Forte@Sun.COM
9197836SJohn.Forte@Sun.COM /*
9207836SJohn.Forte@Sun.COM * copy orig aio to copy, including the nsc_buf_t
9217836SJohn.Forte@Sun.COM */
9227836SJohn.Forte@Sun.COM int
rdc_dup_aio(rdc_aio_t * orig,rdc_aio_t * copy)9237836SJohn.Forte@Sun.COM rdc_dup_aio(rdc_aio_t *orig, rdc_aio_t *copy)
9247836SJohn.Forte@Sun.COM {
9257836SJohn.Forte@Sun.COM int rc;
9267836SJohn.Forte@Sun.COM bcopy(orig, copy, sizeof (*orig));
9277836SJohn.Forte@Sun.COM copy->handle = NULL;
9287836SJohn.Forte@Sun.COM
9297836SJohn.Forte@Sun.COM if (orig->handle == NULL) /* no buf to alloc/copy */
9307836SJohn.Forte@Sun.COM return (0);
9317836SJohn.Forte@Sun.COM
9327836SJohn.Forte@Sun.COM rc = nsc_alloc_abuf(orig->pos, orig->len, 0, ©->handle);
9337836SJohn.Forte@Sun.COM if (!RDC_SUCCESS(rc)) {
9347836SJohn.Forte@Sun.COM #ifdef DEBUG
935*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!rdc_dup_aio: alloc_buf failed (%d)", rc);
9367836SJohn.Forte@Sun.COM #endif
9377836SJohn.Forte@Sun.COM return (rc);
9387836SJohn.Forte@Sun.COM }
9397836SJohn.Forte@Sun.COM rc = nsc_copy(orig->handle, copy->handle, orig->pos,
9407836SJohn.Forte@Sun.COM orig->pos, orig->len);
9417836SJohn.Forte@Sun.COM if (!RDC_SUCCESS(rc)) {
9427836SJohn.Forte@Sun.COM (void) nsc_free_buf(copy->handle);
9437836SJohn.Forte@Sun.COM #ifdef DEBUG
944*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!rdc_dup_aio: copy buf failed (%d)", rc);
9457836SJohn.Forte@Sun.COM #endif
9467836SJohn.Forte@Sun.COM return (rc);
9477836SJohn.Forte@Sun.COM }
9487836SJohn.Forte@Sun.COM return (0);
9497836SJohn.Forte@Sun.COM }
9507836SJohn.Forte@Sun.COM
9517836SJohn.Forte@Sun.COM /*
9527836SJohn.Forte@Sun.COM * rdc_qfill_shldwakeup()
9537836SJohn.Forte@Sun.COM * 0 if the memory queue has filled, and the low water
9547836SJohn.Forte@Sun.COM * mark has not been reached. 0 if diskq is empty.
9557836SJohn.Forte@Sun.COM * 1 if less than low water mark
9567836SJohn.Forte@Sun.COM * net_queue mutex is already held
9577836SJohn.Forte@Sun.COM */
9587836SJohn.Forte@Sun.COM int
rdc_qfill_shldwakeup(rdc_k_info_t * krdc)9597836SJohn.Forte@Sun.COM rdc_qfill_shldwakeup(rdc_k_info_t *krdc)
9607836SJohn.Forte@Sun.COM {
9617836SJohn.Forte@Sun.COM rdc_group_t *group = krdc->group;
9627836SJohn.Forte@Sun.COM rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
9637836SJohn.Forte@Sun.COM net_queue *nq = &group->ra_queue;
9647836SJohn.Forte@Sun.COM disk_queue *dq = &group->diskq;
9657836SJohn.Forte@Sun.COM
9667836SJohn.Forte@Sun.COM ASSERT(MUTEX_HELD(&nq->net_qlock));
9677836SJohn.Forte@Sun.COM
9687836SJohn.Forte@Sun.COM if (!RDC_IS_DISKQ(krdc->group))
9697836SJohn.Forte@Sun.COM return (0);
9707836SJohn.Forte@Sun.COM
9717836SJohn.Forte@Sun.COM if (nq->qfill_sleeping != RDC_QFILL_ASLEEP)
9727836SJohn.Forte@Sun.COM return (0);
9737836SJohn.Forte@Sun.COM
9747836SJohn.Forte@Sun.COM if (nq->qfflags & RDC_QFILLSTOP)
9757836SJohn.Forte@Sun.COM return (1);
9767836SJohn.Forte@Sun.COM
9777836SJohn.Forte@Sun.COM if (nq->qfflags & RDC_QFILLSLEEP)
9787836SJohn.Forte@Sun.COM return (0);
9797836SJohn.Forte@Sun.COM
9807836SJohn.Forte@Sun.COM if (IS_STATE(urdc, RDC_LOGGING) || IS_STATE(urdc, RDC_SYNCING))
9817836SJohn.Forte@Sun.COM return (0);
9827836SJohn.Forte@Sun.COM
9837836SJohn.Forte@Sun.COM mutex_enter(QLOCK(dq));
9847836SJohn.Forte@Sun.COM if ((QNXTIO(dq) == QTAIL(dq)) && !IS_QSTATE(dq, RDC_QFULL)) {
9857836SJohn.Forte@Sun.COM mutex_exit(QLOCK(dq));
9867836SJohn.Forte@Sun.COM return (0);
9877836SJohn.Forte@Sun.COM }
9887836SJohn.Forte@Sun.COM mutex_exit(QLOCK(dq));
9897836SJohn.Forte@Sun.COM
9907836SJohn.Forte@Sun.COM if (nq->qfill_sleeping == RDC_QFILL_ASLEEP) {
9917836SJohn.Forte@Sun.COM if (nq->hwmhit) {
9927836SJohn.Forte@Sun.COM if (nq->blocks <= RDC_LOW_QBLOCKS) {
9937836SJohn.Forte@Sun.COM nq->hwmhit = 0;
9947836SJohn.Forte@Sun.COM } else {
9957836SJohn.Forte@Sun.COM return (0);
9967836SJohn.Forte@Sun.COM }
9977836SJohn.Forte@Sun.COM }
9987836SJohn.Forte@Sun.COM #ifdef DEBUG_DISKQ_NOISY
999*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!Waking up diskq->memq flusher, flags 0x%x"
10007836SJohn.Forte@Sun.COM " idx: %d", rdc_get_vflags(urdc), urdc->index);
10017836SJohn.Forte@Sun.COM #endif
10027836SJohn.Forte@Sun.COM return (1);
10037836SJohn.Forte@Sun.COM }
10047836SJohn.Forte@Sun.COM return (0);
10057836SJohn.Forte@Sun.COM
10067836SJohn.Forte@Sun.COM }
10077836SJohn.Forte@Sun.COM
10087836SJohn.Forte@Sun.COM /*
10097836SJohn.Forte@Sun.COM * rdc_diskq_enqueue
10107836SJohn.Forte@Sun.COM * enqueue one i/o to the diskq
10117836SJohn.Forte@Sun.COM * after appending some metadata to the front
10127836SJohn.Forte@Sun.COM */
10137836SJohn.Forte@Sun.COM int
rdc_diskq_enqueue(rdc_k_info_t * krdc,rdc_aio_t * aio)10147836SJohn.Forte@Sun.COM rdc_diskq_enqueue(rdc_k_info_t *krdc, rdc_aio_t *aio)
10157836SJohn.Forte@Sun.COM {
10167836SJohn.Forte@Sun.COM nsc_vec_t *vec = NULL;
10177836SJohn.Forte@Sun.COM nsc_buf_t *bp = NULL;
10187836SJohn.Forte@Sun.COM nsc_buf_t *qbuf = NULL;
10197836SJohn.Forte@Sun.COM io_hdr *iohdr = NULL;
10207836SJohn.Forte@Sun.COM disk_queue *q;
10217836SJohn.Forte@Sun.COM rdc_group_t *group;
10227836SJohn.Forte@Sun.COM int numvecs;
10237836SJohn.Forte@Sun.COM int i, j, rc = 0;
10247836SJohn.Forte@Sun.COM int retries = 0;
10257836SJohn.Forte@Sun.COM rdc_u_info_t *urdc;
10267836SJohn.Forte@Sun.COM nsc_size_t iofbas; /* len of io + io header len */
10277836SJohn.Forte@Sun.COM int qtail;
10287836SJohn.Forte@Sun.COM int delay_time = 2;
10297836SJohn.Forte@Sun.COM int print_msg = 1;
10307836SJohn.Forte@Sun.COM
10317836SJohn.Forte@Sun.COM #ifdef DEBUG_WRITER_UBERNOISE
10327836SJohn.Forte@Sun.COM int qhead;
10337836SJohn.Forte@Sun.COM #endif
10347836SJohn.Forte@Sun.COM urdc = &rdc_u_info[krdc->index];
10357836SJohn.Forte@Sun.COM group = krdc->group;
10367836SJohn.Forte@Sun.COM q = &group->diskq;
10377836SJohn.Forte@Sun.COM
10387836SJohn.Forte@Sun.COM mutex_enter(QLOCK(q));
10397836SJohn.Forte@Sun.COM
10407836SJohn.Forte@Sun.COM /*
10417836SJohn.Forte@Sun.COM * there is a thread that is blocking because the queue is full,
10427836SJohn.Forte@Sun.COM * don't try to set up this write until all is clear
10437836SJohn.Forte@Sun.COM * check before and after for logging or failed queue just
10447836SJohn.Forte@Sun.COM * in case a thread was in flight while the queue was full,
10457836SJohn.Forte@Sun.COM * and in the proccess of failing
10467836SJohn.Forte@Sun.COM */
10477836SJohn.Forte@Sun.COM while (IS_QSTATE(q, RDC_QFULL)) {
10487836SJohn.Forte@Sun.COM if (IS_STATE(urdc, RDC_DISKQ_FAILED) ||
10497836SJohn.Forte@Sun.COM (IS_STATE(urdc, RDC_LOGGING) &&
10507836SJohn.Forte@Sun.COM !IS_STATE(urdc, RDC_QUEUING))) {
10517836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
10527836SJohn.Forte@Sun.COM if (aio->handle)
10537836SJohn.Forte@Sun.COM (void) nsc_free_buf(aio->handle);
10547836SJohn.Forte@Sun.COM return (-1);
10557836SJohn.Forte@Sun.COM }
10567836SJohn.Forte@Sun.COM cv_wait(&q->qfullcv, QLOCK(q));
10577836SJohn.Forte@Sun.COM
10587836SJohn.Forte@Sun.COM if (IS_STATE(urdc, RDC_DISKQ_FAILED) ||
10597836SJohn.Forte@Sun.COM (IS_STATE(urdc, RDC_LOGGING) &&
10607836SJohn.Forte@Sun.COM !IS_STATE(urdc, RDC_QUEUING))) {
10617836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
10627836SJohn.Forte@Sun.COM if (aio->handle)
10637836SJohn.Forte@Sun.COM (void) nsc_free_buf(aio->handle);
10647836SJohn.Forte@Sun.COM return (-1);
10657836SJohn.Forte@Sun.COM }
10667836SJohn.Forte@Sun.COM
10677836SJohn.Forte@Sun.COM }
10687836SJohn.Forte@Sun.COM
10697836SJohn.Forte@Sun.COM SET_QSTATE(q, QTAILBUSY);
10707836SJohn.Forte@Sun.COM
10717836SJohn.Forte@Sun.COM if (aio->handle == NULL) {
10727836SJohn.Forte@Sun.COM /* we're only going to write the header to the queue */
10737836SJohn.Forte@Sun.COM numvecs = 2; /* kmem_alloc io header + null terminate */
10747836SJohn.Forte@Sun.COM iofbas = FBA_LEN(sizeof (io_hdr));
10757836SJohn.Forte@Sun.COM
10767836SJohn.Forte@Sun.COM } else {
10777836SJohn.Forte@Sun.COM /* find out how many vecs */
10787836SJohn.Forte@Sun.COM numvecs = rdc_count_vecs(aio->handle->sb_vec) + 1;
10797836SJohn.Forte@Sun.COM iofbas = aio->len + FBA_LEN(sizeof (io_hdr));
10807836SJohn.Forte@Sun.COM }
10817836SJohn.Forte@Sun.COM
10827836SJohn.Forte@Sun.COM /*
10837836SJohn.Forte@Sun.COM * this, in conjunction with QTAILBUSY, will prevent
10847836SJohn.Forte@Sun.COM * premature dequeuing
10857836SJohn.Forte@Sun.COM */
10867836SJohn.Forte@Sun.COM
10877836SJohn.Forte@Sun.COM SET_LASTQTAIL(q, QTAIL(q));
10887836SJohn.Forte@Sun.COM
10897836SJohn.Forte@Sun.COM iohdr = (io_hdr *) kmem_zalloc(sizeof (io_hdr), KM_NOSLEEP);
10907836SJohn.Forte@Sun.COM vec = (nsc_vec_t *) kmem_zalloc(sizeof (nsc_vec_t) * numvecs,
10917836SJohn.Forte@Sun.COM KM_NOSLEEP);
10927836SJohn.Forte@Sun.COM
10937836SJohn.Forte@Sun.COM if (!vec || !iohdr) {
10947836SJohn.Forte@Sun.COM if (!vec) {
1095*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!vec kmem alloc failed");
10967836SJohn.Forte@Sun.COM } else {
1097*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!iohdr kmem alloc failed");
10987836SJohn.Forte@Sun.COM }
10997836SJohn.Forte@Sun.COM if (vec)
11007836SJohn.Forte@Sun.COM kmem_free(vec, sizeof (*vec));
11017836SJohn.Forte@Sun.COM if (iohdr)
11027836SJohn.Forte@Sun.COM kmem_free(iohdr, sizeof (*iohdr));
11037836SJohn.Forte@Sun.COM CLR_QSTATE(q, QTAILBUSY);
11047836SJohn.Forte@Sun.COM SET_LASTQTAIL(q, 0);
11057836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
11067836SJohn.Forte@Sun.COM if (aio->handle)
11077836SJohn.Forte@Sun.COM (void) nsc_free_buf(aio->handle);
11087836SJohn.Forte@Sun.COM return (ENOMEM);
11097836SJohn.Forte@Sun.COM }
11107836SJohn.Forte@Sun.COM
11117836SJohn.Forte@Sun.COM vec[numvecs - 1].sv_len = 0;
11127836SJohn.Forte@Sun.COM vec[numvecs - 1].sv_addr = 0;
11137836SJohn.Forte@Sun.COM
11147836SJohn.Forte@Sun.COM /* now add the write itself */
11157836SJohn.Forte@Sun.COM bp = aio->handle;
11167836SJohn.Forte@Sun.COM
11177836SJohn.Forte@Sun.COM for (i = 1, j = 0; bp && bp->sb_vec[j].sv_addr &&
11187836SJohn.Forte@Sun.COM i < numvecs; i++, j++) {
11197836SJohn.Forte@Sun.COM vec[i].sv_len = bp->sb_vec[j].sv_len;
11207836SJohn.Forte@Sun.COM vec[i].sv_addr = bp->sb_vec[j].sv_addr;
11217836SJohn.Forte@Sun.COM }
11227836SJohn.Forte@Sun.COM
11237836SJohn.Forte@Sun.COM retry:
11247836SJohn.Forte@Sun.COM
11257836SJohn.Forte@Sun.COM /* check for queue wrap, then check for overflow */
11267836SJohn.Forte@Sun.COM if (IS_STATE(urdc, RDC_DISKQ_FAILED) ||
11277836SJohn.Forte@Sun.COM (IS_STATE(urdc, RDC_LOGGING) && !IS_STATE(urdc, RDC_QUEUING))) {
11287836SJohn.Forte@Sun.COM kmem_free(iohdr, sizeof (*iohdr));
11297836SJohn.Forte@Sun.COM kmem_free(vec, sizeof (*vec) * numvecs);
11307836SJohn.Forte@Sun.COM CLR_QSTATE(q, QTAILBUSY);
11317836SJohn.Forte@Sun.COM SET_LASTQTAIL(q, 0);
11327836SJohn.Forte@Sun.COM if (IS_QSTATE(q, RDC_QFULL)) { /* wakeup blocked threads */
11337836SJohn.Forte@Sun.COM CLR_QSTATE(q, RDC_QFULL);
11347836SJohn.Forte@Sun.COM cv_broadcast(&q->qfullcv);
11357836SJohn.Forte@Sun.COM }
11367836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
11377836SJohn.Forte@Sun.COM if (aio->handle)
11387836SJohn.Forte@Sun.COM (void) nsc_free_buf(aio->handle);
11397836SJohn.Forte@Sun.COM
11407836SJohn.Forte@Sun.COM return (-1);
11417836SJohn.Forte@Sun.COM }
11427836SJohn.Forte@Sun.COM
11437836SJohn.Forte@Sun.COM if (QTAILSHLDWRAP(q, iofbas)) {
11447836SJohn.Forte@Sun.COM /*
11457836SJohn.Forte@Sun.COM * just go back to the beginning of the disk
11467836SJohn.Forte@Sun.COM * it's not worth the trouble breaking up the write
11477836SJohn.Forte@Sun.COM */
11487836SJohn.Forte@Sun.COM #ifdef DEBUG_DISKQWRAP
1149*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!wrapping Q tail: " QDISPLAY(q));
11507836SJohn.Forte@Sun.COM #endif
11517836SJohn.Forte@Sun.COM /*LINTED*/
11527836SJohn.Forte@Sun.COM WRAPQTAIL(q);
11537836SJohn.Forte@Sun.COM }
11547836SJohn.Forte@Sun.COM
11557836SJohn.Forte@Sun.COM /*
11567836SJohn.Forte@Sun.COM * prepend the write's metadata
11577836SJohn.Forte@Sun.COM */
11587836SJohn.Forte@Sun.COM rdc_fill_ioheader(aio, iohdr, QTAIL(q));
11597836SJohn.Forte@Sun.COM
11607836SJohn.Forte@Sun.COM vec[0].sv_len = FBA_SIZE(1);
11617836SJohn.Forte@Sun.COM vec[0].sv_addr = (uchar_t *)iohdr;
11627836SJohn.Forte@Sun.COM
11637836SJohn.Forte@Sun.COM /* check for tail < head */
11647836SJohn.Forte@Sun.COM
11657836SJohn.Forte@Sun.COM if (!(FITSONQ(q, iofbas))) {
11667836SJohn.Forte@Sun.COM /*
11677836SJohn.Forte@Sun.COM * don't allow any more writes to start
11687836SJohn.Forte@Sun.COM */
11697836SJohn.Forte@Sun.COM SET_QSTATE(q, RDC_QFULL);
11707836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
11717836SJohn.Forte@Sun.COM
11727836SJohn.Forte@Sun.COM if ((!group->rdc_writer) && !IS_STATE(urdc, RDC_LOGGING))
11737836SJohn.Forte@Sun.COM (void) rdc_writer(krdc->index);
11747836SJohn.Forte@Sun.COM
11757836SJohn.Forte@Sun.COM delay(delay_time);
11767836SJohn.Forte@Sun.COM q->throttle_delay += delay_time;
11777836SJohn.Forte@Sun.COM retries++;
11787836SJohn.Forte@Sun.COM delay_time *= 2; /* fairly aggressive */
11797836SJohn.Forte@Sun.COM if ((retries >= 8) || (delay_time >= 256)) {
11807836SJohn.Forte@Sun.COM delay_time = 2;
11817836SJohn.Forte@Sun.COM if (print_msg) {
1182*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!enqueue: disk queue %s full",
11837836SJohn.Forte@Sun.COM &urdc->disk_queue[0]);
11847836SJohn.Forte@Sun.COM print_msg = 0;
11857836SJohn.Forte@Sun.COM #ifdef DEBUG
1186*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!qinfo: " QDISPLAY(q));
11877836SJohn.Forte@Sun.COM #else
1188*9093SRamana.Srikanth@Sun.COM cmn_err(CE_CONT, "!qinfo: " QDISPLAYND(q));
11897836SJohn.Forte@Sun.COM #endif
11907836SJohn.Forte@Sun.COM }
11917836SJohn.Forte@Sun.COM /*
11927836SJohn.Forte@Sun.COM * if this is a no-block queue, or this is a blocking
11937836SJohn.Forte@Sun.COM * queue that is not flushing. reset and log
11947836SJohn.Forte@Sun.COM */
11957836SJohn.Forte@Sun.COM if ((QSTATE(q) & RDC_QNOBLOCK) ||
11967836SJohn.Forte@Sun.COM (IS_STATE(urdc, RDC_QUEUING))) {
11977836SJohn.Forte@Sun.COM
11987836SJohn.Forte@Sun.COM if (IS_STATE(urdc, RDC_QUEUING)) {
1199*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!SNDR: disk queue %s full and not flushing. "
12007836SJohn.Forte@Sun.COM "giving up", &urdc->disk_queue[0]);
1201*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!SNDR: %s:%s entering logging mode",
12027836SJohn.Forte@Sun.COM urdc->secondary.intf, urdc->secondary.file);
12037836SJohn.Forte@Sun.COM }
12047836SJohn.Forte@Sun.COM
12057836SJohn.Forte@Sun.COM rdc_fail_diskq(krdc, RDC_WAIT,
1206*9093SRamana.Srikanth@Sun.COM RDC_DOLOG | RDC_NOFAIL);
12077836SJohn.Forte@Sun.COM kmem_free(iohdr, sizeof (*iohdr));
12087836SJohn.Forte@Sun.COM kmem_free(vec, sizeof (*vec) * numvecs);
12097836SJohn.Forte@Sun.COM mutex_enter(QLOCK(q));
12107836SJohn.Forte@Sun.COM CLR_QSTATE(q, QTAILBUSY | RDC_QFULL);
12117836SJohn.Forte@Sun.COM cv_broadcast(&q->qfullcv);
12127836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
12137836SJohn.Forte@Sun.COM SET_LASTQTAIL(q, 0);
12147836SJohn.Forte@Sun.COM if (aio->handle)
12157836SJohn.Forte@Sun.COM (void) nsc_free_buf(aio->handle);
12167836SJohn.Forte@Sun.COM return (ENOMEM);
12177836SJohn.Forte@Sun.COM }
12187836SJohn.Forte@Sun.COM }
12197836SJohn.Forte@Sun.COM
12207836SJohn.Forte@Sun.COM mutex_enter(QLOCK(q));
12217836SJohn.Forte@Sun.COM goto retry;
12227836SJohn.Forte@Sun.COM
12237836SJohn.Forte@Sun.COM }
12247836SJohn.Forte@Sun.COM
12257836SJohn.Forte@Sun.COM qtail = QTAIL(q);
12267836SJohn.Forte@Sun.COM #ifdef DEBUG_WRITER_UBERNOISE
12277836SJohn.Forte@Sun.COM qhead = QHEAD(q);
12287836SJohn.Forte@Sun.COM #endif
12297836SJohn.Forte@Sun.COM
12307836SJohn.Forte@Sun.COM /* update tail pointer, nitems on queue and blocks on queue */
12317836SJohn.Forte@Sun.COM INC_QTAIL(q, iofbas); /* increment tail over i/o size + ioheader size */
12327836SJohn.Forte@Sun.COM INC_QNITEMS(q, 1);
12337836SJohn.Forte@Sun.COM /* increment counter for i/o blocks only */
12347836SJohn.Forte@Sun.COM INC_QBLOCKS(q, (iofbas - FBA_LEN(sizeof (io_hdr))));
12357836SJohn.Forte@Sun.COM
12367836SJohn.Forte@Sun.COM if (QNITEMS(q) > q->nitems_hwm)
12377836SJohn.Forte@Sun.COM q->nitems_hwm = QNITEMS(q);
12387836SJohn.Forte@Sun.COM if (QBLOCKS(q) > q->blocks_hwm)
12397836SJohn.Forte@Sun.COM q->blocks_hwm = QBLOCKS(q);
12407836SJohn.Forte@Sun.COM
12417836SJohn.Forte@Sun.COM if (IS_QSTATE(q, RDC_QFULL)) {
12427836SJohn.Forte@Sun.COM CLR_QSTATE(q, RDC_QFULL);
12437836SJohn.Forte@Sun.COM cv_broadcast(&q->qfullcv);
12447836SJohn.Forte@Sun.COM }
12457836SJohn.Forte@Sun.COM
12467836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
12477836SJohn.Forte@Sun.COM
12487836SJohn.Forte@Sun.COM /*
12497836SJohn.Forte@Sun.COM * if (krdc->io_kstats) {
12507836SJohn.Forte@Sun.COM * mutex_enter(krdc->io_kstats->ks_lock);
12517836SJohn.Forte@Sun.COM * kstat_waitq_enter(KSTAT_IO_PTR(krdc->io_kstats));
12527836SJohn.Forte@Sun.COM * mutex_exit(krdc->io_kstats->ks_lock);
12537836SJohn.Forte@Sun.COM * }
12547836SJohn.Forte@Sun.COM */
12557836SJohn.Forte@Sun.COM
12567836SJohn.Forte@Sun.COM DTRACE_PROBE(rdc_diskq_rsrv);
12577836SJohn.Forte@Sun.COM
12587836SJohn.Forte@Sun.COM if (_rdc_rsrv_diskq(group)) {
1259*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!rdc_enqueue: %s reserve failed",
12607836SJohn.Forte@Sun.COM &urdc->disk_queue[0]);
12617836SJohn.Forte@Sun.COM rdc_fail_diskq(krdc, RDC_WAIT, RDC_DOLOG);
12627836SJohn.Forte@Sun.COM kmem_free(iohdr, sizeof (*iohdr));
12637836SJohn.Forte@Sun.COM kmem_free(vec, sizeof (*vec) * numvecs);
12647836SJohn.Forte@Sun.COM mutex_enter(QLOCK(q));
12657836SJohn.Forte@Sun.COM CLR_QSTATE(q, QTAILBUSY);
12667836SJohn.Forte@Sun.COM SET_LASTQTAIL(q, 0);
12677836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
12687836SJohn.Forte@Sun.COM if (aio->handle)
12697836SJohn.Forte@Sun.COM (void) nsc_free_buf(aio->handle);
12707836SJohn.Forte@Sun.COM return (-1);
12717836SJohn.Forte@Sun.COM }
12727836SJohn.Forte@Sun.COM
12737836SJohn.Forte@Sun.COM /* XXX for now do this, but later pre-alloc handle in enable/resume */
12747836SJohn.Forte@Sun.COM
12757836SJohn.Forte@Sun.COM DTRACE_PROBE(rdc_diskq_alloc_start);
12767836SJohn.Forte@Sun.COM rc = nsc_alloc_buf(group->diskqfd, qtail, iofbas,
12777836SJohn.Forte@Sun.COM NSC_NOCACHE | NSC_WRITE | NSC_NODATA, &qbuf);
12787836SJohn.Forte@Sun.COM
12797836SJohn.Forte@Sun.COM DTRACE_PROBE(rdc_diskq_alloc_end);
12807836SJohn.Forte@Sun.COM
12817836SJohn.Forte@Sun.COM if (!RDC_SUCCESS(rc)) {
1282*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!disk queue %s alloc failed(%d) %" NSC_SZFMT,
12837836SJohn.Forte@Sun.COM &urdc->disk_queue[0], rc, iofbas);
12847836SJohn.Forte@Sun.COM rdc_fail_diskq(krdc, RDC_WAIT, RDC_DOLOG);
12857836SJohn.Forte@Sun.COM rc = ENOMEM;
12867836SJohn.Forte@Sun.COM goto fail;
12877836SJohn.Forte@Sun.COM }
12887836SJohn.Forte@Sun.COM /* move vec and write to queue */
12897836SJohn.Forte@Sun.COM qbuf->sb_vec = &vec[0];
12907836SJohn.Forte@Sun.COM
12917836SJohn.Forte@Sun.COM #ifdef DEBUG_WRITER_UBERNOISE
12927836SJohn.Forte@Sun.COM
1293*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!about to write to queue, qbuf: %p, qhead: %d, "
12947836SJohn.Forte@Sun.COM "qtail: %d, len: %d contents: %c%c%c%c%c",
12957836SJohn.Forte@Sun.COM (void *) qbuf, qhead, qtail, iofbas,
12967836SJohn.Forte@Sun.COM qbuf->sb_vec[1].sv_addr[0],
12977836SJohn.Forte@Sun.COM qbuf->sb_vec[1].sv_addr[1],
12987836SJohn.Forte@Sun.COM qbuf->sb_vec[1].sv_addr[2],
12997836SJohn.Forte@Sun.COM qbuf->sb_vec[1].sv_addr[3],
13007836SJohn.Forte@Sun.COM qbuf->sb_vec[1].sv_addr[4]);
1301*9093SRamana.Srikanth@Sun.COM cmn_err(CE_CONT, "!qinfo: " QDISPLAYND(q));
13027836SJohn.Forte@Sun.COM
13037836SJohn.Forte@Sun.COM #endif
13047836SJohn.Forte@Sun.COM
13057836SJohn.Forte@Sun.COM DTRACE_PROBE2(rdc_diskq_nswrite_start, int, qtail, nsc_size_t, iofbas);
13067836SJohn.Forte@Sun.COM rc = nsc_write(qbuf, qtail, iofbas, 0);
13077836SJohn.Forte@Sun.COM DTRACE_PROBE2(rdc_diskq_nswrite_end, int, qtail, nsc_size_t, iofbas);
13087836SJohn.Forte@Sun.COM
13097836SJohn.Forte@Sun.COM if (!RDC_SUCCESS(rc)) {
1310*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!disk queue %s write failed %d",
13117836SJohn.Forte@Sun.COM &urdc->disk_queue[0], rc);
13127836SJohn.Forte@Sun.COM rdc_fail_diskq(krdc, RDC_WAIT, RDC_DOLOG);
13137836SJohn.Forte@Sun.COM goto fail;
13147836SJohn.Forte@Sun.COM
13157836SJohn.Forte@Sun.COM }
13167836SJohn.Forte@Sun.COM
13177836SJohn.Forte@Sun.COM mutex_enter(QLOCK(q));
13187836SJohn.Forte@Sun.COM
13197836SJohn.Forte@Sun.COM SET_LASTQTAIL(q, 0);
13207836SJohn.Forte@Sun.COM CLR_QSTATE(q, QTAILBUSY);
13217836SJohn.Forte@Sun.COM
13227836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
13237836SJohn.Forte@Sun.COM
13247836SJohn.Forte@Sun.COM fail:
13257836SJohn.Forte@Sun.COM
13267836SJohn.Forte@Sun.COM /*
13277836SJohn.Forte@Sun.COM * return what should be returned
13287836SJohn.Forte@Sun.COM * the aio is returned in _rdc_write after status is gathered.
13297836SJohn.Forte@Sun.COM */
13307836SJohn.Forte@Sun.COM
13317836SJohn.Forte@Sun.COM if (qbuf)
13327836SJohn.Forte@Sun.COM qbuf->sb_vec = 0;
13337836SJohn.Forte@Sun.COM (void) nsc_free_buf(qbuf);
13347836SJohn.Forte@Sun.COM
13357836SJohn.Forte@Sun.COM if (aio->handle)
13367836SJohn.Forte@Sun.COM (void) nsc_free_buf(aio->handle);
13377836SJohn.Forte@Sun.COM
13387836SJohn.Forte@Sun.COM _rdc_rlse_diskq(group);
13397836SJohn.Forte@Sun.COM DTRACE_PROBE(rdc_diskq_rlse);
13407836SJohn.Forte@Sun.COM
13417836SJohn.Forte@Sun.COM /* free the iohdr and the vecs */
13427836SJohn.Forte@Sun.COM
13437836SJohn.Forte@Sun.COM if (iohdr)
13447836SJohn.Forte@Sun.COM kmem_free(iohdr, sizeof (*iohdr));
13457836SJohn.Forte@Sun.COM if (vec)
13467836SJohn.Forte@Sun.COM kmem_free(vec, sizeof (*vec) * numvecs);
13477836SJohn.Forte@Sun.COM
13487836SJohn.Forte@Sun.COM /* if no flusher running, start one */
13497836SJohn.Forte@Sun.COM if ((!krdc->group->rdc_writer) && !IS_STATE(urdc, RDC_LOGGING))
13507836SJohn.Forte@Sun.COM (void) rdc_writer(krdc->index);
13517836SJohn.Forte@Sun.COM
13527836SJohn.Forte@Sun.COM return (rc);
13537836SJohn.Forte@Sun.COM }
13547836SJohn.Forte@Sun.COM
13557836SJohn.Forte@Sun.COM /*
13567836SJohn.Forte@Sun.COM * place this on the pending list of io_hdr's out for flushing
13577836SJohn.Forte@Sun.COM */
13587836SJohn.Forte@Sun.COM void
rdc_add_iohdr(io_hdr * header,rdc_group_t * group)13597836SJohn.Forte@Sun.COM rdc_add_iohdr(io_hdr *header, rdc_group_t *group)
13607836SJohn.Forte@Sun.COM {
13617836SJohn.Forte@Sun.COM disk_queue *q = NULL;
13627836SJohn.Forte@Sun.COM #ifdef DEBUG
13637836SJohn.Forte@Sun.COM io_hdr *p;
13647836SJohn.Forte@Sun.COM #endif
13657836SJohn.Forte@Sun.COM
13667836SJohn.Forte@Sun.COM q = &group->diskq;
13677836SJohn.Forte@Sun.COM
13687836SJohn.Forte@Sun.COM /* paranoia */
13697836SJohn.Forte@Sun.COM header->dat.next = NULL;
13707836SJohn.Forte@Sun.COM
13717836SJohn.Forte@Sun.COM mutex_enter(QLOCK(q));
13727836SJohn.Forte@Sun.COM #ifdef DEBUG /* AAAH! double flush!? */
13737836SJohn.Forte@Sun.COM p = q->iohdrs;
13747836SJohn.Forte@Sun.COM while (p) {
13757836SJohn.Forte@Sun.COM if (p->dat.qpos == header->dat.qpos) {
1376*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!ADDING DUPLICATE HEADER %" NSC_SZFMT,
13777836SJohn.Forte@Sun.COM p->dat.qpos);
13787836SJohn.Forte@Sun.COM kmem_free(header, sizeof (*header));
13797836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
13807836SJohn.Forte@Sun.COM return;
13817836SJohn.Forte@Sun.COM }
13827836SJohn.Forte@Sun.COM p = p->dat.next;
13837836SJohn.Forte@Sun.COM }
13847836SJohn.Forte@Sun.COM #endif
13857836SJohn.Forte@Sun.COM if (q->iohdrs == NULL) {
13867836SJohn.Forte@Sun.COM q->iohdrs = q->hdr_last = header;
13877836SJohn.Forte@Sun.COM q->hdrcnt = 1;
13887836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
13897836SJohn.Forte@Sun.COM return;
13907836SJohn.Forte@Sun.COM }
13917836SJohn.Forte@Sun.COM
13927836SJohn.Forte@Sun.COM q->hdr_last->dat.next = header;
13937836SJohn.Forte@Sun.COM q->hdr_last = header;
13947836SJohn.Forte@Sun.COM q->hdrcnt++;
13957836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
13967836SJohn.Forte@Sun.COM return;
13977836SJohn.Forte@Sun.COM
13987836SJohn.Forte@Sun.COM }
13997836SJohn.Forte@Sun.COM
14007836SJohn.Forte@Sun.COM /*
14017836SJohn.Forte@Sun.COM * mark an io header as flushed. If it is the qhead,
14027836SJohn.Forte@Sun.COM * then update the qpointers
14037836SJohn.Forte@Sun.COM * free the io_hdrs
14047836SJohn.Forte@Sun.COM * called after the bitmap is cleared by flusher
14057836SJohn.Forte@Sun.COM */
14067836SJohn.Forte@Sun.COM void
rdc_clr_iohdr(rdc_k_info_t * krdc,nsc_size_t qpos)14077836SJohn.Forte@Sun.COM rdc_clr_iohdr(rdc_k_info_t *krdc, nsc_size_t qpos)
14087836SJohn.Forte@Sun.COM {
14097836SJohn.Forte@Sun.COM rdc_group_t *group = krdc->group;
14107836SJohn.Forte@Sun.COM disk_queue *q = NULL;
14117836SJohn.Forte@Sun.COM io_hdr *hp = NULL;
14127836SJohn.Forte@Sun.COM io_hdr *p = NULL;
14137836SJohn.Forte@Sun.COM int found = 0;
14147836SJohn.Forte@Sun.COM int cnt = 0;
14157836SJohn.Forte@Sun.COM
14167836SJohn.Forte@Sun.COM #ifndef NSC_MULTI_TERABYTE
14177836SJohn.Forte@Sun.COM ASSERT(qpos >= 0); /* assertion to validate change for 64bit */
14187836SJohn.Forte@Sun.COM if (qpos < 0) /* not a diskq offset */
14197836SJohn.Forte@Sun.COM return;
14207836SJohn.Forte@Sun.COM #endif
14217836SJohn.Forte@Sun.COM
14227836SJohn.Forte@Sun.COM q = &group->diskq;
14237836SJohn.Forte@Sun.COM mutex_enter(QLOCK(q));
14247836SJohn.Forte@Sun.COM
14257836SJohn.Forte@Sun.COM hp = p = q->iohdrs;
14267836SJohn.Forte@Sun.COM
14277836SJohn.Forte@Sun.COM /* find outstanding io_hdr */
14287836SJohn.Forte@Sun.COM while (hp) {
14297836SJohn.Forte@Sun.COM if (hp->dat.qpos == qpos) {
14307836SJohn.Forte@Sun.COM found++;
14317836SJohn.Forte@Sun.COM break;
14327836SJohn.Forte@Sun.COM }
14337836SJohn.Forte@Sun.COM cnt++;
14347836SJohn.Forte@Sun.COM p = hp;
14357836SJohn.Forte@Sun.COM hp = hp->dat.next;
14367836SJohn.Forte@Sun.COM }
14377836SJohn.Forte@Sun.COM
14387836SJohn.Forte@Sun.COM if (!found) {
14397836SJohn.Forte@Sun.COM if (RDC_BETWEEN(QHEAD(q), QNXTIO(q), qpos)) {
14407836SJohn.Forte@Sun.COM #ifdef DEBUG
1441*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!iohdr already cleared? "
14427836SJohn.Forte@Sun.COM "qpos %" NSC_SZFMT " cnt %d ", qpos, cnt);
1443*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!Qinfo: " QDISPLAY(q));
14447836SJohn.Forte@Sun.COM #endif
14457836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
14467836SJohn.Forte@Sun.COM return;
14477836SJohn.Forte@Sun.COM }
14487836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
14497836SJohn.Forte@Sun.COM return;
14507836SJohn.Forte@Sun.COM }
14517836SJohn.Forte@Sun.COM
14527836SJohn.Forte@Sun.COM /* mark it as flushed */
14537836SJohn.Forte@Sun.COM hp->dat.iostatus = RDC_IOHDR_DONE;
14547836SJohn.Forte@Sun.COM
14557836SJohn.Forte@Sun.COM /*
14567836SJohn.Forte@Sun.COM * if it is the head pointer, travel the list updating the queue
14577836SJohn.Forte@Sun.COM * pointers until the next unflushed is reached, freeing on the way.
14587836SJohn.Forte@Sun.COM */
14597836SJohn.Forte@Sun.COM while (hp && (hp->dat.qpos == QHEAD(q)) &&
14607836SJohn.Forte@Sun.COM (hp->dat.iostatus == RDC_IOHDR_DONE)) {
14617836SJohn.Forte@Sun.COM #ifdef DEBUG_FLUSHER_UBERNOISE
1462*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!clr_iohdr info: magic %x type %d pos %d"
14637836SJohn.Forte@Sun.COM " qpos %d hpos %d len %d flag 0x%x iostatus %x setid %d",
14647836SJohn.Forte@Sun.COM hp->dat.magic, hp->dat.type, hp->dat.pos, hp->dat.qpos,
14657836SJohn.Forte@Sun.COM hp->dat.hpos, hp->dat.len, hp->dat.flag,
14667836SJohn.Forte@Sun.COM hp->dat.iostatus, hp->dat.setid);
14677836SJohn.Forte@Sun.COM #endif
14687836SJohn.Forte@Sun.COM if (hp->dat.flag & RDC_NULL_BUF) {
14697836SJohn.Forte@Sun.COM INC_QHEAD(q, FBA_LEN(sizeof (io_hdr)));
14707836SJohn.Forte@Sun.COM } else {
14717836SJohn.Forte@Sun.COM INC_QHEAD(q, FBA_LEN(sizeof (io_hdr)) + hp->dat.len);
14727836SJohn.Forte@Sun.COM DEC_QBLOCKS(q, hp->dat.len);
14737836SJohn.Forte@Sun.COM }
14747836SJohn.Forte@Sun.COM
14757836SJohn.Forte@Sun.COM DEC_QNITEMS(q, 1);
14767836SJohn.Forte@Sun.COM
14777836SJohn.Forte@Sun.COM if (QHEADSHLDWRAP(q)) { /* simple enough */
14787836SJohn.Forte@Sun.COM #ifdef DEBUG_DISKQWRAP
1479*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!wrapping Q head: " QDISPLAY(q));
14807836SJohn.Forte@Sun.COM #endif
14817836SJohn.Forte@Sun.COM /*LINTED*/
14827836SJohn.Forte@Sun.COM WRAPQHEAD(q);
14837836SJohn.Forte@Sun.COM }
14847836SJohn.Forte@Sun.COM
14857836SJohn.Forte@Sun.COM /* get rid of the iohdr */
14867836SJohn.Forte@Sun.COM if (hp == q->iohdrs) {
14877836SJohn.Forte@Sun.COM q->iohdrs = hp->dat.next;
14887836SJohn.Forte@Sun.COM kmem_free(hp, sizeof (*hp));
14897836SJohn.Forte@Sun.COM hp = q->iohdrs;
14907836SJohn.Forte@Sun.COM } else {
14917836SJohn.Forte@Sun.COM if (hp == q->hdr_last)
14927836SJohn.Forte@Sun.COM q->hdr_last = p;
14937836SJohn.Forte@Sun.COM p->dat.next = hp->dat.next;
14947836SJohn.Forte@Sun.COM kmem_free(hp, sizeof (*hp));
14957836SJohn.Forte@Sun.COM hp = p->dat.next;
14967836SJohn.Forte@Sun.COM }
14977836SJohn.Forte@Sun.COM q->hdrcnt--;
14987836SJohn.Forte@Sun.COM }
14997836SJohn.Forte@Sun.COM
15007836SJohn.Forte@Sun.COM if (QEMPTY(q) && !IS_QSTATE(q, RDC_QFULL) &&
15017836SJohn.Forte@Sun.COM !(IS_QSTATE(q, RDC_QDISABLEPEND))) {
15027836SJohn.Forte@Sun.COM #ifdef DEBUG_FLUSHER_UBERNOISE
15037836SJohn.Forte@Sun.COM rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
1504*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!clr_iohdr: diskq %s empty, "
15057836SJohn.Forte@Sun.COM "resetting defaults", urdc->disk_queue);
15067836SJohn.Forte@Sun.COM #endif
15077836SJohn.Forte@Sun.COM
15087836SJohn.Forte@Sun.COM rdc_init_diskq_header(group, &q->disk_hdr);
15097836SJohn.Forte@Sun.COM SET_QNXTIO(q, QHEAD(q));
15107836SJohn.Forte@Sun.COM }
15117836SJohn.Forte@Sun.COM
15127836SJohn.Forte@Sun.COM /* wakeup any blocked enqueue threads */
15137836SJohn.Forte@Sun.COM cv_broadcast(&q->qfullcv);
15147836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
15157836SJohn.Forte@Sun.COM }
15167836SJohn.Forte@Sun.COM
15177836SJohn.Forte@Sun.COM /*
15187836SJohn.Forte@Sun.COM * put in whatever useful checks we can on the io header
15197836SJohn.Forte@Sun.COM */
15207836SJohn.Forte@Sun.COM int
rdc_iohdr_ok(io_hdr * hdr)15217836SJohn.Forte@Sun.COM rdc_iohdr_ok(io_hdr *hdr)
15227836SJohn.Forte@Sun.COM {
15237836SJohn.Forte@Sun.COM if (hdr->dat.magic != RDC_IOHDR_MAGIC)
15247836SJohn.Forte@Sun.COM goto bad;
15257836SJohn.Forte@Sun.COM return (1);
15267836SJohn.Forte@Sun.COM bad:
15277836SJohn.Forte@Sun.COM
15287836SJohn.Forte@Sun.COM #ifdef DEBUG
1529*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!Bad io header magic %x type %d pos %" NSC_SZFMT
15307836SJohn.Forte@Sun.COM " hpos %" NSC_SZFMT " qpos %" NSC_SZFMT " len %" NSC_SZFMT
15317836SJohn.Forte@Sun.COM " flag %d iostatus %d setid %d", hdr->dat.magic,
15327836SJohn.Forte@Sun.COM hdr->dat.type, hdr->dat.pos, hdr->dat.hpos, hdr->dat.qpos,
15337836SJohn.Forte@Sun.COM hdr->dat.len, hdr->dat.flag, hdr->dat.iostatus, hdr->dat.setid);
15347836SJohn.Forte@Sun.COM #else
1535*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!Bad io header retrieved");
15367836SJohn.Forte@Sun.COM #endif
15377836SJohn.Forte@Sun.COM return (0);
15387836SJohn.Forte@Sun.COM }
15397836SJohn.Forte@Sun.COM
15407836SJohn.Forte@Sun.COM /*
15417836SJohn.Forte@Sun.COM * rdc_netqueue_insert()
15427836SJohn.Forte@Sun.COM * add an item to a netqueue. No locks necessary as it should only
15437836SJohn.Forte@Sun.COM * be used in a single threaded manor. If that changes, then
15447836SJohn.Forte@Sun.COM * a lock or assertion should be done here
15457836SJohn.Forte@Sun.COM */
15467836SJohn.Forte@Sun.COM void
rdc_netqueue_insert(rdc_aio_t * aio,net_queue * q)15477836SJohn.Forte@Sun.COM rdc_netqueue_insert(rdc_aio_t *aio, net_queue *q)
15487836SJohn.Forte@Sun.COM {
15497836SJohn.Forte@Sun.COM rdc_k_info_t *krdc = &rdc_k_info[aio->index];
15507836SJohn.Forte@Sun.COM
15517836SJohn.Forte@Sun.COM /* paranoid check for bit set */
15527836SJohn.Forte@Sun.COM RDC_CHECK_BIT(krdc, aio->pos, aio->len);
15537836SJohn.Forte@Sun.COM
15547836SJohn.Forte@Sun.COM if (q->net_qhead == NULL) {
15557836SJohn.Forte@Sun.COM q->net_qhead = q->net_qtail = aio;
15567836SJohn.Forte@Sun.COM
15577836SJohn.Forte@Sun.COM } else {
15587836SJohn.Forte@Sun.COM q->net_qtail->next = aio;
15597836SJohn.Forte@Sun.COM q->net_qtail = aio;
15607836SJohn.Forte@Sun.COM }
15617836SJohn.Forte@Sun.COM q->blocks += aio->len;
15627836SJohn.Forte@Sun.COM q->nitems++;
15637836SJohn.Forte@Sun.COM
15647836SJohn.Forte@Sun.COM if (q->nitems > q->nitems_hwm) {
15657836SJohn.Forte@Sun.COM q->nitems_hwm = q->nitems;
15667836SJohn.Forte@Sun.COM }
15677836SJohn.Forte@Sun.COM if (q->blocks > q->blocks_hwm) {
15687836SJohn.Forte@Sun.COM q->nitems_hwm = q->blocks;
15697836SJohn.Forte@Sun.COM }
15707836SJohn.Forte@Sun.COM }
15717836SJohn.Forte@Sun.COM
15727836SJohn.Forte@Sun.COM /*
15737836SJohn.Forte@Sun.COM * rdc_fill_aio(aio, hdr)
15747836SJohn.Forte@Sun.COM * take the pertinent info from an io_hdr and stick it in
15757836SJohn.Forte@Sun.COM * an aio, including seq number, abuf.
15767836SJohn.Forte@Sun.COM */
15777836SJohn.Forte@Sun.COM void
rdc_fill_aio(rdc_group_t * grp,rdc_aio_t * aio,io_hdr * hdr,nsc_buf_t * abuf)15787836SJohn.Forte@Sun.COM rdc_fill_aio(rdc_group_t *grp, rdc_aio_t *aio, io_hdr *hdr, nsc_buf_t *abuf)
15797836SJohn.Forte@Sun.COM {
15807836SJohn.Forte@Sun.COM if (hdr->dat.flag & RDC_NULL_BUF) {
15817836SJohn.Forte@Sun.COM aio->handle = NULL;
15827836SJohn.Forte@Sun.COM } else {
15837836SJohn.Forte@Sun.COM aio->handle = abuf;
15847836SJohn.Forte@Sun.COM }
15857836SJohn.Forte@Sun.COM aio->qhandle = abuf;
15867836SJohn.Forte@Sun.COM aio->pos = hdr->dat.pos;
15877836SJohn.Forte@Sun.COM aio->qpos = hdr->dat.qpos;
15887836SJohn.Forte@Sun.COM aio->len = hdr->dat.len;
15897836SJohn.Forte@Sun.COM aio->flag = hdr->dat.flag;
15907836SJohn.Forte@Sun.COM if ((aio->index = rdc_setid2idx(hdr->dat.setid)) < 0)
15917836SJohn.Forte@Sun.COM return;
15927836SJohn.Forte@Sun.COM mutex_enter(&grp->diskq.disk_qlock);
15937836SJohn.Forte@Sun.COM if (grp->ra_queue.qfflags & RDC_QFILLSLEEP) {
15947836SJohn.Forte@Sun.COM mutex_exit(&grp->diskq.disk_qlock);
15957836SJohn.Forte@Sun.COM aio->seq = RDC_NOSEQ;
15967836SJohn.Forte@Sun.COM return;
15977836SJohn.Forte@Sun.COM }
15987836SJohn.Forte@Sun.COM if (abuf && aio->qhandle) {
15997836SJohn.Forte@Sun.COM abuf->sb_user++;
16007836SJohn.Forte@Sun.COM }
16017836SJohn.Forte@Sun.COM aio->seq = grp->seq++;
16027836SJohn.Forte@Sun.COM if (grp->seq < aio->seq)
16037836SJohn.Forte@Sun.COM grp->seq = RDC_NEWSEQ + 1;
16047836SJohn.Forte@Sun.COM mutex_exit(&grp->diskq.disk_qlock);
16057836SJohn.Forte@Sun.COM hdr->dat.iostatus = aio->seq;
16067836SJohn.Forte@Sun.COM
16077836SJohn.Forte@Sun.COM }
16087836SJohn.Forte@Sun.COM
16097836SJohn.Forte@Sun.COM #ifdef DEBUG
16107836SJohn.Forte@Sun.COM int maxaios_perbuf = 0;
16117836SJohn.Forte@Sun.COM int midaios_perbuf = 0;
16127836SJohn.Forte@Sun.COM int aveaios_perbuf = 0;
16137836SJohn.Forte@Sun.COM int totaios_perbuf = 0;
16147836SJohn.Forte@Sun.COM int buf2qcalls = 0;
16157836SJohn.Forte@Sun.COM
16167836SJohn.Forte@Sun.COM void
calc_perbuf(int items)16177836SJohn.Forte@Sun.COM calc_perbuf(int items)
16187836SJohn.Forte@Sun.COM {
16197836SJohn.Forte@Sun.COM if (totaios_perbuf < 0) {
16207836SJohn.Forte@Sun.COM maxaios_perbuf = 0;
16217836SJohn.Forte@Sun.COM midaios_perbuf = 0;
16227836SJohn.Forte@Sun.COM aveaios_perbuf = 0;
16237836SJohn.Forte@Sun.COM totaios_perbuf = 0;
16247836SJohn.Forte@Sun.COM buf2qcalls = 0;
16257836SJohn.Forte@Sun.COM }
16267836SJohn.Forte@Sun.COM
16277836SJohn.Forte@Sun.COM if (items > maxaios_perbuf)
16287836SJohn.Forte@Sun.COM maxaios_perbuf = items;
16297836SJohn.Forte@Sun.COM midaios_perbuf = maxaios_perbuf / 2;
16307836SJohn.Forte@Sun.COM totaios_perbuf += items;
16317836SJohn.Forte@Sun.COM aveaios_perbuf = totaios_perbuf / buf2qcalls;
16327836SJohn.Forte@Sun.COM }
16337836SJohn.Forte@Sun.COM #endif
16347836SJohn.Forte@Sun.COM
16357836SJohn.Forte@Sun.COM /*
16367836SJohn.Forte@Sun.COM * rdc_discard_tmpq()
16377836SJohn.Forte@Sun.COM * free up the passed temporary queue
16387836SJohn.Forte@Sun.COM * NOTE: no cv's or mutexes have been initialized
16397836SJohn.Forte@Sun.COM */
16407836SJohn.Forte@Sun.COM void
rdc_discard_tmpq(net_queue * q)16417836SJohn.Forte@Sun.COM rdc_discard_tmpq(net_queue *q)
16427836SJohn.Forte@Sun.COM {
16437836SJohn.Forte@Sun.COM rdc_aio_t *aio;
16447836SJohn.Forte@Sun.COM
16457836SJohn.Forte@Sun.COM if (q == NULL)
16467836SJohn.Forte@Sun.COM return;
16477836SJohn.Forte@Sun.COM
16487836SJohn.Forte@Sun.COM while (q->net_qhead) {
16497836SJohn.Forte@Sun.COM aio = q->net_qhead;
16507836SJohn.Forte@Sun.COM q->net_qhead = q->net_qhead->next;
16517836SJohn.Forte@Sun.COM if (aio->qhandle) {
16527836SJohn.Forte@Sun.COM aio->qhandle->sb_user--;
16537836SJohn.Forte@Sun.COM if (aio->qhandle->sb_user == 0) {
16547836SJohn.Forte@Sun.COM rdc_fixlen(aio);
16557836SJohn.Forte@Sun.COM (void) nsc_free_buf(aio->qhandle);
16567836SJohn.Forte@Sun.COM }
16577836SJohn.Forte@Sun.COM }
16587836SJohn.Forte@Sun.COM kmem_free(aio, sizeof (*aio));
16597836SJohn.Forte@Sun.COM q->nitems--;
16607836SJohn.Forte@Sun.COM }
16617836SJohn.Forte@Sun.COM kmem_free(q, sizeof (*q));
16627836SJohn.Forte@Sun.COM
16637836SJohn.Forte@Sun.COM }
16647836SJohn.Forte@Sun.COM
16657836SJohn.Forte@Sun.COM /*
16667836SJohn.Forte@Sun.COM * rdc_diskq_buf2queue()
16677836SJohn.Forte@Sun.COM * take a chunk of the diskq, parse it and assemble
16687836SJohn.Forte@Sun.COM * a chain of rdc_aio_t's.
16697836SJohn.Forte@Sun.COM * updates QNXTIO()
16707836SJohn.Forte@Sun.COM */
16717836SJohn.Forte@Sun.COM net_queue *
rdc_diskq_buf2queue(rdc_group_t * grp,nsc_buf_t ** abuf,int index)16727836SJohn.Forte@Sun.COM rdc_diskq_buf2queue(rdc_group_t *grp, nsc_buf_t **abuf, int index)
16737836SJohn.Forte@Sun.COM {
16747836SJohn.Forte@Sun.COM rdc_aio_t *aio = NULL;
16757836SJohn.Forte@Sun.COM nsc_vec_t *vecp = NULL;
16767836SJohn.Forte@Sun.COM uchar_t *vaddr = NULL;
16777836SJohn.Forte@Sun.COM uchar_t *ioaddr = NULL;
16787836SJohn.Forte@Sun.COM net_queue *netq = NULL;
16797836SJohn.Forte@Sun.COM io_hdr *hdr = NULL;
16807836SJohn.Forte@Sun.COM nsc_buf_t *buf = *abuf;
16817836SJohn.Forte@Sun.COM rdc_u_info_t *urdc = &rdc_u_info[index];
16827836SJohn.Forte@Sun.COM rdc_k_info_t *krdc = &rdc_k_info[index];
16837836SJohn.Forte@Sun.COM disk_queue *dq = &grp->diskq;
16847836SJohn.Forte@Sun.COM net_queue *nq = &grp->ra_queue;
16857836SJohn.Forte@Sun.COM int nullbuf = 0;
16867836SJohn.Forte@Sun.COM nsc_off_t endobuf;
16877836SJohn.Forte@Sun.COM nsc_off_t bufoff;
16887836SJohn.Forte@Sun.COM int vlen;
16897836SJohn.Forte@Sun.COM nsc_off_t fpos;
16907836SJohn.Forte@Sun.COM long bufcnt = 0;
16917836SJohn.Forte@Sun.COM int nullblocks = 0;
16927836SJohn.Forte@Sun.COM int fail = 1;
16937836SJohn.Forte@Sun.COM
16947836SJohn.Forte@Sun.COM if (buf == NULL)
16957836SJohn.Forte@Sun.COM return (NULL);
16967836SJohn.Forte@Sun.COM
16977836SJohn.Forte@Sun.COM netq = kmem_zalloc(sizeof (*netq), KM_NOSLEEP);
16987836SJohn.Forte@Sun.COM if (netq == NULL) {
1699*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!SNDR: unable to allocate net queue");
17007836SJohn.Forte@Sun.COM return (NULL);
17017836SJohn.Forte@Sun.COM }
17027836SJohn.Forte@Sun.COM
17037836SJohn.Forte@Sun.COM vecp = buf->sb_vec;
17047836SJohn.Forte@Sun.COM vlen = vecp->sv_len;
17057836SJohn.Forte@Sun.COM vaddr = vecp->sv_addr;
17067836SJohn.Forte@Sun.COM bufoff = buf->sb_pos;
17077836SJohn.Forte@Sun.COM endobuf = bufoff + buf->sb_len;
17087836SJohn.Forte@Sun.COM
17097836SJohn.Forte@Sun.COM #ifdef DEBUG_FLUSHER_UBERNOISE
1710*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!BUFFOFFENTER %d", bufoff);
17117836SJohn.Forte@Sun.COM #endif
17127836SJohn.Forte@Sun.COM /* CONSTCOND */
17137836SJohn.Forte@Sun.COM while (1) {
17147836SJohn.Forte@Sun.COM if (IS_STATE(urdc, RDC_LOGGING) ||
17157836SJohn.Forte@Sun.COM (nq->qfflags & RDC_QFILLSLEEP)) {
17167836SJohn.Forte@Sun.COM fail = 0;
17177836SJohn.Forte@Sun.COM goto fail;
17187836SJohn.Forte@Sun.COM }
17197836SJohn.Forte@Sun.COM #ifdef DEBUG_FLUSHER_UBERNOISE
1720*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!BUFFOFF_0 %d", bufoff);
17217836SJohn.Forte@Sun.COM #endif
17227836SJohn.Forte@Sun.COM
17237836SJohn.Forte@Sun.COM if ((vaddr == NULL) || (vlen == 0))
17247836SJohn.Forte@Sun.COM break;
17257836SJohn.Forte@Sun.COM
17267836SJohn.Forte@Sun.COM if (vlen <= 0) {
17277836SJohn.Forte@Sun.COM vecp++;
17287836SJohn.Forte@Sun.COM vaddr = vecp->sv_addr;
17297836SJohn.Forte@Sun.COM vlen = vecp->sv_len;
17307836SJohn.Forte@Sun.COM if (vaddr == NULL)
17317836SJohn.Forte@Sun.COM break;
17327836SJohn.Forte@Sun.COM }
17337836SJohn.Forte@Sun.COM
17347836SJohn.Forte@Sun.COM /* get the iohdr information */
17357836SJohn.Forte@Sun.COM
17367836SJohn.Forte@Sun.COM hdr = kmem_zalloc(sizeof (*hdr), KM_NOSLEEP);
17377836SJohn.Forte@Sun.COM if (hdr == NULL) {
17387836SJohn.Forte@Sun.COM cmn_err(CE_WARN,
1739*9093SRamana.Srikanth@Sun.COM "!SNDR: unable to alocate net queue header");
17407836SJohn.Forte@Sun.COM goto fail;
17417836SJohn.Forte@Sun.COM }
17427836SJohn.Forte@Sun.COM
17437836SJohn.Forte@Sun.COM ioaddr = (uchar_t *)hdr;
17447836SJohn.Forte@Sun.COM
17457836SJohn.Forte@Sun.COM bcopy(vaddr, ioaddr, sizeof (*hdr));
17467836SJohn.Forte@Sun.COM
17477836SJohn.Forte@Sun.COM if (!rdc_iohdr_ok(hdr)) {
17487836SJohn.Forte@Sun.COM cmn_err(CE_WARN,
1749*9093SRamana.Srikanth@Sun.COM "!unable to retrieve i/o data from queue %s "
17507836SJohn.Forte@Sun.COM "at offset %" NSC_SZFMT " bp: %" NSC_SZFMT " bl: %"
17517836SJohn.Forte@Sun.COM NSC_SZFMT, urdc->disk_queue,
17527836SJohn.Forte@Sun.COM bufoff, buf->sb_pos, buf->sb_len);
17537836SJohn.Forte@Sun.COM #ifdef DEBUG_DISKQ
1754*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!FAILING QUEUE state: %x",
17557836SJohn.Forte@Sun.COM rdc_get_vflags(urdc));
1756*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!qinfo: " QDISPLAY(dq));
1757*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!VADDR %p, IOADDR %p", vaddr, ioaddr);
1758*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!BUF %p", buf);
17597836SJohn.Forte@Sun.COM #endif
1760*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!qinfo: " QDISPLAYND(dq));
17617836SJohn.Forte@Sun.COM
17627836SJohn.Forte@Sun.COM goto fail;
17637836SJohn.Forte@Sun.COM }
17647836SJohn.Forte@Sun.COM
17657836SJohn.Forte@Sun.COM nullbuf = hdr->dat.flag & RDC_NULL_BUF;
17667836SJohn.Forte@Sun.COM
17677836SJohn.Forte@Sun.COM bufoff += FBA_NUM(sizeof (*hdr));
17687836SJohn.Forte@Sun.COM
17697836SJohn.Forte@Sun.COM /* out of buffer, set nxtio to re read this last hdr */
17707836SJohn.Forte@Sun.COM if (!nullbuf && ((bufoff + hdr->dat.len) > endobuf)) {
17717836SJohn.Forte@Sun.COM break;
17727836SJohn.Forte@Sun.COM }
17737836SJohn.Forte@Sun.COM
17747836SJohn.Forte@Sun.COM bufcnt += FBA_NUM(sizeof (*hdr));
17757836SJohn.Forte@Sun.COM
17767836SJohn.Forte@Sun.COM aio = kmem_zalloc(sizeof (*aio), KM_NOSLEEP);
17777836SJohn.Forte@Sun.COM if (aio == NULL) {
17787836SJohn.Forte@Sun.COM bufcnt -= FBA_NUM(sizeof (*hdr));
1779*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!SNDR: net queue aio alloc failed");
17807836SJohn.Forte@Sun.COM goto fail;
17817836SJohn.Forte@Sun.COM }
17827836SJohn.Forte@Sun.COM
17837836SJohn.Forte@Sun.COM if (!nullbuf) {
17847836SJohn.Forte@Sun.COM /* move to next iohdr in big buf */
17857836SJohn.Forte@Sun.COM bufoff += hdr->dat.len;
17867836SJohn.Forte@Sun.COM bufcnt += hdr->dat.len;
17877836SJohn.Forte@Sun.COM }
17887836SJohn.Forte@Sun.COM
17897836SJohn.Forte@Sun.COM rdc_fill_aio(grp, aio, hdr, buf);
17907836SJohn.Forte@Sun.COM
17917836SJohn.Forte@Sun.COM if (aio->index < 0) {
1792*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!Set id %d not found or no longer "
17937836SJohn.Forte@Sun.COM "enabled, failing disk queue", hdr->dat.setid);
17947836SJohn.Forte@Sun.COM kmem_free(aio, sizeof (*aio));
17957836SJohn.Forte@Sun.COM goto fail;
17967836SJohn.Forte@Sun.COM }
17977836SJohn.Forte@Sun.COM if (aio->seq == RDC_NOSEQ) {
17987836SJohn.Forte@Sun.COM kmem_free(aio, sizeof (*aio));
17997836SJohn.Forte@Sun.COM fail = 0;
18007836SJohn.Forte@Sun.COM goto fail;
18017836SJohn.Forte@Sun.COM }
18027836SJohn.Forte@Sun.COM if (aio->handle == NULL)
18037836SJohn.Forte@Sun.COM nullblocks += aio->len;
18047836SJohn.Forte@Sun.COM
18057836SJohn.Forte@Sun.COM rdc_add_iohdr(hdr, grp);
18067836SJohn.Forte@Sun.COM hdr = NULL; /* don't accidentally free on break or fail */
18077836SJohn.Forte@Sun.COM rdc_netqueue_insert(aio, netq);
18087836SJohn.Forte@Sun.COM
18097836SJohn.Forte@Sun.COM /* no more buffer, skip the below logic */
18107836SJohn.Forte@Sun.COM if ((bufoff + FBA_NUM(sizeof (*hdr))) >= endobuf) {
18117836SJohn.Forte@Sun.COM break;
18127836SJohn.Forte@Sun.COM }
18137836SJohn.Forte@Sun.COM
18147836SJohn.Forte@Sun.COM fpos = bufoff - buf->sb_pos;
18157836SJohn.Forte@Sun.COM vecp = buf->sb_vec;
18167836SJohn.Forte@Sun.COM for (; fpos >= FBA_NUM(vecp->sv_len); vecp++)
18177836SJohn.Forte@Sun.COM fpos -= FBA_NUM(vecp->sv_len);
18187836SJohn.Forte@Sun.COM vlen = vecp->sv_len - FBA_SIZE(fpos);
18197836SJohn.Forte@Sun.COM vaddr = vecp->sv_addr + FBA_SIZE(fpos);
18207836SJohn.Forte@Sun.COM /* abuf = NULL; */
18217836SJohn.Forte@Sun.COM
18227836SJohn.Forte@Sun.COM }
18237836SJohn.Forte@Sun.COM
18247836SJohn.Forte@Sun.COM /* free extraneous header */
18257836SJohn.Forte@Sun.COM if (hdr) {
18267836SJohn.Forte@Sun.COM kmem_free(hdr, sizeof (*hdr));
18277836SJohn.Forte@Sun.COM hdr = NULL;
18287836SJohn.Forte@Sun.COM }
18297836SJohn.Forte@Sun.COM
18307836SJohn.Forte@Sun.COM /*
18317836SJohn.Forte@Sun.COM * probably won't happen, but if we didn't goto fail, but
18327836SJohn.Forte@Sun.COM * we don't contain anything meaningful.. return NULL
18337836SJohn.Forte@Sun.COM * and let the flusher or the sleep/wakeup routines
18347836SJohn.Forte@Sun.COM * decide
18357836SJohn.Forte@Sun.COM */
18367836SJohn.Forte@Sun.COM if (netq && netq->nitems == 0) {
18377836SJohn.Forte@Sun.COM kmem_free(netq, sizeof (*netq));
18387836SJohn.Forte@Sun.COM return (NULL);
18397836SJohn.Forte@Sun.COM }
18407836SJohn.Forte@Sun.COM
18417836SJohn.Forte@Sun.COM #ifdef DEBUG
18427836SJohn.Forte@Sun.COM buf2qcalls++;
18437836SJohn.Forte@Sun.COM calc_perbuf(netq->nitems);
18447836SJohn.Forte@Sun.COM #endif
18457836SJohn.Forte@Sun.COM if (IS_STATE(urdc, RDC_LOGGING) ||
18467836SJohn.Forte@Sun.COM nq->qfflags & RDC_QFILLSLEEP) {
18477836SJohn.Forte@Sun.COM fail = 0;
18487836SJohn.Forte@Sun.COM goto fail;
18497836SJohn.Forte@Sun.COM }
18507836SJohn.Forte@Sun.COM
18517836SJohn.Forte@Sun.COM mutex_enter(QLOCK(dq));
18527836SJohn.Forte@Sun.COM INC_QNXTIO(dq, bufcnt);
18537836SJohn.Forte@Sun.COM mutex_exit(QLOCK(dq));
18547836SJohn.Forte@Sun.COM
18557836SJohn.Forte@Sun.COM netq->net_qtail->orig_len = nullblocks; /* overload */
18567836SJohn.Forte@Sun.COM
18577836SJohn.Forte@Sun.COM return (netq);
18587836SJohn.Forte@Sun.COM
18597836SJohn.Forte@Sun.COM fail:
18607836SJohn.Forte@Sun.COM
18617836SJohn.Forte@Sun.COM if (hdr) {
18627836SJohn.Forte@Sun.COM kmem_free(hdr, sizeof (*hdr));
18637836SJohn.Forte@Sun.COM }
18647836SJohn.Forte@Sun.COM
18657836SJohn.Forte@Sun.COM if (netq) {
18667836SJohn.Forte@Sun.COM if (netq->nitems > 0) {
18677836SJohn.Forte@Sun.COM /* the never can happen case ... */
18687836SJohn.Forte@Sun.COM if ((netq->nitems == 1) &&
18697836SJohn.Forte@Sun.COM (netq->net_qhead->handle == NULL))
18707836SJohn.Forte@Sun.COM (void) nsc_free_buf(buf);
18717836SJohn.Forte@Sun.COM *abuf = NULL;
18727836SJohn.Forte@Sun.COM
18737836SJohn.Forte@Sun.COM }
18747836SJohn.Forte@Sun.COM rdc_discard_tmpq(netq);
18757836SJohn.Forte@Sun.COM }
18767836SJohn.Forte@Sun.COM
18777836SJohn.Forte@Sun.COM mutex_enter(QLOCK(dq));
18787836SJohn.Forte@Sun.COM rdc_dump_iohdrs(dq);
18797836SJohn.Forte@Sun.COM mutex_exit(QLOCK(dq));
18807836SJohn.Forte@Sun.COM
18817836SJohn.Forte@Sun.COM if (fail) { /* real failure, not just state change */
18827836SJohn.Forte@Sun.COM #ifdef DEBUG
1883*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!rdc_diskq_buf2queue: failing disk queue %s",
18847836SJohn.Forte@Sun.COM urdc->disk_queue);
18857836SJohn.Forte@Sun.COM #endif
18867836SJohn.Forte@Sun.COM rdc_fail_diskq(krdc, RDC_NOWAIT, RDC_DOLOG);
18877836SJohn.Forte@Sun.COM }
18887836SJohn.Forte@Sun.COM
18897836SJohn.Forte@Sun.COM return (NULL);
18907836SJohn.Forte@Sun.COM
18917836SJohn.Forte@Sun.COM }
18927836SJohn.Forte@Sun.COM
18937836SJohn.Forte@Sun.COM /*
18947836SJohn.Forte@Sun.COM * rdc_diskq_unqueue
18957836SJohn.Forte@Sun.COM * remove one chunk from the diskq belonging to
18967836SJohn.Forte@Sun.COM * rdc_k_info[index]
18977836SJohn.Forte@Sun.COM * updates the head and tail pointers in the disk header
18987836SJohn.Forte@Sun.COM * but does not write. The header should be written on ack
18997836SJohn.Forte@Sun.COM * flusher should free whatever..
19007836SJohn.Forte@Sun.COM */
19017836SJohn.Forte@Sun.COM rdc_aio_t *
rdc_diskq_unqueue(int index)19027836SJohn.Forte@Sun.COM rdc_diskq_unqueue(int index)
19037836SJohn.Forte@Sun.COM {
19047836SJohn.Forte@Sun.COM int rc, rc1, rc2;
19057836SJohn.Forte@Sun.COM nsc_off_t qhead;
19067836SJohn.Forte@Sun.COM int nullhandle = 0;
19077836SJohn.Forte@Sun.COM io_hdr *iohdr;
19087836SJohn.Forte@Sun.COM rdc_aio_t *aio = NULL;
19097836SJohn.Forte@Sun.COM nsc_buf_t *buf = NULL;
19107836SJohn.Forte@Sun.COM nsc_buf_t *abuf = NULL;
19117836SJohn.Forte@Sun.COM rdc_group_t *group = NULL;
19127836SJohn.Forte@Sun.COM disk_queue *q = NULL;
19137836SJohn.Forte@Sun.COM rdc_k_info_t *krdc = &rdc_k_info[index];
19147836SJohn.Forte@Sun.COM rdc_u_info_t *urdc = &rdc_u_info[index];
19157836SJohn.Forte@Sun.COM
19167836SJohn.Forte@Sun.COM group = krdc->group;
19177836SJohn.Forte@Sun.COM q = &group->diskq;
19187836SJohn.Forte@Sun.COM
19197836SJohn.Forte@Sun.COM if (group->diskqfd == NULL) /* we've been disabled */
19207836SJohn.Forte@Sun.COM return (NULL);
19217836SJohn.Forte@Sun.COM
19227836SJohn.Forte@Sun.COM aio = kmem_zalloc(sizeof (*aio), KM_NOSLEEP);
19237836SJohn.Forte@Sun.COM if (!aio) {
19247836SJohn.Forte@Sun.COM return (NULL);
19257836SJohn.Forte@Sun.COM }
19267836SJohn.Forte@Sun.COM
19277836SJohn.Forte@Sun.COM iohdr = kmem_zalloc(sizeof (*iohdr), KM_NOSLEEP);
19287836SJohn.Forte@Sun.COM if (!iohdr) {
19297836SJohn.Forte@Sun.COM kmem_free(aio, sizeof (*aio));
19307836SJohn.Forte@Sun.COM return (NULL);
19317836SJohn.Forte@Sun.COM }
19327836SJohn.Forte@Sun.COM
19337836SJohn.Forte@Sun.COM mutex_enter(QLOCK(q));
19347836SJohn.Forte@Sun.COM rdc_set_qbusy(q); /* make sure no one disables the queue */
19357836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
19367836SJohn.Forte@Sun.COM
19377836SJohn.Forte@Sun.COM DTRACE_PROBE(rdc_diskq_unq_rsrv);
19387836SJohn.Forte@Sun.COM
19397836SJohn.Forte@Sun.COM if (_rdc_rsrv_diskq(group)) {
1940*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!rdc_unqueue: %s reserve failed",
19417836SJohn.Forte@Sun.COM urdc->disk_queue);
19427836SJohn.Forte@Sun.COM goto fail;
19437836SJohn.Forte@Sun.COM }
19447836SJohn.Forte@Sun.COM
19457836SJohn.Forte@Sun.COM mutex_enter(QHEADLOCK(q));
19467836SJohn.Forte@Sun.COM mutex_enter(QLOCK(q));
19477836SJohn.Forte@Sun.COM
19487836SJohn.Forte@Sun.COM if (IS_STATE(urdc, RDC_DISKQ_FAILED) || IS_STATE(urdc, RDC_LOGGING)) {
19497836SJohn.Forte@Sun.COM rdc_clr_qbusy(q);
19507836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
19517836SJohn.Forte@Sun.COM mutex_exit(QHEADLOCK(q));
19527836SJohn.Forte@Sun.COM kmem_free(aio, sizeof (*aio));
19537836SJohn.Forte@Sun.COM kmem_free(iohdr, sizeof (*iohdr));
19547836SJohn.Forte@Sun.COM return (NULL);
19557836SJohn.Forte@Sun.COM }
19567836SJohn.Forte@Sun.COM
19577836SJohn.Forte@Sun.COM if (QNXTIOSHLDWRAP(q)) {
19587836SJohn.Forte@Sun.COM #ifdef DEBUG_DISKQWRAP
1959*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!wrapping Q nxtio: " QDISPLAY(q));
19607836SJohn.Forte@Sun.COM #endif
19617836SJohn.Forte@Sun.COM /*LINTED*/
19627836SJohn.Forte@Sun.COM WRAPQNXTIO(q);
19637836SJohn.Forte@Sun.COM }
19647836SJohn.Forte@Sun.COM
19657836SJohn.Forte@Sun.COM /* read the metainfo at q->nxt_io first */
19667836SJohn.Forte@Sun.COM if (QNXTIO(q) == QTAIL(q)) { /* empty */
19677836SJohn.Forte@Sun.COM
19687836SJohn.Forte@Sun.COM _rdc_rlse_diskq(group);
19697836SJohn.Forte@Sun.COM if (q->lastio->handle)
19707836SJohn.Forte@Sun.COM (void) nsc_free_buf(q->lastio->handle);
19717836SJohn.Forte@Sun.COM bzero(&(*q->lastio), sizeof (*q->lastio));
19727836SJohn.Forte@Sun.COM
19737836SJohn.Forte@Sun.COM mutex_exit(QHEADLOCK(q));
19747836SJohn.Forte@Sun.COM rdc_clr_qbusy(q);
19757836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
19767836SJohn.Forte@Sun.COM kmem_free(aio, sizeof (*aio));
19777836SJohn.Forte@Sun.COM kmem_free(iohdr, sizeof (*iohdr));
19787836SJohn.Forte@Sun.COM return (NULL);
19797836SJohn.Forte@Sun.COM }
19807836SJohn.Forte@Sun.COM
19817836SJohn.Forte@Sun.COM qhead = QNXTIO(q);
19827836SJohn.Forte@Sun.COM
19837836SJohn.Forte@Sun.COM /*
19847836SJohn.Forte@Sun.COM * have to drop the lock here, sigh. Cannot block incoming io
19857836SJohn.Forte@Sun.COM * we have to wait until after this read to find out how
19867836SJohn.Forte@Sun.COM * much to increment QNXTIO. Might as well grab the seq then too
19877836SJohn.Forte@Sun.COM */
19887836SJohn.Forte@Sun.COM
19897836SJohn.Forte@Sun.COM while ((qhead == LASTQTAIL(q)) && (IS_QSTATE(q, QTAILBUSY))) {
19907836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
19917836SJohn.Forte@Sun.COM #ifdef DEBUG_DISKQ
1992*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!Qtail busy delay lastqtail: %d", qhead);
19937836SJohn.Forte@Sun.COM #endif
19947836SJohn.Forte@Sun.COM delay(5);
19957836SJohn.Forte@Sun.COM mutex_enter(QLOCK(q));
19967836SJohn.Forte@Sun.COM }
19977836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
19987836SJohn.Forte@Sun.COM
19997836SJohn.Forte@Sun.COM DTRACE_PROBE(rdc_diskq_iohdr_read_start);
20007836SJohn.Forte@Sun.COM
20017836SJohn.Forte@Sun.COM rc = rdc_ns_io(group->diskqfd, NSC_READ, qhead,
20027836SJohn.Forte@Sun.COM (uchar_t *)iohdr, FBA_SIZE(1));
20037836SJohn.Forte@Sun.COM
20047836SJohn.Forte@Sun.COM DTRACE_PROBE(rdc_diskq_iohdr_read_end);
20057836SJohn.Forte@Sun.COM
20067836SJohn.Forte@Sun.COM if (!RDC_SUCCESS(rc) || !rdc_iohdr_ok(iohdr)) {
2007*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!unable to retrieve i/o data from queue %s"
20087836SJohn.Forte@Sun.COM " at offset %" NSC_SZFMT " rc %d", urdc->disk_queue,
20097836SJohn.Forte@Sun.COM qhead, rc);
20107836SJohn.Forte@Sun.COM #ifdef DEBUG_DISKQ
2011*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!qinfo: " QDISPLAY(q));
20127836SJohn.Forte@Sun.COM #endif
20137836SJohn.Forte@Sun.COM mutex_exit(QHEADLOCK(q));
20147836SJohn.Forte@Sun.COM goto fail;
20157836SJohn.Forte@Sun.COM }
20167836SJohn.Forte@Sun.COM
20177836SJohn.Forte@Sun.COM /* XXX process buffer here, creating rdc_aio_t's */
20187836SJohn.Forte@Sun.COM
20197836SJohn.Forte@Sun.COM mutex_enter(QLOCK(q));
20207836SJohn.Forte@Sun.COM /* update the next pointer */
20217836SJohn.Forte@Sun.COM if (iohdr->dat.flag == RDC_NULL_BUF) {
20227836SJohn.Forte@Sun.COM INC_QNXTIO(q, FBA_LEN(sizeof (io_hdr)));
20237836SJohn.Forte@Sun.COM nullhandle = 1;
20247836SJohn.Forte@Sun.COM } else {
20257836SJohn.Forte@Sun.COM INC_QNXTIO(q, (FBA_LEN(sizeof (io_hdr)) + iohdr->dat.len));
20267836SJohn.Forte@Sun.COM }
20277836SJohn.Forte@Sun.COM
20287836SJohn.Forte@Sun.COM aio->seq = group->seq++;
20297836SJohn.Forte@Sun.COM if (group->seq < aio->seq)
20307836SJohn.Forte@Sun.COM group->seq = RDC_NEWSEQ + 1;
20317836SJohn.Forte@Sun.COM
20327836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
20337836SJohn.Forte@Sun.COM mutex_exit(QHEADLOCK(q));
20347836SJohn.Forte@Sun.COM
20357836SJohn.Forte@Sun.COM #ifdef DEBUG_FLUSHER_UBERNOISE
20367836SJohn.Forte@Sun.COM p = &iohdr->dat;
2037*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!unqueued iohdr from %d pos: %d len: %d flag: %d "
20387836SJohn.Forte@Sun.COM "iostatus: %d setid: %d time: %d", qhead, p->pos, p->len,
20397836SJohn.Forte@Sun.COM p->flag, p->iostatus, p->setid, p->time);
20407836SJohn.Forte@Sun.COM #endif
20417836SJohn.Forte@Sun.COM
20427836SJohn.Forte@Sun.COM if (nullhandle) /* nothing to get from queue */
20437836SJohn.Forte@Sun.COM goto nullbuf;
20447836SJohn.Forte@Sun.COM
20457836SJohn.Forte@Sun.COM /* now that we know how much to get (iohdr.dat.len), get it */
20467836SJohn.Forte@Sun.COM DTRACE_PROBE(rdc_diskq_unq_allocbuf1_start);
20477836SJohn.Forte@Sun.COM
20487836SJohn.Forte@Sun.COM rc = nsc_alloc_buf(group->diskqfd, qhead + 1, iohdr->dat.len,
20497836SJohn.Forte@Sun.COM NSC_NOCACHE | NSC_READ, &buf);
20507836SJohn.Forte@Sun.COM
20517836SJohn.Forte@Sun.COM DTRACE_PROBE(rdc_diskq_unq_allocbuf1_end);
20527836SJohn.Forte@Sun.COM
20537836SJohn.Forte@Sun.COM /* and get somewhere to keep it for a bit */
20547836SJohn.Forte@Sun.COM DTRACE_PROBE(rdc_diskq_unq_allocbuf2_start);
20557836SJohn.Forte@Sun.COM
20567836SJohn.Forte@Sun.COM rc1 = nsc_alloc_abuf(qhead + 1, iohdr->dat.len, 0, &abuf);
20577836SJohn.Forte@Sun.COM
20587836SJohn.Forte@Sun.COM DTRACE_PROBE(rdc_diskq_unq_allocbuf2_end);
20597836SJohn.Forte@Sun.COM
20607836SJohn.Forte@Sun.COM if (!RDC_SUCCESS(rc) || !RDC_SUCCESS(rc1)) { /* uh-oh */
2061*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!disk queue %s read failure",
20627836SJohn.Forte@Sun.COM urdc->disk_queue);
20637836SJohn.Forte@Sun.COM goto fail;
20647836SJohn.Forte@Sun.COM }
20657836SJohn.Forte@Sun.COM
20667836SJohn.Forte@Sun.COM /* move it on over... */
20677836SJohn.Forte@Sun.COM rc2 = nsc_copy(buf, abuf, qhead + 1, qhead + 1, iohdr->dat.len);
20687836SJohn.Forte@Sun.COM
20697836SJohn.Forte@Sun.COM if (!RDC_SUCCESS(rc2)) {
20707836SJohn.Forte@Sun.COM #ifdef DEBUG
2071*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!nsc_copy failed for diskq unqueue");
20727836SJohn.Forte@Sun.COM #endif
20737836SJohn.Forte@Sun.COM goto fail;
20747836SJohn.Forte@Sun.COM }
20757836SJohn.Forte@Sun.COM
20767836SJohn.Forte@Sun.COM /* let go of the real buf, we've got the abuf */
20777836SJohn.Forte@Sun.COM (void) nsc_free_buf(buf);
20787836SJohn.Forte@Sun.COM buf = NULL;
20797836SJohn.Forte@Sun.COM
20807836SJohn.Forte@Sun.COM aio->handle = abuf;
20817836SJohn.Forte@Sun.COM /* Hack in the original sb_pos */
20827836SJohn.Forte@Sun.COM aio->handle->sb_pos = iohdr->dat.hpos;
20837836SJohn.Forte@Sun.COM
20847836SJohn.Forte@Sun.COM /* skip the RDC_HANDLE_LIMITS check */
20857836SJohn.Forte@Sun.COM abuf->sb_user |= RDC_DISKQUE;
20867836SJohn.Forte@Sun.COM
20877836SJohn.Forte@Sun.COM nullbuf:
20887836SJohn.Forte@Sun.COM if (nullhandle) {
20897836SJohn.Forte@Sun.COM aio->handle = NULL;
20907836SJohn.Forte@Sun.COM }
20917836SJohn.Forte@Sun.COM
20927836SJohn.Forte@Sun.COM /* set up the rest of the aio values, seq set above ... */
20937836SJohn.Forte@Sun.COM aio->pos = iohdr->dat.pos;
20947836SJohn.Forte@Sun.COM aio->qpos = iohdr->dat.qpos;
20957836SJohn.Forte@Sun.COM aio->len = iohdr->dat.len;
20967836SJohn.Forte@Sun.COM aio->flag = iohdr->dat.flag;
20977836SJohn.Forte@Sun.COM aio->index = rdc_setid2idx(iohdr->dat.setid);
20987836SJohn.Forte@Sun.COM if (aio->index < 0) { /* uh-oh */
20997836SJohn.Forte@Sun.COM #ifdef DEBUG
2100*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!rdc_diskq_unqueue: index < 0");
21017836SJohn.Forte@Sun.COM #endif
21027836SJohn.Forte@Sun.COM goto fail;
21037836SJohn.Forte@Sun.COM }
21047836SJohn.Forte@Sun.COM
21057836SJohn.Forte@Sun.COM
21067836SJohn.Forte@Sun.COM #ifdef DEBUG_FLUSHER_UBERNOISE_STAMP
21077836SJohn.Forte@Sun.COM h = &q->disk_hdr.h;
2108*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!stamping diskq header:\n"
21097836SJohn.Forte@Sun.COM "magic: %x\nstate: %d\nhead_offset: %d\n"
21107836SJohn.Forte@Sun.COM "tail_offset: %d\ndisk_size: %d\nnitems: %d\nblocks: %d\n",
21117836SJohn.Forte@Sun.COM h->magic, h->state, h->head_offset, h->tail_offset,
21127836SJohn.Forte@Sun.COM h->disk_size, h->nitems, h->blocks);
21137836SJohn.Forte@Sun.COM #endif
21147836SJohn.Forte@Sun.COM
21157836SJohn.Forte@Sun.COM _rdc_rlse_diskq(group);
21167836SJohn.Forte@Sun.COM
21177836SJohn.Forte@Sun.COM mutex_enter(QLOCK(q));
21187836SJohn.Forte@Sun.COM rdc_clr_qbusy(q);
21197836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
21207836SJohn.Forte@Sun.COM
21217836SJohn.Forte@Sun.COM DTRACE_PROBE(rdc_diskq_unq_rlse);
21227836SJohn.Forte@Sun.COM
21237836SJohn.Forte@Sun.COM iohdr->dat.iostatus = aio->seq;
21247836SJohn.Forte@Sun.COM rdc_add_iohdr(iohdr, group);
21257836SJohn.Forte@Sun.COM
21267836SJohn.Forte@Sun.COM #ifdef DEBUG_FLUSHER_UBERNOISE
21277836SJohn.Forte@Sun.COM if (!nullhandle) {
2128*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!UNQUEUING, %p"
21297836SJohn.Forte@Sun.COM " contents: %c%c%c%c%c pos: %d len: %d",
21307836SJohn.Forte@Sun.COM (void *)aio->handle,
21317836SJohn.Forte@Sun.COM aio->handle->sb_vec[0].sv_addr[0],
21327836SJohn.Forte@Sun.COM aio->handle->sb_vec[0].sv_addr[1],
21337836SJohn.Forte@Sun.COM aio->handle->sb_vec[0].sv_addr[2],
21347836SJohn.Forte@Sun.COM aio->handle->sb_vec[0].sv_addr[3],
21357836SJohn.Forte@Sun.COM aio->handle->sb_vec[0].sv_addr[4],
21367836SJohn.Forte@Sun.COM aio->handle->sb_pos, aio->handle->sb_len);
21377836SJohn.Forte@Sun.COM } else {
2138*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!UNQUEUING, NULL " QDISPLAY(q));
21397836SJohn.Forte@Sun.COM }
2140*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!qinfo: " QDISPLAY(q));
21417836SJohn.Forte@Sun.COM #endif
21427836SJohn.Forte@Sun.COM
21437836SJohn.Forte@Sun.COM return (aio);
21447836SJohn.Forte@Sun.COM
21457836SJohn.Forte@Sun.COM fail:
21467836SJohn.Forte@Sun.COM if (aio)
21477836SJohn.Forte@Sun.COM kmem_free(aio, sizeof (*aio));
21487836SJohn.Forte@Sun.COM if (iohdr)
21497836SJohn.Forte@Sun.COM kmem_free(iohdr, sizeof (*iohdr));
21507836SJohn.Forte@Sun.COM if (buf)
21517836SJohn.Forte@Sun.COM (void) nsc_free_buf(buf);
21527836SJohn.Forte@Sun.COM if (abuf)
21537836SJohn.Forte@Sun.COM (void) nsc_free_buf(abuf);
21547836SJohn.Forte@Sun.COM
21557836SJohn.Forte@Sun.COM _rdc_rlse_diskq(group);
21567836SJohn.Forte@Sun.COM #ifdef DEBUG
2157*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!diskq_unqueue: failing diskq");
21587836SJohn.Forte@Sun.COM #endif
21597836SJohn.Forte@Sun.COM mutex_enter(QLOCK(q));
21607836SJohn.Forte@Sun.COM rdc_clr_qbusy(q);
21617836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
21627836SJohn.Forte@Sun.COM
21637836SJohn.Forte@Sun.COM rdc_fail_diskq(krdc, RDC_NOWAIT, RDC_DOLOG);
21647836SJohn.Forte@Sun.COM
21657836SJohn.Forte@Sun.COM return (NULL);
21667836SJohn.Forte@Sun.COM }
21677836SJohn.Forte@Sun.COM
21687836SJohn.Forte@Sun.COM int
rdc_diskq_inuse(rdc_set_t * set,char * diskq)21697836SJohn.Forte@Sun.COM rdc_diskq_inuse(rdc_set_t *set, char *diskq)
21707836SJohn.Forte@Sun.COM {
21717836SJohn.Forte@Sun.COM rdc_u_info_t *urdc;
21727836SJohn.Forte@Sun.COM char *group;
21737836SJohn.Forte@Sun.COM int index;
21747836SJohn.Forte@Sun.COM
21757836SJohn.Forte@Sun.COM group = set->group_name;
21767836SJohn.Forte@Sun.COM
21777836SJohn.Forte@Sun.COM ASSERT(MUTEX_HELD(&rdc_conf_lock));
21787836SJohn.Forte@Sun.COM
21797836SJohn.Forte@Sun.COM if ((rdc_lookup_bitmap(diskq) >= 0) ||
21807836SJohn.Forte@Sun.COM (rdc_lookup_configured(diskq) >= 0)) {
21817836SJohn.Forte@Sun.COM return (1);
21827836SJohn.Forte@Sun.COM }
21837836SJohn.Forte@Sun.COM for (index = 0; index < rdc_max_sets; index++) {
21847836SJohn.Forte@Sun.COM urdc = &rdc_u_info[index];
21857836SJohn.Forte@Sun.COM
21867836SJohn.Forte@Sun.COM if (!IS_ENABLED(urdc))
21877836SJohn.Forte@Sun.COM continue;
21887836SJohn.Forte@Sun.COM
21897836SJohn.Forte@Sun.COM /* same diskq different group */
21907836SJohn.Forte@Sun.COM if ((strcmp(urdc->disk_queue, diskq) == 0) &&
21917836SJohn.Forte@Sun.COM (urdc->group_name[0] == '\0' ||
21927836SJohn.Forte@Sun.COM strcmp(urdc->group_name, group))) {
21937836SJohn.Forte@Sun.COM return (1);
21947836SJohn.Forte@Sun.COM }
21957836SJohn.Forte@Sun.COM }
21967836SJohn.Forte@Sun.COM /* last, but not least, lets see if someone is getting really funky */
21977836SJohn.Forte@Sun.COM if ((strcmp(set->disk_queue, set->primary.file) == 0) ||
21987836SJohn.Forte@Sun.COM (strcmp(set->disk_queue, set->primary.bitmap) == 0)) {
21997836SJohn.Forte@Sun.COM return (1);
22007836SJohn.Forte@Sun.COM }
22017836SJohn.Forte@Sun.COM
22027836SJohn.Forte@Sun.COM return (0);
22037836SJohn.Forte@Sun.COM
22047836SJohn.Forte@Sun.COM }
22057836SJohn.Forte@Sun.COM
22067836SJohn.Forte@Sun.COM #ifdef DEBUG
22077836SJohn.Forte@Sun.COM int maxlen = 0;
22087836SJohn.Forte@Sun.COM int avelen = 0;
22097836SJohn.Forte@Sun.COM int totalen = 0;
22107836SJohn.Forte@Sun.COM int lencalls = 0;
22117836SJohn.Forte@Sun.COM
22127836SJohn.Forte@Sun.COM void
update_lenstats(int len)22137836SJohn.Forte@Sun.COM update_lenstats(int len)
22147836SJohn.Forte@Sun.COM {
22157836SJohn.Forte@Sun.COM if (lencalls == 0) {
22167836SJohn.Forte@Sun.COM lencalls = 1;
22177836SJohn.Forte@Sun.COM avelen = 0;
22187836SJohn.Forte@Sun.COM maxlen = 0;
22197836SJohn.Forte@Sun.COM totalen = 0;
22207836SJohn.Forte@Sun.COM }
22217836SJohn.Forte@Sun.COM
22227836SJohn.Forte@Sun.COM if (len > maxlen)
22237836SJohn.Forte@Sun.COM maxlen = len;
22247836SJohn.Forte@Sun.COM totalen += len;
22257836SJohn.Forte@Sun.COM avelen = totalen / lencalls;
22267836SJohn.Forte@Sun.COM }
22277836SJohn.Forte@Sun.COM #endif
22287836SJohn.Forte@Sun.COM
22297836SJohn.Forte@Sun.COM /*
22307836SJohn.Forte@Sun.COM * rdc_calc_len()
22317836SJohn.Forte@Sun.COM * returns the size of the diskq that can be read for dequeuing
22327836SJohn.Forte@Sun.COM * always <= RDC_MAX_DISKQREAD
22337836SJohn.Forte@Sun.COM */
22347836SJohn.Forte@Sun.COM int
rdc_calc_len(rdc_k_info_t * krdc,disk_queue * dq)22357836SJohn.Forte@Sun.COM rdc_calc_len(rdc_k_info_t *krdc, disk_queue *dq)
22367836SJohn.Forte@Sun.COM {
22377836SJohn.Forte@Sun.COM nsc_size_t len = 0;
22387836SJohn.Forte@Sun.COM
22397836SJohn.Forte@Sun.COM ASSERT(MUTEX_HELD(QLOCK(dq)));
22407836SJohn.Forte@Sun.COM
22417836SJohn.Forte@Sun.COM /* ---H-----N-----T--- */
22427836SJohn.Forte@Sun.COM if (QNXTIO(dq) < QTAIL(dq)) {
22437836SJohn.Forte@Sun.COM
22447836SJohn.Forte@Sun.COM len = min(RDC_MAX_DISKQREAD, QTAIL(dq) - QNXTIO(dq));
22457836SJohn.Forte@Sun.COM
22467836SJohn.Forte@Sun.COM /* ---T-----H-----N--- */
22477836SJohn.Forte@Sun.COM } else if (QNXTIO(dq) > QTAIL(dq)) {
22487836SJohn.Forte@Sun.COM if (QWRAP(dq)) {
22497836SJohn.Forte@Sun.COM len = min(RDC_MAX_DISKQREAD, QWRAP(dq) - QNXTIO(dq));
22507836SJohn.Forte@Sun.COM } else { /* should never happen */
22517836SJohn.Forte@Sun.COM len = min(RDC_MAX_DISKQREAD, QSIZE(dq) - QNXTIO(dq));
22527836SJohn.Forte@Sun.COM }
22537836SJohn.Forte@Sun.COM } else if (QNXTIO(dq) == QTAIL(dq)) {
22547836SJohn.Forte@Sun.COM if (QWRAP(dq) && !IS_QSTATE(dq, QNXTIOWRAPD))
22557836SJohn.Forte@Sun.COM len = min(RDC_MAX_DISKQREAD, QWRAP(dq) - QNXTIO(dq));
22567836SJohn.Forte@Sun.COM }
22577836SJohn.Forte@Sun.COM
22587836SJohn.Forte@Sun.COM len = min(len, krdc->maxfbas);
22597836SJohn.Forte@Sun.COM
22607836SJohn.Forte@Sun.COM #ifdef DEBUG
22617836SJohn.Forte@Sun.COM lencalls++;
22627836SJohn.Forte@Sun.COM update_lenstats(len);
22637836SJohn.Forte@Sun.COM #endif
22647836SJohn.Forte@Sun.COM
22657836SJohn.Forte@Sun.COM return ((int)len);
22667836SJohn.Forte@Sun.COM }
22677836SJohn.Forte@Sun.COM
22687836SJohn.Forte@Sun.COM /*
22697836SJohn.Forte@Sun.COM * lie a little if we can, so we don't get tied up in
22707836SJohn.Forte@Sun.COM * _nsc_wait_dbuf() on the next read. sb_len MUST be
22717836SJohn.Forte@Sun.COM * restored before nsc_free_buf() however, or we will
22727836SJohn.Forte@Sun.COM * be looking at memory leak city..
22737836SJohn.Forte@Sun.COM * so update the entire queue with the info as well
22747836SJohn.Forte@Sun.COM * and the one that ends up freeing it, can fix the len
22757836SJohn.Forte@Sun.COM * IMPORTANT: This assumes that we are not cached, in
22767836SJohn.Forte@Sun.COM * 3.2 caching was turned off for data volumes, if that
22777836SJohn.Forte@Sun.COM * changes, then this must too
22787836SJohn.Forte@Sun.COM */
22797836SJohn.Forte@Sun.COM void
rdc_trim_buf(nsc_buf_t * buf,net_queue * q)22807836SJohn.Forte@Sun.COM rdc_trim_buf(nsc_buf_t *buf, net_queue *q)
22817836SJohn.Forte@Sun.COM {
22827836SJohn.Forte@Sun.COM rdc_aio_t *p;
22837836SJohn.Forte@Sun.COM int len;
22847836SJohn.Forte@Sun.COM
22857836SJohn.Forte@Sun.COM if (buf == NULL || q == NULL)
22867836SJohn.Forte@Sun.COM return;
22877836SJohn.Forte@Sun.COM
22887836SJohn.Forte@Sun.COM if (q && (buf->sb_len >
22897836SJohn.Forte@Sun.COM (q->blocks + q->nitems - q->net_qtail->orig_len))) {
22907836SJohn.Forte@Sun.COM len = buf->sb_len;
22917836SJohn.Forte@Sun.COM buf->sb_len = (q->blocks + q->nitems - q->net_qtail->orig_len);
22927836SJohn.Forte@Sun.COM }
22937836SJohn.Forte@Sun.COM
22947836SJohn.Forte@Sun.COM p = q->net_qhead;
22957836SJohn.Forte@Sun.COM do {
22967836SJohn.Forte@Sun.COM p->orig_len = len;
22977836SJohn.Forte@Sun.COM p = p->next;
22987836SJohn.Forte@Sun.COM
22997836SJohn.Forte@Sun.COM } while (p);
23007836SJohn.Forte@Sun.COM
23017836SJohn.Forte@Sun.COM }
23027836SJohn.Forte@Sun.COM
23037836SJohn.Forte@Sun.COM /*
23047836SJohn.Forte@Sun.COM * rdc_read_diskq_buf()
23057836SJohn.Forte@Sun.COM * read a large as possible chunk of the diskq into a nsc_buf_t
23067836SJohn.Forte@Sun.COM * and convert it to a net_queue of rdc_aio_t's to be appended
23077836SJohn.Forte@Sun.COM * to the group's netqueue
23087836SJohn.Forte@Sun.COM */
23097836SJohn.Forte@Sun.COM net_queue *
rdc_read_diskq_buf(int index)23107836SJohn.Forte@Sun.COM rdc_read_diskq_buf(int index)
23117836SJohn.Forte@Sun.COM {
23127836SJohn.Forte@Sun.COM nsc_buf_t *buf = NULL;
23137836SJohn.Forte@Sun.COM net_queue *tmpnq = NULL;
23147836SJohn.Forte@Sun.COM disk_queue *dq = NULL;
23157836SJohn.Forte@Sun.COM rdc_k_info_t *krdc = &rdc_k_info[index];
23167836SJohn.Forte@Sun.COM rdc_u_info_t *urdc = &rdc_u_info[index];
23177836SJohn.Forte@Sun.COM rdc_group_t *group = krdc->group;
23187836SJohn.Forte@Sun.COM net_queue *nq = &group->ra_queue;
23197836SJohn.Forte@Sun.COM int len = 0;
23207836SJohn.Forte@Sun.COM int rc;
23217836SJohn.Forte@Sun.COM int fail = 0;
23227836SJohn.Forte@Sun.COM int offset = 0;
23237836SJohn.Forte@Sun.COM
23247836SJohn.Forte@Sun.COM if (group == NULL || group->diskqfd == NULL) {
23257836SJohn.Forte@Sun.COM DTRACE_PROBE(rdc_read_diskq_buf_bail1);
23267836SJohn.Forte@Sun.COM return (NULL);
23277836SJohn.Forte@Sun.COM }
23287836SJohn.Forte@Sun.COM
23297836SJohn.Forte@Sun.COM dq = &group->diskq;
23307836SJohn.Forte@Sun.COM
23317836SJohn.Forte@Sun.COM mutex_enter(QLOCK(dq));
23327836SJohn.Forte@Sun.COM rdc_set_qbusy(dq); /* prevent disables on the queue */
23337836SJohn.Forte@Sun.COM mutex_exit(QLOCK(dq));
23347836SJohn.Forte@Sun.COM
23357836SJohn.Forte@Sun.COM if (_rdc_rsrv_diskq(group)) {
2336*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!rdc_readdiskqbuf: %s reserve failed",
23377836SJohn.Forte@Sun.COM urdc->disk_queue);
23387836SJohn.Forte@Sun.COM mutex_enter(QLOCK(dq));
23397836SJohn.Forte@Sun.COM rdc_clr_qbusy(dq); /* prevent disables on the queue */
23407836SJohn.Forte@Sun.COM mutex_exit(QLOCK(dq));
23417836SJohn.Forte@Sun.COM return (NULL);
23427836SJohn.Forte@Sun.COM }
23437836SJohn.Forte@Sun.COM
23447836SJohn.Forte@Sun.COM mutex_enter(QHEADLOCK(dq));
23457836SJohn.Forte@Sun.COM mutex_enter(QLOCK(dq));
23467836SJohn.Forte@Sun.COM
23477836SJohn.Forte@Sun.COM if (IS_STATE(urdc, RDC_DISKQ_FAILED) ||
23487836SJohn.Forte@Sun.COM IS_STATE(urdc, RDC_LOGGING) ||
23497836SJohn.Forte@Sun.COM (nq->qfflags & RDC_QFILLSLEEP)) {
23507836SJohn.Forte@Sun.COM mutex_exit(QLOCK(dq));
23517836SJohn.Forte@Sun.COM mutex_exit(QHEADLOCK(dq));
23527836SJohn.Forte@Sun.COM DTRACE_PROBE(rdc_read_diskq_buf_bail2);
23537836SJohn.Forte@Sun.COM goto done;
23547836SJohn.Forte@Sun.COM }
23557836SJohn.Forte@Sun.COM
23567836SJohn.Forte@Sun.COM /*
23577836SJohn.Forte@Sun.COM * real corner case here, we need to let the flusher wrap first.
23587836SJohn.Forte@Sun.COM * we've gotten too far ahead, so just delay and try again
23597836SJohn.Forte@Sun.COM */
23607836SJohn.Forte@Sun.COM if (IS_QSTATE(dq, QNXTIOWRAPD) && AUXQWRAP(dq)) {
23617836SJohn.Forte@Sun.COM mutex_exit(QLOCK(dq));
23627836SJohn.Forte@Sun.COM mutex_exit(QHEADLOCK(dq));
23637836SJohn.Forte@Sun.COM goto done;
23647836SJohn.Forte@Sun.COM }
23657836SJohn.Forte@Sun.COM
23667836SJohn.Forte@Sun.COM if (QNXTIOSHLDWRAP(dq)) {
23677836SJohn.Forte@Sun.COM #ifdef DEBUG_DISKQWRAP
2368*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!wrapping Q nxtio: " QDISPLAY(dq));
23697836SJohn.Forte@Sun.COM #endif
23707836SJohn.Forte@Sun.COM /*LINTED*/
23717836SJohn.Forte@Sun.COM WRAPQNXTIO(dq);
23727836SJohn.Forte@Sun.COM }
23737836SJohn.Forte@Sun.COM
23747836SJohn.Forte@Sun.COM /* read the metainfo at q->nxt_io first */
23757836SJohn.Forte@Sun.COM if (!QNITEMS(dq)) { /* empty */
23767836SJohn.Forte@Sun.COM
23777836SJohn.Forte@Sun.COM if (dq->lastio->handle)
23787836SJohn.Forte@Sun.COM (void) nsc_free_buf(dq->lastio->handle);
23797836SJohn.Forte@Sun.COM bzero(&(*dq->lastio), sizeof (*dq->lastio));
23807836SJohn.Forte@Sun.COM mutex_exit(QLOCK(dq));
23817836SJohn.Forte@Sun.COM mutex_exit(QHEADLOCK(dq));
23827836SJohn.Forte@Sun.COM DTRACE_PROBE(rdc_read_diskq_buf_bail3);
23837836SJohn.Forte@Sun.COM goto done;
23847836SJohn.Forte@Sun.COM }
23857836SJohn.Forte@Sun.COM
23867836SJohn.Forte@Sun.COM
23877836SJohn.Forte@Sun.COM len = rdc_calc_len(krdc, dq);
23887836SJohn.Forte@Sun.COM
23897836SJohn.Forte@Sun.COM if ((len <= 0) || (IS_STATE(urdc, RDC_LOGGING)) ||
23907836SJohn.Forte@Sun.COM (IS_STATE(urdc, RDC_DISKQ_FAILED)) ||
23917836SJohn.Forte@Sun.COM (nq->qfflags & RDC_QFILLSLEEP)) {
23927836SJohn.Forte@Sun.COM mutex_exit(QLOCK(dq));
23937836SJohn.Forte@Sun.COM mutex_exit(QHEADLOCK(dq));
23947836SJohn.Forte@Sun.COM /*
23957836SJohn.Forte@Sun.COM * a write could be trying to get on the queue, or if
23967836SJohn.Forte@Sun.COM * the queue is really really small, a complete image
23977836SJohn.Forte@Sun.COM * of it could be on the net queue waiting for flush.
23987836SJohn.Forte@Sun.COM * the latter being a fairly stupid scenario and a gross
23997836SJohn.Forte@Sun.COM * misconfiguration.. but what the heck, why make the thread
24007836SJohn.Forte@Sun.COM * thrash around.. just pause a little here.
24017836SJohn.Forte@Sun.COM */
24027836SJohn.Forte@Sun.COM if (len <= 0)
24037836SJohn.Forte@Sun.COM delay(50);
24047836SJohn.Forte@Sun.COM
2405*9093SRamana.Srikanth@Sun.COM DTRACE_PROBE3(rdc_read_diskq_buf_bail4, int, len,
2406*9093SRamana.Srikanth@Sun.COM int, rdc_get_vflags(urdc), int, nq->qfflags);
24077836SJohn.Forte@Sun.COM
24087836SJohn.Forte@Sun.COM goto done;
24097836SJohn.Forte@Sun.COM }
24107836SJohn.Forte@Sun.COM
24117836SJohn.Forte@Sun.COM DTRACE_PROBE2(rdc_calc_len, int, len, int, (int)QNXTIO(dq));
24127836SJohn.Forte@Sun.COM
24137836SJohn.Forte@Sun.COM #ifdef DEBUG_FLUSHER_UBERNOISE
2414*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!CALC_LEN(%d) h:%d n%d t%d, w%d",
24157836SJohn.Forte@Sun.COM len, QHEAD(dq), QNXTIO(dq), QTAIL(dq), QWRAP(dq));
2416*9093SRamana.Srikanth@Sun.COM cmn_err(CE_CONT, "!qinfo: " QDISPLAYND(dq));
24177836SJohn.Forte@Sun.COM #endif
24187836SJohn.Forte@Sun.COM SET_QCOALBOUNDS(dq, QNXTIO(dq) + len);
24197836SJohn.Forte@Sun.COM
24207836SJohn.Forte@Sun.COM while ((LASTQTAIL(dq) > 0) && !QWRAP(dq) &&
24217836SJohn.Forte@Sun.COM ((QNXTIO(dq) + len) >= LASTQTAIL(dq)) &&
24227836SJohn.Forte@Sun.COM (IS_QSTATE(dq, QTAILBUSY))) {
24237836SJohn.Forte@Sun.COM mutex_exit(QLOCK(dq));
24247836SJohn.Forte@Sun.COM
24257836SJohn.Forte@Sun.COM #ifdef DEBUG_FLUSHER_UBERNOISE
2426*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!Qtail busy delay nxtio %d len %d "
24277836SJohn.Forte@Sun.COM "lastqtail: %d", QNXTIO(dq), len, LASTQTAIL(dq));
24287836SJohn.Forte@Sun.COM #endif
24297836SJohn.Forte@Sun.COM delay(20);
24307836SJohn.Forte@Sun.COM mutex_enter(QLOCK(dq));
24317836SJohn.Forte@Sun.COM }
24327836SJohn.Forte@Sun.COM
24337836SJohn.Forte@Sun.COM offset = QNXTIO(dq);
24347836SJohn.Forte@Sun.COM
24357836SJohn.Forte@Sun.COM /*
24367836SJohn.Forte@Sun.COM * one last check to see if we have gone logging, or should.
24377836SJohn.Forte@Sun.COM * we may have released the mutex above, so check again
24387836SJohn.Forte@Sun.COM */
24397836SJohn.Forte@Sun.COM if ((IS_STATE(urdc, RDC_LOGGING)) ||
24407836SJohn.Forte@Sun.COM (IS_STATE(urdc, RDC_DISKQ_FAILED)) ||
24417836SJohn.Forte@Sun.COM (nq->qfflags & RDC_QFILLSLEEP)) {
24427836SJohn.Forte@Sun.COM mutex_exit(QLOCK(dq));
24437836SJohn.Forte@Sun.COM mutex_exit(QHEADLOCK(dq));
24447836SJohn.Forte@Sun.COM goto done;
24457836SJohn.Forte@Sun.COM }
24467836SJohn.Forte@Sun.COM
24477836SJohn.Forte@Sun.COM mutex_exit(QLOCK(dq));
24487836SJohn.Forte@Sun.COM mutex_exit(QHEADLOCK(dq));
24497836SJohn.Forte@Sun.COM
24507836SJohn.Forte@Sun.COM DTRACE_PROBE2(rdc_buf2q_preread, int, offset, int, len);
24517836SJohn.Forte@Sun.COM
24527836SJohn.Forte@Sun.COM rc = nsc_alloc_buf(group->diskqfd, offset, len,
24537836SJohn.Forte@Sun.COM NSC_NOCACHE | NSC_READ, &buf);
24547836SJohn.Forte@Sun.COM
24557836SJohn.Forte@Sun.COM if (!RDC_SUCCESS(rc)) {
2456*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!disk queue %s read failure pos %" NSC_SZFMT
24577836SJohn.Forte@Sun.COM " len %d", urdc->disk_queue, QNXTIO(dq), len);
24587836SJohn.Forte@Sun.COM fail++;
24597836SJohn.Forte@Sun.COM buf = NULL;
24607836SJohn.Forte@Sun.COM DTRACE_PROBE(rdc_read_diskq_buf_bail5);
24617836SJohn.Forte@Sun.COM goto done;
24627836SJohn.Forte@Sun.COM }
24637836SJohn.Forte@Sun.COM
24647836SJohn.Forte@Sun.COM DTRACE_PROBE2(rdc_buf2q_postread, int, offset, nsc_size_t, buf->sb_len);
24657836SJohn.Forte@Sun.COM
24667836SJohn.Forte@Sun.COM /*
24677836SJohn.Forte@Sun.COM * convert buf to a net_queue. buf2queue will
24687836SJohn.Forte@Sun.COM * update the QNXTIO pointer for us, based on
24697836SJohn.Forte@Sun.COM * the last readable queue item
24707836SJohn.Forte@Sun.COM */
24717836SJohn.Forte@Sun.COM tmpnq = rdc_diskq_buf2queue(group, &buf, index);
24727836SJohn.Forte@Sun.COM
24737836SJohn.Forte@Sun.COM #ifdef DEBUG_FLUSHER_UBERNOISE
2474*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!QBUF p: %d l: %d p+l: %d users: %d qblocks: %d ",
24757836SJohn.Forte@Sun.COM "qitems: %d WASTED: %d", buf->sb_pos, buf->sb_len,
24767836SJohn.Forte@Sun.COM buf->sb_pos+buf->sb_len, buf->sb_user, tmpnq?tmpnq->blocks:-1,
24777836SJohn.Forte@Sun.COM tmpnq?tmpnq->nitems:-1,
24787836SJohn.Forte@Sun.COM tmpnq?((buf->sb_len-tmpnq->nitems) - tmpnq->blocks):-1);
24797836SJohn.Forte@Sun.COM #endif
24807836SJohn.Forte@Sun.COM
24817836SJohn.Forte@Sun.COM DTRACE_PROBE3(rdc_buf2que_returned, net_queue *, tmpnq?tmpnq:0,
2482*9093SRamana.Srikanth@Sun.COM uint64_t, tmpnq?tmpnq->nitems:0,
2483*9093SRamana.Srikanth@Sun.COM uint_t, tmpnq?tmpnq->net_qhead->seq:0);
24847836SJohn.Forte@Sun.COM done:
24857836SJohn.Forte@Sun.COM
24867836SJohn.Forte@Sun.COM /* we don't need to retain the buf */
24877836SJohn.Forte@Sun.COM if (tmpnq == NULL)
24887836SJohn.Forte@Sun.COM if (buf) {
24897836SJohn.Forte@Sun.COM (void) nsc_free_buf(buf);
24907836SJohn.Forte@Sun.COM buf = NULL;
24917836SJohn.Forte@Sun.COM }
24927836SJohn.Forte@Sun.COM
24937836SJohn.Forte@Sun.COM rdc_trim_buf(buf, tmpnq);
24947836SJohn.Forte@Sun.COM
24957836SJohn.Forte@Sun.COM mutex_enter(QLOCK(dq));
24967836SJohn.Forte@Sun.COM rdc_clr_qbusy(dq);
24977836SJohn.Forte@Sun.COM mutex_exit(QLOCK(dq));
24987836SJohn.Forte@Sun.COM
24997836SJohn.Forte@Sun.COM _rdc_rlse_diskq(group);
25007836SJohn.Forte@Sun.COM
25017836SJohn.Forte@Sun.COM if (fail) {
25027836SJohn.Forte@Sun.COM rdc_fail_diskq(krdc, RDC_NOWAIT, RDC_DOLOG);
25037836SJohn.Forte@Sun.COM tmpnq = NULL;
25047836SJohn.Forte@Sun.COM }
25057836SJohn.Forte@Sun.COM
25067836SJohn.Forte@Sun.COM return (tmpnq);
25077836SJohn.Forte@Sun.COM }
25087836SJohn.Forte@Sun.COM
25097836SJohn.Forte@Sun.COM /*
25107836SJohn.Forte@Sun.COM * rdc_dequeue()
25117836SJohn.Forte@Sun.COM * removes the head of the memory queue
25127836SJohn.Forte@Sun.COM */
25137836SJohn.Forte@Sun.COM rdc_aio_t *
rdc_dequeue(rdc_k_info_t * krdc,int * rc)25147836SJohn.Forte@Sun.COM rdc_dequeue(rdc_k_info_t *krdc, int *rc)
25157836SJohn.Forte@Sun.COM {
25167836SJohn.Forte@Sun.COM net_queue *q = &krdc->group->ra_queue;
25177836SJohn.Forte@Sun.COM disk_queue *dq = &krdc->group->diskq;
25187836SJohn.Forte@Sun.COM rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
25197836SJohn.Forte@Sun.COM rdc_aio_t *aio;
25207836SJohn.Forte@Sun.COM
25217836SJohn.Forte@Sun.COM *rc = 0;
25227836SJohn.Forte@Sun.COM
25237836SJohn.Forte@Sun.COM if (q == NULL)
25247836SJohn.Forte@Sun.COM return (NULL);
25257836SJohn.Forte@Sun.COM
25267836SJohn.Forte@Sun.COM mutex_enter(&q->net_qlock);
25277836SJohn.Forte@Sun.COM
25287836SJohn.Forte@Sun.COM aio = q->net_qhead;
25297836SJohn.Forte@Sun.COM
25307836SJohn.Forte@Sun.COM if (aio == NULL) {
25317836SJohn.Forte@Sun.COM #ifdef DEBUG
2532*9093SRamana.Srikanth@Sun.COM if (q->nitems != 0 || q->blocks != 0 || q->net_qtail != 0) {
25337836SJohn.Forte@Sun.COM cmn_err(CE_PANIC,
2534*9093SRamana.Srikanth@Sun.COM "rdc_dequeue(1): q %p, q blocks %" NSC_SZFMT
2535*9093SRamana.Srikanth@Sun.COM " , nitems %" NSC_SZFMT ", qhead %p qtail %p",
2536*9093SRamana.Srikanth@Sun.COM (void *) q, q->blocks, q->nitems,
2537*9093SRamana.Srikanth@Sun.COM (void *) aio, (void *) q->net_qtail);
25387836SJohn.Forte@Sun.COM }
25397836SJohn.Forte@Sun.COM #endif
25407836SJohn.Forte@Sun.COM
25417836SJohn.Forte@Sun.COM mutex_exit(&q->net_qlock);
25427836SJohn.Forte@Sun.COM
25437836SJohn.Forte@Sun.COM if ((!IS_STATE(urdc, RDC_LOGGING)) &&
25447836SJohn.Forte@Sun.COM (!(q->qfflags & RDC_QFILLSLEEP)) &&
25457836SJohn.Forte@Sun.COM (!IS_STATE(urdc, RDC_SYNCING)) && (QNITEMS(dq) > 0)) {
25467836SJohn.Forte@Sun.COM *rc = EAGAIN;
25477836SJohn.Forte@Sun.COM }
25487836SJohn.Forte@Sun.COM
25497836SJohn.Forte@Sun.COM goto done;
25507836SJohn.Forte@Sun.COM }
25517836SJohn.Forte@Sun.COM
25527836SJohn.Forte@Sun.COM /* aio remove from q */
25537836SJohn.Forte@Sun.COM
25547836SJohn.Forte@Sun.COM q->net_qhead = aio->next;
25557836SJohn.Forte@Sun.COM aio->next = NULL;
25567836SJohn.Forte@Sun.COM
25577836SJohn.Forte@Sun.COM if (q->net_qtail == aio)
25587836SJohn.Forte@Sun.COM q->net_qtail = q->net_qhead;
25597836SJohn.Forte@Sun.COM
25607836SJohn.Forte@Sun.COM q->blocks -= aio->len;
25617836SJohn.Forte@Sun.COM q->nitems--;
25627836SJohn.Forte@Sun.COM
25637836SJohn.Forte@Sun.COM #ifdef DEBUG
25647836SJohn.Forte@Sun.COM if (q->net_qhead == NULL) {
2565*9093SRamana.Srikanth@Sun.COM if (q->nitems != 0 || q->blocks != 0 || q->net_qtail != 0) {
2566*9093SRamana.Srikanth@Sun.COM cmn_err(CE_PANIC, "rdc_dequeue(2): q %p, q blocks %"
2567*9093SRamana.Srikanth@Sun.COM NSC_SZFMT " nitems %" NSC_SZFMT
2568*9093SRamana.Srikanth@Sun.COM " , qhead %p qtail %p",
2569*9093SRamana.Srikanth@Sun.COM (void *) q, q->blocks, q->nitems,
2570*9093SRamana.Srikanth@Sun.COM (void *) q->net_qhead, (void *) q->net_qtail);
25717836SJohn.Forte@Sun.COM }
25727836SJohn.Forte@Sun.COM }
25737836SJohn.Forte@Sun.COM #endif
25747836SJohn.Forte@Sun.COM mutex_exit(&q->net_qlock);
25757836SJohn.Forte@Sun.COM done:
25767836SJohn.Forte@Sun.COM
25777836SJohn.Forte@Sun.COM mutex_enter(&q->net_qlock);
25787836SJohn.Forte@Sun.COM
25797836SJohn.Forte@Sun.COM if (rdc_qfill_shldwakeup(krdc))
25807836SJohn.Forte@Sun.COM cv_broadcast(&q->qfcv);
25817836SJohn.Forte@Sun.COM
25827836SJohn.Forte@Sun.COM /*
25837836SJohn.Forte@Sun.COM * clear EAGAIN if
25847836SJohn.Forte@Sun.COM * logging or q filler thread is sleeping or stopping altogether
25857836SJohn.Forte@Sun.COM * or if q filler thread is dead already
25867836SJohn.Forte@Sun.COM * or if syncing, this will return a null aio, with no error code set
25877836SJohn.Forte@Sun.COM * telling the flusher to die
25887836SJohn.Forte@Sun.COM */
25897836SJohn.Forte@Sun.COM if (*rc == EAGAIN) {
25907836SJohn.Forte@Sun.COM if (IS_STATE(urdc, RDC_LOGGING) ||
25917836SJohn.Forte@Sun.COM (q->qfflags & (RDC_QFILLSLEEP | RDC_QFILLSTOP)) ||
25927836SJohn.Forte@Sun.COM (IS_QSTATE(dq, (RDC_QDISABLEPEND | RDC_STOPPINGFLUSH))) ||
25937836SJohn.Forte@Sun.COM (q->qfill_sleeping == RDC_QFILL_DEAD) ||
25947836SJohn.Forte@Sun.COM (IS_STATE(urdc, RDC_SYNCING)))
25957836SJohn.Forte@Sun.COM *rc = 0;
25967836SJohn.Forte@Sun.COM }
25977836SJohn.Forte@Sun.COM
25987836SJohn.Forte@Sun.COM mutex_exit(&q->net_qlock);
25997836SJohn.Forte@Sun.COM
26007836SJohn.Forte@Sun.COM return (aio);
26017836SJohn.Forte@Sun.COM
26027836SJohn.Forte@Sun.COM }
26037836SJohn.Forte@Sun.COM
26047836SJohn.Forte@Sun.COM /*
26057836SJohn.Forte@Sun.COM * rdc_qfill_shldsleep()
26067836SJohn.Forte@Sun.COM * returns 1 if the qfilling code should cv_wait() 0 if not.
26077836SJohn.Forte@Sun.COM * reasons for going into cv_wait();
26087836SJohn.Forte@Sun.COM * there is nothing in the diskq to flush to mem.
26097836SJohn.Forte@Sun.COM * the memory queue has gotten too big and needs more flushing attn.
26107836SJohn.Forte@Sun.COM */
26117836SJohn.Forte@Sun.COM int
rdc_qfill_shldsleep(rdc_k_info_t * krdc)26127836SJohn.Forte@Sun.COM rdc_qfill_shldsleep(rdc_k_info_t *krdc)
26137836SJohn.Forte@Sun.COM {
26147836SJohn.Forte@Sun.COM net_queue *nq = &krdc->group->ra_queue;
26157836SJohn.Forte@Sun.COM disk_queue *dq = &krdc->group->diskq;
26167836SJohn.Forte@Sun.COM rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
26177836SJohn.Forte@Sun.COM
26187836SJohn.Forte@Sun.COM ASSERT(MUTEX_HELD(&nq->net_qlock));
26197836SJohn.Forte@Sun.COM
26207836SJohn.Forte@Sun.COM if (!RDC_IS_DISKQ(krdc->group))
26217836SJohn.Forte@Sun.COM return (1);
26227836SJohn.Forte@Sun.COM
26237836SJohn.Forte@Sun.COM if (nq->qfflags & RDC_QFILLSLEEP) {
26247836SJohn.Forte@Sun.COM #ifdef DEBUG_DISKQ_NOISY
2625*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!Sleeping diskq->memq flusher: QFILLSLEEP idx: %d",
26267836SJohn.Forte@Sun.COM krdc->index);
26277836SJohn.Forte@Sun.COM #endif
26287836SJohn.Forte@Sun.COM return (1);
26297836SJohn.Forte@Sun.COM }
26307836SJohn.Forte@Sun.COM
26317836SJohn.Forte@Sun.COM if (IS_STATE(urdc, RDC_LOGGING) || IS_STATE(urdc, RDC_SYNCING)) {
26327836SJohn.Forte@Sun.COM #ifdef DEBUG_DISKQ_NOISY
2633*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!Sleeping diskq->memq flusher: Sync|Log (0x%x)"
26347836SJohn.Forte@Sun.COM " idx: %d", rdc_get_vflags(urdc), urdc->index);
26357836SJohn.Forte@Sun.COM #endif
26367836SJohn.Forte@Sun.COM return (1);
26377836SJohn.Forte@Sun.COM }
26387836SJohn.Forte@Sun.COM
26397836SJohn.Forte@Sun.COM mutex_enter(QLOCK(dq));
26407836SJohn.Forte@Sun.COM if ((QNXTIO(dq) == QTAIL(dq)) && !IS_QSTATE(dq, RDC_QFULL)) {
26417836SJohn.Forte@Sun.COM #ifdef DEBUG_DISKQ_NOISY
2642*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!Sleeping diskq->memq flusher: QEMPTY");
26437836SJohn.Forte@Sun.COM #endif
26447836SJohn.Forte@Sun.COM mutex_exit(QLOCK(dq));
26457836SJohn.Forte@Sun.COM return (1);
26467836SJohn.Forte@Sun.COM }
26477836SJohn.Forte@Sun.COM mutex_exit(QLOCK(dq));
26487836SJohn.Forte@Sun.COM
26497836SJohn.Forte@Sun.COM if (nq->blocks >= RDC_MAX_QBLOCKS) {
26507836SJohn.Forte@Sun.COM nq->hwmhit = 1;
26517836SJohn.Forte@Sun.COM /* stuck flushers ? */
26527836SJohn.Forte@Sun.COM #ifdef DEBUG_DISKQ_NOISY
2653*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!Sleeping diskq->memq flusher: memq full:"
26547836SJohn.Forte@Sun.COM " seq: %d seqack %d", krdc->group->seq,
26557836SJohn.Forte@Sun.COM krdc->group->seqack);
26567836SJohn.Forte@Sun.COM #endif
26577836SJohn.Forte@Sun.COM return (1);
26587836SJohn.Forte@Sun.COM }
26597836SJohn.Forte@Sun.COM
26607836SJohn.Forte@Sun.COM return (0);
26617836SJohn.Forte@Sun.COM }
26627836SJohn.Forte@Sun.COM
26637836SJohn.Forte@Sun.COM /*
26647836SJohn.Forte@Sun.COM * rdc_join_netqueues(a, b)
26657836SJohn.Forte@Sun.COM * appends queue b to queue a updating all the queue info
26667836SJohn.Forte@Sun.COM * as it is assumed queue a is the important one,
26677836SJohn.Forte@Sun.COM * it's mutex must be held. no one can add to queue b
26687836SJohn.Forte@Sun.COM */
26697836SJohn.Forte@Sun.COM void
rdc_join_netqueues(net_queue * q,net_queue * tmpq)26707836SJohn.Forte@Sun.COM rdc_join_netqueues(net_queue *q, net_queue *tmpq)
26717836SJohn.Forte@Sun.COM {
26727836SJohn.Forte@Sun.COM ASSERT(MUTEX_HELD(&q->net_qlock));
26737836SJohn.Forte@Sun.COM
26747836SJohn.Forte@Sun.COM if (q->net_qhead == NULL) { /* empty */
26757836SJohn.Forte@Sun.COM #ifdef DEBUG
26767836SJohn.Forte@Sun.COM if (q->blocks != 0 || q->nitems != 0) {
2677*9093SRamana.Srikanth@Sun.COM cmn_err(CE_PANIC, "rdc filler: q %p, qhead 0, "
2678*9093SRamana.Srikanth@Sun.COM " q blocks %" NSC_SZFMT ", nitems %" NSC_SZFMT,
2679*9093SRamana.Srikanth@Sun.COM (void *) q, q->blocks, q->nitems);
26807836SJohn.Forte@Sun.COM }
26817836SJohn.Forte@Sun.COM #endif
26827836SJohn.Forte@Sun.COM q->net_qhead = tmpq->net_qhead;
26837836SJohn.Forte@Sun.COM q->net_qtail = tmpq->net_qtail;
26847836SJohn.Forte@Sun.COM q->nitems = tmpq->nitems;
26857836SJohn.Forte@Sun.COM q->blocks = tmpq->blocks;
26867836SJohn.Forte@Sun.COM } else {
26877836SJohn.Forte@Sun.COM q->net_qtail->next = tmpq->net_qhead;
26887836SJohn.Forte@Sun.COM q->net_qtail = tmpq->net_qtail;
26897836SJohn.Forte@Sun.COM q->nitems += tmpq->nitems;
26907836SJohn.Forte@Sun.COM q->blocks += tmpq->blocks;
26917836SJohn.Forte@Sun.COM }
26927836SJohn.Forte@Sun.COM
26937836SJohn.Forte@Sun.COM if (q->nitems > q->nitems_hwm) {
26947836SJohn.Forte@Sun.COM q->nitems_hwm = q->nitems;
26957836SJohn.Forte@Sun.COM }
26967836SJohn.Forte@Sun.COM
26977836SJohn.Forte@Sun.COM if (q->blocks > q->blocks_hwm) {
26987836SJohn.Forte@Sun.COM q->blocks_hwm = q->blocks;
26997836SJohn.Forte@Sun.COM }
27007836SJohn.Forte@Sun.COM }
27017836SJohn.Forte@Sun.COM
27027836SJohn.Forte@Sun.COM /*
27037836SJohn.Forte@Sun.COM * rdc_qfiller_thr() single thread that moves
27047836SJohn.Forte@Sun.COM * data from the diskq to a memory queue for
27057836SJohn.Forte@Sun.COM * the flusher to pick up.
27067836SJohn.Forte@Sun.COM */
27077836SJohn.Forte@Sun.COM void
rdc_qfiller_thr(rdc_k_info_t * krdc)27087836SJohn.Forte@Sun.COM rdc_qfiller_thr(rdc_k_info_t *krdc)
27097836SJohn.Forte@Sun.COM {
27107836SJohn.Forte@Sun.COM rdc_group_t *grp = krdc->group;
27117836SJohn.Forte@Sun.COM rdc_u_info_t *urdc = &rdc_u_info[krdc->index];
27127836SJohn.Forte@Sun.COM net_queue *q = &grp->ra_queue;
27137836SJohn.Forte@Sun.COM net_queue *tmpq = NULL;
27147836SJohn.Forte@Sun.COM int index = krdc->index;
27157836SJohn.Forte@Sun.COM
27167836SJohn.Forte@Sun.COM q->qfill_sleeping = RDC_QFILL_AWAKE;
27177836SJohn.Forte@Sun.COM while (!(q->qfflags & RDC_QFILLSTOP)) {
27187836SJohn.Forte@Sun.COM if (!RDC_IS_DISKQ(grp) ||
27197836SJohn.Forte@Sun.COM IS_STATE(urdc, RDC_LOGGING) ||
27207836SJohn.Forte@Sun.COM IS_STATE(urdc, RDC_DISKQ_FAILED) ||
27217836SJohn.Forte@Sun.COM (q->qfflags & RDC_QFILLSLEEP)) {
27227836SJohn.Forte@Sun.COM goto nulltmpq;
27237836SJohn.Forte@Sun.COM }
27247836SJohn.Forte@Sun.COM
27257836SJohn.Forte@Sun.COM DTRACE_PROBE(qfiller_top);
27267836SJohn.Forte@Sun.COM tmpq = rdc_read_diskq_buf(index);
27277836SJohn.Forte@Sun.COM
27287836SJohn.Forte@Sun.COM if (tmpq == NULL)
27297836SJohn.Forte@Sun.COM goto nulltmpq;
27307836SJohn.Forte@Sun.COM
27317836SJohn.Forte@Sun.COM if ((q->qfflags & RDC_QFILLSLEEP) ||
27327836SJohn.Forte@Sun.COM IS_STATE(urdc, RDC_LOGGING)) {
27337836SJohn.Forte@Sun.COM rdc_discard_tmpq(tmpq);
27347836SJohn.Forte@Sun.COM goto nulltmpq;
27357836SJohn.Forte@Sun.COM }
27367836SJohn.Forte@Sun.COM
27377836SJohn.Forte@Sun.COM mutex_enter(&q->net_qlock);
27387836SJohn.Forte@Sun.COM
27397836SJohn.Forte@Sun.COM /* race with log, redundant yet paranoid */
27407836SJohn.Forte@Sun.COM if ((q->qfflags & RDC_QFILLSLEEP) ||
27417836SJohn.Forte@Sun.COM IS_STATE(urdc, RDC_LOGGING)) {
27427836SJohn.Forte@Sun.COM rdc_discard_tmpq(tmpq);
27437836SJohn.Forte@Sun.COM mutex_exit(&q->net_qlock);
27447836SJohn.Forte@Sun.COM goto nulltmpq;
27457836SJohn.Forte@Sun.COM }
27467836SJohn.Forte@Sun.COM
27477836SJohn.Forte@Sun.COM
27487836SJohn.Forte@Sun.COM rdc_join_netqueues(q, tmpq);
27497836SJohn.Forte@Sun.COM kmem_free(tmpq, sizeof (*tmpq));
27507836SJohn.Forte@Sun.COM tmpq = NULL;
27517836SJohn.Forte@Sun.COM
27527836SJohn.Forte@Sun.COM mutex_exit(&q->net_qlock);
27537836SJohn.Forte@Sun.COM nulltmpq:
27547836SJohn.Forte@Sun.COM /*
27557836SJohn.Forte@Sun.COM * sleep for a while if we can.
27567836SJohn.Forte@Sun.COM * the enqueuing or flushing code will
27577836SJohn.Forte@Sun.COM * wake us if if necessary.
27587836SJohn.Forte@Sun.COM */
27597836SJohn.Forte@Sun.COM mutex_enter(&q->net_qlock);
27607836SJohn.Forte@Sun.COM while (rdc_qfill_shldsleep(krdc)) {
27617836SJohn.Forte@Sun.COM q->qfill_sleeping = RDC_QFILL_ASLEEP;
27627836SJohn.Forte@Sun.COM DTRACE_PROBE(qfiller_sleep);
27637836SJohn.Forte@Sun.COM cv_wait(&q->qfcv, &q->net_qlock);
27647836SJohn.Forte@Sun.COM DTRACE_PROBE(qfiller_wakeup);
27657836SJohn.Forte@Sun.COM q->qfill_sleeping = RDC_QFILL_AWAKE;
27667836SJohn.Forte@Sun.COM if (q->qfflags & RDC_QFILLSTOP) {
27677836SJohn.Forte@Sun.COM #ifdef DEBUG_DISKQ
27687836SJohn.Forte@Sun.COM cmn_err(CE_NOTE,
2769*9093SRamana.Srikanth@Sun.COM "!rdc_qfiller_thr: recieved kill signal");
27707836SJohn.Forte@Sun.COM #endif
27717836SJohn.Forte@Sun.COM mutex_exit(&q->net_qlock);
27727836SJohn.Forte@Sun.COM goto done;
27737836SJohn.Forte@Sun.COM }
27747836SJohn.Forte@Sun.COM }
27757836SJohn.Forte@Sun.COM mutex_exit(&q->net_qlock);
27767836SJohn.Forte@Sun.COM
27777836SJohn.Forte@Sun.COM DTRACE_PROBE(qfiller_bottom);
27787836SJohn.Forte@Sun.COM }
27797836SJohn.Forte@Sun.COM done:
27807836SJohn.Forte@Sun.COM DTRACE_PROBE(qfiller_done);
27817836SJohn.Forte@Sun.COM q->qfill_sleeping = RDC_QFILL_DEAD; /* the big sleep */
27827836SJohn.Forte@Sun.COM
27837836SJohn.Forte@Sun.COM #ifdef DEBUG
2784*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!rdc_qfiller_thr stopping");
27857836SJohn.Forte@Sun.COM #endif
27867836SJohn.Forte@Sun.COM q->qfflags &= ~RDC_QFILLSTOP;
27877836SJohn.Forte@Sun.COM
27887836SJohn.Forte@Sun.COM }
27897836SJohn.Forte@Sun.COM
27907836SJohn.Forte@Sun.COM int
_rdc_add_diskq(int index,char * diskq)27917836SJohn.Forte@Sun.COM _rdc_add_diskq(int index, char *diskq)
27927836SJohn.Forte@Sun.COM {
27937836SJohn.Forte@Sun.COM rdc_k_info_t *krdc, *kp;
27947836SJohn.Forte@Sun.COM rdc_u_info_t *urdc, *up;
27957836SJohn.Forte@Sun.COM rdc_group_t *group;
27967836SJohn.Forte@Sun.COM int rc;
27977836SJohn.Forte@Sun.COM
27987836SJohn.Forte@Sun.COM krdc = &rdc_k_info[index];
27997836SJohn.Forte@Sun.COM urdc = &rdc_u_info[index];
28007836SJohn.Forte@Sun.COM group = krdc->group;
28017836SJohn.Forte@Sun.COM
28027836SJohn.Forte@Sun.COM if (!diskq || urdc->disk_queue[0]) { /* how'd that happen? */
28037836SJohn.Forte@Sun.COM #ifdef DEBUG
2804*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!NULL diskq in _rdc_add_diskq");
28057836SJohn.Forte@Sun.COM #endif
28067836SJohn.Forte@Sun.COM rc = -1;
28077836SJohn.Forte@Sun.COM goto fail;
28087836SJohn.Forte@Sun.COM }
28097836SJohn.Forte@Sun.COM
28107836SJohn.Forte@Sun.COM /* if the enable fails, this is bzero'ed */
28117836SJohn.Forte@Sun.COM (void) strncpy(urdc->disk_queue, diskq, NSC_MAXPATH);
28127836SJohn.Forte@Sun.COM group->flags &= ~RDC_MEMQUE;
28137836SJohn.Forte@Sun.COM group->flags |= RDC_DISKQUE;
28147836SJohn.Forte@Sun.COM
28157836SJohn.Forte@Sun.COM #ifdef DEBUG
2816*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!adding diskq to group %s", urdc->group_name);
28177836SJohn.Forte@Sun.COM #endif
28187836SJohn.Forte@Sun.COM mutex_enter(&rdc_conf_lock);
28197836SJohn.Forte@Sun.COM rc = rdc_enable_diskq(krdc);
28207836SJohn.Forte@Sun.COM mutex_exit(&rdc_conf_lock);
28217836SJohn.Forte@Sun.COM
28227836SJohn.Forte@Sun.COM if (rc == RDC_EQNOADD) {
28237836SJohn.Forte@Sun.COM goto fail;
28247836SJohn.Forte@Sun.COM }
28257836SJohn.Forte@Sun.COM
28267836SJohn.Forte@Sun.COM RDC_ZERO_BITREF(krdc);
28277836SJohn.Forte@Sun.COM for (kp = krdc->group_next; kp != krdc; kp = kp->group_next) {
28287836SJohn.Forte@Sun.COM up = &rdc_u_info[kp->index];
28297836SJohn.Forte@Sun.COM (void) strncpy(up->disk_queue, diskq, NSC_MAXPATH);
28307836SJohn.Forte@Sun.COM /* size lives in the diskq structure, already set by enable */
28317836SJohn.Forte@Sun.COM RDC_ZERO_BITREF(kp);
28327836SJohn.Forte@Sun.COM }
28337836SJohn.Forte@Sun.COM
28347836SJohn.Forte@Sun.COM fail:
28357836SJohn.Forte@Sun.COM return (rc);
28367836SJohn.Forte@Sun.COM
28377836SJohn.Forte@Sun.COM }
28387836SJohn.Forte@Sun.COM
28397836SJohn.Forte@Sun.COM /*
28407836SJohn.Forte@Sun.COM * add a diskq to an existing set/group
28417836SJohn.Forte@Sun.COM */
28427836SJohn.Forte@Sun.COM int
rdc_add_diskq(rdc_config_t * uparms,spcs_s_info_t kstatus)28437836SJohn.Forte@Sun.COM rdc_add_diskq(rdc_config_t *uparms, spcs_s_info_t kstatus)
28447836SJohn.Forte@Sun.COM {
28457836SJohn.Forte@Sun.COM char *diskq;
28467836SJohn.Forte@Sun.COM int rc;
28477836SJohn.Forte@Sun.COM int index;
28487836SJohn.Forte@Sun.COM rdc_k_info_t *krdc, *this;
28497836SJohn.Forte@Sun.COM rdc_u_info_t *urdc;
28507836SJohn.Forte@Sun.COM rdc_group_t *group;
28517836SJohn.Forte@Sun.COM nsc_size_t vol_size = 0;
28527836SJohn.Forte@Sun.COM nsc_size_t req_size = 0;
28537836SJohn.Forte@Sun.COM
28547836SJohn.Forte@Sun.COM mutex_enter(&rdc_conf_lock);
28557836SJohn.Forte@Sun.COM index = rdc_lookup_byname(uparms->rdc_set);
28567836SJohn.Forte@Sun.COM mutex_exit(&rdc_conf_lock);
28577836SJohn.Forte@Sun.COM if (index < 0) {
28587836SJohn.Forte@Sun.COM spcs_s_add(kstatus, RDC_EALREADY, uparms->rdc_set->primary.file,
28597836SJohn.Forte@Sun.COM uparms->rdc_set->secondary.file);
28607836SJohn.Forte@Sun.COM rc = RDC_EALREADY;
28617836SJohn.Forte@Sun.COM goto failed;
28627836SJohn.Forte@Sun.COM }
28637836SJohn.Forte@Sun.COM urdc = &rdc_u_info[index];
2864*9093SRamana.Srikanth@Sun.COM krdc = &rdc_k_info[index];
2865*9093SRamana.Srikanth@Sun.COM this = &rdc_k_info[index];
28667836SJohn.Forte@Sun.COM group = krdc->group;
28677836SJohn.Forte@Sun.COM diskq = uparms->rdc_set->disk_queue;
28687836SJohn.Forte@Sun.COM
28697836SJohn.Forte@Sun.COM if (!IS_ASYNC(urdc)) {
28707836SJohn.Forte@Sun.COM spcs_s_add(kstatus, RDC_EQWRONGMODE, urdc->primary.intf,
28717836SJohn.Forte@Sun.COM urdc->primary.file, urdc->secondary.intf,
28727836SJohn.Forte@Sun.COM urdc->secondary.file);
28737836SJohn.Forte@Sun.COM rc = RDC_EQNOQUEUE;
28747836SJohn.Forte@Sun.COM goto failed;
28757836SJohn.Forte@Sun.COM }
28767836SJohn.Forte@Sun.COM
28777836SJohn.Forte@Sun.COM do {
28787836SJohn.Forte@Sun.COM if (!IS_STATE(urdc, RDC_LOGGING)) {
28797836SJohn.Forte@Sun.COM spcs_s_add(kstatus, RDC_EQNOTLOGGING,
28807836SJohn.Forte@Sun.COM uparms->rdc_set->disk_queue);
28817836SJohn.Forte@Sun.COM rc = RDC_EQNOTLOGGING;
28827836SJohn.Forte@Sun.COM goto failed;
28837836SJohn.Forte@Sun.COM }
28847836SJohn.Forte@Sun.COM /* make sure that we have enough bitmap vol */
28857836SJohn.Forte@Sun.COM req_size = RDC_BITMAP_FBA + FBA_LEN(krdc->bitmap_size);
28867836SJohn.Forte@Sun.COM req_size += FBA_LEN(krdc->bitmap_size * BITS_IN_BYTE);
28877836SJohn.Forte@Sun.COM
28887836SJohn.Forte@Sun.COM rc = _rdc_rsrv_devs(krdc, RDC_BMP, RDC_INTERNAL);
28897836SJohn.Forte@Sun.COM
28907836SJohn.Forte@Sun.COM if (!RDC_SUCCESS(rc)) {
28917836SJohn.Forte@Sun.COM cmn_err(CE_WARN,
2892*9093SRamana.Srikanth@Sun.COM "!rdc_open_diskq: Bitmap reserve failed");
28937836SJohn.Forte@Sun.COM spcs_s_add(kstatus, RDC_EBITMAP,
28947836SJohn.Forte@Sun.COM urdc->primary.bitmap);
28957836SJohn.Forte@Sun.COM rc = RDC_EBITMAP;
28967836SJohn.Forte@Sun.COM goto failed;
28977836SJohn.Forte@Sun.COM }
28987836SJohn.Forte@Sun.COM
28997836SJohn.Forte@Sun.COM (void) nsc_partsize(krdc->bitmapfd, &vol_size);
29007836SJohn.Forte@Sun.COM
29017836SJohn.Forte@Sun.COM _rdc_rlse_devs(krdc, RDC_BMP);
29027836SJohn.Forte@Sun.COM
29037836SJohn.Forte@Sun.COM if (vol_size < req_size) {
29047836SJohn.Forte@Sun.COM spcs_s_add(kstatus, RDC_EBITMAP2SMALL,
29057836SJohn.Forte@Sun.COM urdc->primary.bitmap);
29067836SJohn.Forte@Sun.COM rc = RDC_EBITMAP2SMALL;
29077836SJohn.Forte@Sun.COM goto failed;
29087836SJohn.Forte@Sun.COM }
29097836SJohn.Forte@Sun.COM
29107836SJohn.Forte@Sun.COM krdc = krdc->group_next;
29117836SJohn.Forte@Sun.COM urdc = &rdc_u_info[krdc->index];
29127836SJohn.Forte@Sun.COM
29137836SJohn.Forte@Sun.COM } while (krdc != this);
29147836SJohn.Forte@Sun.COM
29157836SJohn.Forte@Sun.COM if (urdc->disk_queue[0] != '\0') {
29167836SJohn.Forte@Sun.COM spcs_s_add(kstatus, RDC_EQALREADY, urdc->primary.intf,
29177836SJohn.Forte@Sun.COM urdc->primary.file, urdc->secondary.intf,
29187836SJohn.Forte@Sun.COM urdc->secondary.file);
29197836SJohn.Forte@Sun.COM rc = RDC_EQALREADY;
29207836SJohn.Forte@Sun.COM goto failed;
29217836SJohn.Forte@Sun.COM }
29227836SJohn.Forte@Sun.COM
29237836SJohn.Forte@Sun.COM if (uparms->options & RDC_OPT_SECONDARY) { /* how'd we get here? */
29247836SJohn.Forte@Sun.COM spcs_s_add(kstatus, RDC_EQWRONGMODE);
29257836SJohn.Forte@Sun.COM rc = RDC_EQWRONGMODE;
29267836SJohn.Forte@Sun.COM goto failed;
29277836SJohn.Forte@Sun.COM }
29287836SJohn.Forte@Sun.COM
29297836SJohn.Forte@Sun.COM mutex_enter(&rdc_conf_lock);
29307836SJohn.Forte@Sun.COM if (rdc_diskq_inuse(uparms->rdc_set, uparms->rdc_set->disk_queue)) {
29317836SJohn.Forte@Sun.COM spcs_s_add(kstatus, RDC_EDISKQINUSE,
29327836SJohn.Forte@Sun.COM uparms->rdc_set->disk_queue);
29337836SJohn.Forte@Sun.COM rc = RDC_EDISKQINUSE;
29347836SJohn.Forte@Sun.COM mutex_exit(&rdc_conf_lock);
29357836SJohn.Forte@Sun.COM goto failed;
29367836SJohn.Forte@Sun.COM }
29377836SJohn.Forte@Sun.COM mutex_exit(&rdc_conf_lock);
29387836SJohn.Forte@Sun.COM
29397836SJohn.Forte@Sun.COM rdc_group_enter(krdc);
29407836SJohn.Forte@Sun.COM rc = _rdc_add_diskq(urdc->index, diskq);
29417836SJohn.Forte@Sun.COM if (rc < 0 || rc == RDC_EQNOADD) {
29427836SJohn.Forte@Sun.COM group->flags &= ~RDC_DISKQUE;
29437836SJohn.Forte@Sun.COM group->flags |= RDC_MEMQUE;
29447836SJohn.Forte@Sun.COM spcs_s_add(kstatus, RDC_EQNOADD, uparms->rdc_set->disk_queue);
29457836SJohn.Forte@Sun.COM rc = RDC_EQNOADD;
29467836SJohn.Forte@Sun.COM }
29477836SJohn.Forte@Sun.COM rdc_group_exit(krdc);
29487836SJohn.Forte@Sun.COM failed:
29497836SJohn.Forte@Sun.COM return (rc);
29507836SJohn.Forte@Sun.COM }
29517836SJohn.Forte@Sun.COM
29527836SJohn.Forte@Sun.COM int
_rdc_init_diskq(rdc_k_info_t * krdc)29537836SJohn.Forte@Sun.COM _rdc_init_diskq(rdc_k_info_t *krdc)
29547836SJohn.Forte@Sun.COM {
29557836SJohn.Forte@Sun.COM rdc_group_t *group = krdc->group;
29567836SJohn.Forte@Sun.COM disk_queue *q = &group->diskq;
29577836SJohn.Forte@Sun.COM
29587836SJohn.Forte@Sun.COM rdc_init_diskq_header(group, &group->diskq.disk_hdr);
29597836SJohn.Forte@Sun.COM SET_QNXTIO(q, QHEAD(q));
29607836SJohn.Forte@Sun.COM
29617836SJohn.Forte@Sun.COM if (rdc_stamp_diskq(krdc, 0, RDC_NOLOG) < 0)
29627836SJohn.Forte@Sun.COM goto fail;
29637836SJohn.Forte@Sun.COM
29647836SJohn.Forte@Sun.COM return (0);
29657836SJohn.Forte@Sun.COM fail:
29667836SJohn.Forte@Sun.COM return (-1);
29677836SJohn.Forte@Sun.COM }
29687836SJohn.Forte@Sun.COM
29697836SJohn.Forte@Sun.COM /*
29707836SJohn.Forte@Sun.COM * inititalize the disk queue. This is a destructive
29717836SJohn.Forte@Sun.COM * operation that will not check for emptiness of the queue.
29727836SJohn.Forte@Sun.COM */
29737836SJohn.Forte@Sun.COM int
rdc_init_diskq(rdc_config_t * uparms,spcs_s_info_t kstatus)29747836SJohn.Forte@Sun.COM rdc_init_diskq(rdc_config_t *uparms, spcs_s_info_t kstatus)
29757836SJohn.Forte@Sun.COM {
29767836SJohn.Forte@Sun.COM int rc = 0;
29777836SJohn.Forte@Sun.COM int index;
29787836SJohn.Forte@Sun.COM rdc_k_info_t *krdc, *kp;
29797836SJohn.Forte@Sun.COM rdc_u_info_t *urdc, *up;
29807836SJohn.Forte@Sun.COM rdc_set_t *uset;
29817836SJohn.Forte@Sun.COM rdc_group_t *group;
29827836SJohn.Forte@Sun.COM disk_queue *qp;
29837836SJohn.Forte@Sun.COM
29847836SJohn.Forte@Sun.COM uset = uparms->rdc_set;
29857836SJohn.Forte@Sun.COM
29867836SJohn.Forte@Sun.COM mutex_enter(&rdc_conf_lock);
29877836SJohn.Forte@Sun.COM index = rdc_lookup_byname(uset);
29887836SJohn.Forte@Sun.COM mutex_exit(&rdc_conf_lock);
29897836SJohn.Forte@Sun.COM if (index < 0) {
29907836SJohn.Forte@Sun.COM spcs_s_add(kstatus, RDC_EALREADY, uset->primary.file,
29917836SJohn.Forte@Sun.COM uset->secondary.file);
29927836SJohn.Forte@Sun.COM rc = RDC_EALREADY;
29937836SJohn.Forte@Sun.COM goto fail;
29947836SJohn.Forte@Sun.COM }
29957836SJohn.Forte@Sun.COM
29967836SJohn.Forte@Sun.COM krdc = &rdc_k_info[index];
29977836SJohn.Forte@Sun.COM urdc = &rdc_u_info[index];
29987836SJohn.Forte@Sun.COM group = krdc->group;
29997836SJohn.Forte@Sun.COM qp = &group->diskq;
30007836SJohn.Forte@Sun.COM
30017836SJohn.Forte@Sun.COM if (!IS_STATE(urdc, RDC_SYNCING) && !IS_STATE(urdc, RDC_LOGGING)) {
30027836SJohn.Forte@Sun.COM spcs_s_add(kstatus, RDC_EQUEISREP, urdc->disk_queue);
30037836SJohn.Forte@Sun.COM rc = RDC_EQUEISREP;
30047836SJohn.Forte@Sun.COM goto fail;
30057836SJohn.Forte@Sun.COM }
30067836SJohn.Forte@Sun.COM
30077836SJohn.Forte@Sun.COM /*
30087836SJohn.Forte@Sun.COM * a couple of big "ifs" here. in the first implementation
30097836SJohn.Forte@Sun.COM * neither of these will be possible. This will come into
30107836SJohn.Forte@Sun.COM * play when we persist the queue across reboots
30117836SJohn.Forte@Sun.COM */
30127836SJohn.Forte@Sun.COM if (!(uparms->options & RDC_OPT_FORCE_QINIT)) {
30137836SJohn.Forte@Sun.COM if (!QEMPTY(qp)) {
30147836SJohn.Forte@Sun.COM if (group->rdc_writer) {
30157836SJohn.Forte@Sun.COM spcs_s_add(kstatus, RDC_EQFLUSHING,
30167836SJohn.Forte@Sun.COM urdc->disk_queue);
30177836SJohn.Forte@Sun.COM rc = RDC_EQFLUSHING;
30187836SJohn.Forte@Sun.COM } else {
30197836SJohn.Forte@Sun.COM spcs_s_add(kstatus, RDC_EQNOTEMPTY,
30207836SJohn.Forte@Sun.COM urdc->disk_queue);
30217836SJohn.Forte@Sun.COM rc = RDC_EQNOTEMPTY;
30227836SJohn.Forte@Sun.COM }
30237836SJohn.Forte@Sun.COM goto fail;
30247836SJohn.Forte@Sun.COM }
30257836SJohn.Forte@Sun.COM }
30267836SJohn.Forte@Sun.COM
30277836SJohn.Forte@Sun.COM mutex_enter(QLOCK(qp));
30287836SJohn.Forte@Sun.COM if (_rdc_init_diskq(krdc) < 0) {
30297836SJohn.Forte@Sun.COM mutex_exit(QLOCK(qp));
30307836SJohn.Forte@Sun.COM goto fail;
30317836SJohn.Forte@Sun.COM }
30327836SJohn.Forte@Sun.COM rdc_dump_iohdrs(qp);
30337836SJohn.Forte@Sun.COM
30347836SJohn.Forte@Sun.COM rdc_group_enter(krdc);
30357836SJohn.Forte@Sun.COM
30367836SJohn.Forte@Sun.COM rdc_clr_flags(urdc, RDC_QUEUING);
30377836SJohn.Forte@Sun.COM for (kp = krdc->group_next; kp != krdc; kp = kp->group_next) {
30387836SJohn.Forte@Sun.COM up = &rdc_u_info[kp->index];
30397836SJohn.Forte@Sun.COM rdc_clr_flags(up, RDC_QUEUING);
30407836SJohn.Forte@Sun.COM }
30417836SJohn.Forte@Sun.COM rdc_group_exit(krdc);
30427836SJohn.Forte@Sun.COM
30437836SJohn.Forte@Sun.COM mutex_exit(QLOCK(qp));
30447836SJohn.Forte@Sun.COM
30457836SJohn.Forte@Sun.COM return (0);
30467836SJohn.Forte@Sun.COM fail:
30477836SJohn.Forte@Sun.COM /* generic queue failure */
30487836SJohn.Forte@Sun.COM if (!rc) {
30497836SJohn.Forte@Sun.COM spcs_s_add(kstatus, RDC_EQINITFAIL, urdc->disk_queue);
30507836SJohn.Forte@Sun.COM rc = RDC_EQINITFAIL;
30517836SJohn.Forte@Sun.COM }
30527836SJohn.Forte@Sun.COM
30537836SJohn.Forte@Sun.COM return (rc);
30547836SJohn.Forte@Sun.COM }
30557836SJohn.Forte@Sun.COM
30567836SJohn.Forte@Sun.COM int
_rdc_kill_diskq(rdc_u_info_t * urdc)30577836SJohn.Forte@Sun.COM _rdc_kill_diskq(rdc_u_info_t *urdc)
30587836SJohn.Forte@Sun.COM {
30597836SJohn.Forte@Sun.COM rdc_k_info_t *krdc = &rdc_k_info[urdc->index];
30607836SJohn.Forte@Sun.COM rdc_group_t *group = krdc->group;
30617836SJohn.Forte@Sun.COM disk_queue *q = &group->diskq;
30627836SJohn.Forte@Sun.COM rdc_u_info_t *up;
30637836SJohn.Forte@Sun.COM rdc_k_info_t *p;
30647836SJohn.Forte@Sun.COM
30657836SJohn.Forte@Sun.COM group->flags |= RDC_DISKQ_KILL;
30667836SJohn.Forte@Sun.COM #ifdef DEBUG
3067*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!disabling disk queue %s", urdc->disk_queue);
30687836SJohn.Forte@Sun.COM #endif
30697836SJohn.Forte@Sun.COM
30707836SJohn.Forte@Sun.COM mutex_enter(QLOCK(q));
30717836SJohn.Forte@Sun.COM rdc_init_diskq_header(group, &q->disk_hdr);
30727836SJohn.Forte@Sun.COM rdc_dump_iohdrs(q);
30737836SJohn.Forte@Sun.COM
30747836SJohn.Forte@Sun.COM /*
30757836SJohn.Forte@Sun.COM * nsc_close the queue and zero out the queue name
30767836SJohn.Forte@Sun.COM */
30777836SJohn.Forte@Sun.COM rdc_wait_qbusy(q);
30787836SJohn.Forte@Sun.COM rdc_close_diskq(group);
30797836SJohn.Forte@Sun.COM mutex_exit(QLOCK(q));
30807836SJohn.Forte@Sun.COM SET_QSIZE(q, 0);
30817836SJohn.Forte@Sun.COM rdc_clr_flags(urdc, RDC_DISKQ_FAILED);
30827836SJohn.Forte@Sun.COM bzero(urdc->disk_queue, NSC_MAXPATH);
30837836SJohn.Forte@Sun.COM for (p = krdc->group_next; p != krdc; p = p->group_next) {
30847836SJohn.Forte@Sun.COM up = &rdc_u_info[p->index];
30857836SJohn.Forte@Sun.COM rdc_clr_flags(up, RDC_DISKQ_FAILED);
30867836SJohn.Forte@Sun.COM bzero(up->disk_queue, NSC_MAXPATH);
30877836SJohn.Forte@Sun.COM }
30887836SJohn.Forte@Sun.COM
30897836SJohn.Forte@Sun.COM #ifdef DEBUG
3090*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!_rdc_kill_diskq: enabling memory queue");
30917836SJohn.Forte@Sun.COM #endif
30927836SJohn.Forte@Sun.COM group->flags &= ~(RDC_DISKQUE|RDC_DISKQ_KILL);
30937836SJohn.Forte@Sun.COM group->flags |= RDC_MEMQUE;
30947836SJohn.Forte@Sun.COM return (0);
30957836SJohn.Forte@Sun.COM }
30967836SJohn.Forte@Sun.COM
30977836SJohn.Forte@Sun.COM /*
30987836SJohn.Forte@Sun.COM * remove this diskq regardless of whether it is draining or not
30997836SJohn.Forte@Sun.COM * stops the flusher by invalidating the qdata (ie, instant empty)
31007836SJohn.Forte@Sun.COM * remove the disk qeueue from the group, leaving the group with a memory
31017836SJohn.Forte@Sun.COM * queue.
31027836SJohn.Forte@Sun.COM */
31037836SJohn.Forte@Sun.COM int
rdc_kill_diskq(rdc_config_t * uparms,spcs_s_info_t kstatus)31047836SJohn.Forte@Sun.COM rdc_kill_diskq(rdc_config_t *uparms, spcs_s_info_t kstatus)
31057836SJohn.Forte@Sun.COM {
31067836SJohn.Forte@Sun.COM int rc;
31077836SJohn.Forte@Sun.COM int index;
31087836SJohn.Forte@Sun.COM rdc_u_info_t *urdc;
31097836SJohn.Forte@Sun.COM rdc_k_info_t *krdc;
31107836SJohn.Forte@Sun.COM rdc_set_t *rdc_set = uparms->rdc_set;
31117836SJohn.Forte@Sun.COM
31127836SJohn.Forte@Sun.COM mutex_enter(&rdc_conf_lock);
31137836SJohn.Forte@Sun.COM index = rdc_lookup_byname(uparms->rdc_set);
31147836SJohn.Forte@Sun.COM mutex_exit(&rdc_conf_lock);
31157836SJohn.Forte@Sun.COM
31167836SJohn.Forte@Sun.COM if (index < 0) {
31177836SJohn.Forte@Sun.COM spcs_s_add(kstatus, RDC_EALREADY, rdc_set->primary.file,
31187836SJohn.Forte@Sun.COM rdc_set->secondary.file);
31197836SJohn.Forte@Sun.COM rc = RDC_EALREADY;
31207836SJohn.Forte@Sun.COM goto failed;
31217836SJohn.Forte@Sun.COM }
31227836SJohn.Forte@Sun.COM
31237836SJohn.Forte@Sun.COM urdc = &rdc_u_info[index];
31247836SJohn.Forte@Sun.COM krdc = &rdc_k_info[index];
31257836SJohn.Forte@Sun.COM
31267836SJohn.Forte@Sun.COM if (!RDC_IS_DISKQ(krdc->group)) {
31277836SJohn.Forte@Sun.COM spcs_s_add(kstatus, RDC_EQNOQUEUE, rdc_set->primary.intf,
31287836SJohn.Forte@Sun.COM rdc_set->primary.file, rdc_set->secondary.intf,
31297836SJohn.Forte@Sun.COM rdc_set->secondary.file);
31307836SJohn.Forte@Sun.COM rc = RDC_EQNOQUEUE;
31317836SJohn.Forte@Sun.COM goto failed;
31327836SJohn.Forte@Sun.COM }
31337836SJohn.Forte@Sun.COM
31347836SJohn.Forte@Sun.COM /*
31357836SJohn.Forte@Sun.COM * if (!IS_STATE(urdc, RDC_LOGGING)) {
31367836SJohn.Forte@Sun.COM * spcs_s_add(kstatus, RDC_EQNOTLOGGING,
31377836SJohn.Forte@Sun.COM * uparms->rdc_set->disk_queue);
31387836SJohn.Forte@Sun.COM * rc = RDC_EQNOTLOGGING;
31397836SJohn.Forte@Sun.COM * goto failed;
31407836SJohn.Forte@Sun.COM * }
31417836SJohn.Forte@Sun.COM */
31427836SJohn.Forte@Sun.COM rdc_unintercept_diskq(krdc->group); /* stop protecting queue */
31437836SJohn.Forte@Sun.COM rdc_group_enter(krdc); /* to prevent further flushing */
31447836SJohn.Forte@Sun.COM rc = _rdc_kill_diskq(urdc);
31457836SJohn.Forte@Sun.COM rdc_group_exit(krdc);
31467836SJohn.Forte@Sun.COM
31477836SJohn.Forte@Sun.COM failed:
31487836SJohn.Forte@Sun.COM return (rc);
31497836SJohn.Forte@Sun.COM }
31507836SJohn.Forte@Sun.COM
31517836SJohn.Forte@Sun.COM /*
31527836SJohn.Forte@Sun.COM * remove a diskq from a group.
31537836SJohn.Forte@Sun.COM * removal of a diskq from a set, or rather
31547836SJohn.Forte@Sun.COM * a set from a queue, is done by reconfigging out
31557836SJohn.Forte@Sun.COM * of the group. This removes the diskq from a whole
31567836SJohn.Forte@Sun.COM * group and replaces it with a memory based queue
31577836SJohn.Forte@Sun.COM */
31587836SJohn.Forte@Sun.COM #define NUM_RETRIES 15 /* Number of retries to wait if no progress */
31597836SJohn.Forte@Sun.COM int
rdc_rem_diskq(rdc_config_t * uparms,spcs_s_info_t kstatus)31607836SJohn.Forte@Sun.COM rdc_rem_diskq(rdc_config_t *uparms, spcs_s_info_t kstatus)
31617836SJohn.Forte@Sun.COM {
31627836SJohn.Forte@Sun.COM int index;
31637836SJohn.Forte@Sun.COM rdc_u_info_t *urdc;
31647836SJohn.Forte@Sun.COM rdc_k_info_t *krdc;
31657836SJohn.Forte@Sun.COM rdc_k_info_t *this;
31667836SJohn.Forte@Sun.COM volatile rdc_group_t *group;
31677836SJohn.Forte@Sun.COM volatile disk_queue *diskq;
31687836SJohn.Forte@Sun.COM int threads, counter;
31697836SJohn.Forte@Sun.COM long blocks;
31707836SJohn.Forte@Sun.COM
31717836SJohn.Forte@Sun.COM mutex_enter(&rdc_conf_lock);
31727836SJohn.Forte@Sun.COM index = rdc_lookup_byname(uparms->rdc_set);
31737836SJohn.Forte@Sun.COM mutex_exit(&rdc_conf_lock);
31747836SJohn.Forte@Sun.COM if (index < 0) {
31757836SJohn.Forte@Sun.COM spcs_s_add(kstatus, RDC_EALREADY, uparms->rdc_set->primary.file,
31767836SJohn.Forte@Sun.COM uparms->rdc_set->secondary.file);
31777836SJohn.Forte@Sun.COM return (RDC_EALREADY);
31787836SJohn.Forte@Sun.COM }
31797836SJohn.Forte@Sun.COM
31807836SJohn.Forte@Sun.COM urdc = &rdc_u_info[index];
3181*9093SRamana.Srikanth@Sun.COM this = &rdc_k_info[index];
3182*9093SRamana.Srikanth@Sun.COM krdc = &rdc_k_info[index];
31837836SJohn.Forte@Sun.COM
31847836SJohn.Forte@Sun.COM do {
31857836SJohn.Forte@Sun.COM if (!IS_STATE(urdc, RDC_LOGGING)) {
31867836SJohn.Forte@Sun.COM spcs_s_add(kstatus, RDC_EQNOTLOGGING,
31877836SJohn.Forte@Sun.COM urdc->disk_queue);
31887836SJohn.Forte@Sun.COM return (RDC_EQNOTLOGGING);
31897836SJohn.Forte@Sun.COM }
31907836SJohn.Forte@Sun.COM krdc = krdc->group_next;
31917836SJohn.Forte@Sun.COM urdc = &rdc_u_info[krdc->index];
31927836SJohn.Forte@Sun.COM
31937836SJohn.Forte@Sun.COM } while (krdc != this);
31947836SJohn.Forte@Sun.COM
31957836SJohn.Forte@Sun.COM /*
31967836SJohn.Forte@Sun.COM * If there is no group or diskq configured, we can leave now
31977836SJohn.Forte@Sun.COM */
31987836SJohn.Forte@Sun.COM if (!(group = krdc->group) || !(diskq = &group->diskq))
31997836SJohn.Forte@Sun.COM return (0);
32007836SJohn.Forte@Sun.COM
32017836SJohn.Forte@Sun.COM
32027836SJohn.Forte@Sun.COM /*
32037836SJohn.Forte@Sun.COM * Wait if not QEMPTY or threads still active
32047836SJohn.Forte@Sun.COM */
32057836SJohn.Forte@Sun.COM counter = 0;
32067836SJohn.Forte@Sun.COM while (!QEMPTY(diskq) || group->rdc_thrnum) {
32077836SJohn.Forte@Sun.COM
32087836SJohn.Forte@Sun.COM /*
32097836SJohn.Forte@Sun.COM * Capture counters to determine if progress is being made
32107836SJohn.Forte@Sun.COM */
32117836SJohn.Forte@Sun.COM blocks = QBLOCKS(diskq);
32127836SJohn.Forte@Sun.COM threads = group->rdc_thrnum;
32137836SJohn.Forte@Sun.COM
32147836SJohn.Forte@Sun.COM /*
32157836SJohn.Forte@Sun.COM * Wait
32167836SJohn.Forte@Sun.COM */
32177836SJohn.Forte@Sun.COM delay(HZ);
32187836SJohn.Forte@Sun.COM
32197836SJohn.Forte@Sun.COM /*
32207836SJohn.Forte@Sun.COM * Has the group or disk queue gone away while delayed?
32217836SJohn.Forte@Sun.COM */
32227836SJohn.Forte@Sun.COM if (!(group = krdc->group) || !(diskq = &group->diskq))
32237836SJohn.Forte@Sun.COM return (0);
32247836SJohn.Forte@Sun.COM
32257836SJohn.Forte@Sun.COM /*
32267836SJohn.Forte@Sun.COM * Are we still seeing progress?
32277836SJohn.Forte@Sun.COM */
32287836SJohn.Forte@Sun.COM if (blocks == QBLOCKS(diskq) && threads == group->rdc_thrnum) {
32297836SJohn.Forte@Sun.COM /*
32307836SJohn.Forte@Sun.COM * No progress see, decrement retry counter
32317836SJohn.Forte@Sun.COM */
32327836SJohn.Forte@Sun.COM if (counter++ > NUM_RETRIES) {
32337836SJohn.Forte@Sun.COM /*
32347836SJohn.Forte@Sun.COM * No progress seen, increment retry counter
32357836SJohn.Forte@Sun.COM */
32367836SJohn.Forte@Sun.COM int rc = group->rdc_thrnum ?
3237*9093SRamana.Srikanth@Sun.COM RDC_EQFLUSHING : RDC_EQNOTEMPTY;
32387836SJohn.Forte@Sun.COM spcs_s_add(kstatus, rc, urdc->disk_queue);
32397836SJohn.Forte@Sun.COM return (rc);
32407836SJohn.Forte@Sun.COM }
32417836SJohn.Forte@Sun.COM } else {
32427836SJohn.Forte@Sun.COM /*
32437836SJohn.Forte@Sun.COM * Reset counter, as we've made progress
32447836SJohn.Forte@Sun.COM */
32457836SJohn.Forte@Sun.COM counter = 0;
32467836SJohn.Forte@Sun.COM }
32477836SJohn.Forte@Sun.COM }
32487836SJohn.Forte@Sun.COM
32497836SJohn.Forte@Sun.COM return (0);
32507836SJohn.Forte@Sun.COM }
3251