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