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
cachefs_log_kstat_snapshot(kstat_t * ksp,void * buf,int rw)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
cachefs_log_save_lc(cachefscache_t * cachep)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 *
cachefs_log_create_cookie(cachefs_log_control_t * lc)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
cachefs_log_destroy_cookie(cachefs_log_cookie_t * cl)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
cachefs_log_logfile_open(cachefscache_t * cachep,char * path)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
cachefs_log_error(cachefscache_t * cachep,int error,int getlock)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
cachefs_log_write_header(struct vnode * vp,cachefscache_t * cachep,int error)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
cachefs_log_enqueue(cachefscache_t * cachep,void * record,int size,xdrproc_t translate)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
cachefs_log_process_queue(cachefscache_t * cachep,int getlock)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
cachefs_xdr_logfile_header(XDR * xdrs,struct cachefs_log_logfile_header * h)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
cachefs_log_mount(cachefscache_t * cachep,int Errno,struct vfs * vfsp,fscache_t * fscp,char * upath,enum uio_seg seg,char * cacheid)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
cachefs_xdr_mount(XDR * xdrs,struct cachefs_log_mount_record * rec)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
cachefs_log_umount(cachefscache_t * cachep,int Errno,struct vfs * vfsp)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
cachefs_xdr_umount(XDR * xdrs,struct cachefs_log_umount_record * rec)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
cachefs_log_getpage(cachefscache_t * cachep,int Errno,struct vfs * vfsp,fid_t * fidp,ino64_t fileno,uid_t uid,u_offset_t offset,size_t len)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
cachefs_xdr_getpage(XDR * xdrs,struct cachefs_log_getpage_record * rec)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
cachefs_log_readdir(cachefscache_t * cachep,int Errno,struct vfs * vfsp,fid_t * fidp,ino64_t fileno,uid_t uid,u_offset_t offset,int eof)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
cachefs_xdr_readdir(XDR * xdrs,struct cachefs_log_readdir_record * rec)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
cachefs_log_readlink(cachefscache_t * cachep,int Errno,struct vfs * vfsp,fid_t * fidp,ino64_t fileno,uid_t uid,size_t length)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
cachefs_xdr_readlink(XDR * xdrs,struct cachefs_log_readlink_record * rec)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
cachefs_log_remove(cachefscache_t * cachep,int Errno,struct vfs * vfsp,fid_t * fidp,ino64_t fileno,uid_t uid)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
cachefs_xdr_remove(XDR * xdrs,struct cachefs_log_remove_record * rec)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
cachefs_log_rmdir(cachefscache_t * cachep,int Errno,struct vfs * vfsp,fid_t * fidp,ino64_t fileno,uid_t uid)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
cachefs_xdr_rmdir(XDR * xdrs,struct cachefs_log_rmdir_record * rec)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
cachefs_log_truncate(cachefscache_t * cachep,int Errno,struct vfs * vfsp,fid_t * fidp,ino64_t fileno,uid_t uid,u_offset_t size)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
cachefs_xdr_truncate(XDR * xdrs,struct cachefs_log_truncate_record * rec)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
cachefs_log_putpage(cachefscache_t * cachep,int Errno,struct vfs * vfsp,fid_t * fidp,ino64_t fileno,uid_t uid,u_offset_t offset,size_t len)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
cachefs_xdr_putpage(XDR * xdrs,struct cachefs_log_putpage_record * rec)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
cachefs_log_create(cachefscache_t * cachep,int Errno,struct vfs * vfsp,fid_t * filefidp,ino64_t fileno,uid_t uid)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
cachefs_xdr_create(XDR * xdrs,struct cachefs_log_create_record * rec)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
cachefs_log_mkdir(cachefscache_t * cachep,int Errno,struct vfs * vfsp,fid_t * cfidp,ino64_t fileno,uid_t uid)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
cachefs_xdr_mkdir(XDR * xdrs,struct cachefs_log_mkdir_record * rec)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
cachefs_log_rename(cachefscache_t * cachep,int Errno,struct vfs * vfsp,fid_t * gfp,ino64_t fileno,int removed,uid_t uid)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
cachefs_xdr_rename(XDR * xdrs,struct cachefs_log_rename_record * rec)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
cachefs_log_symlink(cachefscache_t * cachep,int Errno,struct vfs * vfsp,fid_t * fidp,ino64_t fileno,uid_t uid,int size)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
cachefs_xdr_symlink(XDR * xdrs,struct cachefs_log_symlink_record * rec)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
cachefs_log_populate(cachefscache_t * cachep,int Errno,struct vfs * vfsp,fid_t * fidp,ino64_t fileno,u_offset_t off,size_t popsize)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
cachefs_xdr_populate(XDR * xdrs,struct cachefs_log_populate_record * rec)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
cachefs_log_csymlink(cachefscache_t * cachep,int Errno,struct vfs * vfsp,fid_t * fidp,ino64_t fileno,int size)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
cachefs_xdr_csymlink(XDR * xdrs,struct cachefs_log_csymlink_record * rec)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
cachefs_log_filldir(cachefscache_t * cachep,int Errno,struct vfs * vfsp,fid_t * fidp,ino64_t fileno,u_offset_t size)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
cachefs_xdr_filldir(XDR * xdrs,struct cachefs_log_filldir_record * rec)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
cachefs_log_mdcreate(cachefscache_t * cachep,int Errno,struct vfs * vfsp,fid_t * fidp,ino64_t fileno,uint_t count)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
cachefs_xdr_mdcreate(XDR * xdrs,struct cachefs_log_mdcreate_record * rec)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
cachefs_log_gpfront(cachefscache_t * cachep,int Errno,struct vfs * vfsp,fid_t * fidp,ino64_t fileno,uid_t uid,u_offset_t offset,uint_t len)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
cachefs_xdr_gpfront(XDR * xdrs,struct cachefs_log_gpfront_record * rec)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
cachefs_log_rfdir(cachefscache_t * cachep,int Errno,struct vfs * vfsp,fid_t * fidp,ino64_t fileno,uid_t uid)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
cachefs_xdr_rfdir(XDR * xdrs,struct cachefs_log_rfdir_record * rec)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
cachefs_log_ualloc(cachefscache_t * cachep,int Errno,struct vfs * vfsp,fid_t * fidp,ino64_t fileno,u_offset_t off,size_t len)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
cachefs_xdr_ualloc(XDR * xdrs,struct cachefs_log_ualloc_record * rec)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
cachefs_log_calloc(cachefscache_t * cachep,int Errno,struct vfs * vfsp,fid_t * fidp,ino64_t fileno,u_offset_t off,size_t len)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
cachefs_xdr_calloc(XDR * xdrs,struct cachefs_log_calloc_record * rec)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
cachefs_log_nocache(cachefscache_t * cachep,int Errno,struct vfs * vfsp,fid_t * fidp,ino64_t fileno)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
cachefs_xdr_nocache(XDR * xdrs,struct cachefs_log_nocache_record * rec)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