Print this page
11083 support NFS server in zone
Portions contributed by: Dan Kruchinin <dan.kruchinin@nexenta.com>
Portions contributed by: Stepan Zastupov <stepan.zastupov@gmail.com>
Portions contributed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Portions contributed by: Mike Zeller <mike@mikezeller.net>
Portions contributed by: Dan McDonald <danmcd@joyent.com>
Portions contributed by: Gordon Ross <gordon.w.ross@gmail.com>
Portions contributed by: Vitaliy Gusev <gusev.vitaliy@gmail.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Jason King <jbk@joyent.com>
Reviewed by: C Fraire <cfraire@me.com>
Change-Id: I22f289d357503f9b48a0bc2482cc4328a6d43d16
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/nfs/nfs_log.c
+++ new/usr/src/uts/common/fs/nfs/nfs_log.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
|
↓ open down ↓ |
10 lines elided |
↑ open up ↑ |
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 +
21 22 /*
22 23 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
23 24 */
24 25
26 +/*
27 + * Copyright 2018 Nexenta Systems, Inc.
28 + */
29 +
25 30 #include <sys/cred.h>
26 31 #include <sys/cmn_err.h>
27 32 #include <sys/debug.h>
28 33 #include <sys/systm.h>
29 34 #include <sys/kmem.h>
30 35 #include <sys/disp.h>
31 36 #include <sys/atomic.h>
32 37 #include <rpc/types.h>
33 38 #include <nfs/nfs.h>
34 39 #include <nfs/nfssys.h>
35 40 #include <nfs/export.h>
|
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
36 41 #include <nfs/rnode.h>
37 42 #include <rpc/auth.h>
38 43 #include <rpc/svc.h>
39 44 #include <rpc/xdr.h>
40 45 #include <rpc/clnt.h>
41 46 #include <nfs/nfs_log.h>
42 47
43 48 #define NUM_RECORDS_TO_WRITE 256
44 49 #define NUM_BYTES_TO_WRITE 65536
45 50
46 -extern krwlock_t exported_lock;
47 -
48 51 static int nfslog_num_records_to_write = NUM_RECORDS_TO_WRITE;
49 52 static int nfslog_num_bytes_to_write = NUM_BYTES_TO_WRITE;
50 53
51 54 /*
52 55 * This struct is used to 'hide' the details of managing the log
53 56 * records internally to the logging code. Allocation routines
54 57 * are used to obtain pieces of memory for XDR encoding. This struct
55 58 * is a 'header' to those areas and a opaque cookie is used to pass
56 59 * this data structure between the allocating function and the put
57 60 * function.
58 61 */
59 62 struct lr_alloc {
60 63 struct lr_alloc *next; /* links for write queuing */
61 64 struct lr_alloc *prev;
62 65 #define LR_ALLOC_NOFREE 0x1 /* not present, call free */
63 66 int lr_flags;
64 67 caddr_t log_record; /* address to XDR encoding */
65 68 size_t size; /* final size of encoding */
66 69 struct kmem_cache *alloc_cache; /* keep track of cache ptr */
67 70 struct exportinfo *exi; /* who are we related to? */
68 71 struct log_buffer *lb;
69 72 };
70 73
71 74 struct flush_thread_params {
72 75 struct nfsl_flush_args tp_args;
73 76 int tp_error;
74 77 };
75 78
76 79 static int log_file_create(caddr_t, struct log_file **);
77 80 static void log_file_rele(struct log_file *);
78 81 static struct log_buffer *log_buffer_create(caddr_t);
79 82 static void log_buffer_rele(struct log_buffer *);
80 83 static int nfslog_record_append2all(struct lr_alloc *);
81 84 static int nfslog_logbuffer_rename(struct log_buffer *);
82 85 static void nfslog_logfile_wait(struct log_file *);
83 86 static int nfslog_logfile_rename(char *, char *);
84 87 static void nfslog_do_flush(struct flush_thread_params *);
85 88 static void create_buffer_header(caddr_t *, size_t *, size_t *);
86 89
87 90 static int nfslog_write_logrecords(struct log_file *, struct lr_alloc *, int);
88 91 static void nfslog_free_logrecords(struct lr_alloc *);
89 92 static int nfslog_records_flush_to_disk(struct log_buffer *);
90 93 static int nfslog_records_flush_to_disk_nolock(struct log_buffer *);
91 94
92 95 /*
93 96 * Read/Write lock that protects 'nfslog_buffer_list'.
94 97 * This lock must be held when searching or modifying 'nfslog_buffer_list'.
95 98 */
96 99 static krwlock_t nfslog_buffer_list_lock;
97 100
98 101 /*
99 102 * The list of "log_buffer" structures.
100 103 */
101 104 struct log_buffer *nfslog_buffer_list = NULL;
102 105
103 106
104 107 #define LOG_BUFFER_HOLD(lbp) { \
105 108 mutex_enter(&(lbp)->lb_lock); \
106 109 (lbp)->lb_refcnt++; \
107 110 mutex_exit(&(lbp)->lb_lock); \
108 111 }
109 112
110 113 #define LOG_FILE_HOLD(lfp) { \
111 114 mutex_enter(&(lfp)->lf_lock); \
112 115 (lfp)->lf_refcnt++; \
113 116 mutex_exit(&(lfp)->lf_lock); \
114 117 }
115 118
116 119 #define LOG_FILE_RELE(lfp) { \
117 120 log_file_rele(lfp); \
118 121 }
119 122
120 123 /*
121 124 * These two macros are used to prep a logfile data structure and
122 125 * associated file for writing data. Note that the lf_lock is
123 126 * held as a result of the call to the first macro. This is used
124 127 * for serialization correctness between the logbuffer struct and
125 128 * the logfile struct.
126 129 */
127 130 #define LOG_FILE_LOCK_TO_WRITE(lfp) { \
128 131 mutex_enter(&(lfp)->lf_lock); \
129 132 (lfp)->lf_refcnt++; \
130 133 (lfp)->lf_writers++; \
131 134 }
132 135
133 136 #define LOG_FILE_UNLOCK_FROM_WRITE(lfp) { \
134 137 (lfp)->lf_writers--; \
135 138 if ((lfp)->lf_writers == 0 && ((lfp)->lf_flags & L_WAITING)) { \
136 139 (lfp)->lf_flags &= ~L_WAITING; \
137 140 cv_broadcast(&(lfp)->lf_cv_waiters); \
138 141 } \
139 142 mutex_exit(&(lfp)->lf_lock); \
140 143 log_file_rele(lfp); \
141 144 }
142 145
143 146 int rfsl_log_buffer = 0;
144 147 static int rfsl_log_file = 0;
145 148
146 149 /* This array is used for memory allocation of record encoding spaces */
147 150 static struct {
148 151 int size;
149 152 struct kmem_cache *mem_cache;
150 153 char *cache_name;
151 154 } nfslog_mem_alloc[] = {
152 155 #define SMALL_INDX 0
153 156 { NFSLOG_SMALL_RECORD_SIZE - sizeof (struct lr_alloc),
154 157 NULL, NFSLOG_SMALL_REC_NAME },
155 158 #define MEDIUM_INDX 1
156 159 { NFSLOG_MEDIUM_RECORD_SIZE - sizeof (struct lr_alloc),
157 160 NULL, NFSLOG_MEDIUM_REC_NAME },
158 161 #define LARGE_INDX 2
159 162 { NFSLOG_LARGE_RECORD_SIZE - sizeof (struct lr_alloc),
160 163 NULL, NFSLOG_LARGE_REC_NAME },
161 164 { (-1), NULL }
162 165 };
163 166
164 167 /* Used to calculate the 'real' allocation size */
165 168 #define ALLOC_SIZE(index) \
166 169 (nfslog_mem_alloc[index].size + sizeof (struct lr_alloc))
167 170
168 171 /*
169 172 * Initialize logging data buffer cache
170 173 */
171 174 void
172 175 nfslog_init()
173 176 {
174 177 int indx;
175 178
176 179 rw_init(&nfslog_buffer_list_lock, NULL, RW_DEFAULT, NULL);
177 180
178 181 /*
179 182 * Initialize the kmem caches for encoding
180 183 */
181 184 for (indx = 0; nfslog_mem_alloc[indx].size != (-1); indx++) {
182 185 nfslog_mem_alloc[indx].mem_cache =
183 186 kmem_cache_create(nfslog_mem_alloc[indx].cache_name,
184 187 ALLOC_SIZE(indx), 0, NULL, NULL, NULL, NULL, NULL, 0);
185 188 }
186 189 }
187 190
188 191 /*
189 192 * Sets up the necessary log file and related buffers to enable logging
190 193 * on the given export point.
191 194 * Returns 0 on success, non-zero on failure.
192 195 */
193 196 int
194 197 nfslog_setup(struct exportinfo *exi)
195 198 {
196 199 struct exportdata *kex;
197 200 struct log_buffer *lbp;
198 201 struct log_buffer *nlbp;
199 202
200 203 kex = &exi->exi_export;
201 204 ASSERT(kex->ex_flags & EX_LOG);
202 205
203 206 /*
204 207 * Logging is enabled for the new export point, check
205 208 * the existing log_buffer structures to see if the
206 209 * desired buffer has already been opened. If so, point
207 210 * the new exportinfo's exi_logbuffer to the existing
208 211 * one.
209 212 */
210 213 rw_enter(&nfslog_buffer_list_lock, RW_READER);
211 214 for (lbp = nfslog_buffer_list; lbp != NULL; lbp = lbp->lb_next) {
212 215 LOGGING_DPRINT((10,
213 216 "searching for buffer... found log_buffer '%s'\n",
214 217 lbp->lb_path));
215 218 if (strcmp(lbp->lb_path, kex->ex_log_buffer) == 0) {
216 219 /* Found our match. Ref it and return */
217 220 LOG_BUFFER_HOLD(lbp);
218 221 exi->exi_logbuffer = lbp;
219 222 LOGGING_DPRINT((10, "\tfound log_buffer for '%s'\n",
220 223 kex->ex_log_buffer));
221 224 rw_exit(&nfslog_buffer_list_lock);
222 225 return (0);
223 226 }
224 227 }
225 228 rw_exit(&nfslog_buffer_list_lock);
226 229
227 230 /*
228 231 * New buffer needed, allocate it.
229 232 * The buffer list lock has been dropped so we will need to search
230 233 * the list again to ensure that another thread has not added
231 234 * a matching buffer.
232 235 */
233 236 if ((nlbp = log_buffer_create(kex->ex_log_buffer)) == NULL) {
234 237 /*
235 238 * Failed the buffer creation for some reason so we
236 239 * will need to return.
237 240 */
238 241 return (EIO);
239 242 }
240 243
241 244 rw_enter(&nfslog_buffer_list_lock, RW_WRITER);
242 245 for (lbp = nfslog_buffer_list; lbp != NULL;
243 246 lbp = lbp->lb_next) {
244 247 if (strcmp(lbp->lb_path, kex->ex_log_buffer) == 0) {
245 248 /*
246 249 * A log_buffer already exists for the
247 250 * indicated buffer, use it instead.
248 251 */
249 252 LOG_BUFFER_HOLD(lbp);
250 253
251 254 exi->exi_logbuffer = lbp;
252 255
253 256 LOGGING_DPRINT((10, "found log_buffer for '%s' "
254 257 "after allocation\n", kex->ex_log_buffer));
255 258
256 259 rw_exit(&nfslog_buffer_list_lock);
257 260
258 261 log_buffer_rele(nlbp);
259 262
260 263 return (0);
261 264 }
262 265 }
263 266 /*
264 267 * Didn't find an existing log_buffer for this buffer,
265 268 * use the the newly created one, and add to list. We
266 269 * increment the reference count because the node is
267 270 * entered into the global list.
268 271 */
269 272 LOGGING_DPRINT((10, "exportfs: adding nlbp=%p to list\n",
270 273 (void *)nlbp));
271 274
272 275 nlbp->lb_next = nfslog_buffer_list;
273 276 nfslog_buffer_list = nlbp;
274 277
275 278 LOG_BUFFER_HOLD(nlbp); /* hold is for export entry */
276 279 exi->exi_logbuffer = nlbp;
277 280
278 281 rw_exit(&nfslog_buffer_list_lock);
279 282
280 283 return (0);
281 284 }
282 285
283 286 /*
284 287 * Disables logging for the given export point.
285 288 */
286 289 void
287 290 nfslog_disable(struct exportinfo *exi)
288 291 {
289 292 log_buffer_rele(exi->exi_logbuffer);
290 293 }
291 294
292 295 /*
293 296 * Creates the corresponding log_buffer and log_file structures
294 297 * for the the buffer named 'name'.
295 298 * Returns a pointer to the log_buffer structure with reference one.
296 299 */
297 300 static struct log_buffer *
298 301 log_buffer_create(caddr_t name)
299 302 {
300 303 struct log_buffer *buffer;
301 304 struct log_file *logfile;
302 305 int namelen = strlen(name);
303 306
304 307 LOGGING_DPRINT((10, "log_buffer_create: %s\n", name));
305 308 if (log_file_create(name, &logfile))
306 309 return (NULL);
307 310
308 311 buffer = (struct log_buffer *)kmem_alloc(sizeof (*buffer), KM_SLEEP);
309 312 buffer->lb_refcnt = 1;
310 313 buffer->lb_rec_id = 0;
311 314 buffer->lb_path = (caddr_t)kmem_alloc(namelen + 1, KM_SLEEP);
312 315 bcopy(name, buffer->lb_path, namelen + 1);
313 316 buffer->lb_logfile = logfile;
314 317 buffer->lb_records = NULL;
315 318 buffer->lb_num_recs = 0;
316 319 buffer->lb_size_queued = 0;
317 320 mutex_init(&buffer->lb_lock, NULL, MUTEX_DEFAULT, NULL);
318 321 rfsl_log_buffer++;
319 322
320 323 return (buffer);
321 324 }
322 325
323 326 /*
324 327 * Release a log_buffer structure
325 328 */
326 329 static void
327 330 log_buffer_rele(struct log_buffer *lbp)
328 331 {
329 332 int len;
330 333
331 334 mutex_enter(&lbp->lb_lock);
332 335 if (--lbp->lb_refcnt > 1) {
333 336 mutex_exit(&lbp->lb_lock);
334 337 return;
335 338 }
336 339
337 340 if (lbp->lb_refcnt < 0) {
338 341 panic("log_rele: log_buffer refcnt < 0");
339 342 /*NOTREACHED*/
340 343 }
341 344
342 345 /*
343 346 * Need to drop the lb_lock before acquiring the
344 347 * nfslog_buffer_list_lock. To avoid double free we need
345 348 * to hold an additional reference to the log buffer.
346 349 * This will ensure that no two threads will simultaneously
347 350 * be trying to free the same log buffer.
348 351 */
349 352
350 353 if (lbp->lb_refcnt == 1) {
351 354
352 355 /*
353 356 * If the ref count is 1, then the last
354 357 * unshare/reference has been given up and we need to
355 358 * clean up the buffer and remove it from the buffer
356 359 * list.
357 360 */
358 361 LOGGING_DPRINT((10,
359 362 "log_buffer_rele lbp=%p disconnecting\n", (void *)lbp));
360 363 /*
361 364 * Hold additional reference before dropping the lb_lock
362 365 */
363 366
364 367 lbp->lb_refcnt++;
365 368 mutex_exit(&lbp->lb_lock);
366 369
367 370 /*
368 371 * Make sure that all of the buffered records are written.
369 372 * Don't bother checking the write return value since there
370 373 * isn't much we can do at this point.
371 374 */
372 375 (void) nfslog_records_flush_to_disk(lbp);
373 376
374 377 rw_enter(&nfslog_buffer_list_lock, RW_WRITER);
375 378 mutex_enter(&lbp->lb_lock);
376 379 /*
377 380 * Drop the reference count held above.
378 381 * If the ref count is still > 1 then someone has
379 382 * stepped in to use this log buffer. unlock and return.
380 383 */
381 384 if (--lbp->lb_refcnt > 1) {
382 385 mutex_exit(&lbp->lb_lock);
383 386 rw_exit(&nfslog_buffer_list_lock);
384 387 return;
385 388 }
386 389
387 390 if (lbp == nfslog_buffer_list) {
388 391 nfslog_buffer_list = lbp->lb_next;
389 392 } else {
390 393 struct log_buffer *tlbp;
391 394
392 395 /* Drop the log_buffer from the master list */
393 396 for (tlbp = nfslog_buffer_list; tlbp->lb_next != NULL;
394 397 tlbp = tlbp->lb_next) {
395 398 if (tlbp->lb_next == lbp) {
396 399 tlbp->lb_next = lbp->lb_next;
397 400 break;
398 401 }
399 402 }
400 403 }
401 404
402 405 mutex_exit(&lbp->lb_lock);
403 406 rw_exit(&nfslog_buffer_list_lock);
404 407 }
405 408 /*
406 409 * ref count zero; finish clean up.
407 410 */
408 411 LOGGING_DPRINT((10, "log_buffer_rele lbp=%p freeing\n", (void *)lbp));
409 412
410 413 log_file_rele(lbp->lb_logfile);
411 414 len = strlen(lbp->lb_path) + 1;
412 415 kmem_free(lbp->lb_path, len);
413 416 kmem_free(lbp, sizeof (*lbp));
414 417 rfsl_log_buffer--;
415 418 }
416 419
417 420 /*
418 421 * Creates the corresponding log_file structure for the buffer
419 422 * named 'log_file_name'.
420 423 * 'log_file_name' is created by concatenating 'origname' and LOG_INPROG_STRING.
421 424 * 'logfile' is set to be the log_file structure with reference one.
422 425 */
423 426 static int
424 427 log_file_create(caddr_t origname, struct log_file **lfpp)
425 428 {
426 429 vnode_t *vp = NULL;
427 430 char *name;
428 431 int namelen;
429 432 int error;
430 433 struct log_file *logfile = NULL;
431 434 vattr_t va;
432 435 caddr_t loghdr = NULL;
433 436 size_t loghdr_len = 0;
434 437 size_t loghdr_free = 0;
435 438
436 439 namelen = strlen(origname) + strlen(LOG_INPROG_STRING);
437 440 name = (caddr_t)kmem_alloc(namelen + 1, KM_SLEEP);
438 441 (void) sprintf(name, "%s%s", origname, LOG_INPROG_STRING);
439 442
440 443 LOGGING_DPRINT((3, "log_file_create: %s\n", name));
441 444 if (error = vn_open(name, UIO_SYSSPACE, FCREAT|FWRITE|FOFFMAX,
442 445 LOG_MODE, &vp, CRCREAT, 0)) {
443 446 nfs_cmn_err(error, CE_WARN,
444 447 "log_file_create: Can not open %s - error %m", name);
445 448 goto out;
446 449 }
447 450 LOGGING_DPRINT((3, "log_file_create: %s vp=%p v_count=%d\n",
448 451 name, (void *)vp, vp->v_count));
449 452
450 453 logfile = (struct log_file *)kmem_zalloc(sizeof (*logfile), KM_SLEEP);
451 454 logfile->lf_path = name;
452 455 /*
453 456 * No need to bump the vnode reference count since it is set
454 457 * to one by vn_open().
455 458 */
456 459 logfile->lf_vp = vp;
457 460 logfile->lf_refcnt = 1;
458 461 mutex_init(&logfile->lf_lock, NULL, MUTEX_DEFAULT, NULL);
459 462 rfsl_log_file++;
460 463
461 464 va.va_mask = AT_SIZE;
462 465 error = VOP_GETATTR(vp, &va, 0, CRED(), NULL);
463 466 if (error) {
464 467 nfs_cmn_err(error, CE_WARN,
465 468 "log_file_create: Can not stat %s - error = %m", name);
466 469 goto out;
467 470 }
468 471
469 472 if (va.va_size == 0) {
470 473 struct lr_alloc lr;
471 474
472 475 /*
473 476 * Write Header.
474 477 */
475 478 create_buffer_header(&loghdr, &loghdr_len, &loghdr_free);
476 479 /*
477 480 * Dummy up a lr_alloc struct for the write
478 481 */
479 482 lr.next = lr.prev = &lr;
480 483 lr.lr_flags = 0;
481 484 lr.log_record = loghdr;
482 485 lr.size = loghdr_len;
483 486 lr.alloc_cache = NULL;
484 487 lr.exi = NULL;
485 488 lr.lb = NULL;
486 489
487 490 mutex_enter(&logfile->lf_lock);
488 491
489 492 error = nfslog_write_logrecords(logfile, &lr, 1);
490 493
491 494 mutex_exit(&logfile->lf_lock);
492 495
493 496 if (error != 0) {
494 497 nfs_cmn_err(error, CE_WARN,
495 498 "log_file_create: Can not write header "
496 499 "on %s - error = %m", name);
497 500 goto out;
498 501 }
499 502 }
500 503 *lfpp = logfile;
501 504
502 505 if (loghdr != NULL)
503 506 kmem_free(loghdr, loghdr_free);
504 507
505 508 return (0);
506 509
507 510 out:
508 511 if (vp != NULL) {
509 512 int error1;
510 513 error1 = VOP_CLOSE(vp, FCREAT|FWRITE|FOFFMAX, 1, (offset_t)0,
511 514 CRED(), NULL);
512 515 if (error1) {
513 516 nfs_cmn_err(error1, CE_WARN,
514 517 "log_file_create: Can not close %s - "
515 518 "error = %m", name);
516 519 }
517 520 VN_RELE(vp);
518 521 }
519 522
520 523 kmem_free(name, namelen + 1);
521 524 if (logfile != NULL) {
522 525 mutex_destroy(&logfile->lf_lock);
523 526 kmem_free(logfile, sizeof (*logfile));
524 527 rfsl_log_file--;
525 528 }
526 529 if (loghdr != NULL)
527 530 kmem_free(loghdr, loghdr_free);
528 531
529 532 return (error);
530 533 }
531 534
532 535 /*
533 536 * Release a log_file structure
534 537 */
535 538 static void
536 539 log_file_rele(struct log_file *lfp)
537 540 {
538 541 int len;
539 542 int error;
540 543
541 544 mutex_enter(&lfp->lf_lock);
542 545 if (--lfp->lf_refcnt > 0) {
543 546 LOGGING_DPRINT((10,
544 547 "log_file_rele lfp=%p decremented refcnt to %d\n",
545 548 (void *)lfp, lfp->lf_refcnt));
546 549 mutex_exit(&lfp->lf_lock);
547 550 return;
548 551 }
549 552 if (lfp->lf_refcnt < 0) {
550 553 panic("log_file_rele: log_file refcnt < 0");
551 554 /*NOTREACHED*/
552 555 }
553 556
554 557 LOGGING_DPRINT((10, "log_file_rele lfp=%p freeing node\n",
555 558 (void *)lfp));
556 559
557 560 lfp->lf_flags &= ~(L_PRINTED | L_ERROR);
558 561
559 562 ASSERT(lfp->lf_flags == 0);
560 563 ASSERT(lfp->lf_writers == 0);
561 564
562 565 if (error = VOP_CLOSE(lfp->lf_vp, FCREAT|FWRITE|FOFFMAX, 1, (offset_t)0,
563 566 CRED(), NULL)) {
564 567 nfs_cmn_err(error, CE_WARN,
565 568 "NFS: Could not close log buffer %s - error = %m",
566 569 lfp->lf_path);
567 570 #ifdef DEBUG
568 571 } else {
569 572 LOGGING_DPRINT((3,
570 573 "log_file_rele: %s has been closed vp=%p v_count=%d\n",
571 574 lfp->lf_path, (void *)lfp->lf_vp, lfp->lf_vp->v_count));
572 575 #endif
573 576 }
574 577 VN_RELE(lfp->lf_vp);
575 578
576 579 len = strlen(lfp->lf_path) + 1;
577 580 kmem_free(lfp->lf_path, len);
578 581 kmem_free(lfp, sizeof (*lfp));
579 582 rfsl_log_file--;
580 583 }
581 584
582 585 /*
583 586 * Allocates a record of the size specified.
584 587 * 'exi' identifies the exportinfo structure being logged.
585 588 * 'size' indicates how much memory should be allocated
586 589 * 'cookie' is used to store an opaque value for the caller for later use
587 590 * 'flags' currently ignored.
|
↓ open down ↓ |
530 lines elided |
↑ open up ↑ |
588 591 *
589 592 * Returns a pointer to the beginning of the allocated memory.
590 593 * 'cookie' is a pointer to the 'lr_alloc' struct; this will be used
591 594 * to keep track of the encoded record and contains all the info
592 595 * for enqueuing the record on the log buffer for later writing.
593 596 *
594 597 * nfslog_record_put() must be used to 'free' this record or allocation.
595 598 */
596 599 /* ARGSUSED */
597 600 void *
598 -nfslog_record_alloc(
599 - struct exportinfo *exi,
600 - int alloc_indx,
601 - void **cookie,
602 - int flags)
601 +nfslog_record_alloc(struct exportinfo *exi, int alloc_indx, void **cookie,
602 + int flags)
603 603 {
604 604 struct lr_alloc *lrp;
605 605
606 606 lrp = (struct lr_alloc *)
607 607 kmem_cache_alloc(nfslog_mem_alloc[alloc_indx].mem_cache,
608 608 KM_NOSLEEP);
609 609
610 610 if (lrp == NULL) {
611 611 *cookie = NULL;
612 612 return (NULL);
613 613 }
614 614
615 615 lrp->next = lrp;
616 616 lrp->prev = lrp;
617 617 lrp->lr_flags = 0;
618 618
619 619 lrp->log_record = (caddr_t)((uintptr_t)lrp +
620 620 (uintptr_t)sizeof (struct lr_alloc));
621 621 lrp->size = nfslog_mem_alloc[alloc_indx].size;
622 622 lrp->alloc_cache = nfslog_mem_alloc[alloc_indx].mem_cache;
623 623 lrp->exi = exi;
624 624
625 625 if (exi->exi_export.ex_flags & EX_LOG) {
626 626 LOG_BUFFER_HOLD(exi->exi_logbuffer);
627 627 lrp->lb = exi->exi_logbuffer;
628 628 } else {
629 629 lrp->lb = NULL;
630 630 }
631 631
632 632 *cookie = (void *)lrp;
633 633
634 634 LOGGING_DPRINT((3,
635 635 "nfslog_record_alloc(log_buffer=%p mem=%p size=%lu)\n",
636 636 (void *)exi->exi_logbuffer, (void *)lrp->log_record, lrp->size));
637 637 return (lrp->log_record);
638 638 }
639 639
640 640 /*
641 641 * After the above nfslog_record_alloc() has been called and a record
642 642 * encoded into the buffer that was returned, this function is called
643 643 * to handle appropriate disposition of the newly created record.
644 644 * The cookie value is the one that was returned from nfslog_record_alloc().
|
↓ open down ↓ |
32 lines elided |
↑ open up ↑ |
645 645 * Size is the actual size of the record that was encoded. This is
646 646 * passed in because the size used for the alloc was just an approximation.
647 647 * The sync parameter is used to tell us if we need to force this record
648 648 * to disk and if not it will be queued for later writing.
649 649 *
650 650 * Note that if the size parameter has a value of 0, then the record is
651 651 * not written to the log and the associated data structures are released.
652 652 */
653 653 void
654 654 nfslog_record_put(void *cookie, size_t size, bool_t sync,
655 - unsigned int which_buffers)
655 + unsigned int which_buffers)
656 656 {
657 657 struct lr_alloc *lrp = (struct lr_alloc *)cookie;
658 658 struct log_buffer *lbp = lrp->lb;
659 659
660 660 /*
661 661 * If the caller has nothing to write or if there is
662 662 * an apparent error, rele the buffer and free.
663 663 */
664 664 if (size == 0 || size > lrp->size) {
665 665 nfslog_free_logrecords(lrp);
666 666 return;
667 667 }
668 668
669 669 /*
670 670 * Reset the size to what actually needs to be written
671 671 * This is used later on when the iovec is built for
672 672 * writing the records to the log file.
673 673 */
674 674 lrp->size = size;
675 675
676 676 /* append to all if public exi */
677 677 if (which_buffers == NFSLOG_ALL_BUFFERS) {
678 678 (void) nfslog_record_append2all(lrp);
679 679 nfslog_free_logrecords(lrp);
680 680 return;
681 681 }
682 682
683 683 /* Insert the record on the list to be written */
684 684 mutex_enter(&lbp->lb_lock);
685 685 if (lbp->lb_records == NULL) {
686 686 lbp->lb_records = (caddr_t)lrp;
687 687 lbp->lb_num_recs = 1;
688 688 lbp->lb_size_queued = lrp->size;
689 689 } else {
690 690 insque(lrp, ((struct lr_alloc *)lbp->lb_records)->prev);
691 691 lbp->lb_num_recs++;
692 692 lbp->lb_size_queued += lrp->size;
693 693 }
694 694
695 695 /*
696 696 * Determine if the queue for this log buffer should be flushed.
697 697 * This is done by either the number of records queued, the total
698 698 * size of all records queued or by the request of the caller
699 699 * via the sync parameter.
700 700 */
701 701 if (lbp->lb_size_queued >= nfslog_num_bytes_to_write ||
702 702 lbp->lb_num_recs > nfslog_num_records_to_write || sync == TRUE) {
703 703 mutex_exit(&lbp->lb_lock);
704 704 (void) nfslog_records_flush_to_disk(lbp);
705 705 } else {
706 706 mutex_exit(&lbp->lb_lock);
707 707 }
708 708
709 709 }
710 710
711 711 /*
712 712 * Examine the log_buffer struct to see if there are queue log records
713 713 * that need to be written to disk. If some exist, pull them off of
714 714 * the log buffer and write them to the log file.
715 715 */
716 716 static int
717 717 nfslog_records_flush_to_disk(struct log_buffer *lbp)
718 718 {
719 719
720 720 mutex_enter(&lbp->lb_lock);
721 721
722 722 if (lbp->lb_records == NULL) {
723 723 mutex_exit(&lbp->lb_lock);
724 724 return (0);
725 725 }
726 726 return (nfslog_records_flush_to_disk_nolock(lbp));
727 727 }
728 728
729 729 /*
730 730 * Function requires that the caller holds lb_lock.
731 731 * Function flushes any records in the log buffer to the disk.
732 732 * Function drops the lb_lock on return.
733 733 */
734 734
735 735 static int
736 736 nfslog_records_flush_to_disk_nolock(struct log_buffer *lbp)
737 737 {
738 738 struct log_file *lfp = NULL;
739 739 struct lr_alloc *lrp_writers;
740 740 int num_recs;
741 741 int error = 0;
742 742
743 743 ASSERT(MUTEX_HELD(&lbp->lb_lock));
744 744
745 745 lfp = lbp->lb_logfile;
746 746
747 747 LOG_FILE_LOCK_TO_WRITE(lfp);
748 748 ASSERT(lbp->lb_records != NULL);
749 749
750 750 lrp_writers = (struct lr_alloc *)lbp->lb_records;
751 751 lbp->lb_records = NULL;
752 752 num_recs = lbp->lb_num_recs;
753 753 lbp->lb_num_recs = 0;
754 754 lbp->lb_size_queued = 0;
755 755 mutex_exit(&lbp->lb_lock);
756 756 error = nfslog_write_logrecords(lfp, lrp_writers, num_recs);
757 757
758 758 LOG_FILE_UNLOCK_FROM_WRITE(lfp);
759 759
760 760 nfslog_free_logrecords(lrp_writers);
|
↓ open down ↓ |
95 lines elided |
↑ open up ↑ |
761 761 return (error);
762 762 }
763 763
764 764
765 765 /*
766 766 * Take care of writing the provided log record(s) to the log file.
767 767 * We group the log records with an iovec and use VOP_WRITE to append
768 768 * them to the end of the log file.
769 769 */
770 770 static int
771 -nfslog_write_logrecords(struct log_file *lfp,
772 - struct lr_alloc *lrp_writers, int num_recs)
771 +nfslog_write_logrecords(struct log_file *lfp, struct lr_alloc *lrp_writers,
772 + int num_recs)
773 773 {
774 774 struct uio uio;
775 775 struct iovec *iovp;
776 776 int size_iovecs;
777 777 vnode_t *vp;
778 778 struct vattr va;
779 779 struct lr_alloc *lrp;
780 780 int i;
781 781 ssize_t len;
782 782 int ioflag = FAPPEND;
783 783 int error = 0;
784 784
785 785 ASSERT(MUTEX_HELD(&lfp->lf_lock));
786 786
787 787 vp = lfp->lf_vp;
788 788
789 789 size_iovecs = sizeof (struct iovec) * num_recs;
790 790 iovp = (struct iovec *)kmem_alloc(size_iovecs, KM_NOSLEEP);
791 791
792 792 if (iovp == NULL) {
793 793 error = ENOMEM;
794 794 goto out;
795 795 }
796 796
797 797 /* Build the iovec based on the list of log records */
798 798 i = 0;
799 799 len = 0;
800 800 lrp = lrp_writers;
801 801 do {
802 802 iovp[i].iov_base = lrp->log_record;
803 803 iovp[i].iov_len = lrp->size;
804 804 len += lrp->size;
805 805 lrp = lrp->next;
806 806 i++;
807 807 } while (lrp != lrp_writers);
808 808
809 809 ASSERT(i == num_recs);
810 810
811 811 uio.uio_iov = iovp;
812 812 uio.uio_iovcnt = num_recs;
813 813 uio.uio_loffset = 0;
814 814 uio.uio_segflg = (short)UIO_SYSSPACE;
815 815 uio.uio_resid = len;
816 816 uio.uio_llimit = (rlim64_t)MAXOFFSET_T;
817 817 uio.uio_fmode = FWRITE;
818 818 uio.uio_extflg = UIO_COPY_DEFAULT;
819 819
820 820 /*
821 821 * Save the size. If the write fails, reset the size to avoid
822 822 * corrupted log buffer files.
823 823 */
824 824 va.va_mask = AT_SIZE;
825 825
826 826 (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL); /* UIO_WRITE */
827 827 if ((error = VOP_GETATTR(vp, &va, 0, CRED(), NULL)) == 0) {
828 828 if ((len + va.va_size) < (MAXOFF32_T)) {
829 829 error = VOP_WRITE(vp, &uio, ioflag, CRED(), NULL);
830 830 VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
831 831 if (uio.uio_resid)
832 832 error = ENOSPC;
833 833 if (error)
834 834 (void) VOP_SETATTR(vp, &va, 0, CRED(), NULL);
835 835 } else {
836 836 VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
837 837 if (!(lfp->lf_flags & L_PRINTED)) {
838 838 cmn_err(CE_WARN,
839 839 "NFS Logging: buffer file %s exceeds 2GB; "
840 840 "stopped writing buffer \n", lfp->lf_path);
841 841 }
842 842 error = ENOSPC;
843 843 }
844 844 } else {
845 845 VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
846 846 }
847 847
848 848 kmem_free(iovp, size_iovecs);
849 849
850 850 out:
851 851 if (error) {
852 852 if (!(lfp->lf_flags & L_PRINTED)) {
853 853 nfs_cmn_err(error, CE_WARN,
854 854 "NFS Logging disabled for buffer %s - "
855 855 "write error = %m\n", lfp->lf_path);
856 856 lfp->lf_flags |= L_PRINTED;
857 857 }
858 858 } else if (lfp->lf_flags & (L_ERROR | L_PRINTED)) {
859 859 lfp->lf_flags &= ~(L_ERROR | L_PRINTED);
860 860 cmn_err(CE_WARN,
861 861 "NFS Logging re-enabled for buffer %s\n", lfp->lf_path);
862 862 }
863 863
864 864 return (error);
865 865 }
866 866
867 867 static void
868 868 nfslog_free_logrecords(struct lr_alloc *lrp_writers)
869 869 {
870 870 struct lr_alloc *lrp = lrp_writers;
871 871 struct lr_alloc *lrp_free;
872 872
873 873 do {
874 874 lrp_free = lrp;
875 875
876 876 lrp = lrp->next;
877 877
878 878 /*
879 879 * Check to see if we are supposed to free this structure
880 880 * and relese the log_buffer ref count.
881 881 * It may be the case that the caller does not want this
882 882 * structure and its record contents freed just yet.
883 883 */
884 884 if ((lrp_free->lr_flags & LR_ALLOC_NOFREE) == 0) {
885 885 if (lrp_free->lb != NULL)
886 886 log_buffer_rele(lrp_free->lb);
887 887 if (lrp_free->alloc_cache) /* double check */
888 888 kmem_cache_free(lrp_free->alloc_cache,
889 889 (void *)lrp_free);
890 890 } else {
891 891 /*
892 892 * after being pulled from the list the
893 893 * pointers need to be reinitialized.
894 894 */
895 895 lrp_free->next = lrp_free;
896 896 lrp_free->prev = lrp_free;
897 897 }
898 898
899 899 } while (lrp != lrp_writers);
900 900 }
901 901
902 902 /*
903 903 * Rename lbp->lb_logfile to reflect the true name requested by 'share'
904 904 */
905 905 static int
906 906 nfslog_logbuffer_rename(struct log_buffer *lbp)
907 907 {
908 908 struct log_file *lf;
909 909 int error;
910 910 struct log_file *logfile;
911 911
912 912 /*
913 913 * Try our best to get the cache records into the log file
914 914 * before the rename occurs.
915 915 */
916 916 (void) nfslog_records_flush_to_disk(lbp);
917 917
918 918 /*
919 919 * Hold lb_lock before retrieving
920 920 * lb_logfile.
921 921 * Hold a reference to the
922 922 * "lf" structure. this is
923 923 * same as LOG_FILE_HOLD()
924 924 */
925 925 mutex_enter(&(lbp)->lb_lock);
926 926 lf = lbp->lb_logfile;
927 927 mutex_enter(&(lf)->lf_lock);
928 928 mutex_exit(&(lbp)->lb_lock);
929 929 lf->lf_refcnt++;
930 930 mutex_exit(&(lf)->lf_lock);
931 931
932 932 LOGGING_DPRINT((10, "nfslog_logbuffer_rename: renaming %s to %s\n",
933 933 lf->lf_path, lbp->lb_path));
934 934
935 935 /*
936 936 * rename the current buffer to what the daemon expects
937 937 */
938 938 if (error = nfslog_logfile_rename(lf->lf_path, lbp->lb_path))
939 939 goto out;
940 940
941 941 /*
942 942 * Create a new working buffer file and have all new data sent there.
943 943 */
944 944 if (error = log_file_create(lbp->lb_path, &logfile)) {
945 945 /* Attempt to rename to original */
946 946 (void) nfslog_logfile_rename(lbp->lb_path, lf->lf_path);
947 947 goto out;
948 948 }
949 949
950 950 /*
951 951 * Hold the lb_lock here, this will make
952 952 * all the threads trying to access lb->logfile block
953 953 * and get a new logfile structure instead of old one.
954 954 */
955 955 mutex_enter(&(lbp)->lb_lock);
956 956 lbp->lb_logfile = logfile;
957 957 mutex_exit(&(lbp)->lb_lock);
958 958
959 959 LOG_FILE_RELE(lf); /* release log_buffer's reference */
960 960
961 961 /*
962 962 * Wait for log_file to be in a quiescent state before we
963 963 * return to our caller to let it proceed with the reading of
964 964 * this file.
965 965 */
966 966 nfslog_logfile_wait(lf);
967 967
968 968 out:
969 969 /*
970 970 * Release our reference on "lf" in two different cases.
971 971 * 1. Error condition, release only the reference
972 972 * that we held at the begining of this
973 973 * routine on "lf" structure.
974 974 * 2. Fall through condition, no errors but the old
975 975 * logfile structure "lf" has been replaced with
976 976 * the new "logfile" structure, so release the
977 977 * reference that was part of the creation of
978 978 * "lf" structure to free up the resources.
979 979 */
980 980
981 981 LOG_FILE_RELE(lf);
982 982
983 983 return (error);
984 984 }
985 985
986 986 /*
987 987 * Renames the 'from' file to 'new'.
988 988 */
989 989 static int
990 990 nfslog_logfile_rename(char *from, char *new)
991 991 {
992 992 int error;
993 993
994 994 if (error = vn_rename(from, new, UIO_SYSSPACE)) {
995 995 cmn_err(CE_WARN,
996 996 "nfslog_logfile_rename: couldn't rename %s to %s\n",
997 997 from, new);
998 998 }
999 999 return (error);
1000 1000 }
1001 1001
1002 1002 /*
1003 1003 * Wait for the log_file writers to finish before returning
1004 1004 */
1005 1005 static void
1006 1006 nfslog_logfile_wait(struct log_file *lf)
1007 1007 {
1008 1008 mutex_enter(&lf->lf_lock);
1009 1009 while (lf->lf_writers > 0) {
1010 1010 lf->lf_flags |= L_WAITING;
1011 1011 (void) cv_wait_sig(&lf->lf_cv_waiters, &lf->lf_lock);
1012 1012 }
1013 1013 mutex_exit(&lf->lf_lock);
1014 1014 }
1015 1015
1016 1016 static int
1017 1017 nfslog_record_append2all(struct lr_alloc *lrp)
1018 1018 {
1019 1019 struct log_buffer *lbp, *nlbp;
1020 1020 int error, ret_error = 0;
1021 1021 int lr_flags = lrp->lr_flags;
1022 1022
1023 1023 rw_enter(&nfslog_buffer_list_lock, RW_READER);
1024 1024 if ((lbp = nfslog_buffer_list) != NULL)
1025 1025 LOG_BUFFER_HOLD(lbp);
1026 1026 for (nlbp = NULL; lbp != NULL; lbp = nlbp) {
1027 1027 if ((nlbp = lbp->lb_next) != NULL) {
1028 1028 /*
1029 1029 * Remember next element in the list
1030 1030 */
1031 1031 LOG_BUFFER_HOLD(nlbp);
1032 1032 }
1033 1033 rw_exit(&nfslog_buffer_list_lock);
1034 1034
1035 1035 /*
1036 1036 * Insert the record on the buffer's list to be written
1037 1037 * and then flush the records to the log file.
1038 1038 * Make sure to set the no free flag so that the
1039 1039 * record can be used for the next write
1040 1040 */
1041 1041 lrp->lr_flags = LR_ALLOC_NOFREE;
1042 1042
1043 1043 ASSERT(lbp != NULL);
1044 1044 mutex_enter(&lbp->lb_lock);
1045 1045 if (lbp->lb_records == NULL) {
1046 1046 lbp->lb_records = (caddr_t)lrp;
1047 1047 lbp->lb_num_recs = 1;
1048 1048 lbp->lb_size_queued = lrp->size;
1049 1049 } else {
1050 1050 insque(lrp, ((struct lr_alloc *)lbp->lb_records)->prev);
1051 1051 lbp->lb_num_recs++;
1052 1052 lbp->lb_size_queued += lrp->size;
1053 1053 }
1054 1054
1055 1055 /*
1056 1056 * Flush log records to disk.
1057 1057 * Function is called with lb_lock held.
1058 1058 * Function drops the lb_lock on return.
1059 1059 */
1060 1060 error = nfslog_records_flush_to_disk_nolock(lbp);
1061 1061
1062 1062 if (error) {
1063 1063 ret_error = -1;
1064 1064 nfs_cmn_err(error, CE_WARN,
1065 1065 "rfsl_log_pubfh: could not append record to "
1066 1066 "\"%s\" error = %m\n", lbp->lb_path);
1067 1067 }
1068 1068 log_buffer_rele(lbp);
1069 1069 rw_enter(&nfslog_buffer_list_lock, RW_READER);
1070 1070 }
1071 1071 rw_exit(&nfslog_buffer_list_lock);
1072 1072
1073 1073 lrp->lr_flags = lr_flags;
1074 1074
1075 1075 return (ret_error);
1076 1076 }
1077 1077
1078 1078 #ifdef DEBUG
1079 1079 static int logging_debug = 0;
1080 1080
1081 1081 /*
1082 1082 * 0) no debugging
1083 1083 * 3) current test software
1084 1084 * 10) random stuff
1085 1085 */
1086 1086 void
1087 1087 nfslog_dprint(const int level, const char *fmt, ...)
1088 1088 {
1089 1089 va_list args;
1090 1090
1091 1091 if (logging_debug == level ||
1092 1092 (logging_debug > 10 && (logging_debug - 10) >= level)) {
1093 1093 va_start(args, fmt);
1094 1094 (void) vprintf(fmt, args);
1095 1095 va_end(args);
1096 1096 }
1097 1097 }
1098 1098
1099 1099 #endif /* DEBUG */
1100 1100
1101 1101 /*
1102 1102 * NFS Log Flush system call
1103 1103 * Caller must check privileges.
1104 1104 */
1105 1105 /* ARGSUSED */
1106 1106 int
1107 1107 nfsl_flush(struct nfsl_flush_args *args, model_t model)
1108 1108 {
1109 1109 struct flush_thread_params *tparams;
1110 1110 struct nfsl_flush_args *nfsl_args;
1111 1111 int error = 0;
1112 1112 ulong_t buffer_len;
1113 1113 STRUCT_HANDLE(nfsl_flush_args, uap);
1114 1114
1115 1115 STRUCT_SET_HANDLE(uap, model, args);
1116 1116
1117 1117 tparams = (struct flush_thread_params *)
1118 1118 kmem_zalloc(sizeof (*tparams), KM_SLEEP);
1119 1119
1120 1120 nfsl_args = &tparams->tp_args;
1121 1121 nfsl_args->version = STRUCT_FGET(uap, version);
1122 1122 if (nfsl_args->version != NFSL_FLUSH_ARGS_VERS) {
1123 1123 cmn_err(CE_WARN, "nfsl_flush: exected version %d, got %d",
1124 1124 NFSL_FLUSH_ARGS_VERS, nfsl_args->version);
1125 1125 return (EIO);
1126 1126 }
1127 1127
1128 1128 nfsl_args->directive = STRUCT_FGET(uap, directive);
1129 1129 if ((nfsl_args->directive & NFSL_ALL) == 0) {
1130 1130 /*
1131 1131 * Process a specific buffer
1132 1132 */
1133 1133 nfsl_args->buff_len = STRUCT_FGET(uap, buff_len);
1134 1134
1135 1135 nfsl_args->buff = (char *)
1136 1136 kmem_alloc(nfsl_args->buff_len, KM_NOSLEEP);
1137 1137 if (nfsl_args->buff == NULL)
1138 1138 return (ENOMEM);
1139 1139
1140 1140 error = copyinstr((const char *)STRUCT_FGETP(uap, buff),
1141 1141 nfsl_args->buff, nfsl_args->buff_len, &buffer_len);
1142 1142 if (error)
1143 1143 return (EFAULT);
1144 1144
1145 1145 if (nfsl_args->buff_len != buffer_len)
1146 1146 return (EFAULT);
1147 1147 }
1148 1148
1149 1149 LOGGING_DPRINT((10, "nfsl_flush: Flushing %s buffer(s)\n",
1150 1150 nfsl_args->directive & NFSL_ALL ? "all" : nfsl_args->buff));
1151 1151
1152 1152 if (nfsl_args->directive & NFSL_SYNC) {
1153 1153 /*
|
↓ open down ↓ |
371 lines elided |
↑ open up ↑ |
1154 1154 * Do the work synchronously
1155 1155 */
1156 1156 nfslog_do_flush(tparams);
1157 1157 error = tparams->tp_error;
1158 1158 kmem_free(nfsl_args->buff, nfsl_args->buff_len);
1159 1159 kmem_free(tparams, sizeof (*tparams));
1160 1160 } else {
1161 1161 /*
1162 1162 * Do the work asynchronously
1163 1163 */
1164 - (void) thread_create(NULL, 0, nfslog_do_flush,
1165 - tparams, 0, &p0, TS_RUN, minclsyspri);
1164 + (void) zthread_create(NULL, 0, nfslog_do_flush,
1165 + tparams, 0, minclsyspri);
1166 1166 }
1167 1167
1168 1168 return (error);
1169 1169 }
1170 1170
1171 1171 /*
1172 1172 * This is where buffer flushing would occur, but there is no buffering
1173 1173 * at this time.
1174 1174 * Possibly rename the log buffer for processing.
1175 1175 * Sets tparams->ta_error equal to the value of the error that occurred,
1176 1176 * 0 otherwise.
1177 1177 * Returns ENOENT if the buffer is not found.
1178 1178 */
1179 1179 static void
1180 1180 nfslog_do_flush(struct flush_thread_params *tparams)
1181 1181 {
1182 1182 struct nfsl_flush_args *args;
1183 1183 struct log_buffer *lbp, *nlbp;
1184 1184 int error = ENOENT;
1185 1185 int found = 0;
1186 1186 char *buf_inprog; /* name of buff in progress */
1187 1187 int buf_inprog_len;
1188 1188
1189 1189 /*
1190 1190 * Sanity check on the arguments.
1191 1191 */
1192 1192 if (!tparams)
1193 1193 return;
1194 1194 args = &tparams->tp_args;
1195 1195 if (!args)
1196 1196 return;
1197 1197
1198 1198 rw_enter(&nfslog_buffer_list_lock, RW_READER);
1199 1199 if ((lbp = nfslog_buffer_list) != NULL) {
1200 1200 LOG_BUFFER_HOLD(lbp);
1201 1201 }
1202 1202 for (nlbp = NULL; lbp != NULL; lbp = nlbp) {
1203 1203 if ((nlbp = lbp->lb_next) != NULL) {
1204 1204 LOG_BUFFER_HOLD(nlbp);
1205 1205 }
1206 1206 rw_exit(&nfslog_buffer_list_lock);
1207 1207 if (args->directive & NFSL_ALL) {
1208 1208 (void) nfslog_records_flush_to_disk(lbp);
1209 1209 } else {
1210 1210 if ((strcmp(lbp->lb_path, args->buff) == 0) &&
1211 1211 (args->directive & NFSL_RENAME)) {
1212 1212 error = nfslog_logbuffer_rename(lbp);
1213 1213 found++;
1214 1214 if (nlbp != NULL)
1215 1215 log_buffer_rele(nlbp);
1216 1216 log_buffer_rele(lbp);
1217 1217 break;
1218 1218 }
1219 1219 }
1220 1220 log_buffer_rele(lbp);
1221 1221 rw_enter(&nfslog_buffer_list_lock, RW_READER);
1222 1222 }
1223 1223 if (!found)
1224 1224 rw_exit(&nfslog_buffer_list_lock);
1225 1225
1226 1226 if (!found && ((args->directive & NFSL_ALL) == 0) &&
1227 1227 (args->directive & NFSL_RENAME)) {
1228 1228 /*
1229 1229 * The specified buffer is not currently in use,
1230 1230 * simply rename the file indicated.
1231 1231 */
1232 1232 buf_inprog_len = strlen(args->buff) +
1233 1233 strlen(LOG_INPROG_STRING) + 1;
1234 1234 buf_inprog = (caddr_t)kmem_alloc(buf_inprog_len, KM_SLEEP);
1235 1235 (void) sprintf(buf_inprog, "%s%s",
1236 1236 args->buff, LOG_INPROG_STRING);
1237 1237
1238 1238 error = nfslog_logfile_rename(buf_inprog, args->buff);
1239 1239
1240 1240 kmem_free(buf_inprog, buf_inprog_len);
1241 1241 }
|
↓ open down ↓ |
66 lines elided |
↑ open up ↑ |
1242 1242
1243 1243 out:
1244 1244 if ((args->directive & NFSL_SYNC) == 0) {
1245 1245 /*
1246 1246 * Work was performed asynchronously, the caller is
1247 1247 * no longer waiting for us.
1248 1248 * Free the thread arguments and exit.
1249 1249 */
1250 1250 kmem_free(args->buff, args->buff_len);
1251 1251 kmem_free(tparams, sizeof (*tparams));
1252 - thread_exit();
1253 - /* NOTREACHED */
1252 + zthread_exit();
1254 1253 }
1255 1254
1256 1255 tparams->tp_error = error;
1257 1256 }
1258 1257
1259 1258 /*
1260 1259 * Generate buffer_header.
1261 1260 * 'loghdr' points the the buffer_header, and *reclen
1262 1261 * contains the length of the buffer.
1263 1262 */
1264 1263 static void
1265 1264 create_buffer_header(caddr_t *loghdr, size_t *reclen, size_t *freesize)
1266 1265 {
1267 1266 timestruc_t now;
1268 1267 nfslog_buffer_header lh;
1269 1268 XDR xdrs;
1270 1269 unsigned int final_size;
1271 1270
1272 1271
1273 1272 /* pick some size that will hold the buffer_header */
1274 1273 *freesize = NFSLOG_SMALL_RECORD_SIZE;
1275 1274
1276 1275 /*
1277 1276 * Fill header
1278 1277 */
1279 1278 lh.bh_length = 0; /* don't know yet how large it will be */
1280 1279 lh.bh_version = NFSLOG_BUF_VERSION;
1281 1280 lh.bh_flags = 0;
1282 1281 lh.bh_offset = 0;
1283 1282 gethrestime(&now);
1284 1283 TIMESPEC_TO_TIMESPEC32(&lh.bh_timestamp, &now);
1285 1284
1286 1285 /*
1287 1286 * Encode the header
1288 1287 */
1289 1288 *loghdr = (caddr_t)kmem_alloc(*freesize, KM_SLEEP);
1290 1289 xdrmem_create(&xdrs, *loghdr, *freesize, XDR_ENCODE);
1291 1290
1292 1291 (void) xdr_nfslog_buffer_header(&xdrs, &lh);
1293 1292
1294 1293 /*
1295 1294 * Reset with final size of the encoded data
1296 1295 */
1297 1296 final_size = xdr_getpos(&xdrs);
1298 1297 xdr_setpos(&xdrs, 0);
1299 1298 (void) xdr_u_int(&xdrs, &final_size);
1300 1299
1301 1300 *reclen = (size_t)final_size;
1302 1301 }
1303 1302
1304 1303 /*
1305 1304 * ****************************************************************
1306 1305 * RPC dispatch table for logging
1307 1306 * Indexed by program, version, proc
1308 1307 * Based on NFS dispatch table.
1309 1308 */
1310 1309 struct nfslog_proc_disp {
1311 1310 bool_t (*xdrargs)();
1312 1311 bool_t (*xdrres)();
1313 1312 bool_t affects_transactions; /* Operation affects transaction */
1314 1313 /* processing */
1315 1314 };
1316 1315
1317 1316 struct nfslog_vers_disp {
1318 1317 int nfslog_dis_nprocs; /* number of procs */
1319 1318 struct nfslog_proc_disp *nfslog_dis_proc_table; /* proc array */
1320 1319 };
1321 1320
1322 1321 struct nfslog_prog_disp {
1323 1322 int nfslog_dis_prog; /* program number */
1324 1323 int nfslog_dis_versmin; /* Minimum version value */
1325 1324 int nfslog_dis_nvers; /* Number of version values */
1326 1325 struct nfslog_vers_disp *nfslog_dis_vers_table; /* versions array */
1327 1326 };
1328 1327
1329 1328 static int rfs_log_bad = 0; /* incremented on bad log attempts */
1330 1329 static int rfs_log_good = 0; /* incremented on successful log attempts */
1331 1330
1332 1331 /*
1333 1332 * Define the actions taken per prog/vers/proc:
1334 1333 *
1335 1334 * In some cases, the nl types are the same as the nfs types and a simple
1336 1335 * bcopy should suffice. Rather that define tens of identical procedures,
1337 1336 * simply define these to bcopy. Similarly this takes care of different
1338 1337 * procs that use same parameter struct.
1339 1338 */
1340 1339
1341 1340 static struct nfslog_proc_disp nfslog_proc_v2[] = {
1342 1341 /*
1343 1342 * NFS VERSION 2
1344 1343 */
1345 1344
1346 1345 /* RFS_NULL = 0 */
1347 1346 {xdr_void, xdr_void, FALSE},
1348 1347
1349 1348 /* RFS_GETATTR = 1 */
1350 1349 {xdr_fhandle, xdr_nfslog_getattrres, FALSE},
1351 1350
1352 1351 /* RFS_SETATTR = 2 */
1353 1352 {xdr_nfslog_setattrargs, xdr_nfsstat, TRUE},
1354 1353
1355 1354 /* RFS_ROOT = 3 *** NO LONGER SUPPORTED *** */
1356 1355 {xdr_void, xdr_void, FALSE},
1357 1356
1358 1357 /* RFS_LOOKUP = 4 */
1359 1358 {xdr_nfslog_diropargs, xdr_nfslog_diropres, TRUE},
1360 1359
1361 1360 /* RFS_READLINK = 5 */
1362 1361 {xdr_fhandle, xdr_nfslog_rdlnres, FALSE},
1363 1362
1364 1363 /* RFS_READ = 6 */
1365 1364 {xdr_nfslog_nfsreadargs, xdr_nfslog_rdresult, TRUE},
1366 1365
1367 1366 /* RFS_WRITECACHE = 7 *** NO LONGER SUPPORTED *** */
1368 1367 {xdr_void, xdr_void, FALSE},
1369 1368
1370 1369 /* RFS_WRITE = 8 */
1371 1370 {xdr_nfslog_writeargs, xdr_nfslog_writeresult, TRUE},
1372 1371
1373 1372 /* RFS_CREATE = 9 */
1374 1373 {xdr_nfslog_createargs, xdr_nfslog_diropres, TRUE},
1375 1374
1376 1375 /* RFS_REMOVE = 10 */
1377 1376 {xdr_nfslog_diropargs, xdr_nfsstat, TRUE},
1378 1377
1379 1378 /* RFS_RENAME = 11 */
1380 1379 {xdr_nfslog_rnmargs, xdr_nfsstat, TRUE},
1381 1380
1382 1381 /* RFS_LINK = 12 */
1383 1382 {xdr_nfslog_linkargs, xdr_nfsstat, TRUE},
1384 1383
1385 1384 /* RFS_SYMLINK = 13 */
1386 1385 {xdr_nfslog_symlinkargs, xdr_nfsstat, TRUE},
1387 1386
1388 1387 /* RFS_MKDIR = 14 */
1389 1388 {xdr_nfslog_createargs, xdr_nfslog_diropres, TRUE},
1390 1389
1391 1390 /* RFS_RMDIR = 15 */
1392 1391 {xdr_nfslog_diropargs, xdr_nfsstat, TRUE},
1393 1392
1394 1393 /* RFS_READDIR = 16 */
1395 1394 {xdr_nfslog_rddirargs, xdr_nfslog_rddirres, TRUE},
1396 1395
1397 1396 /* RFS_STATFS = 17 */
1398 1397 {xdr_fhandle, xdr_nfslog_statfs, FALSE},
1399 1398 };
1400 1399
1401 1400
1402 1401 /*
1403 1402 * NFS VERSION 3
1404 1403 */
1405 1404
1406 1405 static struct nfslog_proc_disp nfslog_proc_v3[] = {
1407 1406
1408 1407 /* NFSPROC3_NULL = 0 */
1409 1408 {xdr_void, xdr_void, FALSE},
1410 1409
1411 1410 /* NFSPROC3_GETATTR = 1 */
1412 1411 {xdr_nfslog_nfs_fh3, xdr_nfslog_GETATTR3res, FALSE},
1413 1412
1414 1413 /* NFSPROC3_SETATTR = 2 */
1415 1414 {xdr_nfslog_SETATTR3args, xdr_nfslog_SETATTR3res, TRUE},
1416 1415
1417 1416 /* NFSPROC3_LOOKUP = 3 */
1418 1417 {xdr_nfslog_diropargs3, xdr_nfslog_LOOKUP3res, TRUE},
1419 1418
1420 1419 /* NFSPROC3_ACCESS = 4 */
1421 1420 {xdr_nfslog_ACCESS3args, xdr_nfslog_ACCESS3res, FALSE},
1422 1421
1423 1422 /* NFSPROC3_READLINK = 5 */
1424 1423 {xdr_nfslog_nfs_fh3, xdr_nfslog_READLINK3res, FALSE},
1425 1424
1426 1425 /* NFSPROC3_READ = 6 */
1427 1426 {xdr_nfslog_READ3args, xdr_nfslog_READ3res, TRUE},
1428 1427
1429 1428 /* NFSPROC3_WRITE = 7 */
1430 1429 {xdr_nfslog_WRITE3args, xdr_nfslog_WRITE3res, TRUE},
1431 1430
1432 1431 /* NFSPROC3_CREATE = 8 */
1433 1432 {xdr_nfslog_CREATE3args, xdr_nfslog_CREATE3res, TRUE},
1434 1433
1435 1434 /* NFSPROC3_MKDIR = 9 */
1436 1435 {xdr_nfslog_MKDIR3args, xdr_nfslog_MKDIR3res, TRUE},
1437 1436
1438 1437 /* NFSPROC3_SYMLINK = 10 */
1439 1438 {xdr_nfslog_SYMLINK3args, xdr_nfslog_SYMLINK3res, TRUE},
1440 1439
1441 1440 /* NFSPROC3_MKNOD = 11 */
1442 1441 {xdr_nfslog_MKNOD3args, xdr_nfslog_MKNOD3res, TRUE},
1443 1442
1444 1443 /* NFSPROC3_REMOVE = 12 */
1445 1444 {xdr_nfslog_REMOVE3args, xdr_nfslog_REMOVE3res, TRUE},
1446 1445
1447 1446 /* NFSPROC3_RMDIR = 13 */
1448 1447 {xdr_nfslog_RMDIR3args, xdr_nfslog_RMDIR3res, TRUE},
1449 1448
1450 1449 /* NFSPROC3_RENAME = 14 */
1451 1450 {xdr_nfslog_RENAME3args, xdr_nfslog_RENAME3res, TRUE},
1452 1451
1453 1452 /* NFSPROC3_LINK = 15 */
1454 1453 {xdr_nfslog_LINK3args, xdr_nfslog_LINK3res, TRUE},
1455 1454
1456 1455 /* NFSPROC3_READDIR = 16 */
1457 1456 {xdr_nfslog_READDIR3args, xdr_nfslog_READDIR3res, TRUE},
1458 1457
1459 1458 /* NFSPROC3_READDIRPLUS = 17 */
1460 1459 {xdr_nfslog_READDIRPLUS3args, xdr_nfslog_READDIRPLUS3res, TRUE},
1461 1460
1462 1461 /* NFSPROC3_FSSTAT = 18 */
1463 1462 {xdr_nfslog_FSSTAT3args, xdr_nfslog_FSSTAT3res, FALSE},
1464 1463
1465 1464 /* NFSPROC3_FSINFO = 19 */
1466 1465 {xdr_nfslog_FSINFO3args, xdr_nfslog_FSINFO3res, FALSE},
1467 1466
1468 1467 /* NFSPROC3_PATHCONF = 20 */
1469 1468 {xdr_nfslog_PATHCONF3args, xdr_nfslog_PATHCONF3res, FALSE},
1470 1469
1471 1470 /* NFSPROC3_COMMIT = 21 */
1472 1471 {xdr_nfslog_COMMIT3args, xdr_nfslog_COMMIT3res, FALSE},
1473 1472 };
1474 1473
1475 1474 static struct nfslog_proc_disp nfslog_proc_v1[] = {
1476 1475 /*
1477 1476 * NFSLOG VERSION 1
1478 1477 */
1479 1478
1480 1479 /* NFSLOG_NULL = 0 */
1481 1480 {xdr_void, xdr_void, TRUE},
1482 1481
1483 1482 /* NFSLOG_SHARE = 1 */
1484 1483 {xdr_nfslog_sharefsargs, xdr_nfslog_sharefsres, TRUE},
1485 1484
1486 1485 /* NFSLOG_UNSHARE = 2 */
1487 1486 {xdr_nfslog_sharefsargs, xdr_nfslog_sharefsres, TRUE},
1488 1487
1489 1488 /* NFSLOG_LOOKUP = 3 */
1490 1489 {xdr_nfslog_diropargs3, xdr_nfslog_LOOKUP3res, TRUE},
1491 1490
1492 1491 /* NFSLOG_GETFH = 4 */
1493 1492 {xdr_nfslog_getfhargs, xdr_nfsstat, TRUE},
1494 1493 };
1495 1494
1496 1495 static struct nfslog_vers_disp nfslog_vers_disptable[] = {
1497 1496 {sizeof (nfslog_proc_v2) / sizeof (nfslog_proc_v2[0]),
1498 1497 nfslog_proc_v2},
1499 1498 {sizeof (nfslog_proc_v3) / sizeof (nfslog_proc_v3[0]),
1500 1499 nfslog_proc_v3},
1501 1500 };
1502 1501
1503 1502 static struct nfslog_vers_disp nfslog_nfslog_vers_disptable[] = {
1504 1503 {sizeof (nfslog_proc_v1) / sizeof (nfslog_proc_v1[0]),
1505 1504 nfslog_proc_v1},
1506 1505 };
1507 1506
1508 1507 static struct nfslog_prog_disp nfslog_dispatch_table[] = {
1509 1508 {NFS_PROGRAM, NFS_VERSMIN,
1510 1509 (sizeof (nfslog_vers_disptable) /
1511 1510 sizeof (nfslog_vers_disptable[0])),
1512 1511 nfslog_vers_disptable},
1513 1512
1514 1513 {NFSLOG_PROGRAM, NFSLOG_VERSMIN,
1515 1514 (sizeof (nfslog_nfslog_vers_disptable) /
1516 1515 sizeof (nfslog_nfslog_vers_disptable[0])),
1517 1516 nfslog_nfslog_vers_disptable},
1518 1517 };
1519 1518
1520 1519 static int nfslog_dispatch_table_arglen = sizeof (nfslog_dispatch_table) /
1521 1520 sizeof (nfslog_dispatch_table[0]);
|
↓ open down ↓ |
258 lines elided |
↑ open up ↑ |
1522 1521
1523 1522 /*
1524 1523 * This function will determine the appropriate export info struct to use
1525 1524 * and allocate a record id to be used in the written log buffer.
1526 1525 * Usually this is a straightforward operation but the existence of the
1527 1526 * multicomponent lookup and its semantics of crossing file system
1528 1527 * boundaries add to the complexity. See the comments below...
1529 1528 */
1530 1529 struct exportinfo *
1531 1530 nfslog_get_exi(
1531 + nfs_export_t *ne,
1532 1532 struct exportinfo *exi,
1533 1533 struct svc_req *req,
1534 1534 caddr_t res,
1535 1535 unsigned int *nfslog_rec_id)
1536 1536 {
1537 1537 struct log_buffer *lb;
1538 1538 struct exportinfo *exi_ret = NULL;
1539 1539 fhandle_t *fh;
1540 1540 nfs_fh3 *fh3;
1541 1541
1542 1542 if (exi == NULL)
1543 1543 return (NULL);
1544 1544
1545 1545 /*
1546 1546 * If the exi is marked for logging, allocate a record id and return
1547 1547 */
1548 1548 if (exi->exi_export.ex_flags & EX_LOG) {
1549 1549 lb = exi->exi_logbuffer;
1550 1550
1551 1551 /* obtain the unique record id for the caller */
1552 1552 *nfslog_rec_id = atomic_add_32_nv(&lb->lb_rec_id, (int32_t)1);
|
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
1553 1553
1554 1554 /*
1555 1555 * The caller will expect to be able to exi_rele() it,
1556 1556 * so exi->exi_count must be incremented before it can
1557 1557 * be returned, to make it uniform with exi_ret->exi_count
1558 1558 */
1559 1559 exi_hold(exi);
1560 1560 return (exi);
1561 1561 }
1562 1562
1563 - if (exi != exi_public)
1563 + if (exi != ne->exi_public)
1564 1564 return (NULL);
1565 1565
1566 1566 /*
1567 1567 * Here we have an exi that is not marked for logging.
1568 1568 * It is possible that this request is a multicomponent lookup
1569 1569 * that was done from the public file handle (not logged) and
1570 1570 * the resulting file handle being returned to the client exists
1571 1571 * in a file system that is being logged. If this is the case
1572 1572 * we need to log this multicomponent lookup to the appropriate
1573 1573 * log buffer. This will allow for the appropriate path name
1574 1574 * mapping to occur at user level.
1575 1575 */
1576 1576 if (req->rq_prog == NFS_PROGRAM) {
1577 1577 switch (req->rq_vers) {
1578 1578 case NFS_V3:
1579 1579 if ((req->rq_proc == NFSPROC3_LOOKUP) &&
1580 1580 (((LOOKUP3res *)res)->status == NFS3_OK)) {
1581 1581 fh3 = &((LOOKUP3res *)res)->res_u.ok.object;
1582 1582 exi_ret = checkexport(&fh3->fh3_fsid,
1583 1583 FH3TOXFIDP(fh3));
1584 1584 }
1585 1585 break;
1586 1586
1587 1587 case NFS_VERSION:
1588 1588 if ((req->rq_proc == RFS_LOOKUP) &&
1589 1589 (((struct nfsdiropres *)
1590 1590 res)->dr_status == NFS_OK)) {
1591 1591 fh = &((struct nfsdiropres *)res)->
1592 1592 dr_u.dr_drok_u.drok_fhandle;
1593 1593 exi_ret = checkexport(&fh->fh_fsid,
1594 1594 (fid_t *)&fh->fh_xlen);
1595 1595 }
1596 1596 break;
1597 1597 default:
1598 1598 break;
1599 1599 }
1600 1600 }
1601 1601
1602 1602 if (exi_ret != NULL && exi_ret->exi_export.ex_flags & EX_LOG) {
1603 1603 lb = exi_ret->exi_logbuffer;
1604 1604 /* obtain the unique record id for the caller */
1605 1605 *nfslog_rec_id = atomic_add_32_nv(&lb->lb_rec_id, (int32_t)1);
1606 1606
1607 1607 return (exi_ret);
1608 1608 }
1609 1609 return (NULL);
1610 1610 }
1611 1611
1612 1612 #ifdef DEBUG
1613 1613 static long long rfslog_records_ignored = 0;
1614 1614 #endif
1615 1615
1616 1616 /*
1617 1617 * nfslog_write_record - Fill in the record buffer for writing out.
|
↓ open down ↓ |
44 lines elided |
↑ open up ↑ |
1618 1618 * If logrecp is null, log it, otherwise, malloc the record and return it.
1619 1619 *
1620 1620 * It is the responsibility of the caller to check whether this exportinfo
1621 1621 * has logging enabled.
1622 1622 * Note that nfslog_share_public_record() only needs to check for the
1623 1623 * existence of at least one logbuffer to which the public filehandle record
1624 1624 * needs to be logged.
1625 1625 */
1626 1626 void
1627 1627 nfslog_write_record(struct exportinfo *exi, struct svc_req *req,
1628 - caddr_t args, caddr_t res, cred_t *cr, struct netbuf *pnb,
1629 - unsigned int record_id, unsigned int which_buffers)
1628 + caddr_t args, caddr_t res, cred_t *cr, struct netbuf *pnb,
1629 + unsigned int record_id, unsigned int which_buffers)
1630 1630 {
1631 1631 struct nfslog_prog_disp *progtable; /* prog struct */
1632 1632 struct nfslog_vers_disp *verstable; /* version struct */
1633 1633 struct nfslog_proc_disp *disp = NULL; /* proc struct */
1634 1634 int i, vers;
1635 1635 void *log_cookie; /* for logrecord if */
1636 1636 caddr_t buffer;
1637 1637 XDR xdrs;
1638 1638 unsigned int final_size;
1639 1639 int encode_ok;
1640 1640 int alloc_indx;
1641 1641
1642 1642 ASSERT(exi != NULL); ASSERT(req != NULL); ASSERT(args != NULL);
1643 1643 ASSERT(res != NULL); ASSERT(cr != NULL);
1644 1644
1645 1645 /*
1646 1646 * Find program element
1647 1647 * Search the list since program can not be used as index
1648 1648 */
1649 1649 for (i = 0; (i < nfslog_dispatch_table_arglen); i++) {
1650 1650 if (req->rq_prog == nfslog_dispatch_table[i].nfslog_dis_prog)
1651 1651 break;
1652 1652 }
1653 1653 if (i >= nfslog_dispatch_table_arglen) { /* program not logged */
1654 1654 /* not an error */
1655 1655 return;
1656 1656 }
1657 1657
1658 1658 /*
1659 1659 * Extract the dispatch functions based on program/version
1660 1660 */
1661 1661 progtable = &nfslog_dispatch_table[i];
1662 1662 vers = req->rq_vers - progtable->nfslog_dis_versmin;
1663 1663 verstable = &progtable->nfslog_dis_vers_table[vers];
1664 1664 disp = &verstable->nfslog_dis_proc_table[req->rq_proc];
1665 1665
1666 1666 if (!(exi->exi_export.ex_flags & EX_LOG_ALLOPS) &&
1667 1667 !disp->affects_transactions) {
1668 1668 /*
1669 1669 * Only interested in logging operations affecting
1670 1670 * transaction generation. This is not one of them.
1671 1671 */
1672 1672 #ifdef DEBUG
1673 1673 rfslog_records_ignored++;
1674 1674 #endif
1675 1675 return;
1676 1676 }
1677 1677
1678 1678 switch (req->rq_prog) {
1679 1679 case NFS_PROGRAM:
1680 1680 switch (req->rq_vers) {
1681 1681 case NFS_V3:
1682 1682 switch (req->rq_proc) {
1683 1683 case NFSPROC3_READDIRPLUS:
1684 1684 alloc_indx = MEDIUM_INDX;
1685 1685 break;
1686 1686 default:
1687 1687 alloc_indx = SMALL_INDX;
1688 1688 break;
1689 1689 }
1690 1690 break;
1691 1691 default:
1692 1692 alloc_indx = SMALL_INDX;
1693 1693 break;
1694 1694 }
1695 1695 break;
1696 1696 case NFSLOG_PROGRAM:
1697 1697 alloc_indx = MEDIUM_INDX;
1698 1698 break;
1699 1699 default:
1700 1700 alloc_indx = SMALL_INDX;
1701 1701 break;
1702 1702 }
1703 1703
1704 1704 do {
1705 1705 encode_ok = FALSE;
1706 1706
1707 1707 /* Pick the size to alloc; end of the road - return */
1708 1708 if (nfslog_mem_alloc[alloc_indx].size == (-1)) {
1709 1709 cmn_err(CE_WARN,
1710 1710 "NFSLOG: unable to encode record - prog=%d "
1711 1711 "proc = %d", req->rq_prog, req->rq_proc);
1712 1712 return;
1713 1713 }
1714 1714
1715 1715 buffer = nfslog_record_alloc(exi, alloc_indx, &log_cookie, 0);
1716 1716 if (buffer == NULL) {
1717 1717 /* Error processing - no space alloced */
1718 1718 rfs_log_bad++;
1719 1719 cmn_err(CE_WARN, "NFSLOG: can't get record");
1720 1720 return;
1721 1721 }
1722 1722
1723 1723 xdrmem_create(&xdrs, buffer,
1724 1724 nfslog_mem_alloc[alloc_indx].size, XDR_ENCODE);
1725 1725
1726 1726 /*
1727 1727 * Encode the header, args and results of the record
1728 1728 */
1729 1729 if (xdr_nfslog_request_record(&xdrs, exi, req, cr, pnb,
1730 1730 nfslog_mem_alloc[alloc_indx].size, record_id) &&
1731 1731 (*disp->xdrargs)(&xdrs, args) &&
1732 1732 (*disp->xdrres)(&xdrs, res)) {
1733 1733 encode_ok = TRUE;
1734 1734
1735 1735 rfs_log_good++;
1736 1736 /*
1737 1737 * Get the final size of the encoded
1738 1738 * data and insert that length at the
1739 1739 * beginning.
1740 1740 */
1741 1741 final_size = xdr_getpos(&xdrs);
1742 1742 xdr_setpos(&xdrs, 0);
1743 1743 (void) xdr_u_int(&xdrs, &final_size);
1744 1744 } else {
1745 1745 /* Oops, the encode failed so we need to free memory */
1746 1746 nfslog_record_put(log_cookie, 0, FALSE, which_buffers);
1747 1747 alloc_indx++;
1748 1748 }
1749 1749
1750 1750 } while (encode_ok == FALSE);
1751 1751
1752 1752
1753 1753 /*
1754 1754 * Take the final log record and put it in the log file.
1755 1755 * This may be queued to the file internally and written
1756 1756 * later unless the last parameter is TRUE.
|
↓ open down ↓ |
117 lines elided |
↑ open up ↑ |
1757 1757 * If the record_id is 0 then this is most likely a share/unshare
1758 1758 * request and it should be written synchronously to the log file.
1759 1759 */
1760 1760 nfslog_record_put(log_cookie,
1761 1761 final_size, (record_id == 0), which_buffers);
1762 1762 }
1763 1763
1764 1764 static char *
1765 1765 get_publicfh_path(int *alloc_length)
1766 1766 {
1767 - extern struct exportinfo *exi_public;
1768 1767 char *pubpath;
1768 + nfs_export_t *ne = nfs_get_export();
1769 1769
1770 - rw_enter(&exported_lock, RW_READER);
1770 + rw_enter(&ne->exported_lock, RW_READER);
1771 1771
1772 - *alloc_length = exi_public->exi_export.ex_pathlen + 1;
1772 + *alloc_length = ne->exi_public->exi_export.ex_pathlen + 1;
1773 1773 pubpath = kmem_alloc(*alloc_length, KM_SLEEP);
1774 1774
1775 - (void) strcpy(pubpath, exi_public->exi_export.ex_path);
1775 + (void) strcpy(pubpath, ne->exi_public->exi_export.ex_path);
1776 1776
1777 - rw_exit(&exported_lock);
1777 + rw_exit(&ne->exported_lock);
1778 1778
1779 1779 return (pubpath);
1780 1780 }
1781 1781
1782 1782 static void
1783 1783 log_public_record(struct exportinfo *exi, cred_t *cr)
1784 1784 {
1785 1785 struct svc_req req;
1786 1786 struct netbuf nb = {0, 0, NULL};
1787 1787 int free_length = 0;
1788 1788 diropargs3 args;
1789 1789 LOOKUP3res res;
1790 1790
1791 1791 bzero(&req, sizeof (req));
1792 1792 req.rq_prog = NFSLOG_PROGRAM;
1793 1793 req.rq_vers = NFSLOG_VERSION;
1794 1794 req.rq_proc = NFSLOG_LOOKUP;
1795 1795 req.rq_cred.oa_flavor = AUTH_NONE;
1796 1796
1797 1797 bzero(&args, sizeof (diropargs3));
1798 1798 bzero(&res, sizeof (LOOKUP3res));
1799 1799
1800 1800 args.dir.fh3_length = 0;
1801 1801 if ((args.name = get_publicfh_path(&free_length)) == NULL)
1802 1802 return;
1803 1803 args.dirp = &args.dir;
1804 1804
1805 1805 res.status = NFS3_OK;
1806 1806 res.res_u.ok.object.fh3_length = 0;
1807 1807
1808 1808 /*
1809 1809 * Calling this function with the exi_public
1810 1810 * will have the effect of appending the record
1811 1811 * to each of the open log buffers
1812 1812 */
1813 1813 nfslog_write_record(exi, &req,
1814 1814 (caddr_t)&args, (caddr_t)&res, cr, &nb, 0, NFSLOG_ALL_BUFFERS);
1815 1815
1816 1816 kmem_free(args.name, free_length);
1817 1817 }
1818 1818
1819 1819 /*
1820 1820 * nfslog_share_record - logs a share request.
1821 1821 * This is not an NFS request, but we pretend here...
1822 1822 */
1823 1823 void
1824 1824 nfslog_share_record(struct exportinfo *exi, cred_t *cr)
1825 1825 {
1826 1826 struct svc_req req;
1827 1827 int res = 0;
1828 1828 struct netbuf nb = {0, 0, NULL};
1829 1829
1830 1830 ASSERT(exi != NULL);
1831 1831
1832 1832 if (nfslog_buffer_list == NULL)
1833 1833 return;
1834 1834
1835 1835 if (exi->exi_export.ex_flags & EX_LOG) {
1836 1836 bzero(&req, sizeof (req));
1837 1837 req.rq_prog = NFSLOG_PROGRAM;
1838 1838 req.rq_vers = NFSLOG_VERSION;
1839 1839 req.rq_proc = NFSLOG_SHARE;
1840 1840 req.rq_cred.oa_flavor = AUTH_NONE;
1841 1841 nfslog_write_record(exi, &req, (caddr_t)exi, (caddr_t)&res, cr,
1842 1842 &nb, 0, NFSLOG_ONE_BUFFER);
1843 1843 }
1844 1844
1845 1845 log_public_record(exi, cr);
1846 1846 }
1847 1847
1848 1848 /*
1849 1849 * nfslog_unshare_record - logs an unshare request.
1850 1850 * This is not an NFS request, but we pretend here...
1851 1851 */
1852 1852 void
1853 1853 nfslog_unshare_record(struct exportinfo *exi, cred_t *cr)
1854 1854 {
1855 1855 struct svc_req req;
1856 1856 int res = 0;
1857 1857 struct netbuf nb = {0, 0, NULL};
1858 1858
1859 1859 ASSERT(exi != NULL);
1860 1860 ASSERT(exi->exi_export.ex_flags & EX_LOG);
1861 1861
1862 1862 bzero(&req, sizeof (req));
|
↓ open down ↓ |
75 lines elided |
↑ open up ↑ |
1863 1863 req.rq_prog = NFSLOG_PROGRAM;
1864 1864 req.rq_vers = NFSLOG_VERSION;
1865 1865 req.rq_proc = NFSLOG_UNSHARE;
1866 1866 req.rq_cred.oa_flavor = AUTH_NONE;
1867 1867 nfslog_write_record(exi, &req,
1868 1868 (caddr_t)exi, (caddr_t)&res, cr, &nb, 0, NFSLOG_ONE_BUFFER);
1869 1869 }
1870 1870
1871 1871
1872 1872 void
1873 -nfslog_getfh(struct exportinfo *exi,
1874 - fhandle *fh,
1875 - char *fname,
1876 - enum uio_seg seg,
1877 - cred_t *cr)
1873 +nfslog_getfh(struct exportinfo *exi, fhandle *fh, char *fname, enum uio_seg seg,
1874 + cred_t *cr)
1878 1875 {
1879 1876 struct svc_req req;
1880 1877 int res = 0;
1881 1878 struct netbuf nb = {0, 0, NULL};
1882 1879 int error = 0;
1883 1880 char *namebuf;
1884 1881 size_t len;
1885 1882 nfslog_getfhargs gfh;
1886 1883
1887 1884 ASSERT(exi != NULL);
1888 1885 ASSERT(exi->exi_export.ex_flags & EX_LOG);
1889 1886
1890 1887 bzero(&req, sizeof (req));
1891 1888 req.rq_prog = NFSLOG_PROGRAM;
1892 1889 req.rq_vers = NFSLOG_VERSION;
1893 1890 req.rq_proc = NFSLOG_GETFH;
1894 1891 req.rq_cred.oa_flavor = AUTH_NONE;
1895 1892
1896 1893 namebuf = kmem_alloc(MAXPATHLEN + 4, KM_SLEEP);
1897 1894 if (seg == UIO_USERSPACE) {
1898 1895 error = copyinstr(fname, namebuf, MAXPATHLEN, &len);
1899 1896 } else {
1900 1897 error = copystr(fname, namebuf, MAXPATHLEN, &len);
1901 1898 }
1902 1899
1903 1900 if (!error) {
1904 1901 gfh.gfh_fh_buf = *fh;
1905 1902 gfh.gfh_path = namebuf;
1906 1903
1907 1904 nfslog_write_record(exi, &req, (caddr_t)&gfh, (caddr_t)&res,
1908 1905 cr, &nb, 0, NFSLOG_ONE_BUFFER);
1909 1906 }
1910 1907 kmem_free(namebuf, MAXPATHLEN + 4);
1911 1908 }
|
↓ open down ↓ |
24 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX