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 explicitly 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, NULL, 202 0); 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, NULL, NULL, NULL)) != 0) && 251 ((error = VOP_CREATE(cachep->c_dirvp, LOG_STATUS_NAME, &attr, EXCL, 252 0600, &savevp, kcred, 0, NULL, NULL)) != 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 occurred. 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 occurred 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, NULL, 442 0); 443 444 if (getlock) 445 mutex_exit(&cachep->c_log_mutex); 446 } 447 448 static int 449 cachefs_log_write_header(struct vnode *vp, cachefscache_t *cachep, int error) 450 { 451 struct cachefs_log_logfile_header header, oheader; 452 char buffy[2 * sizeof (header)]; 453 int Errno = 0; 454 struct vattr attr; 455 int gotold = 0; 456 XDR xdrm; 457 458 attr.va_mask = AT_SIZE; 459 if ((error = VOP_GETATTR(vp, &attr, 0, kcred, NULL)) != 0) 460 goto out; 461 if (attr.va_size != 0) { 462 error = vn_rdwr(UIO_READ, vp, buffy, 463 MIN(sizeof (buffy), attr.va_size), 464 0LL, UIO_SYSSPACE, 0, (rlim64_t)RLIM_INFINITY, kcred, NULL); 465 if (error != 0) 466 goto out; 467 468 xdrm.x_ops = NULL; 469 xdrmem_create(&xdrm, buffy, sizeof (buffy), XDR_DECODE); 470 if ((xdrm.x_ops == NULL) || 471 (! cachefs_xdr_logfile_header(&xdrm, &oheader))) { 472 if (xdrm.x_ops != NULL) 473 xdr_destroy(&xdrm); 474 error = EINVAL; 475 goto out; 476 } 477 xdr_destroy(&xdrm); 478 gotold = 1; 479 480 if (oheader.lh_magic != CACHEFS_LOG_MAGIC) { 481 error = EINVAL; 482 goto out; 483 } 484 } 485 486 xdrm.x_ops = NULL; 487 488 xdrmem_create(&xdrm, buffy, sizeof (buffy), XDR_ENCODE); 489 490 if (gotold) { 491 header = oheader; 492 } else { 493 header.lh_magic = CACHEFS_LOG_MAGIC; 494 header.lh_revision = CACHEFS_LOG_FILE_REV; 495 header.lh_blocks = cachep->c_usage.cu_blksused; 496 header.lh_files = cachep->c_usage.cu_filesused; 497 header.lh_maxbsize = MAXBSIZE; 498 header.lh_pagesize = PAGESIZE; 499 } 500 501 /* these are things that we stomp over for every header write */ 502 header.lh_errno = Errno; 503 504 if (! cachefs_xdr_logfile_header(&xdrm, &header)) { 505 error = ENOMEM; 506 goto out; 507 } 508 509 error = vn_rdwr(UIO_WRITE, vp, 510 (caddr_t)buffy, xdr_getpos(&xdrm), 511 0LL, UIO_SYSSPACE, FSYNC, (rlim64_t)RLIM_INFINITY, kcred, NULL); 512 if (error) 513 goto out; 514 515 out: 516 if (xdrm.x_ops != NULL) 517 xdr_destroy(&xdrm); 518 return (error); 519 } 520 521 /* 522 * enqueues a record to be written to the logfile. 523 */ 524 525 static void 526 cachefs_log_enqueue(cachefscache_t *cachep, void *record, int size, 527 xdrproc_t translate) 528 { 529 cachefs_log_cookie_t *cl; 530 cachefs_log_work_list_t newnode, oldnode; 531 532 mutex_enter(&cachep->c_log_mutex); 533 cl = cachep->c_log; 534 535 if (cl == NULL) { /* someone turned off logging out from under us */ 536 mutex_exit(&cachep->c_log_mutex); 537 cachefs_kmem_free(record, size); 538 return; 539 } 540 ASSERT(cl->cl_magic == CACHEFS_LOG_MAGIC); 541 542 cl->cl_size += size; 543 newnode = cachefs_kmem_zalloc(sizeof (*newnode), KM_NOSLEEP); 544 if ((cl->cl_size > CACHEFS_LOG_MAX_BUFFERED) || (newnode == NULL)) { 545 cachefs_log_error(cachep, ENOMEM, 0); 546 if (newnode != NULL) 547 cachefs_kmem_free(newnode, sizeof (*newnode)); 548 cachefs_kmem_free(record, size); 549 mutex_exit(&cachep->c_log_mutex); 550 return; 551 } 552 553 newnode->data = record; 554 newnode->size = size; 555 newnode->translate = translate; 556 newnode->next = NULL; 557 558 oldnode = (cachefs_log_work_list_t)cl->cl_tail; 559 if (oldnode != NULL) 560 oldnode->next = newnode; 561 cl->cl_tail = newnode; 562 if (cl->cl_head == NULL) 563 cl->cl_head = newnode; 564 mutex_exit(&cachep->c_log_mutex); 565 566 if (cl->cl_size >= CACHEFS_LOG_LOWATER) { 567 mutex_enter(&cachep->c_workq.wq_queue_lock); 568 cachep->c_workq.wq_logwork = 1; 569 cv_signal(&cachep->c_workq.wq_req_cv); 570 mutex_exit(&cachep->c_workq.wq_queue_lock); 571 } 572 } 573 574 /* 575 * processes the log queue. run by an async worker thread, or via 576 * cachefs_cache_sync(). 577 */ 578 579 void 580 cachefs_log_process_queue(cachefscache_t *cachep, int getlock) 581 { 582 cachefs_log_cookie_t *cl; 583 cachefs_log_work_list_t work, workhead, oldwork; 584 struct vnode *logvp = NULL; 585 struct uio uio; 586 struct iovec iov; 587 int error = 0; 588 XDR xdrm; 589 char *buffy = NULL; 590 591 /* 592 * NULL out the x_ops field of XDR. this way, if x_ops != 593 * NULL, we know that we did the xdr*_create() successfully. 594 * this is documented in the xdr_create man page. 595 */ 596 597 xdrm.x_ops = NULL; 598 599 /* see if we're still logging */ 600 if (getlock) 601 mutex_enter(&cachep->c_log_mutex); 602 cl = cachep->c_log; 603 if ((cl == NULL) || (cl->cl_magic != CACHEFS_LOG_MAGIC)) { 604 if (getlock) 605 mutex_exit(&cachep->c_log_mutex); 606 return; 607 } 608 609 /* get the work, and let go of the mutex asap. */ 610 workhead = cl->cl_head; 611 cl->cl_head = cl->cl_tail = NULL; 612 cl->cl_size = 0; 613 logvp = cl->cl_logvp; 614 ASSERT(logvp != NULL); 615 if (logvp == NULL) { 616 if (getlock) 617 mutex_exit(&cachep->c_log_mutex); 618 return; 619 } 620 VN_HOLD(logvp); 621 if (getlock) 622 mutex_exit(&cachep->c_log_mutex); 623 624 /* we don't use vn_rdwr() because there's no way to set FNONBLOCK */ 625 626 uio.uio_iov = &iov; 627 uio.uio_iovcnt = 1; 628 uio.uio_loffset = 0; /* fake -- we do FAPPEND */ 629 uio.uio_segflg = (short)UIO_SYSSPACE; 630 uio.uio_llimit = MAXOFFSET_T; 631 uio.uio_fmode = FWRITE | FNONBLOCK; 632 uio.uio_extflg = UIO_COPY_CACHED; 633 634 buffy = cachefs_kmem_alloc(CACHEFS_LOG_ENCODE_SIZE, KM_SLEEP); 635 xdrmem_create(&xdrm, buffy, CACHEFS_LOG_ENCODE_SIZE, XDR_ENCODE); 636 637 (void) VOP_RWLOCK(logvp, V_WRITELOCK_TRUE, NULL); 638 for (work = workhead; work != NULL; work = work->next) { 639 if (! (work->translate)(&xdrm, work->data)) { 640 VOP_RWUNLOCK(logvp, V_WRITELOCK_TRUE, NULL); 641 error = ENOMEM; 642 goto out; 643 } 644 645 iov.iov_base = buffy; 646 iov.iov_len = uio.uio_resid = xdr_getpos(&xdrm); 647 (void) xdr_setpos(&xdrm, 0); 648 649 error = VOP_WRITE(logvp, &uio, FAPPEND, kcred, NULL); 650 651 /* XXX future -- check for EAGAIN */ 652 653 if ((error) || (uio.uio_resid)) { 654 if (uio.uio_resid != 0) 655 error = EIO; 656 VOP_RWUNLOCK(logvp, V_WRITELOCK_TRUE, NULL); 657 goto out; 658 } 659 } 660 VOP_RWUNLOCK(logvp, V_WRITELOCK_TRUE, NULL); 661 662 out: 663 if (xdrm.x_ops != NULL) 664 xdr_destroy(&xdrm); 665 if (buffy != NULL) 666 cachefs_kmem_free(buffy, CACHEFS_LOG_ENCODE_SIZE); 667 668 /* 669 * if an error occurred, we need to free the buffers ourselves. 670 * cachefs_destory_cookie() can't do it. 671 */ 672 673 work = workhead; 674 while (work != NULL) { 675 cachefs_kmem_free(work->data, work->size); 676 oldwork = work; 677 work = work->next; 678 cachefs_kmem_free(oldwork, sizeof (*oldwork)); 679 } 680 if (logvp != NULL) 681 VN_RELE(logvp); 682 if (error) { 683 cachefs_log_error(cachep, error, 1); 684 return; 685 } 686 } 687 688 static bool_t 689 cachefs_xdr_logfile_header(XDR *xdrs, struct cachefs_log_logfile_header *h) 690 { 691 if ((! xdr_u_int(xdrs, &h->lh_magic)) || 692 (! xdr_u_int(xdrs, &h->lh_revision)) || 693 (! xdr_int(xdrs, &h->lh_errno)) || 694 (! xdr_u_int(xdrs, &h->lh_blocks)) || 695 (! xdr_u_int(xdrs, &h->lh_files)) || 696 (! xdr_u_int(xdrs, &h->lh_maxbsize)) || 697 (! xdr_u_int(xdrs, &h->lh_pagesize))) 698 return (FALSE); 699 700 return (TRUE); 701 } 702 703 /* 704 * the routines for logging each transaction follow... 705 */ 706 707 void 708 cachefs_log_mount(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 709 fscache_t *fscp, char *upath, enum uio_seg seg, char *cacheid) 710 { 711 struct cachefs_log_mount_record *record; 712 char *cacheidt; 713 char *path = NULL; 714 size_t len; 715 int len1, len2; 716 int size, error; 717 718 /* In Solaris 64 - if can't represent time don't bother */ 719 OUT_IF_TIME_OVERFLOW(cachep, time) 720 if (seg == UIO_USERSPACE) { 721 path = cachefs_kmem_alloc(MAXPATHLEN, KM_NOSLEEP); 722 if (path == NULL) { 723 cachefs_log_error(cachep, ENOMEM, 1); 724 goto out; 725 } 726 if ((error = copyinstr(upath, path, MAXPATHLEN, &len)) != 0) { 727 cachefs_log_error(cachep, error, 1); 728 goto out; 729 } 730 } else { 731 path = upath; 732 } 733 734 len1 = (path != NULL) ? strlen(path) : 0; 735 len2 = (cacheid != NULL) ? strlen(cacheid) : 0; 736 size = (int)sizeof (*record) + len1 + len2 - 737 (int)CLPAD(cachefs_log_mount_record, path); 738 record = cachefs_kmem_zalloc(size, KM_NOSLEEP); 739 if (record == NULL) { 740 cachefs_log_error(cachep, ENOMEM, 1); 741 goto out; 742 } 743 744 record->type = CACHEFS_LOG_MOUNT; 745 record->time = time; 746 747 record->error = Errno; 748 record->vfsp = (uint64_t)(uintptr_t)vfsp; 749 750 if (fscp) { 751 record->flags = fscp->fs_info.fi_mntflags; 752 record->popsize = fscp->fs_info.fi_popsize; 753 record->fgsize = fscp->fs_info.fi_fgsize; 754 } 755 756 record->pathlen = (ushort_t)len1; 757 record->cacheidlen = (ushort_t)len2; 758 if (path != NULL) 759 (void) strcpy(record->path, path); 760 cacheidt = record->path + len1 + 1; 761 if (cacheid != NULL) 762 (void) strcpy(cacheidt, cacheid); 763 764 cachefs_log_enqueue(cachep, record, size, cachefs_xdr_mount); 765 766 out: 767 if ((seg == UIO_USERSPACE) && (path != NULL)) 768 cachefs_kmem_free(path, MAXPATHLEN); 769 } 770 771 static bool_t 772 cachefs_xdr_mount(XDR *xdrs, struct cachefs_log_mount_record *rec) 773 { 774 char *path = rec->path; 775 char *cacheid; 776 777 cacheid = path + strlen(path) + 1; 778 779 if ((! xdr_int(xdrs, &rec->type)) || 780 (! xdr_int(xdrs, &rec->error)) || 781 (! xdr_cfs_time_t(xdrs, &rec->time)) || 782 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 783 (! xdr_u_int(xdrs, &rec->flags)) || 784 (! xdr_u_int(xdrs, &rec->popsize)) || 785 (! xdr_u_int(xdrs, &rec->fgsize)) || 786 (! xdr_u_short(xdrs, &rec->pathlen)) || 787 (! xdr_u_short(xdrs, &rec->cacheidlen)) || 788 (! xdr_wrapstring(xdrs, &path)) || 789 (! xdr_wrapstring(xdrs, &cacheid))) 790 return (FALSE); 791 792 return (TRUE); 793 } 794 795 void 796 cachefs_log_umount(cachefscache_t *cachep, int Errno, struct vfs *vfsp) 797 { 798 struct cachefs_log_umount_record *record; 799 800 /* In Solaris 64 - if can't represent time don't bother */ 801 RET_IF_TIME_OVERFLOW(cachep, time) 802 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 803 if (record == NULL) { 804 cachefs_log_error(cachep, ENOMEM, 1); 805 return; 806 } 807 808 record->type = CACHEFS_LOG_UMOUNT; 809 record->time = time; 810 811 record->error = Errno; 812 record->vfsp = (uint64_t)(uintptr_t)vfsp; 813 814 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 815 cachefs_xdr_umount); 816 } 817 818 static bool_t 819 cachefs_xdr_umount(XDR *xdrs, struct cachefs_log_umount_record *rec) 820 { 821 if ((! xdr_int(xdrs, &rec->type)) || 822 (! xdr_int(xdrs, &rec->error)) || 823 (! xdr_cfs_time_t(xdrs, &rec->time)) || 824 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp)))) 825 return (FALSE); 826 827 return (TRUE); 828 } 829 830 void 831 cachefs_log_getpage(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 832 fid_t *fidp, ino64_t fileno, uid_t uid, u_offset_t offset, size_t len) 833 { 834 struct cachefs_log_getpage_record *record; 835 836 /* In Solaris 64 - if can't represent time don't bother */ 837 RET_IF_TIME_OVERFLOW(cachep, time) 838 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 839 if (record == NULL) { 840 cachefs_log_error(cachep, ENOMEM, 1); 841 return; 842 } 843 844 record->type = CACHEFS_LOG_GETPAGE; 845 record->time = time; 846 847 record->error = Errno; 848 record->vfsp = (uint64_t)(uintptr_t)vfsp; 849 if (fidp != NULL) { 850 CACHEFS_FID_COPY(fidp, &record->fid); 851 } 852 record->fileno = fileno; 853 record->uid = uid; 854 record->offset = offset; 855 record->len = (uint_t)len; 856 857 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 858 cachefs_xdr_getpage); 859 } 860 861 static bool_t 862 cachefs_xdr_getpage(XDR *xdrs, struct cachefs_log_getpage_record *rec) 863 { 864 if ((! xdr_int(xdrs, &rec->type)) || 865 (! xdr_int(xdrs, &rec->error)) || 866 (! xdr_cfs_time_t(xdrs, &rec->time)) || 867 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 868 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 869 (! xdr_ino64(xdrs, &rec->fileno)) || 870 (! xdr_u_int(xdrs, &rec->uid)) || 871 (! xdr_u_longlong_t(xdrs, &rec->offset)) || 872 (! xdr_u_int(xdrs, &rec->len))) 873 return (FALSE); 874 875 return (TRUE); 876 } 877 878 void 879 cachefs_log_readdir(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 880 fid_t *fidp, ino64_t fileno, uid_t uid, u_offset_t offset, int eof) 881 { 882 struct cachefs_log_readdir_record *record; 883 884 /* In Solaris 64 - if can't represent time don't bother */ 885 RET_IF_TIME_OVERFLOW(cachep, time) 886 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 887 if (record == NULL) { 888 cachefs_log_error(cachep, ENOMEM, 1); 889 return; 890 } 891 892 record->type = CACHEFS_LOG_READDIR; 893 record->time = time; 894 895 record->error = Errno; 896 record->vfsp = (uint64_t)(uintptr_t)vfsp; 897 if (fidp != NULL) { 898 CACHEFS_FID_COPY(fidp, &record->fid); 899 } 900 record->fileno = fileno; 901 record->uid = uid; 902 record->offset = offset; 903 record->eof = eof; 904 905 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 906 cachefs_xdr_readdir); 907 } 908 909 static bool_t 910 cachefs_xdr_readdir(XDR *xdrs, struct cachefs_log_readdir_record *rec) 911 { 912 if ((! xdr_int(xdrs, &rec->type)) || 913 (! xdr_int(xdrs, &rec->error)) || 914 (! xdr_cfs_time_t(xdrs, &rec->time)) || 915 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 916 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 917 (! xdr_ino64(xdrs, &rec->fileno)) || 918 (! xdr_u_int(xdrs, &rec->uid)) || 919 (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->offset)) || 920 (! xdr_int(xdrs, &rec->eof))) 921 return (FALSE); 922 923 return (TRUE); 924 } 925 926 void 927 cachefs_log_readlink(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 928 fid_t *fidp, ino64_t fileno, uid_t uid, size_t length) 929 { 930 struct cachefs_log_readlink_record *record; 931 932 /* In Solaris 64 - if can't represent time don't bother */ 933 RET_IF_TIME_OVERFLOW(cachep, time) 934 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 935 if (record == NULL) { 936 cachefs_log_error(cachep, ENOMEM, 1); 937 return; 938 } 939 940 record->type = CACHEFS_LOG_READLINK; 941 record->time = time; 942 943 record->error = Errno; 944 record->vfsp = (uint64_t)(uintptr_t)vfsp; 945 if (fidp != NULL) { 946 CACHEFS_FID_COPY(fidp, &record->fid); 947 } 948 record->fileno = fileno; 949 record->uid = uid; 950 record->length = (uint_t)length; 951 952 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 953 cachefs_xdr_readlink); 954 } 955 956 static bool_t 957 cachefs_xdr_readlink(XDR *xdrs, struct cachefs_log_readlink_record *rec) 958 { 959 if ((! xdr_int(xdrs, &rec->type)) || 960 (! xdr_int(xdrs, &rec->error)) || 961 (! xdr_cfs_time_t(xdrs, &rec->time)) || 962 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 963 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 964 (! xdr_ino64(xdrs, &rec->fileno)) || 965 (! xdr_u_int(xdrs, &rec->uid)) || 966 (! xdr_u_int(xdrs, &rec->length))) 967 return (FALSE); 968 969 return (TRUE); 970 } 971 972 void 973 cachefs_log_remove(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 974 fid_t *fidp, ino64_t fileno, uid_t uid) 975 { 976 struct cachefs_log_remove_record *record; 977 978 /* In Solaris 64 - if can't represent time don't bother */ 979 RET_IF_TIME_OVERFLOW(cachep, time) 980 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 981 if (record == NULL) { 982 cachefs_log_error(cachep, ENOMEM, 1); 983 return; 984 } 985 986 record->type = CACHEFS_LOG_REMOVE; 987 record->time = time; 988 989 record->error = Errno; 990 record->vfsp = (uint64_t)(uintptr_t)vfsp; 991 if (fidp != NULL) { 992 CACHEFS_FID_COPY(fidp, &record->fid); 993 } 994 record->fileno = fileno; 995 record->uid = uid; 996 997 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 998 cachefs_xdr_remove); 999 } 1000 1001 static bool_t 1002 cachefs_xdr_remove(XDR *xdrs, struct cachefs_log_remove_record *rec) 1003 { 1004 if ((! xdr_int(xdrs, &rec->type)) || 1005 (! xdr_int(xdrs, &rec->error)) || 1006 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1007 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1008 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1009 (! xdr_ino64(xdrs, &rec->fileno)) || 1010 (! xdr_u_int(xdrs, &rec->uid))) 1011 return (FALSE); 1012 1013 return (TRUE); 1014 } 1015 1016 void 1017 cachefs_log_rmdir(cachefscache_t *cachep, int Errno, 1018 struct vfs *vfsp, fid_t *fidp, ino64_t fileno, uid_t uid) 1019 { 1020 struct cachefs_log_rmdir_record *record; 1021 1022 /* In Solaris 64 - if can't represent time don't bother */ 1023 RET_IF_TIME_OVERFLOW(cachep, time) 1024 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1025 if (record == NULL) { 1026 cachefs_log_error(cachep, ENOMEM, 1); 1027 return; 1028 } 1029 1030 record->type = CACHEFS_LOG_RMDIR; 1031 record->time = time; 1032 1033 record->error = Errno; 1034 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1035 if (fidp != NULL) { 1036 CACHEFS_FID_COPY(fidp, &record->fid); 1037 } 1038 record->fileno = fileno; 1039 record->uid = uid; 1040 1041 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1042 cachefs_xdr_rmdir); 1043 } 1044 1045 static bool_t 1046 cachefs_xdr_rmdir(XDR *xdrs, struct cachefs_log_rmdir_record *rec) 1047 { 1048 if ((! xdr_int(xdrs, &rec->type)) || 1049 (! xdr_int(xdrs, &rec->error)) || 1050 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1051 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1052 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1053 (! xdr_ino64(xdrs, &rec->fileno)) || 1054 (! xdr_u_int(xdrs, &rec->uid))) 1055 return (FALSE); 1056 1057 return (TRUE); 1058 } 1059 1060 void 1061 cachefs_log_truncate(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1062 fid_t *fidp, ino64_t fileno, uid_t uid, u_offset_t size) 1063 { 1064 struct cachefs_log_truncate_record *record; 1065 1066 /* In Solaris 64 - if can't represent time don't bother */ 1067 RET_IF_TIME_OVERFLOW(cachep, time) 1068 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1069 if (record == NULL) { 1070 cachefs_log_error(cachep, ENOMEM, 1); 1071 return; 1072 } 1073 1074 record->type = CACHEFS_LOG_TRUNCATE; 1075 record->time = time; 1076 1077 record->error = Errno; 1078 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1079 if (fidp != NULL) { 1080 CACHEFS_FID_COPY(fidp, &record->fid); 1081 } 1082 record->fileno = fileno; 1083 record->uid = uid; 1084 record->size = size; 1085 1086 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1087 cachefs_xdr_truncate); 1088 } 1089 1090 static bool_t 1091 cachefs_xdr_truncate(XDR *xdrs, struct cachefs_log_truncate_record *rec) 1092 { 1093 if ((! xdr_int(xdrs, &rec->type)) || 1094 (! xdr_int(xdrs, &rec->error)) || 1095 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1096 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1097 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1098 (! xdr_ino64(xdrs, &rec->fileno)) || 1099 (! xdr_u_int(xdrs, &rec->uid)) || 1100 (! xdr_u_longlong_t(xdrs, &rec->size))) 1101 return (FALSE); 1102 1103 return (TRUE); 1104 } 1105 1106 void 1107 cachefs_log_putpage(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1108 fid_t *fidp, ino64_t fileno, uid_t uid, u_offset_t offset, size_t len) 1109 { 1110 struct cachefs_log_putpage_record *record; 1111 1112 /* In Solaris 64 - if can't represent time don't bother */ 1113 RET_IF_TIME_OVERFLOW(cachep, time) 1114 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1115 if (record == NULL) { 1116 cachefs_log_error(cachep, ENOMEM, 1); 1117 return; 1118 } 1119 1120 record->type = CACHEFS_LOG_PUTPAGE; 1121 record->time = time; 1122 1123 record->error = Errno; 1124 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1125 if (fidp != NULL) { 1126 CACHEFS_FID_COPY(fidp, &record->fid); 1127 } 1128 record->fileno = fileno; 1129 record->uid = uid; 1130 record->offset = offset; 1131 record->len = (uint_t)len; 1132 1133 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1134 cachefs_xdr_putpage); 1135 } 1136 1137 static bool_t 1138 cachefs_xdr_putpage(XDR *xdrs, struct cachefs_log_putpage_record *rec) 1139 { 1140 if ((! xdr_int(xdrs, &rec->type)) || 1141 (! xdr_int(xdrs, &rec->error)) || 1142 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1143 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1144 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1145 (! xdr_ino64(xdrs, &rec->fileno)) || 1146 (! xdr_u_int(xdrs, &rec->uid)) || 1147 (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->offset)) || 1148 (! xdr_u_int(xdrs, &rec->len))) 1149 return (FALSE); 1150 1151 return (TRUE); 1152 } 1153 1154 void 1155 cachefs_log_create(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1156 fid_t *filefidp, ino64_t fileno, uid_t uid) 1157 { 1158 struct cachefs_log_create_record *record; 1159 1160 /* In Solaris 64 - if can't represent time don't bother */ 1161 RET_IF_TIME_OVERFLOW(cachep, time) 1162 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1163 if (record == NULL) { 1164 cachefs_log_error(cachep, ENOMEM, 1); 1165 return; 1166 } 1167 1168 record->type = CACHEFS_LOG_CREATE; 1169 record->time = time; 1170 1171 record->error = Errno; 1172 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1173 if (filefidp != NULL) { 1174 CACHEFS_FID_COPY(filefidp, &record->fid); 1175 } 1176 record->fileno = fileno; 1177 record->uid = uid; 1178 1179 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1180 cachefs_xdr_create); 1181 } 1182 1183 static bool_t 1184 cachefs_xdr_create(XDR *xdrs, struct cachefs_log_create_record *rec) 1185 { 1186 if ((! xdr_int(xdrs, &rec->type)) || 1187 (! xdr_int(xdrs, &rec->error)) || 1188 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1189 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1190 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1191 (! xdr_ino64(xdrs, &rec->fileno)) || 1192 (! xdr_u_int(xdrs, &rec->uid))) 1193 return (FALSE); 1194 1195 return (TRUE); 1196 } 1197 1198 void 1199 cachefs_log_mkdir(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1200 fid_t *cfidp, ino64_t fileno, uid_t uid) 1201 { 1202 struct cachefs_log_mkdir_record *record; 1203 int size; 1204 1205 /* In Solaris 64 - if can't represent time don't bother */ 1206 RET_IF_TIME_OVERFLOW(cachep, time) 1207 size = (int)sizeof (*record); 1208 record = cachefs_kmem_zalloc(size, KM_NOSLEEP); 1209 if (record == NULL) { 1210 cachefs_log_error(cachep, ENOMEM, 1); 1211 return; 1212 } 1213 1214 record->type = CACHEFS_LOG_MKDIR; 1215 record->time = time; 1216 1217 record->error = Errno; 1218 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1219 if (cfidp != NULL) { 1220 CACHEFS_FID_COPY(cfidp, &record->fid); 1221 } 1222 record->fileno = fileno; 1223 record->uid = uid; 1224 1225 cachefs_log_enqueue(cachep, record, size, 1226 cachefs_xdr_mkdir); 1227 } 1228 1229 static bool_t 1230 cachefs_xdr_mkdir(XDR *xdrs, struct cachefs_log_mkdir_record *rec) 1231 { 1232 if ((! xdr_int(xdrs, &rec->type)) || 1233 (! xdr_int(xdrs, &rec->error)) || 1234 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1235 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1236 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1237 (! xdr_ino64(xdrs, &rec->fileno)) || 1238 (! xdr_u_int(xdrs, &rec->uid))) 1239 return (FALSE); 1240 1241 return (TRUE); 1242 } 1243 1244 void 1245 cachefs_log_rename(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1246 fid_t *gfp, ino64_t fileno, int removed, uid_t uid) 1247 { 1248 struct cachefs_log_rename_record *record; 1249 1250 /* In Solaris 64 - if can't represent time don't bother */ 1251 RET_IF_TIME_OVERFLOW(cachep, time) 1252 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1253 if (record == NULL) { 1254 cachefs_log_error(cachep, ENOMEM, 1); 1255 return; 1256 } 1257 1258 record->type = CACHEFS_LOG_RENAME; 1259 record->time = time; 1260 1261 record->error = Errno; 1262 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1263 if (gfp != NULL) { 1264 CACHEFS_FID_COPY(gfp, &record->gone); 1265 } 1266 record->fileno = fileno; 1267 record->removed = removed; 1268 record->uid = uid; 1269 1270 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1271 cachefs_xdr_rename); 1272 } 1273 1274 static bool_t 1275 cachefs_xdr_rename(XDR *xdrs, struct cachefs_log_rename_record *rec) 1276 { 1277 if ((! xdr_int(xdrs, &rec->type)) || 1278 (! xdr_int(xdrs, &rec->error)) || 1279 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1280 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1281 (! xdr_opaque(xdrs, (caddr_t)&rec->gone, sizeof (rec->gone))) || 1282 (! xdr_int(xdrs, &rec->removed)) || 1283 (! xdr_u_int(xdrs, &rec->uid))) 1284 return (FALSE); 1285 1286 return (TRUE); 1287 } 1288 1289 1290 void 1291 cachefs_log_symlink(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1292 fid_t *fidp, ino64_t fileno, uid_t uid, int size) 1293 { 1294 struct cachefs_log_symlink_record *record; 1295 1296 /* In Solaris 64 - if can't represent time don't bother */ 1297 RET_IF_TIME_OVERFLOW(cachep, time) 1298 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1299 if (record == NULL) { 1300 cachefs_log_error(cachep, ENOMEM, 1); 1301 return; 1302 } 1303 1304 record->type = CACHEFS_LOG_SYMLINK; 1305 record->time = time; 1306 1307 record->error = Errno; 1308 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1309 if (fidp != NULL) { 1310 CACHEFS_FID_COPY(fidp, &record->fid); 1311 } 1312 record->fileno = fileno; 1313 record->uid = uid; 1314 record->size = size; 1315 1316 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1317 cachefs_xdr_symlink); 1318 } 1319 1320 static bool_t 1321 cachefs_xdr_symlink(XDR *xdrs, struct cachefs_log_symlink_record *rec) 1322 { 1323 if ((! xdr_int(xdrs, &rec->type)) || 1324 (! xdr_int(xdrs, &rec->error)) || 1325 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1326 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1327 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1328 (! xdr_ino64(xdrs, &rec->fileno)) || 1329 (! xdr_u_int(xdrs, &rec->uid)) || 1330 (! xdr_u_int(xdrs, &rec->size))) 1331 return (FALSE); 1332 1333 return (TRUE); 1334 } 1335 1336 void 1337 cachefs_log_populate(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1338 fid_t *fidp, ino64_t fileno, u_offset_t off, size_t popsize) 1339 { 1340 struct cachefs_log_populate_record *record; 1341 1342 /* In Solaris 64 - if can't represent time don't bother */ 1343 RET_IF_TIME_OVERFLOW(cachep, time) 1344 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1345 if (record == NULL) { 1346 cachefs_log_error(cachep, ENOMEM, 1); 1347 return; 1348 } 1349 1350 record->type = CACHEFS_LOG_POPULATE; 1351 record->time = time; 1352 record->error = Errno; 1353 1354 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1355 if (fidp != NULL) { 1356 CACHEFS_FID_COPY(fidp, &record->fid); 1357 } 1358 record->fileno = fileno; 1359 record->off = off; 1360 record->size = (int)popsize; 1361 1362 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1363 cachefs_xdr_populate); 1364 } 1365 1366 static bool_t 1367 cachefs_xdr_populate(XDR *xdrs, struct cachefs_log_populate_record *rec) 1368 { 1369 if ((! xdr_int(xdrs, &rec->type)) || 1370 (! xdr_int(xdrs, &rec->error)) || 1371 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1372 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1373 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1374 (! xdr_ino64(xdrs, &rec->fileno)) || 1375 (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->off)) || 1376 (! xdr_u_int(xdrs, &rec->size))) 1377 return (FALSE); 1378 1379 return (TRUE); 1380 } 1381 1382 void 1383 cachefs_log_csymlink(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1384 fid_t *fidp, ino64_t fileno, int size) 1385 { 1386 struct cachefs_log_csymlink_record *record; 1387 1388 /* In Solaris 64 - if can't represent time don't bother */ 1389 RET_IF_TIME_OVERFLOW(cachep, time) 1390 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1391 if (record == NULL) { 1392 cachefs_log_error(cachep, ENOMEM, 1); 1393 return; 1394 } 1395 1396 record->type = CACHEFS_LOG_CSYMLINK; 1397 record->time = time; 1398 record->error = Errno; 1399 1400 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1401 if (fidp != NULL) { 1402 CACHEFS_FID_COPY(fidp, &record->fid); 1403 } 1404 record->fileno = fileno; 1405 record->size = size; 1406 1407 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1408 cachefs_xdr_csymlink); 1409 } 1410 1411 static bool_t 1412 cachefs_xdr_csymlink(XDR *xdrs, struct cachefs_log_csymlink_record *rec) 1413 { 1414 if ((! xdr_int(xdrs, &rec->type)) || 1415 (! xdr_int(xdrs, &rec->error)) || 1416 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1417 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1418 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1419 (! xdr_ino64(xdrs, &rec->fileno)) || 1420 (! xdr_int(xdrs, &rec->size))) 1421 return (FALSE); 1422 1423 return (TRUE); 1424 } 1425 1426 void 1427 cachefs_log_filldir(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1428 fid_t *fidp, ino64_t fileno, u_offset_t size) 1429 { 1430 struct cachefs_log_filldir_record *record; 1431 1432 /* In Solaris 64 - if can't represent time don't bother */ 1433 RET_IF_TIME_OVERFLOW(cachep, time) 1434 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1435 if (record == NULL) { 1436 cachefs_log_error(cachep, ENOMEM, 1); 1437 return; 1438 } 1439 1440 record->type = CACHEFS_LOG_FILLDIR; 1441 record->time = time; 1442 record->error = Errno; 1443 1444 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1445 if (fidp != NULL) { 1446 CACHEFS_FID_COPY(fidp, &record->fid); 1447 } 1448 record->fileno = fileno; 1449 record->size = (uint_t)size; 1450 1451 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1452 cachefs_xdr_filldir); 1453 } 1454 1455 static bool_t 1456 cachefs_xdr_filldir(XDR *xdrs, struct cachefs_log_filldir_record *rec) 1457 { 1458 if ((! xdr_int(xdrs, &rec->type)) || 1459 (! xdr_int(xdrs, &rec->error)) || 1460 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1461 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1462 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1463 (! xdr_ino64(xdrs, &rec->fileno)) || 1464 (! xdr_u_int(xdrs, (uint_t *)&rec->size))) 1465 return (FALSE); 1466 1467 return (TRUE); 1468 } 1469 1470 void 1471 cachefs_log_mdcreate(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1472 fid_t *fidp, ino64_t fileno, uint_t count) 1473 { 1474 struct cachefs_log_mdcreate_record *record; 1475 1476 /* In Solaris 64 - if can't represent time don't bother */ 1477 RET_IF_TIME_OVERFLOW(cachep, time) 1478 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1479 if (record == NULL) { 1480 cachefs_log_error(cachep, ENOMEM, 1); 1481 return; 1482 } 1483 1484 record->type = CACHEFS_LOG_MDCREATE; 1485 record->time = time; 1486 record->error = Errno; 1487 1488 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1489 if (fidp != NULL) { 1490 CACHEFS_FID_COPY(fidp, &record->fid); 1491 } 1492 record->fileno = fileno; 1493 record->count = count; 1494 1495 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1496 cachefs_xdr_mdcreate); 1497 } 1498 1499 static bool_t 1500 cachefs_xdr_mdcreate(XDR *xdrs, struct cachefs_log_mdcreate_record *rec) 1501 { 1502 if ((! xdr_int(xdrs, &rec->type)) || 1503 (! xdr_int(xdrs, &rec->error)) || 1504 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1505 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1506 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1507 (! xdr_ino64(xdrs, &rec->fileno)) || 1508 (! xdr_u_int(xdrs, &rec->count))) 1509 return (FALSE); 1510 1511 return (TRUE); 1512 } 1513 1514 void 1515 cachefs_log_gpfront(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1516 fid_t *fidp, ino64_t fileno, uid_t uid, u_offset_t offset, uint_t len) 1517 { 1518 struct cachefs_log_gpfront_record *record; 1519 1520 /* In Solaris 64 - if can't represent time don't bother */ 1521 RET_IF_TIME_OVERFLOW(cachep, time) 1522 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1523 if (record == NULL) { 1524 cachefs_log_error(cachep, ENOMEM, 1); 1525 return; 1526 } 1527 1528 record->type = CACHEFS_LOG_GPFRONT; 1529 record->time = time; 1530 record->error = Errno; 1531 1532 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1533 if (fidp != NULL) { 1534 CACHEFS_FID_COPY(fidp, &record->fid); 1535 } 1536 record->fileno = fileno; 1537 record->uid = uid; 1538 record->off = offset; 1539 record->len = len; 1540 1541 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1542 cachefs_xdr_gpfront); 1543 } 1544 1545 static bool_t 1546 cachefs_xdr_gpfront(XDR *xdrs, struct cachefs_log_gpfront_record *rec) 1547 { 1548 if ((! xdr_int(xdrs, &rec->type)) || 1549 (! xdr_int(xdrs, &rec->error)) || 1550 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1551 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1552 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1553 (! xdr_ino64(xdrs, &rec->fileno)) || 1554 (! xdr_u_int(xdrs, &rec->uid)) || 1555 (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->off)) || 1556 (! xdr_u_int(xdrs, &rec->len))) 1557 return (FALSE); 1558 1559 return (TRUE); 1560 } 1561 1562 void 1563 cachefs_log_rfdir(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1564 fid_t *fidp, ino64_t fileno, uid_t uid) 1565 { 1566 struct cachefs_log_rfdir_record *record; 1567 1568 /* In Solaris 64 - if can't represent time don't bother */ 1569 RET_IF_TIME_OVERFLOW(cachep, time) 1570 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1571 if (record == NULL) { 1572 cachefs_log_error(cachep, ENOMEM, 1); 1573 return; 1574 } 1575 1576 record->type = CACHEFS_LOG_RFDIR; 1577 record->time = time; 1578 record->error = Errno; 1579 1580 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1581 if (fidp != NULL) { 1582 CACHEFS_FID_COPY(fidp, &record->fid); 1583 } 1584 record->fileno = fileno; 1585 record->uid = uid; 1586 1587 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1588 cachefs_xdr_rfdir); 1589 } 1590 1591 static bool_t 1592 cachefs_xdr_rfdir(XDR *xdrs, struct cachefs_log_rfdir_record *rec) 1593 { 1594 if ((! xdr_int(xdrs, &rec->type)) || 1595 (! xdr_int(xdrs, &rec->error)) || 1596 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1597 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1598 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1599 (! xdr_ino64(xdrs, &rec->fileno)) || 1600 (! xdr_u_int(xdrs, &rec->uid))) 1601 return (FALSE); 1602 1603 return (TRUE); 1604 } 1605 1606 void 1607 cachefs_log_ualloc(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1608 fid_t *fidp, ino64_t fileno, u_offset_t off, size_t len) 1609 { 1610 struct cachefs_log_ualloc_record *record; 1611 1612 /* In Solaris 64 - if can't represent time don't bother */ 1613 RET_IF_TIME_OVERFLOW(cachep, time) 1614 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1615 if (record == NULL) { 1616 cachefs_log_error(cachep, ENOMEM, 1); 1617 return; 1618 } 1619 1620 record->type = CACHEFS_LOG_UALLOC; 1621 record->time = time; 1622 record->error = Errno; 1623 1624 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1625 if (fidp != NULL) { 1626 CACHEFS_FID_COPY(fidp, &record->fid); 1627 } 1628 record->fileno = fileno; 1629 record->off = off; 1630 record->len = (uint_t)len; 1631 1632 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1633 cachefs_xdr_ualloc); 1634 } 1635 1636 static bool_t 1637 cachefs_xdr_ualloc(XDR *xdrs, struct cachefs_log_ualloc_record *rec) 1638 { 1639 if ((! xdr_int(xdrs, &rec->type)) || 1640 (! xdr_int(xdrs, &rec->error)) || 1641 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1642 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1643 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1644 (! xdr_ino64(xdrs, &rec->fileno)) || 1645 (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->off)) || 1646 (! xdr_u_int(xdrs, (uint_t *)&rec->len))) 1647 return (FALSE); 1648 1649 return (TRUE); 1650 } 1651 1652 void 1653 cachefs_log_calloc(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1654 fid_t *fidp, ino64_t fileno, u_offset_t off, size_t len) 1655 { 1656 struct cachefs_log_calloc_record *record; 1657 1658 /* In Solaris 64 - if can't represent time don't bother */ 1659 RET_IF_TIME_OVERFLOW(cachep, time) 1660 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1661 if (record == NULL) { 1662 cachefs_log_error(cachep, ENOMEM, 1); 1663 return; 1664 } 1665 1666 record->type = CACHEFS_LOG_CALLOC; 1667 record->time = time; 1668 record->error = Errno; 1669 1670 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1671 if (fidp != NULL) { 1672 CACHEFS_FID_COPY(fidp, &record->fid); 1673 } 1674 record->fileno = fileno; 1675 record->off = off; 1676 record->len = (uint_t)len; 1677 1678 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1679 cachefs_xdr_calloc); 1680 } 1681 1682 static bool_t 1683 cachefs_xdr_calloc(XDR *xdrs, struct cachefs_log_calloc_record *rec) 1684 { 1685 if ((! xdr_int(xdrs, &rec->type)) || 1686 (! xdr_int(xdrs, &rec->error)) || 1687 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1688 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1689 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1690 (! xdr_ino64(xdrs, &rec->fileno)) || 1691 (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->off)) || 1692 (! xdr_u_int(xdrs, &rec->len))) 1693 return (FALSE); 1694 1695 return (TRUE); 1696 } 1697 1698 void 1699 cachefs_log_nocache(cachefscache_t *cachep, int Errno, struct vfs *vfsp, 1700 fid_t *fidp, ino64_t fileno) 1701 { 1702 struct cachefs_log_nocache_record *record; 1703 1704 /* In Solaris 64 - if can't represent time don't bother */ 1705 RET_IF_TIME_OVERFLOW(cachep, time) 1706 record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP); 1707 if (record == NULL) { 1708 cachefs_log_error(cachep, ENOMEM, 1); 1709 return; 1710 } 1711 1712 record->type = CACHEFS_LOG_NOCACHE; 1713 record->time = time; 1714 record->error = Errno; 1715 1716 record->vfsp = (uint64_t)(uintptr_t)vfsp; 1717 if (fidp != NULL) { 1718 CACHEFS_FID_COPY(fidp, &record->fid); 1719 } 1720 record->fileno = fileno; 1721 1722 cachefs_log_enqueue(cachep, record, (int)sizeof (*record), 1723 cachefs_xdr_nocache); 1724 1725 } 1726 1727 static bool_t 1728 cachefs_xdr_nocache(XDR *xdrs, struct cachefs_log_nocache_record *rec) 1729 { 1730 if ((! xdr_int(xdrs, &rec->type)) || 1731 (! xdr_int(xdrs, &rec->error)) || 1732 (! xdr_cfs_time_t(xdrs, &rec->time)) || 1733 (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || 1734 (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || 1735 (! xdr_ino64(xdrs, &rec->fileno))) 1736 return (FALSE); 1737 1738 return (TRUE); 1739 } 1740