1 /* $NetBSD: requests.c,v 1.3 2007/01/20 13:52:14 pooka Exp $ */ 2 3 /* 4 * Copyright (c) 2006 Antti Kantee. All Rights Reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the company nor the name of the author may be used to 15 * endorse or promote products derived from this software without specific 16 * prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 19 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 #if !defined(lint) 33 __RCSID("$NetBSD: requests.c,v 1.3 2007/01/20 13:52:14 pooka Exp $"); 34 #endif /* !lint */ 35 36 #include <sys/types.h> 37 #include <sys/ioctl.h> 38 #include <sys/queue.h> 39 40 #include <assert.h> 41 #include <puffs.h> 42 #include <stdio.h> 43 #include <stdlib.h> 44 45 #include "puffs_priv.h" 46 47 struct puffs_getreq * 48 puffs_req_makeget(struct puffs_usermount *pu, size_t buflen, int maxops) 49 { 50 struct puffs_getreq *pgr; 51 uint8_t *buf; 52 53 pgr = malloc(sizeof(struct puffs_getreq)); 54 if (!pgr) 55 return NULL; 56 57 buf = malloc(buflen); 58 if (!buf) { 59 free(pgr); 60 return NULL; 61 } 62 63 pgr->pgr_phg_orig.phg_buf = buf; 64 pgr->pgr_phg_orig.phg_buflen = buflen; 65 pgr->pgr_phg_orig.phg_nops = maxops; 66 67 pgr->pgr_pu = pu; 68 pgr->pgr_nppr = 0; 69 70 return pgr; 71 } 72 73 int 74 puffs_req_loadget(struct puffs_getreq *pgr) 75 { 76 77 assert(pgr->pgr_nppr == 0); 78 79 /* reset */ 80 pgr->pgr_phg = pgr->pgr_phg_orig; 81 82 if (ioctl(pgr->pgr_pu->pu_fd, PUFFSGETOP, &pgr->pgr_phg) == -1) 83 return -1; 84 85 pgr->pgr_nextpreq = pgr->pgr_phg.phg_buf; 86 pgr->pgr_advance = pgr->pgr_nextpreq->preq_buflen; 87 88 return 0; 89 } 90 91 struct puffs_req * 92 puffs_req_get(struct puffs_getreq *pgr) 93 { 94 struct puffs_req *preq; 95 96 if (pgr->pgr_phg.phg_nops == 0) 97 return NULL; 98 99 preq = pgr->pgr_nextpreq; 100 /*LINTED*/ 101 pgr->pgr_nextpreq = 102 (struct puffs_req*)((uint8_t*)preq + pgr->pgr_advance); 103 pgr->pgr_advance = pgr->pgr_nextpreq->preq_buflen; 104 pgr->pgr_phg.phg_nops--; 105 106 return preq; 107 } 108 109 int 110 puffs_req_remainingget(struct puffs_getreq *pgr) 111 { 112 113 return pgr->pgr_phg.phg_nops; 114 } 115 116 void 117 puffs_req_setmaxget(struct puffs_getreq *pgr, int maxops) 118 { 119 120 pgr->pgr_phg.phg_nops = maxops; 121 pgr->pgr_phg_orig.phg_nops = maxops; 122 } 123 124 void 125 puffs_req_destroyget(struct puffs_getreq *pgr) 126 { 127 128 assert(pgr->pgr_nppr == 0); 129 130 free(pgr->pgr_phg_orig.phg_buf); 131 free(pgr); 132 } 133 134 135 struct puffs_putreq * 136 puffs_req_makeput(struct puffs_usermount *pu) 137 { 138 struct puffs_putreq *ppr; 139 140 ppr = malloc(sizeof(struct puffs_putreq)); 141 if (!ppr) 142 return NULL; 143 144 ppr->ppr_php.php_nops = 0; 145 TAILQ_INIT(&ppr->ppr_pccq); 146 147 ppr->ppr_pu = pu; 148 ppr->ppr_pgr = NULL; 149 150 puffs_req_resetput(ppr); 151 152 return ppr; 153 } 154 155 void 156 puffs_req_put(struct puffs_putreq *ppr, struct puffs_req *preq) 157 { 158 159 ppr->ppr_php.php_nops++; 160 161 /* store data */ 162 *ppr->ppr_buf = preq; 163 *ppr->ppr_buflen = preq->preq_buflen; 164 *ppr->ppr_id = preq->preq_id; 165 166 /* and roll forward for next request */ 167 ppr->ppr_buf = &preq->preq_nextbuf; 168 ppr->ppr_buflen = &preq->preq_buflen; 169 ppr->ppr_id = &preq->preq_id; 170 } 171 172 /* 173 * instead of a direct preq, put a cc onto the push queue 174 */ 175 void 176 puffs_req_putcc(struct puffs_putreq *ppr, struct puffs_cc *pcc) 177 { 178 179 TAILQ_INSERT_TAIL(&ppr->ppr_pccq, pcc, entries); 180 puffs_req_put(ppr, pcc->pcc_preq); 181 } 182 183 int 184 puffs_req_putput(struct puffs_putreq *ppr) 185 { 186 187 if (ppr->ppr_php.php_nops) 188 if (ioctl(ppr->ppr_pu->pu_fd, PUFFSPUTOP, &ppr->ppr_php) == -1) 189 return -1; 190 191 return 0; 192 } 193 194 void 195 puffs_req_resetput(struct puffs_putreq *ppr) 196 { 197 struct puffs_cc *pcc; 198 199 if (ppr->ppr_pgr != NULL) { 200 ppr->ppr_pgr->pgr_nppr--; 201 ppr->ppr_pgr = NULL; 202 } 203 204 ppr->ppr_buf = &ppr->ppr_php.php_buf; 205 ppr->ppr_buflen = &ppr->ppr_php.php_buflen; 206 ppr->ppr_id = &ppr->ppr_php.php_id; 207 208 while ((pcc = TAILQ_FIRST(&ppr->ppr_pccq)) != NULL) { 209 TAILQ_REMOVE(&ppr->ppr_pccq, pcc, entries); 210 puffs_cc_destroy(pcc); 211 } 212 } 213 214 void 215 puffs_req_destroyput(struct puffs_putreq *ppr) 216 { 217 218 puffs_req_resetput(ppr); 219 free(ppr); 220 } 221 222 int 223 puffs_req_handle(struct puffs_usermount *pu, struct puffs_getreq *pgr, 224 struct puffs_putreq *ppr, int maxops) 225 { 226 struct puffs_req *preq; 227 int pval; 228 229 puffs_req_setmaxget(pgr, maxops); 230 if (puffs_req_loadget(pgr) == -1) 231 return -1; 232 233 /* interlink pgr and ppr for diagnostic asserts */ 234 pgr->pgr_nppr++; 235 ppr->ppr_pgr = pgr; 236 237 pval = 0; 238 while ((preq = puffs_req_get(pgr)) != NULL 239 && pu->pu_state != PUFFS_STATE_UNMOUNTED) 240 pval = puffs_dopreq(pu, ppr, preq); 241 242 return pval; 243 } 244