1 /* $NetBSD: puffs_compat.c,v 1.2 2010/07/11 11:17:27 pooka Exp $ */ 2 3 /* 4 * Copyright (c) 2010 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 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 /* 29 * This file handles puffs PDUs so that they are compatible between 30 * 32bit<->64bit time_t/dev_t. It enables running a -current kernel 31 * against a 5.0 userland (assuming the protocol otherwise matches!). 32 */ 33 34 #include <sys/cdefs.h> 35 __KERNEL_RCSID(0, "$NetBSD: puffs_compat.c,v 1.2 2010/07/11 11:17:27 pooka Exp $"); 36 37 #include <sys/param.h> 38 #include <sys/atomic.h> 39 #include <sys/kmem.h> 40 #include <sys/kthread.h> 41 #include <sys/lock.h> 42 #include <sys/malloc.h> 43 #include <sys/mount.h> 44 #include <sys/namei.h> 45 #include <sys/proc.h> 46 #include <sys/vnode.h> 47 #include <sys/atomic.h> 48 49 #include <dev/putter/putter_sys.h> 50 51 #include <fs/puffs/puffs_msgif.h> 52 #include <fs/puffs/puffs_sys.h> 53 54 #include <compat/sys/time.h> 55 56 /* 57 * compat types 58 */ 59 struct vattr50 { 60 enum vtype va_type; 61 mode_t va_mode; 62 nlink_t va_nlink; 63 uid_t va_uid; 64 gid_t va_gid; 65 uint32_t va_fsid; 66 ino_t va_fileid; 67 u_quad_t va_size; 68 long va_blocksize; 69 struct timespec50 va_atime; 70 struct timespec50 va_mtime; 71 struct timespec50 va_ctime; 72 struct timespec50 va_birthtime; 73 u_long va_gen; 74 u_long va_flags; 75 uint32_t va_rdev; 76 u_quad_t va_bytes; 77 u_quad_t va_filerev; 78 u_int va_vaflags; 79 long va_spare; 80 }; 81 82 struct puffs50_vfsmsg_fhtonode { 83 struct puffs_req pvfsr_pr; 84 85 void *pvfsr_fhcookie; /* IN */ 86 enum vtype pvfsr_vtype; /* IN */ 87 voff_t pvfsr_size; /* IN */ 88 uint32_t pvfsr_rdev; /* IN */ 89 90 size_t pvfsr_dsize; /* OUT */ 91 uint8_t pvfsr_data[0] /* OUT, XXX */ 92 __aligned(ALIGNBYTES+1); 93 }; 94 95 struct puffs50_vnmsg_lookup { 96 struct puffs_req pvn_pr; 97 98 struct puffs_kcn pvnr_cn; /* OUT */ 99 struct puffs_kcred pvnr_cn_cred; /* OUT */ 100 101 puffs_cookie_t pvnr_newnode; /* IN */ 102 enum vtype pvnr_vtype; /* IN */ 103 voff_t pvnr_size; /* IN */ 104 uint32_t pvnr_rdev; /* IN */ 105 }; 106 107 struct puffs50_vnmsg_create { 108 struct puffs_req pvn_pr; 109 110 struct puffs_kcn pvnr_cn; /* OUT */ 111 struct puffs_kcred pvnr_cn_cred; /* OUT */ 112 113 struct vattr50 pvnr_va; /* OUT */ 114 puffs_cookie_t pvnr_newnode; /* IN */ 115 }; 116 117 struct puffs50_vnmsg_mknod { 118 struct puffs_req pvn_pr; 119 120 struct puffs_kcn pvnr_cn; /* OUT */ 121 struct puffs_kcred pvnr_cn_cred; /* OUT */ 122 123 struct vattr50 pvnr_va; /* OUT */ 124 puffs_cookie_t pvnr_newnode; /* IN */ 125 }; 126 127 #define puffs50_vnmsg_setattr puffs50_vnmsg_setgetattr 128 #define puffs50_vnmsg_getattr puffs50_vnmsg_setgetattr 129 struct puffs50_vnmsg_setgetattr { 130 struct puffs_req pvn_pr; 131 132 struct puffs_kcred pvnr_cred; /* OUT */ 133 struct vattr50 pvnr_va; /* IN/OUT (op depend) */ 134 }; 135 136 struct puffs50_vnmsg_mkdir { 137 struct puffs_req pvn_pr; 138 139 struct puffs_kcn pvnr_cn; /* OUT */ 140 struct puffs_kcred pvnr_cn_cred; /* OUT */ 141 142 struct vattr50 pvnr_va; /* OUT */ 143 puffs_cookie_t pvnr_newnode; /* IN */ 144 }; 145 146 struct puffs50_vnmsg_symlink { 147 struct puffs_req pvn_pr; 148 149 struct puffs_kcn pvnr_cn; /* OUT */ 150 struct puffs_kcred pvnr_cn_cred; /* OUT */ 151 152 struct vattr50 pvnr_va; /* OUT */ 153 puffs_cookie_t pvnr_newnode; /* IN */ 154 char pvnr_link[MAXPATHLEN]; /* OUT */ 155 }; 156 157 /* 158 * vattr translation routines 159 */ 160 161 static void 162 vattr_to_50(const struct vattr *va, struct vattr50 *va50) 163 { 164 165 va50->va_type = va->va_type; 166 va50->va_mode = va->va_mode; 167 va50->va_nlink = va->va_nlink; 168 va50->va_uid = va->va_uid; 169 va50->va_gid = va->va_gid; 170 va50->va_fsid = (uint64_t)va->va_fsid; 171 va50->va_fileid = va->va_fileid; 172 va50->va_size = va->va_size; 173 va50->va_blocksize = va->va_blocksize; 174 timespec_to_timespec50(&va->va_atime, &va50->va_atime); 175 timespec_to_timespec50(&va->va_ctime, &va50->va_ctime); 176 timespec_to_timespec50(&va->va_mtime, &va50->va_mtime); 177 timespec_to_timespec50(&va->va_birthtime, &va50->va_birthtime); 178 va50->va_gen = va->va_gen; 179 va50->va_flags = va->va_flags; 180 va50->va_rdev = (int32_t)va->va_rdev; 181 va50->va_bytes = va->va_bytes; 182 va50->va_filerev = va->va_filerev; 183 va50->va_vaflags = va->va_flags; 184 } 185 186 static void 187 vattr_from_50(const struct vattr50 *va50, struct vattr *va) 188 { 189 190 va->va_type = va50->va_type; 191 va->va_mode = va50->va_mode; 192 va->va_nlink = va50->va_nlink; 193 va->va_uid = va50->va_uid; 194 va->va_gid = va50->va_gid; 195 va->va_fsid = (uint32_t)va50->va_fsid; 196 va->va_fileid = va50->va_fileid; 197 va->va_size = va50->va_size; 198 va->va_blocksize = va50->va_blocksize; 199 timespec50_to_timespec(&va50->va_atime, &va->va_atime); 200 timespec50_to_timespec(&va50->va_ctime, &va->va_ctime); 201 timespec50_to_timespec(&va50->va_mtime, &va->va_mtime); 202 timespec50_to_timespec(&va50->va_birthtime, &va->va_birthtime); 203 va->va_gen = va50->va_gen; 204 va->va_flags = va50->va_flags; 205 va->va_rdev = (uint32_t)va50->va_rdev; 206 va->va_bytes = va50->va_bytes; 207 va->va_filerev = va50->va_filerev; 208 va->va_vaflags = va50->va_flags; 209 } 210 211 /* 212 * XXX: cannot assert that sleeping is possible 213 * (this always a valid assumption for now) 214 */ 215 #define INIT(name, extra) \ 216 struct puffs50_##name *cmsg; \ 217 struct puffs_##name *omsg; \ 218 creq =kmem_zalloc(sizeof(struct puffs50_##name)+extra,KM_SLEEP);\ 219 cmsg = (struct puffs50_##name *)creq; \ 220 omsg = (struct puffs_##name *)oreq; \ 221 delta = sizeof(struct puffs50_##name)-sizeof(struct puffs_##name); 222 #define ASSIGN(field) \ 223 cmsg->field = omsg->field; 224 225 bool 226 puffs_compat_outgoing(struct puffs_req *oreq, 227 struct puffs_req **creqp, ssize_t *deltap) 228 { 229 struct puffs_req *creq = NULL; 230 ssize_t delta = 0; 231 bool rv = false; 232 233 if (PUFFSOP_OPCLASS(oreq->preq_opclass) == PUFFSOP_VFS 234 && oreq->preq_optype == PUFFS_VFS_FHTOVP) { 235 INIT(vfsmsg_fhtonode, 236 ((struct puffs_vfsmsg_fhtonode *)oreq)->pvfsr_dsize); 237 238 ASSIGN(pvfsr_pr); 239 ASSIGN(pvfsr_dsize); 240 memcpy(cmsg->pvfsr_data, omsg->pvfsr_data, cmsg->pvfsr_dsize); 241 } else if (PUFFSOP_OPCLASS(oreq->preq_opclass) == PUFFSOP_VN) { 242 switch (oreq->preq_optype) { 243 case PUFFS_VN_LOOKUP: 244 { 245 INIT(vnmsg_lookup, 0); 246 247 ASSIGN(pvn_pr); 248 ASSIGN(pvnr_cn); 249 ASSIGN(pvnr_cn_cred); 250 251 break; 252 } 253 254 case PUFFS_VN_CREATE: 255 { 256 INIT(vnmsg_create, 0); 257 258 ASSIGN(pvn_pr); 259 ASSIGN(pvnr_cn); 260 ASSIGN(pvnr_cn_cred); 261 vattr_to_50(&omsg->pvnr_va, &cmsg->pvnr_va); 262 263 break; 264 } 265 266 case PUFFS_VN_MKNOD: 267 { 268 INIT(vnmsg_mknod, 0); 269 270 ASSIGN(pvn_pr); 271 ASSIGN(pvnr_cn); 272 ASSIGN(pvnr_cn_cred); 273 vattr_to_50(&omsg->pvnr_va, &cmsg->pvnr_va); 274 275 break; 276 } 277 278 case PUFFS_VN_MKDIR: 279 { 280 INIT(vnmsg_mkdir, 0); 281 282 ASSIGN(pvn_pr); 283 ASSIGN(pvnr_cn); 284 ASSIGN(pvnr_cn_cred); 285 vattr_to_50(&omsg->pvnr_va, &cmsg->pvnr_va); 286 287 break; 288 } 289 290 case PUFFS_VN_SYMLINK: 291 { 292 INIT(vnmsg_symlink, 0); 293 294 ASSIGN(pvn_pr); 295 ASSIGN(pvnr_cn); 296 ASSIGN(pvnr_cn_cred); 297 vattr_to_50(&omsg->pvnr_va, &cmsg->pvnr_va); 298 memcpy(cmsg->pvnr_link, omsg->pvnr_link, 299 sizeof(cmsg->pvnr_link)); 300 301 break; 302 } 303 304 case PUFFS_VN_SETATTR: 305 { 306 INIT(vnmsg_setattr, 0); 307 308 ASSIGN(pvn_pr); 309 ASSIGN(pvnr_cred); 310 vattr_to_50(&omsg->pvnr_va, &cmsg->pvnr_va); 311 312 break; 313 } 314 case PUFFS_VN_GETATTR: 315 { 316 INIT(vnmsg_getattr, 0); 317 318 ASSIGN(pvn_pr); 319 ASSIGN(pvnr_cred); 320 321 break; 322 } 323 324 default: 325 break; 326 } 327 } 328 329 if (creq) { 330 *creqp = creq; 331 *deltap = delta; 332 rv = true; 333 } 334 335 return rv; 336 } 337 #undef INIT 338 #undef ASSIGN 339 340 #define INIT(name) \ 341 struct puffs50_##name *cmsg = (void *)preq; \ 342 struct puffs_##name *omsg = (void *)creq; 343 #define ASSIGN(field) \ 344 omsg->field = cmsg->field; 345 346 void 347 puffs_compat_incoming(struct puffs_req *preq, struct puffs_req *creq) 348 { 349 350 if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VFS 351 && preq->preq_optype == PUFFS_VFS_FHTOVP) { 352 INIT(vfsmsg_fhtonode); 353 354 ASSIGN(pvfsr_pr); 355 356 ASSIGN(pvfsr_fhcookie); 357 ASSIGN(pvfsr_vtype); 358 ASSIGN(pvfsr_size); 359 ASSIGN(pvfsr_rdev); 360 } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN) { 361 switch (preq->preq_optype) { 362 case PUFFS_VN_LOOKUP: 363 { 364 INIT(vnmsg_lookup); 365 366 ASSIGN(pvn_pr); 367 ASSIGN(pvnr_newnode); 368 ASSIGN(pvnr_vtype); 369 ASSIGN(pvnr_size); 370 ASSIGN(pvnr_rdev); 371 372 break; 373 } 374 375 case PUFFS_VN_CREATE: 376 { 377 INIT(vnmsg_create); 378 379 ASSIGN(pvn_pr); 380 ASSIGN(pvnr_newnode); 381 382 break; 383 } 384 385 case PUFFS_VN_MKNOD: 386 { 387 INIT(vnmsg_mknod); 388 389 ASSIGN(pvn_pr); 390 ASSIGN(pvnr_newnode); 391 392 break; 393 } 394 395 case PUFFS_VN_MKDIR: 396 { 397 INIT(vnmsg_mkdir); 398 399 ASSIGN(pvn_pr); 400 ASSIGN(pvnr_newnode); 401 402 break; 403 } 404 405 case PUFFS_VN_SYMLINK: 406 { 407 INIT(vnmsg_symlink); 408 409 ASSIGN(pvn_pr); 410 ASSIGN(pvnr_newnode); 411 412 break; 413 } 414 415 case PUFFS_VN_SETATTR: 416 { 417 INIT(vnmsg_setattr); 418 419 ASSIGN(pvn_pr); 420 421 break; 422 } 423 case PUFFS_VN_GETATTR: 424 { 425 INIT(vnmsg_getattr); 426 427 ASSIGN(pvn_pr); 428 vattr_from_50(&cmsg->pvnr_va, &omsg->pvnr_va); 429 430 break; 431 } 432 433 default: 434 panic("puffs compat ops come in pairs"); 435 } 436 } 437 } 438