1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/errno.h> 29 #include <sys/param.h> 30 #include <sys/types.h> 31 #include <sys/systm.h> 32 #include <sys/user.h> 33 #include <sys/stat.h> 34 #include <sys/kstat.h> 35 #include <sys/time.h> 36 #include <sys/vfs.h> 37 #include <sys/vnode.h> 38 #include <sys/file.h> 39 #include <rpc/types.h> 40 #include <rpc/xdr.h> 41 #include <sys/mode.h> 42 #include <sys/pathname.h> 43 #include <sys/cmn_err.h> 44 #include <sys/debug.h> 45 #include <sys/fs/cachefs_fs.h> 46 #include <sys/fs/cachefs_log.h> 47 #include <vm/seg.h> 48 #include <vm/seg_map.h> 49 #include <sys/sysmacros.h> 50 51 /* 52 * ino64_t is a unsigned long on LP64 and unsigned long long on ILP32, 53 * the compiler emits many warnings when calling xdr_u_longlong_t with an 54 * unsigned long pointer on LP64 even though it's safe. 55 */ 56 #define xdr_ino64(xdrs, p) xdr_u_longlong_t((xdrs), (u_longlong_t *)(p)) 57 58 /* 59 * cfs_time_t is an int in both LP64 and ILP32. To avoid compiler warnings 60 * define its xdr here explicitely 61 */ 62 #define xdr_cfs_time_t(xdrs, p) xdr_int((xdrs), (int *)(p)) 63 64 #define CACHEFS_LOG_MAX_BUFFERED 65536 65 #define CACHEFS_LOG_LOWATER 8192 66 #define CACHEFS_LOG_ENCODE_SIZE 4096 67 68 #if (defined(_SYSCALL32_IMPL) || defined(_LP64)) 69 70 #define OUT_IF_TIME_OVERFLOW(cachep, time) \ 71 if (TIME_OVERFLOW(time)) { \ 72 cachefs_log_error(cachep, EOVERFLOW, 1); \ 73 goto out; \ 74 } 75 76 #define RET_IF_TIME_OVERFLOW(cachep, time) \ 77 if (TIME_OVERFLOW(time)) { \ 78 cachefs_log_error(cachep, EOVERFLOW, 1); \ 79 return; \ 80 } 81 82 #else /* not (_SYSCALL32_IMPL || _LP64) */ 83 84 #define OUT_IF_TIME_OVERFLOW(cachep, time) 85 86 #define RET_IF_TIME_OVERFLOW(cachep, time) 87 88 #endif /* (_SYSCALL32_IMPL || _LP64) */ 89 90 typedef struct cachefs_log_work_list { 91 void *data; 92 size_t size; 93 xdrproc_t translate; 94 struct cachefs_log_work_list *next; 95 } *cachefs_log_work_list_t; 96 97 /* forward declarations of static functions */ 98 static void cachefs_log_enqueue(cachefscache_t *, void *, int, xdrproc_t); 99 static int cachefs_log_save_lc(cachefscache_t *); 100 static int cachefs_log_write_header(struct vnode *, cachefscache_t *, int); 101 102 static bool_t cachefs_xdr_logfile_header(XDR *, 103 struct cachefs_log_logfile_header *); 104 static bool_t cachefs_xdr_mount(XDR *, struct cachefs_log_mount_record *); 105 static bool_t cachefs_xdr_umount(XDR *, struct cachefs_log_umount_record *); 106 static bool_t cachefs_xdr_getpage(XDR *, struct cachefs_log_getpage_record *); 107 static bool_t cachefs_xdr_readdir(XDR *, struct cachefs_log_readdir_record *); 108 static bool_t cachefs_xdr_readlink(XDR *, 109 struct cachefs_log_readlink_record *); 110 static bool_t cachefs_xdr_remove(XDR *, struct cachefs_log_remove_record *); 111 static bool_t cachefs_xdr_rmdir(XDR *, struct cachefs_log_rmdir_record *); 112 static bool_t cachefs_xdr_truncate(XDR *, 113 struct cachefs_log_truncate_record *); 114 static bool_t cachefs_xdr_putpage(XDR *, struct cachefs_log_putpage_record *); 115 static bool_t cachefs_xdr_create(XDR *, struct cachefs_log_create_record *); 116 static bool_t cachefs_xdr_mkdir(XDR *, struct cachefs_log_mkdir_record *); 117 static bool_t cachefs_xdr_rename(XDR *, struct cachefs_log_rename_record *); 118 static bool_t cachefs_xdr_symlink(XDR *, struct cachefs_log_symlink_record *); 119 static bool_t cachefs_xdr_populate(XDR *, 120 struct cachefs_log_populate_record *); 121 static bool_t cachefs_xdr_csymlink(XDR *, 122 struct cachefs_log_csymlink_record *); 123 static bool_t cachefs_xdr_filldir(XDR *, 124 struct cachefs_log_filldir_record *); 125 static bool_t cachefs_xdr_mdcreate(XDR *, 126 struct cachefs_log_mdcreate_record *); 127 static bool_t cachefs_xdr_gpfront(XDR *, 128 struct cachefs_log_gpfront_record *); 129 static bool_t cachefs_xdr_rfdir(XDR *, 130 struct cachefs_log_rfdir_record *); 131 static bool_t cachefs_xdr_ualloc(XDR *, 132 struct cachefs_log_ualloc_record *); 133 static bool_t cachefs_xdr_calloc(XDR *, 134 struct cachefs_log_calloc_record *); 135 static bool_t cachefs_xdr_nocache(XDR *, 136 struct cachefs_log_nocache_record *); 137 138 139 extern time_t time; 140 141 /* 142 * cachefs_log_kstat_snapshot(kstat_t *ksp, void *buf, int rw) 143 * 144 * called from /dev/kstat or somesuch. 145 * 146 */ 147 148 int 149 cachefs_log_kstat_snapshot(kstat_t *ksp, void *buf, int rw) 150 { 151 cachefs_log_control_t *lc = (cachefs_log_control_t *)ksp->ks_data; 152 cachefs_log_control_t *buflc = (cachefs_log_control_t *)buf; 153 cachefscache_t *cachep = (cachefscache_t *)(uintptr_t)lc->lc_cachep; 154 cachefs_log_cookie_t *cl = cachep->c_log; 155 int error = 0; 156 157 ASSERT(MUTEX_HELD(&cachep->c_log_mutex)); 158 159 /* if they just want to read the kstat, get that out of the way. */ 160 if (rw != KSTAT_WRITE) { 161 bcopy(lc, buflc, sizeof (*lc)); 162 return (0); 163 } 164 165 /* make sure they're passing us a valid control cookie */ 166 if ((buflc->lc_cachep != lc->lc_cachep) || 167 (buflc->lc_magic != CACHEFS_LOG_MAGIC)) 168 return (EIO); 169 170 /* 171 * if logging is currently off 172 * o insist that we're being handed a logfile path 173 * o set cl, and give our cachep its value 174 * 175 * after that, if something goes wrong, we must call 176 * cachefs_log_error to clear cachep->c_log. 177 */ 178 if (cl == NULL) { 179 if (buflc->lc_path[0] == '\0') 180 return (EIO); 181 cl = cachep->c_log = cachefs_log_create_cookie(lc); 182 if (cl == NULL) { 183 cachefs_log_error(cachep, ENOMEM, 0); 184 return (EIO); 185 } 186 } 187 188 /* 189 * if we're being handed an empty logpath, then they must be 190 * turning off logging; also, logging must have been turned on 191 * before, or else the previous paragraph would have caught 192 * it. 193 */ 194 if (buflc->lc_path[0] == '\0') { 195 cachefs_log_process_queue(cachep, 0); 196 cachep->c_log = NULL; 197 cachefs_log_destroy_cookie(cl); 198 bzero(lc, sizeof (*lc)); 199 lc->lc_magic = CACHEFS_LOG_MAGIC; 200 lc->lc_cachep = (uint64_t)(uintptr_t)cachep; 201 (void) VOP_REMOVE(cachep->c_dirvp, LOG_STATUS_NAME, kcred); 202 return (0); 203 } 204 205 /* 206 * if we get here, we know that we're being handed a valid log 207 * control cookie, and that a path is set. try to open the 208 * log file, even if it's the same path, because they might 209 * have removed the old log file out from under us. if it 210 * really is the same file, no harm done. 211 */ 212 if ((error = cachefs_log_logfile_open(cachep, buflc->lc_path)) != 0) { 213 cachefs_log_error(cachep, error, 0); 214 return (EIO); 215 } 216 217 /* 218 * if we get here, we have a valid logfile open. we don't do 219 * anything here with the bitmap of what's being logged, other 220 * than copy it. we're home free! 221 */ 222 bcopy(buflc, lc, sizeof (*lc)); 223 if ((error = cachefs_log_save_lc(cachep)) != 0) { 224 cachefs_log_error(cachep, error, 0); 225 return (EIO); 226 } 227 228 return (0); 229 } 230 231 static int 232 cachefs_log_save_lc(cachefscache_t *cachep) 233 { 234 cachefs_log_control_t *lc = (cachefs_log_control_t *)cachep->c_log_ctl; 235 struct vnode *savevp; 236 struct vattr attr; 237 int error = 0; 238 239 if (lc == NULL) 240 return (EINVAL); 241 242 attr.va_mode = S_IFREG | 0666; 243 attr.va_uid = 0; 244 attr.va_gid = 0; 245 attr.va_type = VREG; 246 attr.va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID; 247 248 if (((error = VOP_LOOKUP(cachep->c_dirvp, LOG_STATUS_NAME, &savevp, 249 NULL, 0, NULL, kcred)) != 0) && 250 ((error = VOP_CREATE(cachep->c_dirvp, LOG_STATUS_NAME, &attr, EXCL, 251 0600, &savevp, kcred, 0)) != 0)) 252 return (error); 253 ASSERT(savevp != NULL); 254 if (savevp == NULL) 255 return (ENOENT); 256 257 error = vn_rdwr(UIO_WRITE, savevp, 258 (caddr_t)lc, sizeof (*lc), 259 0LL, UIO_SYSSPACE, FSYNC, (rlim64_t)RLIM_INFINITY, kcred, NULL); 260 261 VN_RELE(savevp); 262 263 return (error); 264 } 265 266 /* 267 * cachefs_log_cookie_t *cachefs_log_create_cookie(void *) 268 * 269 * creates and initializes the cookie, which lives in cachep. called 270 * from either a kstat write which turns on logging, or from 271 * initializing cachep when a log-info-file exists. 272 */ 273 274 cachefs_log_cookie_t * 275 cachefs_log_create_cookie(cachefs_log_control_t *lc) 276 { 277 cachefs_log_cookie_t *rc; 278 279 rc = cachefs_kmem_zalloc(sizeof (*rc), KM_NOSLEEP); 280 if (rc == NULL) 281 return (NULL); 282 283 rc->cl_magic = CACHEFS_LOG_MAGIC; 284 rc->cl_logctl = lc; 285 286 return (rc); 287 } 288 289 /* 290 * void cachefs_log_destroy_cookie(cachefs_log_cookie_t *) 291 * 292 * destroys the log cookie. called from cachefs_log_error, or from 293 * destroying the cachep. 294 * 295 */ 296 297 void 298 cachefs_log_destroy_cookie(cachefs_log_cookie_t *cl) 299 { 300 cachefs_log_work_list_t node, oldnode; 301 302 if (cl == NULL) 303 return; 304 305 ASSERT(cl->cl_magic == CACHEFS_LOG_MAGIC); 306 307 cl->cl_magic++; 308 node = cl->cl_head; 309 while (node != NULL) { 310 cachefs_kmem_free(node->data, node->size); 311 oldnode = node; 312 node = node->next; 313 cachefs_kmem_free(oldnode, sizeof (*oldnode)); 314 } 315 if (cl->cl_logvp != NULL) 316 VN_RELE(cl->cl_logvp); 317 cachefs_kmem_free(cl, sizeof (*cl)); 318 } 319 320 /* 321 * int cachefs_log_logfile_open(cachefscache_t *, char *) 322 * 323 * opens the logfile, and stores the path string if its successful. 324 * 325 * returns an errno if one occured. 326 * 327 */ 328 329 int 330 cachefs_log_logfile_open(cachefscache_t *cachep, char *path) 331 { 332 cachefs_log_cookie_t *cl = cachep->c_log; 333 struct vnode *newvp = NULL; 334 int error = 0; 335 int i; 336 337 ASSERT(MUTEX_HELD(&cachep->c_log_mutex)); 338 ASSERT(cl != NULL); 339 ASSERT(cl->cl_magic == CACHEFS_LOG_MAGIC); 340 341 /* lookup the pathname -- it must already exist! */ 342 error = lookupname(path, UIO_SYSSPACE, FOLLOW, NULL, &newvp); 343 if (error) 344 goto out; 345 ASSERT(newvp != NULL); 346 if (newvp == NULL) { 347 error = ENOENT; /* XXX this shouldn't happen (yeah right) */ 348 goto out; 349 } 350 351 /* easy out if we just re-opened the same logfile */ 352 if (cl->cl_logvp == newvp) { 353 VN_RELE(newvp); 354 goto out; 355 } 356 357 /* XXX we may change this to allow named pipes */ 358 if (newvp->v_type != VREG) { 359 error = EINVAL; 360 goto out; 361 } 362 if (vn_matchops(newvp, cachefs_getvnodeops())) { 363 error = EINVAL; 364 goto out; 365 } 366 367 /* write out the header */ 368 error = cachefs_log_write_header(newvp, cachep, 0); 369 if (error) 370 goto out; 371 372 /* if we get here, we successfully opened the log. */ 373 if (cl->cl_logvp != NULL) 374 VN_RELE(cl->cl_logvp); 375 cl->cl_logvp = newvp; 376 377 /* 378 * `fake' a mount entry for each mounted cachefs filesystem. 379 * this is overkill, but it's easiest and most foolproof way 380 * to do things here. the user-level consumers of the logfile 381 * have to expect extraneous mount entries and deal with it 382 * correctly. 383 */ 384 mutex_exit(&cachep->c_log_mutex); 385 for (i = 0; i < cachefs_kstat_key_n; i++) { 386 cachefs_kstat_key_t *k; 387 struct vfs *vfsp; 388 struct fscache *fscp; 389 390 k = cachefs_kstat_key + i; 391 if (! k->ks_mounted) 392 continue; 393 394 vfsp = (struct vfs *)(uintptr_t)k->ks_vfsp; 395 fscp = VFS_TO_FSCACHE(vfsp); 396 cachefs_log_mount(cachep, 0, vfsp, fscp, 397 (char *)(uintptr_t)k->ks_mountpoint, UIO_SYSSPACE, 398 (char *)(uintptr_t)k->ks_cacheid); 399 } 400 mutex_enter(&cachep->c_log_mutex); 401 402 out: 403 if ((error != 0) && (newvp != NULL)) 404 VN_RELE(newvp); 405 return (error); 406 } 407 408 /* 409 * called when an error occured during logging. send the error to 410 * syslog, invalidate the logfile, and stop logging. 411 */ 412 413 void 414 cachefs_log_error(cachefscache_t *cachep, int error, int getlock) 415 { 416 cachefs_log_cookie_t *cl = cachep->c_log; 417 cachefs_log_control_t *lc = cachep->c_log_ctl; 418 int writable = 0; 419 420 ASSERT((getlock) || (MUTEX_HELD(&cachep->c_log_mutex))); 421 422 if (getlock) 423 mutex_enter(&cachep->c_log_mutex); 424 425 if ((cachep->c_flags & (CACHE_NOCACHE | CACHE_NOFILL)) == 0) 426 writable = 1; 427 428 cmn_err(CE_WARN, "cachefs logging: error %d\n", error); 429 430 if ((writable) && (cl != NULL) && (cl->cl_logvp != NULL)) 431 (void) cachefs_log_write_header(cl->cl_logvp, cachep, error); 432 433 cachep->c_log = NULL; 434 if (cl != NULL) 435 cachefs_log_destroy_cookie(cl); 436 bzero(lc, sizeof (cachefs_log_control_t)); 437 lc->lc_magic = CACHEFS_LOG_MAGIC; 438 lc->lc_cachep = (uint64_t)(uintptr_t)cachep; 439 if (writable) 440 (void) VOP_REMOVE(cachep->c_dirvp, LOG_STATUS_NAME, kcred); 441 442 if (getlock) 443 mutex_exit(&cachep->c_log_mutex); 444 } 445 446 static int 447 cachefs_log_write_header(struct vnode *vp, cachefscache_t *cachep, int error) 448 { 449 struct cachefs_log_logfile_header header, oheader; 450 char buffy[2 * sizeof (header)]; 451 int Errno = 0; 452 struct vattr attr; 453 int gotold = 0; 454 XDR xdrm; 455 456 attr.va_mask = AT_SIZE; 457 if ((error = VOP_GETATTR(vp, &attr, 0, kcred)) != 0) 458 goto out; 459 if (attr.va_size != 0) { 460 error = vn_rdwr(UIO_READ, vp, buffy, 461 MIN(sizeof (buffy), attr.va_size), 462 0LL, UIO_SYSSPACE, 0, (rlim64_t)RLIM_INFINITY, kcred, NULL); 463 if (error != 0) 464 goto out; 465 466 xdrm.x_ops = NULL; 467 xdrmem_create(&xdrm, buffy, sizeof (buffy), XDR_DECODE); 468 if ((xdrm.x_ops == NULL) || 469 (! cachefs_xdr_logfile_header(&xdrm, &oheader))) { 470 if (xdrm.x_ops != NULL) 471 xdr_destroy(&xdrm); 472 error = EINVAL; 473 goto out; 474 } 475 xdr_destroy(&xdrm); 476 gotold = 1; 477 478 if (oheader.lh_magic != CACHEFS_LOG_MAGIC) { 479 error = EINVAL; 480 goto out; 481 } 482 } 483 484 xdrm.x_ops = NULL; 485 486 xdrmem_create(&xdrm, buffy, sizeof (buffy), XDR_ENCODE); 487 488 if (gotold) { 489 header = oheader; 490 } else { 491 header.lh_magic = CACHEFS_LOG_MAGIC; 492 header.lh_revision = CACHEFS_LOG_FILE_REV; 493 header.lh_blocks = cachep->c_usage.cu_blksused; 494 header.lh_files = cachep->c_usage.cu_filesused; 495 header.lh_maxbsize = MAXBSIZE; 496 header.lh_pagesize = PAGESIZE; 497 } 498 499 /* these are things that we stomp over for every header write */ 500 header.lh_errno = Errno; 501 502 if (! cachefs_xdr_logfile_header(&xdrm, &header)) { 503 error = ENOMEM; 504 goto out; 505 } 506 507 error = vn_rdwr(UIO_WRITE, vp, 508 (caddr_t)buffy, xdr_getpos(&xdrm), 509 0LL, UIO_SYSSPACE, FSYNC, (rlim64_t)RLIM_INFINITY, kcred, NULL); 510 if (error) 511 goto out; 512 513 out: 514 if (xdrm.x_ops != NULL) 515 xdr_destroy(&xdrm); 516 return (error); 517 } 518 519 /* 520 * enqueues a record to be written to the logfile. 521 */ 522 523 static void 524 cachefs_log_enqueue(cachefscache_t *cachep, void *record, int size, 525 xdrproc_t translate) 526 { 527 cachefs_log_cookie_t *cl; 528 cachefs_log_work_list_t newnode, oldnode; 529 530 mutex_enter(&cachep->c_log_mutex); 531 cl = cachep->c_log; 532 533 if (cl == NULL) { /* someone turned off logging out from under us */ 534 mutex_exit(&cachep->c_log_mutex); 535 cachefs_kmem_free(record, size); 536 return; 537 } 538 ASSERT(cl->cl_magic == CACHEFS_LOG_MAGIC); 539 540 cl->cl_size += size; 541 newnode = cachefs_kmem_zalloc(sizeof (*newnode), KM_NOSLEEP); 542 if ((cl->cl_size > CACHEFS_LOG_MAX_BUFFERED) || (newnode == NULL)) { 543 cachefs_log_error(cachep, ENOMEM, 0); 544 if (newnode != NULL) 545 cachefs_kmem_free(newnode, sizeof (*newnode)); 546 cachefs_kmem_free(record, size); 547 mutex_exit(&cachep->c_log_mutex); 548 return; 549 } 550 551 newnode->data = record; 552 newnode->size = size; 553 newnode->translate = translate; 554 newnode->next = NULL; 555 556 oldnode = (cachefs_log_work_list_t)cl->cl_tail; 557 if (oldnode != NULL) 558 oldnode->next = newnode; 559 cl->cl_tail = newnode; 560 if (cl->cl_head == NULL) 561 cl->cl_head = newnode; 562 mutex_exit(&cachep->c_log_mutex); 563 564 if (cl->cl_size >= CACHEFS_LOG_LOWATER) { 565 mutex_enter(&cachep->c_workq.wq_queue_lock); 566 cachep->c_workq.wq_logwork = 1; 567 cv_signal(&cachep->c_workq.wq_req_cv); 568 mutex_exit(&cachep->c_workq.wq_queue_lock); 569 } 570 } 571 572 /* 573 * processes the log queue. run by an async worker thread, or via 574 * cachefs_cache_sync(). 575 */ 576 577 void 578 cachefs_log_process_queue(cachefscache_t *cachep, int getlock) 579 { 580 cachefs_log_cookie_t *cl; 581 cachefs_log_work_list_t work, workhead, oldwork; 582 struct vnode *logvp = NULL; 583 struct uio uio; 584 struct iovec iov; 585 int error = 0; 586 XDR xdrm; 587 char *buffy = NULL; 588 589 /* 590 * NULL out the x_ops field of XDR. this way, if x_ops != 591 * NULL, we know that we did the xdr*_create() successfully. 592 * this is documented in the xdr_create man page. 593 */ 594 595 xdrm.x_ops = NULL; 596 597 /* see if we're still logging */ 598 if (getlock) 599 mutex_enter(&cachep->c_log_mutex); 600 cl = cachep->c_log; 601 if ((cl == NULL) || (cl->cl_magic != CACHEFS_LOG_MAGIC)) { 602 if (getlock) 603 mutex_exit(&cachep->c_log_mutex); 604 return; 605 } 606 607 /* get the work, and let go of the mutex asap. */ 608 workhead = cl->cl_head; 609 cl->cl_head = cl->cl_tail = NULL; 610 cl->cl_size = 0; 611 logvp = cl->cl_logvp; 612 ASSERT(logvp != NULL); 613 if (logvp == NULL) { 614 if (getlock) 615 mutex_exit(&cachep->c_log_mutex); 616 return; 617 } 618 VN_HOLD(logvp); 619 if (getlock) 620 mutex_exit(&cachep->c_log_mutex); 621 622 /* we don't use vn_rdwr() because there's no way to set FNONBLOCK */ 623 624 uio.uio_iov = &iov; 625 uio.uio_iovcnt = 1; 626 uio.uio_loffset = 0; /* fake -- we do FAPPEND */ 627 uio.uio_segflg = (short)UIO_SYSSPACE; 628 uio.uio_llimit = MAXOFFSET_T; 629 uio.uio_fmode = FWRITE | FNONBLOCK; 630 uio.uio_extflg = UIO_COPY_CACHED; 631 632 buffy = cachefs_kmem_alloc(CACHEFS_LOG_ENCODE_SIZE, KM_SLEEP); 633 xdrmem_create(&xdrm, buffy, CACHEFS_LOG_ENCODE_SIZE, XDR_ENCODE); 634 635 (void) VOP_RWLOCK(logvp, V_WRITELOCK_TRUE, NULL); 636 for (work = workhead; work != NULL; work = work->next) { 637 if (! (work->translate)(&xdrm, work->data)) { 638 VOP_RWUNLOCK(logvp, V_WRITELOCK_TRUE, NULL); 639 error = ENOMEM; 640 goto out; 641 } 642 643 iov.iov_base = buffy; 644 iov.iov_len = uio.uio_resid = xdr_getpos(&xdrm); 645 (void) xdr_setpos(&xdrm, 0); 646 647 error = VOP_WRITE(logvp, &uio, FAPPEND, kcred, NULL); 648 649 /* XXX future -- check for EAGAIN */ 650 651 if ((error) || (uio.uio_resid)) { 652 if (uio.uio_resid != 0) 653 error = EIO; 654 VOP_RWUNLOCK(logvp, V_WRITELOCK_TRUE, NULL); 655 goto out; 656 } 657 } 658 VOP_RWUNLOCK(logvp, V_WRITELOCK_TRUE, NULL); 659 660 out: 661 if (xdrm.x_ops != NULL) 662 xdr_destroy(&xdrm); 663 if (buffy != NULL) 664 cachefs_kmem_free(buffy, CACHEFS_LOG_ENCODE_SIZE); 665 666 /* 667 * if an error occured, we need to free the buffers ourselves. 668 * cachefs_destory_cookie() can't do it. 669 */ 670 671 work = workhead; 672 while (work != NULL) { 673 cachefs_kmem_free(work->data, work->size); 674 oldwork = work; 675 work = work->next; 676 cachefs_kmem_free(oldwork, sizeof (*oldwork)); 677 } 678 if (logvp != NULL) 679 VN_RELE(logvp); 680 if (error) { 681 cachefs_log_error(cachep, error, 1); 682 return; 683 } 684 } 685 686 static bool_t 687 cachefs_xdr_logfile_header(XDR *xdrs, struct cachefs_log_logfile_header *h) 688 { 689 if ((! xdr_u_int(xdrs, &h->lh_magic)) || 690 (! xdr_u_int(xdrs, &h->lh_revision)) || 691 (! xdr_int(xdrs, &h->lh_errno)) || 692 (! xdr_u_int(xdrs, &h->lh_blocks)) || 693 (! xdr_u_int(xdrs, &h->lh_files)) || 694 (! xdr_u_int(xdrs, &h->lh_maxbsize)) || 695 (! xdr_u_int(xdrs, &h->lh_pagesize))) 696 return (FALSE); 697 698 return (TRUE); 699 } 700 701 /* 702 * the routines for logging each transaction follow... 703 */ 704 705 void 706 cachefs_log_mount(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 707 fscache_t *fscp, char *upath, enum uio_seg seg, char *cacheid) 708 { 709 struct cachefs_log_mount_record *record; 710 char *cacheidt; 711 char *path = NULL; 712 size_t len; 713 int len1, len2; 714 int size, error; 715 716 /* In Solaris 64 - if can't represent time don't bother */ 717 OUT_IF_TIME_OVERFLOW(cachep, time) 718 if (seg == UIO_USERSPACE) { 719 path = cachefs_kmem_alloc(MAXPATHLEN, KM_NOSLEEP); 720 if (path == NULL) { 721 cachefs_log_error(cachep, ENOMEM, 1); 722 goto out; 723 } 724 if ((error = copyinstr(upath, path, MAXPATHLEN, &len)) != 0) { 725 cachefs_log_error(cachep, error, 1); 726 goto out; 727 } 728 } else { 729 path = upath; 730 } 731 732 len1 = (path != NULL) ? strlen(path) : 0; 733 len2 = (cacheid != NULL) ? strlen(cacheid) : 0; 734 size = (int)sizeof (*record) + len1 + len2 - 735 (int)CLPAD(cachefs_log_mount_record, path); 736 record = cachefs_kmem_zalloc(size, KM_NOSLEEP); 737 if (record == NULL) { 738 cachefs_log_error(cachep, ENOMEM, 1); 739 goto out; 740 } 741 742 record->type = CACHEFS_LOG_MOUNT; 743 record->time = time; 744 745 record->error = Errno; 746 record->vfsp = (uint64_t)(uintptr_t)vfsp; 747 748 if (fscp) { 749 record->flags = fscp->fs_info.fi_mntflags; 750 record->popsize = fscp->fs_info.fi_popsize; 751 record->fgsize = fscp->fs_info.fi_fgsize; 752 } 753 754 record->pathlen = (ushort_t)len1; 755 record->cacheidlen = (ushort_t)len2; 756 if (path != NULL) 757 (void) strcpy(record->path, path); 758 cacheidt = record->path + len1 + 1; 759 if (cacheid != NULL) 760 (void) strcpy(cacheidt, cacheid); 761 762 cachefs_log_enqueue(cachep, record, size, cachefs_xdr_mount); 763 764 out: 765 if ((seg == UIO_USERSPACE) && (path != NULL)) 766 cachefs_kmem_free(path, MAXPATHLEN); 767 } 768 769 static bool_t 770 cachefs_xdr_mount(XDR *xdrs, struct cachefs_log_mount_record *rec) 771 { 772 char *path = rec->path; 773 char *cacheid; 774 775 cacheid = path + strlen(path) + 1; 776 777 if ((! xdr_int(xdrs, &rec->type)) || 778 (! xdr_int(xdrs, &rec->error)) || 779 (! xdr_cfs_time_t(xdrs, &rec->time)) || 780 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 781 (! xdr_u_int(xdrs, &rec->flags)) || 782 (! xdr_u_int(xdrs, &rec->popsize)) || 783 (! xdr_u_int(xdrs, &rec->fgsize)) || 784 (! xdr_u_short(xdrs, &rec->pathlen)) || 785 (! xdr_u_short(xdrs, &rec->cacheidlen)) || 786 (! xdr_wrapstring(xdrs, &path)) || 787 (! xdr_wrapstring(xdrs, &cacheid))) 788 return (FALSE); 789 790 return (TRUE); 791 } 792 793 void 794 cachefs_log_umount(cachefscache_t *cachep, int Errno, struct vfs *vfsp) 795 { 796 struct cachefs_log_umount_record *record; 797 798 /* In Solaris 64 - if can't represent time don't bother */ 799 RET_IF_TIME_OVERFLOW(cachep, time) 800 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 801 if (record == NULL) { 802 cachefs_log_error(cachep, ENOMEM, 1); 803 return; 804 } 805 806 record->type = CACHEFS_LOG_UMOUNT; 807 record->time = time; 808 809 record->error = Errno; 810 record->vfsp = (uint64_t)(uintptr_t)vfsp; 811 812 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 813 cachefs_xdr_umount); 814 } 815 816 static bool_t 817 cachefs_xdr_umount(XDR *xdrs, struct cachefs_log_umount_record *rec) 818 { 819 if ((! xdr_int(xdrs, &rec->type)) || 820 (! xdr_int(xdrs, &rec->error)) || 821 (! xdr_cfs_time_t(xdrs, &rec->time)) || 822 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp)))) 823 return (FALSE); 824 825 return (TRUE); 826 } 827 828 void 829 cachefs_log_getpage(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 830 fid_t *fidp, ino64_t fileno, uid_t uid, u_offset_t offset, size_t len) 831 { 832 struct cachefs_log_getpage_record *record; 833 834 /* In Solaris 64 - if can't represent time don't bother */ 835 RET_IF_TIME_OVERFLOW(cachep, time) 836 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 837 if (record == NULL) { 838 cachefs_log_error(cachep, ENOMEM, 1); 839 return; 840 } 841 842 record->type = CACHEFS_LOG_GETPAGE; 843 record->time = time; 844 845 record->error = Errno; 846 record->vfsp = (uint64_t)(uintptr_t)vfsp; 847 if (fidp != NULL) { 848 CACHEFS_FID_COPY(fidp, &record->fid); 849 } 850 record->fileno = fileno; 851 record->uid = uid; 852 record->offset = offset; 853 record->len = (uint_t)len; 854 855 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 856 cachefs_xdr_getpage); 857 } 858 859 static bool_t 860 cachefs_xdr_getpage(XDR *xdrs, struct cachefs_log_getpage_record *rec) 861 { 862 if ((! xdr_int(xdrs, &rec->type)) || 863 (! xdr_int(xdrs, &rec->error)) || 864 (! xdr_cfs_time_t(xdrs, &rec->time)) || 865 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 866 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 867 (! xdr_ino64(xdrs, &rec->fileno)) || 868 (! xdr_u_int(xdrs, &rec->uid)) || 869 (! xdr_u_longlong_t(xdrs, &rec->offset)) || 870 (! xdr_u_int(xdrs, &rec->len))) 871 return (FALSE); 872 873 return (TRUE); 874 } 875 876 void 877 cachefs_log_readdir(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 878 fid_t *fidp, ino64_t fileno, uid_t uid, u_offset_t offset, int eof) 879 { 880 struct cachefs_log_readdir_record *record; 881 882 /* In Solaris 64 - if can't represent time don't bother */ 883 RET_IF_TIME_OVERFLOW(cachep, time) 884 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 885 if (record == NULL) { 886 cachefs_log_error(cachep, ENOMEM, 1); 887 return; 888 } 889 890 record->type = CACHEFS_LOG_READDIR; 891 record->time = time; 892 893 record->error = Errno; 894 record->vfsp = (uint64_t)(uintptr_t)vfsp; 895 if (fidp != NULL) { 896 CACHEFS_FID_COPY(fidp, &record->fid); 897 } 898 record->fileno = fileno; 899 record->uid = uid; 900 record->offset = offset; 901 record->eof = eof; 902 903 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 904 cachefs_xdr_readdir); 905 } 906 907 static bool_t 908 cachefs_xdr_readdir(XDR *xdrs, struct cachefs_log_readdir_record *rec) 909 { 910 if ((! xdr_int(xdrs, &rec->type)) || 911 (! xdr_int(xdrs, &rec->error)) || 912 (! xdr_cfs_time_t(xdrs, &rec->time)) || 913 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 914 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 915 (! xdr_ino64(xdrs, &rec->fileno)) || 916 (! xdr_u_int(xdrs, &rec->uid)) || 917 (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->offset)) || 918 (! xdr_int(xdrs, &rec->eof))) 919 return (FALSE); 920 921 return (TRUE); 922 } 923 924 void 925 cachefs_log_readlink(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 926 fid_t *fidp, ino64_t fileno, uid_t uid, size_t length) 927 { 928 struct cachefs_log_readlink_record *record; 929 930 /* In Solaris 64 - if can't represent time don't bother */ 931 RET_IF_TIME_OVERFLOW(cachep, time) 932 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 933 if (record == NULL) { 934 cachefs_log_error(cachep, ENOMEM, 1); 935 return; 936 } 937 938 record->type = CACHEFS_LOG_READLINK; 939 record->time = time; 940 941 record->error = Errno; 942 record->vfsp = (uint64_t)(uintptr_t)vfsp; 943 if (fidp != NULL) { 944 CACHEFS_FID_COPY(fidp, &record->fid); 945 } 946 record->fileno = fileno; 947 record->uid = uid; 948 record->length = (uint_t)length; 949 950 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 951 cachefs_xdr_readlink); 952 } 953 954 static bool_t 955 cachefs_xdr_readlink(XDR *xdrs, struct cachefs_log_readlink_record *rec) 956 { 957 if ((! xdr_int(xdrs, &rec->type)) || 958 (! xdr_int(xdrs, &rec->error)) || 959 (! xdr_cfs_time_t(xdrs, &rec->time)) || 960 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 961 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 962 (! xdr_ino64(xdrs, &rec->fileno)) || 963 (! xdr_u_int(xdrs, &rec->uid)) || 964 (! xdr_u_int(xdrs, &rec->length))) 965 return (FALSE); 966 967 return (TRUE); 968 } 969 970 void 971 cachefs_log_remove(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 972 fid_t *fidp, ino64_t fileno, uid_t uid) 973 { 974 struct cachefs_log_remove_record *record; 975 976 /* In Solaris 64 - if can't represent time don't bother */ 977 RET_IF_TIME_OVERFLOW(cachep, time) 978 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 979 if (record == NULL) { 980 cachefs_log_error(cachep, ENOMEM, 1); 981 return; 982 } 983 984 record->type = CACHEFS_LOG_REMOVE; 985 record->time = time; 986 987 record->error = Errno; 988 record->vfsp = (uint64_t)(uintptr_t)vfsp; 989 if (fidp != NULL) { 990 CACHEFS_FID_COPY(fidp, &record->fid); 991 } 992 record->fileno = fileno; 993 record->uid = uid; 994 995 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 996 cachefs_xdr_remove); 997 } 998 999 static bool_t 1000 cachefs_xdr_remove(XDR *xdrs, struct cachefs_log_remove_record *rec) 1001 { 1002 if ((! xdr_int(xdrs, &rec->type)) || 1003 (! xdr_int(xdrs, &rec->error)) || 1004 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1005 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1006 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1007 (! xdr_ino64(xdrs, &rec->fileno)) || 1008 (! xdr_u_int(xdrs, &rec->uid))) 1009 return (FALSE); 1010 1011 return (TRUE); 1012 } 1013 1014 void 1015 cachefs_log_rmdir(cachefscache_t *cachep, int Errno, 1016 struct vfs *vfsp, fid_t *fidp, ino64_t fileno, uid_t uid) 1017 { 1018 struct cachefs_log_rmdir_record *record; 1019 1020 /* In Solaris 64 - if can't represent time don't bother */ 1021 RET_IF_TIME_OVERFLOW(cachep, time) 1022 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1023 if (record == NULL) { 1024 cachefs_log_error(cachep, ENOMEM, 1); 1025 return; 1026 } 1027 1028 record->type = CACHEFS_LOG_RMDIR; 1029 record->time = time; 1030 1031 record->error = Errno; 1032 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1033 if (fidp != NULL) { 1034 CACHEFS_FID_COPY(fidp, &record->fid); 1035 } 1036 record->fileno = fileno; 1037 record->uid = uid; 1038 1039 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1040 cachefs_xdr_rmdir); 1041 } 1042 1043 static bool_t 1044 cachefs_xdr_rmdir(XDR *xdrs, struct cachefs_log_rmdir_record *rec) 1045 { 1046 if ((! xdr_int(xdrs, &rec->type)) || 1047 (! xdr_int(xdrs, &rec->error)) || 1048 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1049 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1050 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1051 (! xdr_ino64(xdrs, &rec->fileno)) || 1052 (! xdr_u_int(xdrs, &rec->uid))) 1053 return (FALSE); 1054 1055 return (TRUE); 1056 } 1057 1058 void 1059 cachefs_log_truncate(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1060 fid_t *fidp, ino64_t fileno, uid_t uid, u_offset_t size) 1061 { 1062 struct cachefs_log_truncate_record *record; 1063 1064 /* In Solaris 64 - if can't represent time don't bother */ 1065 RET_IF_TIME_OVERFLOW(cachep, time) 1066 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1067 if (record == NULL) { 1068 cachefs_log_error(cachep, ENOMEM, 1); 1069 return; 1070 } 1071 1072 record->type = CACHEFS_LOG_TRUNCATE; 1073 record->time = time; 1074 1075 record->error = Errno; 1076 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1077 if (fidp != NULL) { 1078 CACHEFS_FID_COPY(fidp, &record->fid); 1079 } 1080 record->fileno = fileno; 1081 record->uid = uid; 1082 record->size = size; 1083 1084 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1085 cachefs_xdr_truncate); 1086 } 1087 1088 static bool_t 1089 cachefs_xdr_truncate(XDR *xdrs, struct cachefs_log_truncate_record *rec) 1090 { 1091 if ((! xdr_int(xdrs, &rec->type)) || 1092 (! xdr_int(xdrs, &rec->error)) || 1093 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1094 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1095 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1096 (! xdr_ino64(xdrs, &rec->fileno)) || 1097 (! xdr_u_int(xdrs, &rec->uid)) || 1098 (! xdr_u_longlong_t(xdrs, &rec->size))) 1099 return (FALSE); 1100 1101 return (TRUE); 1102 } 1103 1104 void 1105 cachefs_log_putpage(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1106 fid_t *fidp, ino64_t fileno, uid_t uid, u_offset_t offset, size_t len) 1107 { 1108 struct cachefs_log_putpage_record *record; 1109 1110 /* In Solaris 64 - if can't represent time don't bother */ 1111 RET_IF_TIME_OVERFLOW(cachep, time) 1112 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1113 if (record == NULL) { 1114 cachefs_log_error(cachep, ENOMEM, 1); 1115 return; 1116 } 1117 1118 record->type = CACHEFS_LOG_PUTPAGE; 1119 record->time = time; 1120 1121 record->error = Errno; 1122 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1123 if (fidp != NULL) { 1124 CACHEFS_FID_COPY(fidp, &record->fid); 1125 } 1126 record->fileno = fileno; 1127 record->uid = uid; 1128 record->offset = offset; 1129 record->len = (uint_t)len; 1130 1131 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1132 cachefs_xdr_putpage); 1133 } 1134 1135 static bool_t 1136 cachefs_xdr_putpage(XDR *xdrs, struct cachefs_log_putpage_record *rec) 1137 { 1138 if ((! xdr_int(xdrs, &rec->type)) || 1139 (! xdr_int(xdrs, &rec->error)) || 1140 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1141 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1142 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1143 (! xdr_ino64(xdrs, &rec->fileno)) || 1144 (! xdr_u_int(xdrs, &rec->uid)) || 1145 (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->offset)) || 1146 (! xdr_u_int(xdrs, &rec->len))) 1147 return (FALSE); 1148 1149 return (TRUE); 1150 } 1151 1152 void 1153 cachefs_log_create(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1154 fid_t *filefidp, ino64_t fileno, uid_t uid) 1155 { 1156 struct cachefs_log_create_record *record; 1157 1158 /* In Solaris 64 - if can't represent time don't bother */ 1159 RET_IF_TIME_OVERFLOW(cachep, time) 1160 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1161 if (record == NULL) { 1162 cachefs_log_error(cachep, ENOMEM, 1); 1163 return; 1164 } 1165 1166 record->type = CACHEFS_LOG_CREATE; 1167 record->time = time; 1168 1169 record->error = Errno; 1170 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1171 if (filefidp != NULL) { 1172 CACHEFS_FID_COPY(filefidp, &record->fid); 1173 } 1174 record->fileno = fileno; 1175 record->uid = uid; 1176 1177 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1178 cachefs_xdr_create); 1179 } 1180 1181 static bool_t 1182 cachefs_xdr_create(XDR *xdrs, struct cachefs_log_create_record *rec) 1183 { 1184 if ((! xdr_int(xdrs, &rec->type)) || 1185 (! xdr_int(xdrs, &rec->error)) || 1186 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1187 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1188 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1189 (! xdr_ino64(xdrs, &rec->fileno)) || 1190 (! xdr_u_int(xdrs, &rec->uid))) 1191 return (FALSE); 1192 1193 return (TRUE); 1194 } 1195 1196 void 1197 cachefs_log_mkdir(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1198 fid_t *cfidp, ino64_t fileno, uid_t uid) 1199 { 1200 struct cachefs_log_mkdir_record *record; 1201 int size; 1202 1203 /* In Solaris 64 - if can't represent time don't bother */ 1204 RET_IF_TIME_OVERFLOW(cachep, time) 1205 size = (int)sizeof (*record); 1206 record = cachefs_kmem_zalloc(size, KM_NOSLEEP); 1207 if (record == NULL) { 1208 cachefs_log_error(cachep, ENOMEM, 1); 1209 return; 1210 } 1211 1212 record->type = CACHEFS_LOG_MKDIR; 1213 record->time = time; 1214 1215 record->error = Errno; 1216 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1217 if (cfidp != NULL) { 1218 CACHEFS_FID_COPY(cfidp, &record->fid); 1219 } 1220 record->fileno = fileno; 1221 record->uid = uid; 1222 1223 cachefs_log_enqueue(cachep, record, size, 1224 cachefs_xdr_mkdir); 1225 } 1226 1227 static bool_t 1228 cachefs_xdr_mkdir(XDR *xdrs, struct cachefs_log_mkdir_record *rec) 1229 { 1230 if ((! xdr_int(xdrs, &rec->type)) || 1231 (! xdr_int(xdrs, &rec->error)) || 1232 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1233 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1234 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1235 (! xdr_ino64(xdrs, &rec->fileno)) || 1236 (! xdr_u_int(xdrs, &rec->uid))) 1237 return (FALSE); 1238 1239 return (TRUE); 1240 } 1241 1242 void 1243 cachefs_log_rename(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1244 fid_t *gfp, ino64_t fileno, int removed, uid_t uid) 1245 { 1246 struct cachefs_log_rename_record *record; 1247 1248 /* In Solaris 64 - if can't represent time don't bother */ 1249 RET_IF_TIME_OVERFLOW(cachep, time) 1250 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1251 if (record == NULL) { 1252 cachefs_log_error(cachep, ENOMEM, 1); 1253 return; 1254 } 1255 1256 record->type = CACHEFS_LOG_RENAME; 1257 record->time = time; 1258 1259 record->error = Errno; 1260 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1261 if (gfp != NULL) { 1262 CACHEFS_FID_COPY(gfp, &record->gone); 1263 } 1264 record->fileno = fileno; 1265 record->removed = removed; 1266 record->uid = uid; 1267 1268 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1269 cachefs_xdr_rename); 1270 } 1271 1272 static bool_t 1273 cachefs_xdr_rename(XDR *xdrs, struct cachefs_log_rename_record *rec) 1274 { 1275 if ((! xdr_int(xdrs, &rec->type)) || 1276 (! xdr_int(xdrs, &rec->error)) || 1277 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1278 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1279 (! xdr_opaque(xdrs, (caddr_t)&rec->gone, sizeof (rec->gone))) || 1280 (! xdr_int(xdrs, &rec->removed)) || 1281 (! xdr_u_int(xdrs, &rec->uid))) 1282 return (FALSE); 1283 1284 return (TRUE); 1285 } 1286 1287 1288 void 1289 cachefs_log_symlink(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1290 fid_t *fidp, ino64_t fileno, uid_t uid, int size) 1291 { 1292 struct cachefs_log_symlink_record *record; 1293 1294 /* In Solaris 64 - if can't represent time don't bother */ 1295 RET_IF_TIME_OVERFLOW(cachep, time) 1296 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1297 if (record == NULL) { 1298 cachefs_log_error(cachep, ENOMEM, 1); 1299 return; 1300 } 1301 1302 record->type = CACHEFS_LOG_SYMLINK; 1303 record->time = time; 1304 1305 record->error = Errno; 1306 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1307 if (fidp != NULL) { 1308 CACHEFS_FID_COPY(fidp, &record->fid); 1309 } 1310 record->fileno = fileno; 1311 record->uid = uid; 1312 record->size = size; 1313 1314 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1315 cachefs_xdr_symlink); 1316 } 1317 1318 static bool_t 1319 cachefs_xdr_symlink(XDR *xdrs, struct cachefs_log_symlink_record *rec) 1320 { 1321 if ((! xdr_int(xdrs, &rec->type)) || 1322 (! xdr_int(xdrs, &rec->error)) || 1323 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1324 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1325 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1326 (! xdr_ino64(xdrs, &rec->fileno)) || 1327 (! xdr_u_int(xdrs, &rec->uid)) || 1328 (! xdr_u_int(xdrs, &rec->size))) 1329 return (FALSE); 1330 1331 return (TRUE); 1332 } 1333 1334 void 1335 cachefs_log_populate(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1336 fid_t *fidp, ino64_t fileno, u_offset_t off, size_t popsize) 1337 { 1338 struct cachefs_log_populate_record *record; 1339 1340 /* In Solaris 64 - if can't represent time don't bother */ 1341 RET_IF_TIME_OVERFLOW(cachep, time) 1342 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1343 if (record == NULL) { 1344 cachefs_log_error(cachep, ENOMEM, 1); 1345 return; 1346 } 1347 1348 record->type = CACHEFS_LOG_POPULATE; 1349 record->time = time; 1350 record->error = Errno; 1351 1352 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1353 if (fidp != NULL) { 1354 CACHEFS_FID_COPY(fidp, &record->fid); 1355 } 1356 record->fileno = fileno; 1357 record->off = off; 1358 record->size = (int)popsize; 1359 1360 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1361 cachefs_xdr_populate); 1362 } 1363 1364 static bool_t 1365 cachefs_xdr_populate(XDR *xdrs, struct cachefs_log_populate_record *rec) 1366 { 1367 if ((! xdr_int(xdrs, &rec->type)) || 1368 (! xdr_int(xdrs, &rec->error)) || 1369 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1370 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1371 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1372 (! xdr_ino64(xdrs, &rec->fileno)) || 1373 (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->off)) || 1374 (! xdr_u_int(xdrs, &rec->size))) 1375 return (FALSE); 1376 1377 return (TRUE); 1378 } 1379 1380 void 1381 cachefs_log_csymlink(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1382 fid_t *fidp, ino64_t fileno, int size) 1383 { 1384 struct cachefs_log_csymlink_record *record; 1385 1386 /* In Solaris 64 - if can't represent time don't bother */ 1387 RET_IF_TIME_OVERFLOW(cachep, time) 1388 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1389 if (record == NULL) { 1390 cachefs_log_error(cachep, ENOMEM, 1); 1391 return; 1392 } 1393 1394 record->type = CACHEFS_LOG_CSYMLINK; 1395 record->time = time; 1396 record->error = Errno; 1397 1398 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1399 if (fidp != NULL) { 1400 CACHEFS_FID_COPY(fidp, &record->fid); 1401 } 1402 record->fileno = fileno; 1403 record->size = size; 1404 1405 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1406 cachefs_xdr_csymlink); 1407 } 1408 1409 static bool_t 1410 cachefs_xdr_csymlink(XDR *xdrs, struct cachefs_log_csymlink_record *rec) 1411 { 1412 if ((! xdr_int(xdrs, &rec->type)) || 1413 (! xdr_int(xdrs, &rec->error)) || 1414 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1415 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1416 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1417 (! xdr_ino64(xdrs, &rec->fileno)) || 1418 (! xdr_int(xdrs, &rec->size))) 1419 return (FALSE); 1420 1421 return (TRUE); 1422 } 1423 1424 void 1425 cachefs_log_filldir(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1426 fid_t *fidp, ino64_t fileno, u_offset_t size) 1427 { 1428 struct cachefs_log_filldir_record *record; 1429 1430 /* In Solaris 64 - if can't represent time don't bother */ 1431 RET_IF_TIME_OVERFLOW(cachep, time) 1432 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1433 if (record == NULL) { 1434 cachefs_log_error(cachep, ENOMEM, 1); 1435 return; 1436 } 1437 1438 record->type = CACHEFS_LOG_FILLDIR; 1439 record->time = time; 1440 record->error = Errno; 1441 1442 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1443 if (fidp != NULL) { 1444 CACHEFS_FID_COPY(fidp, &record->fid); 1445 } 1446 record->fileno = fileno; 1447 record->size = (uint_t)size; 1448 1449 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1450 cachefs_xdr_filldir); 1451 } 1452 1453 static bool_t 1454 cachefs_xdr_filldir(XDR *xdrs, struct cachefs_log_filldir_record *rec) 1455 { 1456 if ((! xdr_int(xdrs, &rec->type)) || 1457 (! xdr_int(xdrs, &rec->error)) || 1458 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1459 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1460 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1461 (! xdr_ino64(xdrs, &rec->fileno)) || 1462 (! xdr_u_int(xdrs, (uint_t *)&rec->size))) 1463 return (FALSE); 1464 1465 return (TRUE); 1466 } 1467 1468 void 1469 cachefs_log_mdcreate(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1470 fid_t *fidp, ino64_t fileno, uint_t count) 1471 { 1472 struct cachefs_log_mdcreate_record *record; 1473 1474 /* In Solaris 64 - if can't represent time don't bother */ 1475 RET_IF_TIME_OVERFLOW(cachep, time) 1476 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1477 if (record == NULL) { 1478 cachefs_log_error(cachep, ENOMEM, 1); 1479 return; 1480 } 1481 1482 record->type = CACHEFS_LOG_MDCREATE; 1483 record->time = time; 1484 record->error = Errno; 1485 1486 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1487 if (fidp != NULL) { 1488 CACHEFS_FID_COPY(fidp, &record->fid); 1489 } 1490 record->fileno = fileno; 1491 record->count = count; 1492 1493 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1494 cachefs_xdr_mdcreate); 1495 } 1496 1497 static bool_t 1498 cachefs_xdr_mdcreate(XDR *xdrs, struct cachefs_log_mdcreate_record *rec) 1499 { 1500 if ((! xdr_int(xdrs, &rec->type)) || 1501 (! xdr_int(xdrs, &rec->error)) || 1502 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1503 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1504 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1505 (! xdr_ino64(xdrs, &rec->fileno)) || 1506 (! xdr_u_int(xdrs, &rec->count))) 1507 return (FALSE); 1508 1509 return (TRUE); 1510 } 1511 1512 void 1513 cachefs_log_gpfront(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1514 fid_t *fidp, ino64_t fileno, uid_t uid, u_offset_t offset, uint_t len) 1515 { 1516 struct cachefs_log_gpfront_record *record; 1517 1518 /* In Solaris 64 - if can't represent time don't bother */ 1519 RET_IF_TIME_OVERFLOW(cachep, time) 1520 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1521 if (record == NULL) { 1522 cachefs_log_error(cachep, ENOMEM, 1); 1523 return; 1524 } 1525 1526 record->type = CACHEFS_LOG_GPFRONT; 1527 record->time = time; 1528 record->error = Errno; 1529 1530 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1531 if (fidp != NULL) { 1532 CACHEFS_FID_COPY(fidp, &record->fid); 1533 } 1534 record->fileno = fileno; 1535 record->uid = uid; 1536 record->off = offset; 1537 record->len = len; 1538 1539 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1540 cachefs_xdr_gpfront); 1541 } 1542 1543 static bool_t 1544 cachefs_xdr_gpfront(XDR *xdrs, struct cachefs_log_gpfront_record *rec) 1545 { 1546 if ((! xdr_int(xdrs, &rec->type)) || 1547 (! xdr_int(xdrs, &rec->error)) || 1548 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1549 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1550 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1551 (! xdr_ino64(xdrs, &rec->fileno)) || 1552 (! xdr_u_int(xdrs, &rec->uid)) || 1553 (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->off)) || 1554 (! xdr_u_int(xdrs, &rec->len))) 1555 return (FALSE); 1556 1557 return (TRUE); 1558 } 1559 1560 void 1561 cachefs_log_rfdir(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1562 fid_t *fidp, ino64_t fileno, uid_t uid) 1563 { 1564 struct cachefs_log_rfdir_record *record; 1565 1566 /* In Solaris 64 - if can't represent time don't bother */ 1567 RET_IF_TIME_OVERFLOW(cachep, time) 1568 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1569 if (record == NULL) { 1570 cachefs_log_error(cachep, ENOMEM, 1); 1571 return; 1572 } 1573 1574 record->type = CACHEFS_LOG_RFDIR; 1575 record->time = time; 1576 record->error = Errno; 1577 1578 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1579 if (fidp != NULL) { 1580 CACHEFS_FID_COPY(fidp, &record->fid); 1581 } 1582 record->fileno = fileno; 1583 record->uid = uid; 1584 1585 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1586 cachefs_xdr_rfdir); 1587 } 1588 1589 static bool_t 1590 cachefs_xdr_rfdir(XDR *xdrs, struct cachefs_log_rfdir_record *rec) 1591 { 1592 if ((! xdr_int(xdrs, &rec->type)) || 1593 (! xdr_int(xdrs, &rec->error)) || 1594 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1595 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1596 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1597 (! xdr_ino64(xdrs, &rec->fileno)) || 1598 (! xdr_u_int(xdrs, &rec->uid))) 1599 return (FALSE); 1600 1601 return (TRUE); 1602 } 1603 1604 void 1605 cachefs_log_ualloc(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1606 fid_t *fidp, ino64_t fileno, u_offset_t off, size_t len) 1607 { 1608 struct cachefs_log_ualloc_record *record; 1609 1610 /* In Solaris 64 - if can't represent time don't bother */ 1611 RET_IF_TIME_OVERFLOW(cachep, time) 1612 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1613 if (record == NULL) { 1614 cachefs_log_error(cachep, ENOMEM, 1); 1615 return; 1616 } 1617 1618 record->type = CACHEFS_LOG_UALLOC; 1619 record->time = time; 1620 record->error = Errno; 1621 1622 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1623 if (fidp != NULL) { 1624 CACHEFS_FID_COPY(fidp, &record->fid); 1625 } 1626 record->fileno = fileno; 1627 record->off = off; 1628 record->len = (uint_t)len; 1629 1630 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1631 cachefs_xdr_ualloc); 1632 } 1633 1634 static bool_t 1635 cachefs_xdr_ualloc(XDR *xdrs, struct cachefs_log_ualloc_record *rec) 1636 { 1637 if ((! xdr_int(xdrs, &rec->type)) || 1638 (! xdr_int(xdrs, &rec->error)) || 1639 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1640 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1641 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1642 (! xdr_ino64(xdrs, &rec->fileno)) || 1643 (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->off)) || 1644 (! xdr_u_int(xdrs, (uint_t *)&rec->len))) 1645 return (FALSE); 1646 1647 return (TRUE); 1648 } 1649 1650 void 1651 cachefs_log_calloc(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1652 fid_t *fidp, ino64_t fileno, u_offset_t off, size_t len) 1653 { 1654 struct cachefs_log_calloc_record *record; 1655 1656 /* In Solaris 64 - if can't represent time don't bother */ 1657 RET_IF_TIME_OVERFLOW(cachep, time) 1658 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1659 if (record == NULL) { 1660 cachefs_log_error(cachep, ENOMEM, 1); 1661 return; 1662 } 1663 1664 record->type = CACHEFS_LOG_CALLOC; 1665 record->time = time; 1666 record->error = Errno; 1667 1668 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1669 if (fidp != NULL) { 1670 CACHEFS_FID_COPY(fidp, &record->fid); 1671 } 1672 record->fileno = fileno; 1673 record->off = off; 1674 record->len = (uint_t)len; 1675 1676 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1677 cachefs_xdr_calloc); 1678 } 1679 1680 static bool_t 1681 cachefs_xdr_calloc(XDR *xdrs, struct cachefs_log_calloc_record *rec) 1682 { 1683 if ((! xdr_int(xdrs, &rec->type)) || 1684 (! xdr_int(xdrs, &rec->error)) || 1685 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1686 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1687 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1688 (! xdr_ino64(xdrs, &rec->fileno)) || 1689 (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->off)) || 1690 (! xdr_u_int(xdrs, &rec->len))) 1691 return (FALSE); 1692 1693 return (TRUE); 1694 } 1695 1696 void 1697 cachefs_log_nocache(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1698 fid_t *fidp, ino64_t fileno) 1699 { 1700 struct cachefs_log_nocache_record *record; 1701 1702 /* In Solaris 64 - if can't represent time don't bother */ 1703 RET_IF_TIME_OVERFLOW(cachep, time) 1704 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1705 if (record == NULL) { 1706 cachefs_log_error(cachep, ENOMEM, 1); 1707 return; 1708 } 1709 1710 record->type = CACHEFS_LOG_NOCACHE; 1711 record->time = time; 1712 record->error = Errno; 1713 1714 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1715 if (fidp != NULL) { 1716 CACHEFS_FID_COPY(fidp, &record->fid); 1717 } 1718 record->fileno = fileno; 1719 1720 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1721 cachefs_xdr_nocache); 1722 1723 } 1724 1725 static bool_t 1726 cachefs_xdr_nocache(XDR *xdrs, struct cachefs_log_nocache_record *rec) 1727 { 1728 if ((! xdr_int(xdrs, &rec->type)) || 1729 (! xdr_int(xdrs, &rec->error)) || 1730 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1731 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1732 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1733 (! xdr_ino64(xdrs, &rec->fileno))) 1734 return (FALSE); 1735 1736 return (TRUE); 1737 } 1738