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
29 #include <sys/param.h>
30 #include <sys/types.h>
31 #include <sys/systm.h>
32 #include <sys/cred.h>
33 #include <sys/proc.h>
34 #include <sys/user.h>
35 #include <sys/vfs.h>
36 #include <sys/vnode.h>
37 #include <sys/pathname.h>
38 #include <sys/uio.h>
39 #include <sys/tiuser.h>
40 #include <sys/sysmacros.h>
41 #include <sys/kmem.h>
42 #include <sys/buf.h>
43 #include <netinet/in.h>
44 #include <rpc/types.h>
45 #include <rpc/xdr.h>
46 #include <rpc/auth.h>
47 #include <rpc/clnt.h>
48 #include <sys/mount.h>
49 #include <sys/ioctl.h>
50 #include <sys/statvfs.h>
51 #include <sys/errno.h>
52 #include <sys/debug.h>
53 #include <sys/cmn_err.h>
54 #include <sys/utsname.h>
55 #include <sys/modctl.h>
56 #include <vm/pvn.h>
57
58 #include <sys/fs/cachefs_fs.h>
59
60 /*
61 * cachefs_max_idle is a global that is tunable.
62 * This value decides how frequently or when the
63 * cachefs_cnode_idleclean is run.
64 * The default value is set to CFS_FS_MAXIDLE.
65 * The tunable if set to X triggers a cleanup when
66 * the number of idle cnodes reach X, and cleans up
67 * (.25 * X) idle cnodes.
68 */
69 int cachefs_max_idle = CFS_FS_MAXIDLE;
70
71
72 struct kmem_cache *cachefs_cnode_cache = NULL;
73
74 /*
75 * Functions for cnode management.
76 */
77
78 /*
79 * Puts cnode on idle list. Only call from an async thread or no
80 * locks held.
81 */
82 /*ARGSUSED1*/
83 void
cachefs_cnode_idle(struct vnode * vp,cred_t * cr)84 cachefs_cnode_idle(struct vnode *vp, cred_t *cr)
85 {
86 cnode_t *cp = VTOC(vp);
87 fscache_t *fscp = C_TO_FSCACHE(cp);
88 int cleanidle;
89 vnode_t *unldvp;
90 cred_t *unlcred;
91 char *unlname;
92 int error;
93
94 /*
95 * The key to this routine is not to drop the vnode count
96 * while on the idle list. This prevents this routine from
97 * being called again by vn_rele on an inactive cnode.
98 * Nothing bad happens if an "active" cnode is put on the idle
99 * list. It eventually gets pulled off.
100 * Also this routine is only called from a thread message sent
101 * by cachefs_inactive(). It is not safe for this routine
102 * to be the "inactive" entry point because of the dnlc.
103 */
104
105 for (;;) {
106 /* get access to the file system */
107 error = cachefs_cd_access(fscp, 0, 1);
108 ASSERT(error == 0);
109
110 /* get exclusive access to this cnode */
111 mutex_enter(&cp->c_statelock);
112
113 /* done with this loop if not unlinking a file */
114 if (cp->c_unldvp == NULL)
115 break;
116
117 /* get unlink info out of the cnode */
118 unldvp = cp->c_unldvp;
119 unlcred = cp->c_unlcred;
120 unlname = cp->c_unlname;
121 cp->c_unldvp = NULL;
122 cp->c_unlcred = NULL;
123 cp->c_unlname = NULL;
124 mutex_exit(&cp->c_statelock);
125
126 /* finish the remove operation */
127 if (fscp->fs_cdconnected == CFS_CD_CONNECTED) {
128 error = cachefs_remove_connected(unldvp,
129 unlname, unlcred, vp);
130 } else {
131 error = cachefs_remove_disconnected(unldvp,
132 unlname, unlcred, vp);
133 }
134
135 /* reacquire cnode lock */
136 mutex_enter(&cp->c_statelock);
137
138 /* if a timeout occurred */
139 if (CFS_TIMEOUT(fscp, error)) {
140 /* restore cnode state */
141 if (cp->c_unldvp == NULL) {
142 cp->c_unldvp = unldvp;
143 cp->c_unlcred = unlcred;
144 cp->c_unlname = unlname;
145 if (fscp->fs_cdconnected == CFS_CD_CONNECTED) {
146 mutex_exit(&cp->c_statelock);
147 cachefs_cd_release(fscp);
148 cachefs_cd_timedout(fscp);
149 continue;
150 } else {
151 cp->c_flags |= CN_PENDRM;
152 mutex_exit(&cp->c_statelock);
153 goto out;
154 }
155 }
156 }
157 /* free up resources */
158 VN_RELE(unldvp);
159 cachefs_kmem_free(unlname, MAXNAMELEN);
160 crfree(unlcred);
161 break;
162 }
163
164 ASSERT((cp->c_flags & CN_IDLE) == 0);
165 /*
166 * If we are going to destroy this cnode,
167 * do it now instead of later.
168 */
169 if (cp->c_flags & (CN_DESTROY | CN_STALE)) {
170 mutex_exit(&cp->c_statelock);
171 (void) cachefs_cnode_inactive(vp, cr);
172 goto out;
173 }
174
175 /*
176 * mark cnode as idle, put it on the idle list, and increment the
177 * number of idle cnodes
178 */
179 cp->c_flags |= CN_IDLE;
180 mutex_enter(&fscp->fs_idlelock);
181 cachefs_cnode_idleadd(cp);
182 if ((fscp->fs_idlecnt > cachefs_max_idle) &&
183 (fscp->fs_idleclean == 0) &&
184 (fscp->fs_cdtransition == 0)) {
185 fscp->fs_idleclean = 1;
186 cleanidle = 1;
187 } else {
188 cleanidle = 0;
189 }
190 mutex_exit(&fscp->fs_idlelock);
191
192 /* release cnode */
193 mutex_exit(&cp->c_statelock);
194
195 /* if should reduce the number of idle cnodes */
196 if (cleanidle) {
197 ASSERT(fscp->fs_idlecnt > 1);
198 fscache_hold(fscp);
199 cachefs_cnode_idleclean(fscp, 0);
200 /* XXX race with cachefs_unmount() calling destroy */
201 fscache_rele(fscp);
202 }
203
204 out:
205 /* release hold on the file system */
206 /* XXX unmount() could have called destroy after fscache_rele() */
207 cachefs_cd_release(fscp);
208 }
209
210 /*
211 * Removes cnodes from the idle list and destroys them.
212 */
213 void
cachefs_cnode_idleclean(fscache_t * fscp,int unmount)214 cachefs_cnode_idleclean(fscache_t *fscp, int unmount)
215 {
216 int remcnt;
217 cnode_t *cp;
218
219 mutex_enter(&fscp->fs_idlelock);
220
221 /* determine number of cnodes to destroy */
222 if (unmount) {
223 /* destroy all plus any that go idle while in this routine */
224 remcnt = fscp->fs_idlecnt * 2;
225 } else {
226 /* reduce to 75% of max allowed idle cnodes */
227 remcnt = (fscp->fs_idlecnt - cachefs_max_idle) +
228 (cachefs_max_idle >> 2);
229 }
230
231 for (; remcnt > 0; remcnt--) {
232 /* get cnode on back of idle list and hold it */
233 cp = fscp->fs_idleback;
234 if (cp == NULL)
235 break;
236 VN_HOLD(CTOV(cp));
237 mutex_exit(&fscp->fs_idlelock);
238
239 /* if the cnode is still on the idle list */
240 mutex_enter(&cp->c_statelock);
241 if (cp->c_flags & CN_IDLE) {
242 cp->c_flags &= ~CN_IDLE;
243
244 /* remove cnode from the idle list */
245 mutex_enter(&fscp->fs_idlelock);
246 cachefs_cnode_idlerem(cp);
247 mutex_exit(&fscp->fs_idlelock);
248 mutex_exit(&cp->c_statelock);
249
250 /* destroy the cnode */
251 VN_RELE(CTOV(cp));
252 (void) cachefs_cnode_inactive(CTOV(cp), kcred);
253 } else {
254 /* cnode went active, just skip it */
255 mutex_exit(&cp->c_statelock);
256 VN_RELE(CTOV(cp));
257 }
258 mutex_enter(&fscp->fs_idlelock);
259 }
260
261 fscp->fs_idleclean = 0;
262 mutex_exit(&fscp->fs_idlelock);
263 }
264
265 /*
266 * This routine does the real work of inactivating a cachefs vnode.
267 */
268 int
cachefs_cnode_inactive(register struct vnode * vp,cred_t * cr)269 cachefs_cnode_inactive(register struct vnode *vp, cred_t *cr)
270 {
271 cnode_t *cp;
272 struct fscache *fscp;
273 struct filegrp *fgp;
274 cachefscache_t *cachep;
275 struct cachefs_metadata *mdp;
276 int meta_destroyed = 0;
277
278 cp = VTOC(vp);
279
280 fscp = C_TO_FSCACHE(cp);
281 cachep = fscp->fs_cache;
282 ASSERT(cachep != NULL);
283 fgp = cp->c_filegrp;
284
285 ASSERT((cp->c_flags & CN_IDLE) == 0);
286
287 /* truncate the front file if necessary */
288 mutex_enter(&cp->c_statelock);
289 if ((cp->c_flags & CN_NOCACHE) && (cp->c_metadata.md_flags & MD_FILE) &&
290 cp->c_metadata.md_frontblks) {
291
292 ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
293
294 #ifdef CFSDEBUG
295 CFS_DEBUG(CFSDEBUG_INVALIDATE)
296 printf("c_cnode_inactive: invalidating %llu\n",
297 (u_longlong_t)cp->c_id.cid_fileno);
298 #endif
299 /*
300 * If the cnode is being populated, and we're not the
301 * populating thread, then block until the pop thread
302 * completes. If we are the pop thread, then we may come in
303 * here, but not to nuke the directory cnode at a critical
304 * juncture.
305 */
306 while ((cp->c_flags & CN_ASYNC_POP_WORKING) &&
307 (cp->c_popthrp != curthread))
308 cv_wait(&cp->c_popcv, &cp->c_statelock);
309
310 cachefs_inval_object(cp);
311 }
312 mutex_exit(&cp->c_statelock);
313
314 for (;;) {
315 /* see if vnode is really inactive */
316 mutex_enter(&vp->v_lock);
317 ASSERT(vp->v_count > 0);
318 if (vp->v_count > 1) {
319 /*
320 * It's impossible for us to be cnode_inactive for
321 * the root cnode _unless_ we are being called from
322 * cachefs_unmount (where inactive is called
323 * explictly). If the count is not 1, there is
324 * still an outstanding reference to the root cnode,
325 * and we return EBUSY; this allows cachefs_unmount
326 * to fail.
327 */
328 if (cp->c_flags & CN_ROOT) {
329 mutex_exit(&vp->v_lock);
330 return (EBUSY);
331 }
332 cp->c_ipending = 0;
333 vp->v_count--; /* release our hold from vn_rele */
334 mutex_exit(&vp->v_lock);
335 return (0);
336 }
337 mutex_exit(&vp->v_lock);
338
339 /* get rid of any pages, do not care if cannot be pushed */
340 if (vn_has_cached_data(vp)) {
341 ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
342 (void) cachefs_putpage_common(vp, (offset_t)0, 0,
343 B_INVAL | B_FORCE, cr);
344 }
345
346 /* if need to sync metadata, the call is a no op for NFSv4 */
347 if ((cp->c_flags & (CN_UPDATED | CN_DESTROY)) == CN_UPDATED) {
348 (void) cachefs_sync_metadata(cp);
349 continue;
350 }
351 break;
352 }
353
354 /*
355 * Lock out possible race with makecachefsnode.
356 * Makecachefsnode will fix up the rl/active list stuff to
357 * be correct when it gets to run.
358 * We have to do the rl/active stuff while the cnode is on the hash
359 * list to sync actions on the rl/active list.
360 */
361 mutex_enter(&fgp->fg_cnodelock);
362 mutex_enter(&cp->c_statelock);
363
364 /* see if vnode is still inactive */
365 mutex_enter(&vp->v_lock);
366 ASSERT(vp->v_count > 0);
367 if (vp->v_count > 1) {
368 cp->c_ipending = 0;
369 vp->v_count--;
370 mutex_exit(&vp->v_lock);
371 mutex_exit(&cp->c_statelock);
372 mutex_exit(&fgp->fg_cnodelock);
373 #ifdef CFSDEBUG
374 CFS_DEBUG(CFSDEBUG_INVALIDATE)
375 printf("cachefs_cnode_inactive: %u vp %p\n",
376 vp->v_count, vp);
377 #endif
378 return (0);
379 }
380 mutex_exit(&vp->v_lock);
381
382 /* check for race with remove */
383 if (cp->c_unldvp) {
384 mutex_exit(&cp->c_statelock);
385 mutex_exit(&fgp->fg_cnodelock);
386
387 /* this causes cachefs_inactive to be called again */
388 VN_RELE(vp);
389 return (0);
390 }
391
392 /* if any pages left, really get rid of them */
393 if (vn_has_cached_data(vp)) {
394 ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
395 (void) pvn_vplist_dirty(vp, 0, NULL, B_INVAL | B_TRUNC, cr);
396 }
397 ASSERT(vp->v_count == 1);
398
399 mdp = &cp->c_metadata;
400
401 /* if we can (and should) destroy the front file and metadata */
402 if ((cp->c_flags & (CN_DESTROY | CN_STALE)) &&
403 (fgp->fg_flags & CFS_FG_WRITE) && !CFS_ISFS_BACKFS_NFSV4(fscp)) {
404 if (mdp->md_rlno) {
405 cachefs_removefrontfile(mdp, &cp->c_id, fgp);
406 cachefs_rlent_moveto(cachep, CACHEFS_RL_FREE,
407 mdp->md_rlno, 0);
408 mdp->md_rlno = 0;
409 mdp->md_rltype = CACHEFS_RL_NONE;
410 }
411 if ((cp->c_flags & CN_ALLOC_PENDING) == 0) {
412 (void) filegrp_destroy_metadata(fgp, &cp->c_id);
413 meta_destroyed = 1;
414 }
415 }
416
417 /* else put the front file on the gc list */
418 else if (mdp->md_rlno &&
419 (fgp->fg_flags & CFS_FG_WRITE) &&
420 (cp->c_metadata.md_rltype == CACHEFS_RL_ACTIVE)) {
421 #ifdef CFSDEBUG
422 cachefs_rlent_verify(cachep, CACHEFS_RL_ACTIVE,
423 mdp->md_rlno);
424 #endif /* CFSDEBUG */
425
426 ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
427 cachefs_rlent_moveto(cachep, CACHEFS_RL_GC, mdp->md_rlno,
428 mdp->md_frontblks);
429 mdp->md_rltype = CACHEFS_RL_GC;
430 cp->c_flags |= CN_UPDATED;
431 }
432
433 /* if idlelist pointer(s) not null, remove from idle list */
434 if ((cp->c_idlefront != NULL) || (cp->c_idleback != NULL)) {
435 mutex_enter(&fscp->fs_idlelock);
436 cachefs_cnode_idlerem(cp);
437 mutex_exit(&fscp->fs_idlelock);
438 }
439
440 /* remove from the filegrp list prior to releasing the cnode lock */
441 cachefs_cnode_listrem(cp);
442
443 mutex_exit(&cp->c_statelock);
444 if (! meta_destroyed)
445 (void) cachefs_sync_metadata(cp);
446
447 mutex_exit(&fgp->fg_cnodelock);
448
449 if (cp->c_cred != NULL) {
450 crfree(cp->c_cred);
451 cp->c_cred = NULL;
452 }
453
454 if (cp->c_frontvp)
455 VN_RELE(cp->c_frontvp);
456
457 if (cp->c_backvp)
458 VN_RELE(cp->c_backvp);
459
460 if (cp->c_acldirvp)
461 VN_RELE(cp->c_acldirvp);
462
463 rw_destroy(&cp->c_rwlock);
464 mutex_destroy(&cp->c_statelock);
465 cv_destroy(&cp->c_popcv);
466 mutex_destroy(&cp->c_iomutex);
467 cv_destroy(&cp->c_iocv);
468
469 /* free up cnode memory */
470 vn_invalid(cp->c_vnode);
471 vn_free(cp->c_vnode);
472 kmem_cache_free(cachefs_cnode_cache, cp);
473
474 filegrp_rele(fgp);
475 (void) fscache_cnodecnt(fscp, -1);
476 return (0);
477 }
478
479 /*
480 * Add a cnode to the filegrp list.
481 */
482 void
cachefs_cnode_listadd(struct cnode * cp)483 cachefs_cnode_listadd(struct cnode *cp)
484 {
485 filegrp_t *fgp = cp->c_filegrp;
486
487 ASSERT(MUTEX_HELD(&fgp->fg_cnodelock));
488 ASSERT(cp->c_next == NULL);
489
490 cp->c_next = fgp->fg_cnodelist;
491 fgp->fg_cnodelist = cp;
492 }
493
494 /*
495 * Remove a cnode from the filegrp list.
496 */
497 void
cachefs_cnode_listrem(struct cnode * cp)498 cachefs_cnode_listrem(struct cnode *cp)
499 {
500 filegrp_t *fgp = cp->c_filegrp;
501 struct cnode **headpp;
502
503 #ifdef CFSDEBUG
504 int found = 0;
505 #endif
506
507 ASSERT(MUTEX_HELD(&fgp->fg_cnodelock));
508 ASSERT(cp->c_idleback == NULL);
509 ASSERT(cp->c_idlefront == NULL);
510
511 for (headpp = &fgp->fg_cnodelist;
512 *headpp != NULL; headpp = &(*headpp)->c_next) {
513 if (*headpp == cp) {
514 *headpp = cp->c_next;
515 cp->c_next = NULL;
516 #ifdef CFSDEBUG
517 found++;
518 #endif
519 break;
520 }
521 }
522 #ifdef CFSDEBUG
523 ASSERT(found);
524 #endif
525 }
526
527 /*
528 * Add a cnode to the front of the fscache idle list.
529 */
530 void
cachefs_cnode_idleadd(struct cnode * cp)531 cachefs_cnode_idleadd(struct cnode *cp)
532 {
533 fscache_t *fscp = C_TO_FSCACHE(cp);
534
535 ASSERT(MUTEX_HELD(&cp->c_statelock));
536 ASSERT(MUTEX_HELD(&fscp->fs_idlelock));
537
538 /* put cnode on the front of the idle list */
539 cp->c_idlefront = fscp->fs_idlefront;
540 cp->c_idleback = NULL;
541
542 if (fscp->fs_idlefront)
543 fscp->fs_idlefront->c_idleback = cp;
544 else {
545 ASSERT(fscp->fs_idleback == NULL);
546 fscp->fs_idleback = cp;
547 }
548 fscp->fs_idlefront = cp;
549 fscp->fs_idlecnt++;
550 }
551
552 /*
553 * Remove a cnode from the fscache idle list.
554 */
555 void
cachefs_cnode_idlerem(struct cnode * cp)556 cachefs_cnode_idlerem(struct cnode *cp)
557 {
558 fscache_t *fscp = C_TO_FSCACHE(cp);
559
560 ASSERT(MUTEX_HELD(&cp->c_statelock));
561 ASSERT(MUTEX_HELD(&fscp->fs_idlelock));
562
563 if (cp->c_idlefront == NULL) {
564 ASSERT(fscp->fs_idleback == cp);
565 fscp->fs_idleback = cp->c_idleback;
566 if (fscp->fs_idleback != NULL)
567 fscp->fs_idleback->c_idlefront = NULL;
568 } else {
569 cp->c_idlefront->c_idleback = cp->c_idleback;
570 }
571
572 if (cp->c_idleback == NULL) {
573 ASSERT(fscp->fs_idlefront == cp);
574 fscp->fs_idlefront = cp->c_idlefront;
575 if (fscp->fs_idlefront != NULL)
576 fscp->fs_idlefront->c_idleback = NULL;
577 } else {
578 cp->c_idleback->c_idlefront = cp->c_idlefront;
579 cp->c_idleback = NULL;
580 }
581 cp->c_idlefront = NULL;
582 fscp->fs_idlecnt--;
583 ASSERT(fscp->fs_idlecnt >= 0);
584 }
585
586 /*
587 * Search the cnode list of the input file group, looking for a cnode which
588 * matches the supplied file ident fileno.
589 *
590 * Returns:
591 * *cpp = NULL, if no valid matching cnode is found
592 * *cpp = address of cnode with matching fileno, with c_statelock held
593 * return status is 0 if no cnode found, or if found & cookies match
594 * return status is 1 if a cnode was found, but the cookies don't match
595 *
596 * Note: must grab the c_statelock for each cnode, or its state could
597 * change while we're processing it. Also, if a cnode is found, must return
598 * with c_statelock still held, so that the cnode state cannot change until
599 * the calling routine releases the lock.
600 */
601 int
cachefs_cnode_find(filegrp_t * fgp,cfs_cid_t * cidp,fid_t * cookiep,struct cnode ** cpp,struct vnode * backvp,vattr_t * vap)602 cachefs_cnode_find(filegrp_t *fgp, cfs_cid_t *cidp, fid_t *cookiep,
603 struct cnode **cpp, struct vnode *backvp, vattr_t *vap)
604 {
605 struct cnode *cp;
606 int badcookie = 0;
607 uint32_t is_nfsv4;
608
609 #ifdef CFSDEBUG
610 CFS_DEBUG(CFSDEBUG_CNODE)
611 cmn_err(CE_NOTE, "cachefs_cnode_find: fileno %llu fgp %p\n",
612 (u_longlong_t)cidp->cid_fileno, (void *)fgp);
613 #endif
614 ASSERT(MUTEX_HELD(&fgp->fg_cnodelock));
615
616 *cpp = NULL;
617 is_nfsv4 = CFS_ISFS_BACKFS_NFSV4(fgp->fg_fscp);
618
619 /*
620 * Cookie should be filled unless disconnected operation or
621 * backfilesystem is NFSv4
622 */
623 if (cookiep == NULL && !CFS_ISFS_SNR(fgp->fg_fscp) &&
624 !CFS_ISFS_BACKFS_NFSV4(fgp->fg_fscp)) {
625 goto out;
626 }
627
628 for (cp = fgp->fg_cnodelist; cp != NULL; cp = cp->c_next) {
629 mutex_enter(&cp->c_statelock);
630
631 if ((cidp->cid_fileno != cp->c_id.cid_fileno &&
632 (is_nfsv4 == FALSE || cp->c_backvp != backvp)) ||
633 (cp->c_flags & (CN_STALE | CN_DESTROY))) {
634 mutex_exit(&cp->c_statelock);
635 continue;
636 }
637
638 /*
639 * Having found a non stale, non destroy pending cnode with
640 * matching fileno, will be exiting the for loop, after
641 * determining return status
642 */
643 *cpp = cp;
644
645 if ((cookiep != NULL) &&
646 ((cookiep->fid_len != cp->c_cookie.fid_len) ||
647 (bcmp((caddr_t)cookiep->fid_data,
648 (caddr_t)&cp->c_cookie.fid_data, cookiep->fid_len)) != 0)) {
649 #ifdef CFSDEBUG
650 CFS_DEBUG(CFSDEBUG_GENERAL) {
651 cmn_err(CE_NOTE,
652 "cachefs: dup fileno %llu, cp %p\n",
653 (u_longlong_t)cidp->cid_fileno, (void *)cp);
654 }
655 #endif
656 badcookie = 1;
657 }
658
659 /*
660 * For NFSv4 since there is no fid, add a check to
661 * ensure the backvp and vap matches that in the cnode.
662 * If it doesn't then someone tried to use a stale cnode.
663 */
664 if (is_nfsv4) {
665 if (backvp && backvp != cp->c_backvp ||
666 vap && vap->va_type != cp->c_attr.va_type ||
667 cidp->cid_fileno != cp->c_id.cid_fileno) {
668 CFS_DPRINT_BACKFS_NFSV4(C_TO_FSCACHE(cp),
669 ("cachefs_cnode_find (nfsv4): stale cnode "
670 "cnode %p, backvp %p, new-backvp %p, vap %p "
671 "fileno=%llx cp-fileno=%llx\n",
672 cp, cp->c_backvp, backvp, vap,
673 cidp->cid_fileno, cp->c_id.cid_fileno));
674 badcookie = 1;
675 }
676 }
677 break;
678 }
679 out:
680
681 #ifdef CFSDEBUG
682 CFS_DEBUG(CFSDEBUG_CNODE)
683 cmn_err(CE_NOTE, "cachefs_cnode_find: cp %p\n", (void *)*cpp);
684 #endif
685 return (badcookie);
686 }
687
688 /*
689 * We have to initialize the cnode contents. Fill in the contents from the
690 * cache (attrcache file), from the info passed in, whatever it takes.
691 */
692 static int
cachefs_cnode_init(cfs_cid_t * cidp,cnode_t * cp,fscache_t * fscp,filegrp_t * fgp,fid_t * cookiep,vattr_t * vap,vnode_t * backvp,int flag,cred_t * cr)693 cachefs_cnode_init(cfs_cid_t *cidp, cnode_t *cp, fscache_t *fscp,
694 filegrp_t *fgp, fid_t *cookiep, vattr_t *vap, vnode_t *backvp,
695 int flag, cred_t *cr)
696 {
697 int error = 0;
698 int slotfound;
699 vnode_t *vp;
700 int null_cookie;
701 cachefscache_t *cachep = fscp->fs_cache;
702
703 bzero(cp, sizeof (cnode_t));
704 cp->c_vnode = vn_alloc(KM_SLEEP);
705
706 vp = CTOV(cp);
707
708 vp->v_data = (caddr_t)cp;
709
710 rw_init(&cp->c_rwlock, NULL, RW_DEFAULT, NULL);
711 mutex_init(&cp->c_statelock, NULL, MUTEX_DEFAULT, NULL);
712 cv_init(&cp->c_popcv, NULL, CV_DEFAULT, NULL);
713 mutex_init(&cp->c_iomutex, NULL, MUTEX_DEFAULT, NULL);
714 cv_init(&cp->c_iocv, NULL, CV_DEFAULT, NULL);
715
716 vn_setops(vp, cachefs_getvnodeops());
717 cp->c_id = *cidp;
718 if (backvp != NULL) {
719 cp->c_backvp = backvp;
720 VN_HOLD(backvp);
721 }
722 cp->c_flags |= flag;
723 filegrp_hold(fgp);
724 cp->c_filegrp = fgp;
725 if (cookiep)
726 cp->c_cookie = *cookiep;
727 mutex_enter(&cp->c_statelock);
728
729 /*
730 * if nocache is set then ignore anything cached for this file,
731 * if nfsv4 flag is set, then create the cnode but don't do
732 * any caching.
733 */
734 if (cp->c_flags & CN_NOCACHE || CFS_ISFS_BACKFS_NFSV4(fscp)) {
735 /*
736 * this case only happens while booting without a cache
737 * or if NFSv4 is the backfilesystem
738 */
739 ASSERT(!CFS_ISFS_SNR(fscp));
740 ASSERT(fscp->fs_cdconnected == CFS_CD_CONNECTED);
741 if (cookiep || CFS_ISFS_BACKFS_NFSV4(fscp)) {
742 error = CFSOP_INIT_COBJECT(fscp, cp, vap, cr);
743 if (error)
744 goto out;
745 cp->c_flags |= CN_UPDATED | CN_ALLOC_PENDING;
746 ASSERT(cp->c_attr.va_type != 0);
747 VN_SET_VFS_TYPE_DEV(vp, fscp->fs_cfsvfsp,
748 cp->c_attr.va_type, cp->c_attr.va_rdev);
749 cachefs_cnode_setlocalstats(cp);
750 } else
751 error = ESTALE;
752 goto out;
753 }
754
755 /*
756 * see if there's a slot for this filegrp/cid fileno
757 * if not, and there's no cookie info, nothing can be done, but if
758 * there's cookie data indicate we need to create a metadata slot.
759 */
760 slotfound = cachefs_cid_inuse(cp->c_filegrp, cidp);
761 if (slotfound == 0) {
762 if (cookiep == NULL) {
763 error = ENOENT;
764 goto out;
765 }
766 cp->c_flags |= CN_ALLOC_PENDING;
767 } else {
768 /*
769 * if a slot was found, then increment the slot in use count
770 * and try to read the metadata.
771 */
772 cp->c_filegrp->fg_header->ach_count++;
773 error = filegrp_read_metadata(cp->c_filegrp, cidp,
774 &cp->c_metadata);
775 }
776 /*
777 * if there wasn't a slot, or an attempt to read it results in ENOENT,
778 * then init the cache object, create the vnode, etc...
779 */
780 if ((slotfound == 0) || (error == ENOENT)) {
781 error = CFSOP_INIT_COBJECT(fscp, cp, vap, cr);
782 if (error)
783 goto out;
784 ASSERT(cp->c_attr.va_type != 0);
785 VN_SET_VFS_TYPE_DEV(vp, fscp->fs_cfsvfsp,
786 cp->c_attr.va_type, cp->c_attr.va_rdev);
787 cp->c_metadata.md_rltype = CACHEFS_RL_NONE;
788 } else if (error == 0) {
789 /* slot found, no error occurred on the metadata read */
790 cp->c_size = cp->c_attr.va_size;
791
792 if ((cachep->c_flags & CACHE_CHECK_RLTYPE) &&
793 (cp->c_metadata.md_rlno != 0) &&
794 (cp->c_metadata.md_rltype == CACHEFS_RL_ACTIVE)) {
795 rl_entry_t rl, *rlp;
796
797 mutex_enter(&cachep->c_contentslock);
798 error = cachefs_rl_entry_get(cachep,
799 cp->c_metadata.md_rlno, &rlp);
800 if (error) {
801 mutex_exit(&cachep->c_contentslock);
802 goto out;
803 }
804 rl = *rlp;
805 mutex_exit(&cachep->c_contentslock);
806 if (cp->c_metadata.md_rltype != rl.rl_current) {
807 cp->c_flags |= CN_UPDATED;
808 cp->c_metadata.md_rltype = rl.rl_current;
809 }
810 }
811
812 /*
813 * If no cookie is specified, or if this is a local file,
814 * accept the one in the metadata.
815 */
816 null_cookie = 0;
817 if ((cookiep == NULL) || (cp->c_id.cid_flags & CFS_CID_LOCAL)) {
818 cookiep = &cp->c_metadata.md_cookie;
819 null_cookie = 1;
820 }
821
822 /* if cookies do not match, reset the metadata */
823 if ((cookiep->fid_len != cp->c_cookie.fid_len) ||
824 (bcmp(&cookiep->fid_data, &cp->c_cookie.fid_data,
825 (size_t)cookiep->fid_len) != 0)) {
826 cp->c_cookie = *cookiep;
827 cp->c_flags |= CN_UPDATED;
828 cp->c_metadata.md_timestamp.tv_sec = 0;
829 /* clear all but the front file bit */
830 cp->c_metadata.md_flags &= MD_FILE;
831 error = CFSOP_INIT_COBJECT(fscp, cp, vap, cr);
832 ASSERT(cp->c_attr.va_type != 0);
833 VN_SET_VFS_TYPE_DEV(vp, fscp->fs_cfsvfsp,
834 cp->c_attr.va_type, cp->c_attr.va_rdev);
835 }
836
837 /* else if the consistency type changed, fix it up */
838 else if (cp->c_metadata.md_consttype != fscp->fs_consttype) {
839 ASSERT(cp->c_attr.va_type != 0);
840 VN_SET_VFS_TYPE_DEV(vp, fscp->fs_cfsvfsp,
841 cp->c_attr.va_type, cp->c_attr.va_rdev);
842 CFSOP_CONVERT_COBJECT(fscp, cp, cr);
843 if (!null_cookie) {
844 error = CFSOP_CHECK_COBJECT(fscp, cp,
845 C_BACK_CHECK, cr);
846 }
847 }
848
849 /* else check the consistency of the data */
850 else {
851 ASSERT(cp->c_attr.va_type != 0);
852 VN_SET_VFS_TYPE_DEV(vp, fscp->fs_cfsvfsp,
853 cp->c_attr.va_type, cp->c_attr.va_rdev);
854 if (!null_cookie) {
855 error = CFSOP_CHECK_COBJECT(fscp, cp, 0, cr);
856 }
857 }
858 } else {
859 goto out;
860 }
861 cachefs_cnode_setlocalstats(cp);
862
863 out:
864 mutex_exit(&cp->c_statelock);
865 if (error) {
866 if (cp->c_frontvp)
867 VN_RELE(cp->c_frontvp);
868 if (cp->c_backvp)
869 VN_RELE(cp->c_backvp);
870 if (cp->c_acldirvp)
871 VN_RELE(cp->c_acldirvp);
872 filegrp_rele(fgp);
873 rw_destroy(&cp->c_rwlock);
874 mutex_destroy(&cp->c_statelock);
875 cv_destroy(&cp->c_popcv);
876 mutex_destroy(&cp->c_iomutex);
877 cv_destroy(&cp->c_iocv);
878 }
879 return (error);
880 }
881
882 /*
883 * Finds the cnode for the specified fileno and fid.
884 * Creates the cnode if it does not exist.
885 * The cnode is returned held.
886 */
887 int
cachefs_cnode_make(cfs_cid_t * cidp,fscache_t * fscp,fid_t * cookiep,vattr_t * vap,vnode_t * backvp,cred_t * cr,int flag,cnode_t ** cpp)888 cachefs_cnode_make(cfs_cid_t *cidp, fscache_t *fscp, fid_t *cookiep,
889 vattr_t *vap, vnode_t *backvp, cred_t *cr, int flag, cnode_t **cpp)
890 {
891 struct cnode *cp;
892 int error;
893 struct filegrp *fgp;
894 struct cachefs_metadata *mdp;
895 fid_t cookie;
896
897 #ifdef CFSDEBUG
898 CFS_DEBUG(CFSDEBUG_CNODE)
899 printf("cachefs_cnode_make: ENTER fileno %llu\n",
900 (u_longlong_t)cidp->cid_fileno);
901 #endif
902
903 /* get the file group that owns this file */
904 mutex_enter(&fscp->fs_fslock);
905 fgp = filegrp_list_find(fscp, cidp);
906 if (fgp == NULL) {
907 fgp = filegrp_create(fscp, cidp);
908 filegrp_list_add(fscp, fgp);
909 }
910 filegrp_hold(fgp);
911 mutex_exit(&fscp->fs_fslock);
912
913 /* grab the cnode list lock */
914 mutex_enter(&fgp->fg_cnodelock);
915
916 if ((fgp->fg_flags & CFS_FG_READ) == 0)
917 flag |= CN_NOCACHE;
918
919 error = 0;
920 cp = NULL;
921
922 /* look for the cnode on the cnode list */
923 error = cachefs_cnode_find(fgp, cidp, cookiep, &cp, backvp, vap);
924
925 /*
926 * If there already is a cnode with this cid but a different cookie,
927 * (or backvp) we're not going to be using the one we found.
928 */
929 if (error && CFS_ISFS_BACKFS_NFSV4(fscp)) {
930 ASSERT(MUTEX_HELD(&cp->c_statelock));
931 cachefs_cnode_stale(cp);
932 mutex_exit(&cp->c_statelock);
933 cp = NULL;
934 error = 0;
935 } else if (error) {
936 ASSERT(cp);
937 ASSERT(cookiep);
938
939 mutex_exit(&cp->c_statelock);
940
941 /*
942 * If backvp is NULL then someone tried to use
943 * a stale cookie.
944 */
945 if (backvp == NULL) {
946 mutex_exit(&fgp->fg_cnodelock);
947 error = ESTALE;
948 goto out;
949 }
950
951 /* verify the backvp */
952 error = cachefs_getcookie(backvp, &cookie, NULL, cr, TRUE);
953 if (error ||
954 ((cookiep->fid_len != cookie.fid_len) ||
955 (bcmp(&cookiep->fid_data, cookie.fid_data,
956 (size_t)cookiep->fid_len) != 0))) {
957 mutex_exit(&fgp->fg_cnodelock);
958 error = ESTALE;
959 goto out;
960 }
961
962 /* make the old cnode give up its front file resources */
963 VN_HOLD(CTOV(cp));
964 (void) cachefs_sync_metadata(cp);
965 mutex_enter(&cp->c_statelock);
966 mdp = &cp->c_metadata;
967 if (mdp->md_rlno) {
968 /* XXX sam: should this assert be NOCACHE? */
969 /* XXX sam: maybe we should handle NOFILL as no-op */
970 ASSERT((fscp->fs_cache->c_flags & CACHE_NOFILL) == 0);
971
972 /* if modified in the cache, move to lost+found */
973 if ((cp->c_attr.va_type == VREG) &&
974 (cp->c_metadata.md_rltype == CACHEFS_RL_MODIFIED)) {
975 error = cachefs_cnode_lostfound(cp, NULL);
976 if (error) {
977 mutex_exit(&cp->c_statelock);
978 VN_RELE(CTOV(cp));
979 mutex_exit(&fgp->fg_cnodelock);
980 error = ESTALE;
981 goto out;
982 }
983 }
984
985 /* else nuke the front file */
986 else {
987 cachefs_cnode_stale(cp);
988 }
989 } else {
990 cachefs_cnode_stale(cp);
991 }
992 mutex_exit(&cp->c_statelock);
993 VN_RELE(CTOV(cp));
994 cp = NULL;
995 error = 0;
996 }
997
998
999 /* if the cnode does not exist */
1000 if (cp == NULL) {
1001 /* XXX should we drop all locks for this? */
1002 cp = kmem_cache_alloc(cachefs_cnode_cache, KM_SLEEP);
1003
1004 error = cachefs_cnode_init(cidp, cp, fscp, fgp,
1005 cookiep, vap, backvp, flag, cr);
1006 if (error) {
1007 mutex_exit(&fgp->fg_cnodelock);
1008 vn_free(cp->c_vnode);
1009 kmem_cache_free(cachefs_cnode_cache, cp);
1010 goto out;
1011 }
1012
1013 if (cp->c_metadata.md_rlno &&
1014 (cp->c_metadata.md_rltype == CACHEFS_RL_GC) &&
1015 ((fscp->fs_cache->c_flags & CACHE_NOFILL) == 0)) {
1016 #ifdef CFSDEBUG
1017 cachefs_rlent_verify(fscp->fs_cache,
1018 CACHEFS_RL_GC, cp->c_metadata.md_rlno);
1019 #endif /* CFSDEBUG */
1020 cachefs_rlent_moveto(fscp->fs_cache,
1021 CACHEFS_RL_ACTIVE, cp->c_metadata.md_rlno,
1022 cp->c_metadata.md_frontblks);
1023 cp->c_metadata.md_rltype = CACHEFS_RL_ACTIVE;
1024 cp->c_flags |= CN_UPDATED;
1025 }
1026
1027 cachefs_cnode_listadd(cp);
1028 vn_exists(cp->c_vnode);
1029 mutex_exit(&fgp->fg_cnodelock);
1030 (void) fscache_cnodecnt(fscp, 1);
1031 }
1032
1033 /* else if the cnode exists */
1034 else {
1035 VN_HOLD(CTOV(cp));
1036
1037 /* remove from idle list if on it */
1038 if (cp->c_flags & CN_IDLE) {
1039 cp->c_flags &= ~CN_IDLE;
1040
1041 mutex_enter(&fscp->fs_idlelock);
1042 cachefs_cnode_idlerem(cp);
1043 mutex_exit(&fscp->fs_idlelock);
1044 VN_RELE(CTOV(cp));
1045 cp->c_ipending = 0;
1046 }
1047 mutex_exit(&cp->c_statelock);
1048 mutex_exit(&fgp->fg_cnodelock);
1049 }
1050
1051 /*
1052 * Assertion to ensure the cnode matches
1053 * the backvp and attribute type information.
1054 */
1055 ASSERT((CFS_ISFS_BACKFS_NFSV4(fscp) == 0) ||
1056 ((cp->c_backvp == backvp) &&
1057 (cp->c_attr.va_type == vap->va_type)));
1058 out:
1059 *cpp = ((error == 0) ? cp : NULL);
1060 filegrp_rele(fgp);
1061
1062 #ifdef CFSDEBUG
1063 CFS_DEBUG(CFSDEBUG_CNODE)
1064 printf("cachefs_cnode_make: EXIT cp %p, error %d\n",
1065 (void *)*cpp, error);
1066 #endif
1067 return (error);
1068 }
1069
1070 /*
1071 * cachefs_cid_inuse()
1072 *
1073 * returns nonzero if a cid has any data in the cache; either a cnode
1074 * or metadata.
1075 */
1076
1077 int
cachefs_cid_inuse(filegrp_t * fgp,cfs_cid_t * cidp)1078 cachefs_cid_inuse(filegrp_t *fgp, cfs_cid_t *cidp)
1079 {
1080 cnode_t *cp;
1081 int status = 0;
1082
1083 ASSERT(MUTEX_HELD(&fgp->fg_cnodelock));
1084
1085 /*
1086 * Since we don't care about the cookie data, we don't care about any
1087 * status that find might return.
1088 */
1089
1090 cp = NULL;
1091 (void) cachefs_cnode_find(fgp, cidp, NULL, &cp, NULL, NULL);
1092 if (cp != NULL) {
1093 mutex_exit(&cp->c_statelock);
1094 status = 1;
1095 return (status);
1096 }
1097
1098 /*
1099 * Don't want to use filegrp_read_metadata, since it will return
1100 * ENOENT if the metadata slot exists but hasn't been written to yet.
1101 * That condition still counts as the slot (metadata) being in use.
1102 * Instead, as long as the filegrp attrcache has been created and
1103 * there's a slot assigned for this cid, then the metadata is in use.
1104 */
1105 if (((fgp->fg_flags & CFS_FG_ALLOC_ATTR) == 0) &&
1106 (filegrp_cid_to_slot(fgp, cidp) != 0))
1107 status = 1;
1108
1109 return (status);
1110 }
1111
1112 /*
1113 * cachefs_fileno_inuse()
1114 *
1115 * returns nonzero if a fileno is known to the cache, as either a
1116 * local or a normal file.
1117 */
1118
1119 int
cachefs_fileno_inuse(fscache_t * fscp,ino64_t fileno)1120 cachefs_fileno_inuse(fscache_t *fscp, ino64_t fileno)
1121 {
1122 cfs_cid_t cid;
1123 filegrp_t *fgp;
1124 int known = 0;
1125
1126 ASSERT(MUTEX_HELD(&fscp->fs_fslock));
1127 cid.cid_fileno = fileno;
1128
1129 /* if there's no filegrp for this cid range, then there's no data */
1130 fgp = filegrp_list_find(fscp, &cid);
1131 if (fgp == NULL)
1132 return (known);
1133
1134 filegrp_hold(fgp);
1135 mutex_enter(&fgp->fg_cnodelock);
1136
1137 cid.cid_flags = CFS_CID_LOCAL;
1138 if (cachefs_cid_inuse(fgp, &cid)) {
1139 known = 1;
1140 goto out;
1141 }
1142 cid.cid_flags = 0;
1143 if (cachefs_cid_inuse(fgp, &cid))
1144 known = 1;
1145 out:
1146 mutex_exit(&fgp->fg_cnodelock);
1147 filegrp_rele(fgp);
1148 return (known);
1149 }
1150
1151 /*
1152 * Creates a cnode from an unused inode in the cache.
1153 * The cnode is returned held.
1154 */
1155 int
cachefs_cnode_create(fscache_t * fscp,vattr_t * vap,int flag,cnode_t ** cpp)1156 cachefs_cnode_create(fscache_t *fscp, vattr_t *vap, int flag, cnode_t **cpp)
1157 {
1158 struct cnode *cp;
1159 int error, found;
1160 struct filegrp *fgp;
1161 cfs_cid_t cid, cid2;
1162
1163 ASSERT(CFS_ISFS_SNR(fscp));
1164 ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
1165
1166 cid.cid_flags = CFS_CID_LOCAL;
1167 cid2.cid_flags = 0;
1168
1169 /* find an unused local file in the cache */
1170 for (;;) {
1171 mutex_enter(&fscp->fs_fslock);
1172
1173 /* make sure we did not wrap */
1174 fscp->fs_info.fi_localfileno++;
1175 if (fscp->fs_info.fi_localfileno == 0)
1176 fscp->fs_info.fi_localfileno = 3;
1177 cid.cid_fileno = fscp->fs_info.fi_localfileno;
1178 fscp->fs_flags |= CFS_FS_DIRTYINFO;
1179
1180 /* avoid fileno conflict in non-local space */
1181 cid2.cid_fileno = cid.cid_fileno;
1182 fgp = filegrp_list_find(fscp, &cid2);
1183 if (fgp != NULL) {
1184 filegrp_hold(fgp);
1185 mutex_enter(&fgp->fg_cnodelock);
1186 found = cachefs_cid_inuse(fgp, &cid2);
1187 mutex_exit(&fgp->fg_cnodelock);
1188 filegrp_rele(fgp);
1189 if (found) {
1190 mutex_exit(&fscp->fs_fslock);
1191 continue;
1192 }
1193 }
1194
1195 /* get the file group that owns this fileno */
1196 fgp = filegrp_list_find(fscp, &cid);
1197 if (fgp == NULL) {
1198 fgp = filegrp_create(fscp, &cid);
1199 filegrp_list_add(fscp, fgp);
1200 }
1201
1202 /* see if there is any room left in this file group */
1203 mutex_enter(&fgp->fg_mutex);
1204 if (fgp->fg_header &&
1205 (fgp->fg_header->ach_count ==
1206 fscp->fs_info.fi_fgsize)) {
1207 /* no more room, set up for the next file group */
1208 fscp->fs_info.fi_localfileno = fgp->fg_id.cid_fileno +
1209 fscp->fs_info.fi_fgsize;
1210 mutex_exit(&fgp->fg_mutex);
1211 mutex_exit(&fscp->fs_fslock);
1212 continue;
1213 }
1214 mutex_exit(&fgp->fg_mutex);
1215
1216 filegrp_hold(fgp);
1217 mutex_exit(&fscp->fs_fslock);
1218
1219 ASSERT((fgp->fg_flags &
1220 (CFS_FG_READ | CFS_FG_WRITE)) ==
1221 (CFS_FG_READ | CFS_FG_WRITE));
1222
1223 /* grab the cnode list lock */
1224 mutex_enter(&fgp->fg_cnodelock);
1225
1226 if ((fgp->fg_flags & CFS_FG_READ) == 0)
1227 flag |= CN_NOCACHE;
1228
1229 /* keep looking if a cnode or metadata exist for this fileno */
1230 if (cachefs_cid_inuse(fgp, &cid)) {
1231 mutex_exit(&fgp->fg_cnodelock);
1232 filegrp_rele(fgp);
1233 #ifdef CFSDEBUG
1234 CFS_DEBUG(CFSDEBUG_CNODE)
1235 cmn_err(CE_NOTE, "cachefs_cnode_create: "
1236 "fileno %llu exists.\n",
1237 (u_longlong_t)cid.cid_fileno);
1238 #endif
1239 continue;
1240 }
1241 break;
1242 }
1243
1244 vap->va_nodeid = cid.cid_fileno;
1245
1246 /* create space for the cnode */
1247 cp = kmem_cache_alloc(cachefs_cnode_cache, KM_SLEEP);
1248
1249 /* set up the cnode */
1250 error = cachefs_cnode_init(&cid, cp, fscp, fgp,
1251 &cp->c_cookie, vap, NULL, flag, kcred);
1252 if (error) {
1253 mutex_exit(&fgp->fg_cnodelock);
1254 vn_free(cp->c_vnode);
1255 kmem_cache_free(cachefs_cnode_cache, cp);
1256 goto out;
1257 }
1258
1259 /* save copy of fileno that is returned to the user */
1260 cp->c_metadata.md_flags |= MD_LOCALFILENO;
1261 cp->c_metadata.md_localfileno = cid.cid_fileno;
1262 cp->c_flags |= CN_UPDATED;
1263
1264 cachefs_cnode_listadd(cp);
1265 mutex_exit(&fgp->fg_cnodelock);
1266 (void) fscache_cnodecnt(fscp, 1);
1267
1268 out:
1269 *cpp = ((error == 0) ? cp : NULL);
1270 filegrp_rele(fgp);
1271 return (error);
1272 }
1273
1274 /*
1275 * Moves the cnode to its new location in the cache.
1276 * Before calling this routine other steps must be taken
1277 * to ensure that other file system routines that operate
1278 * on cnodes do not run.
1279 */
1280 void
cachefs_cnode_move(cnode_t * cp)1281 cachefs_cnode_move(cnode_t *cp)
1282 {
1283 fscache_t *fscp = C_TO_FSCACHE(cp);
1284 cfs_cid_t cid;
1285 filegrp_t *fgp;
1286 filegrp_t *ofgp = cp->c_filegrp;
1287 struct cachefs_metadata *mdp;
1288 cnode_t *xcp;
1289 char oname[CFS_FRONTFILE_NAME_SIZE];
1290 char nname[CFS_FRONTFILE_NAME_SIZE];
1291 int ffnuke = 0;
1292 int error;
1293
1294 ASSERT(CFS_ISFS_SNR(fscp));
1295 ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
1296 ASSERT(cp->c_id.cid_flags & CFS_CID_LOCAL);
1297 ASSERT(cp->c_attr.va_nodeid != 0);
1298
1299 /* construct the cid of the new file location */
1300 cid.cid_fileno = cp->c_attr.va_nodeid;
1301 cid.cid_flags = 0;
1302
1303 /* see if there already is a file occupying our slot */
1304 error = cachefs_cnode_make(&cid, fscp, NULL, NULL, NULL, kcred,
1305 0, &xcp);
1306 if (error == 0) {
1307 mutex_enter(&xcp->c_statelock);
1308 cachefs_cnode_stale(xcp);
1309 mutex_exit(&xcp->c_statelock);
1310 VN_RELE(CTOV(xcp));
1311 xcp = NULL;
1312 error = 0;
1313 }
1314
1315 /* get the file group that this file is moving to */
1316 mutex_enter(&fscp->fs_fslock);
1317 fgp = filegrp_list_find(fscp, &cid);
1318 if (fgp == NULL) {
1319 fgp = filegrp_create(fscp, &cid);
1320 filegrp_list_add(fscp, fgp);
1321 }
1322 filegrp_hold(fgp);
1323 mutex_exit(&fscp->fs_fslock);
1324
1325 /* XXX fix to not have to create metadata to hold rl slot */
1326 /* get a metadata slot in the new file group */
1327 if (fgp->fg_flags & CFS_FG_ALLOC_ATTR) {
1328 (void) filegrp_allocattr(fgp);
1329 }
1330 /* XXX can fix create_metadata to call allocattr if necessary? */
1331 error = filegrp_create_metadata(fgp, &cp->c_metadata, &cid);
1332 if (error)
1333 ffnuke = 1;
1334 if ((ffnuke == 0) && filegrp_ffhold(fgp))
1335 ffnuke = 1;
1336
1337 /* move the front file to the new file group */
1338 if ((ffnuke == 0) && (cp->c_metadata.md_flags & MD_FILE)) {
1339 make_ascii_name(&cp->c_id, oname);
1340 make_ascii_name(&cid, nname);
1341 error = VOP_RENAME(ofgp->fg_dirvp, oname, fgp->fg_dirvp,
1342 nname, kcred, NULL, 0);
1343 if (error) {
1344 ffnuke = 1;
1345 #ifdef CFSDEBUG
1346 if (error != ENOSPC) {
1347 CFS_DEBUG(CFSDEBUG_CNODE)
1348 printf("cachefs: cnode_move "
1349 "1: error %d\n", error);
1350 }
1351 #endif
1352 }
1353 }
1354
1355 /* remove the file from the old file group */
1356 mutex_enter(&ofgp->fg_cnodelock);
1357 mutex_enter(&cp->c_statelock);
1358 if (cp->c_frontvp) {
1359 VN_RELE(cp->c_frontvp);
1360 cp->c_frontvp = NULL;
1361 }
1362 if (cp->c_acldirvp) {
1363 VN_RELE(cp->c_acldirvp);
1364 cp->c_acldirvp = NULL;
1365 }
1366 mdp = &cp->c_metadata;
1367 if (mdp->md_rlno) {
1368 if (ffnuke) {
1369 cachefs_removefrontfile(mdp, &cp->c_id, ofgp);
1370 cachefs_rlent_moveto(fscp->fs_cache,
1371 CACHEFS_RL_FREE, mdp->md_rlno, 0);
1372 mdp->md_rlno = 0;
1373 mdp->md_rltype = CACHEFS_RL_NONE;
1374 } else {
1375 filegrp_ffrele(ofgp);
1376 }
1377 }
1378 if (ffnuke)
1379 mdp->md_flags &= ~MD_PACKED;
1380 if ((cp->c_flags & CN_ALLOC_PENDING) == 0) {
1381 (void) filegrp_destroy_metadata(ofgp, &cp->c_id);
1382 cp->c_flags |= CN_ALLOC_PENDING;
1383 }
1384 cachefs_cnode_listrem(cp);
1385 cp->c_filegrp = NULL;
1386 mutex_exit(&cp->c_statelock);
1387 mutex_exit(&ofgp->fg_cnodelock);
1388
1389 /* add the cnode to the new file group */
1390 mutex_enter(&fgp->fg_cnodelock);
1391 mutex_enter(&cp->c_statelock);
1392 cp->c_id = cid;
1393 cp->c_filegrp = fgp;
1394 cp->c_flags |= CN_UPDATED;
1395 mutex_exit(&cp->c_statelock);
1396 cachefs_cnode_listadd(cp);
1397 if (mdp->md_rlno)
1398 cachefs_rl_changefileno(fscp->fs_cache, mdp->md_rlno,
1399 cp->c_id.cid_fileno);
1400 mutex_exit(&fgp->fg_cnodelock);
1401
1402 filegrp_rele(ofgp);
1403 }
1404
1405 /*
1406 * Syncs out the specified cnode.
1407 * Only called via cnode_traverse from fscache_sync
1408 */
1409 void
cachefs_cnode_sync(cnode_t * cp)1410 cachefs_cnode_sync(cnode_t *cp)
1411 {
1412 vnode_t *vp = CTOV(cp);
1413 int error = 0;
1414 fscache_t *fscp = C_TO_FSCACHE(cp);
1415 int held = 0;
1416
1417 if (cp->c_flags & (CN_STALE | CN_DESTROY))
1418 return;
1419
1420 if (fscp->fs_backvfsp && fscp->fs_backvfsp->vfs_flag & VFS_RDONLY)
1421 return;
1422
1423 for (;;) {
1424 /* get (or renew) access to the file system */
1425 if (held) {
1426 cachefs_cd_release(fscp);
1427 held = 0;
1428 }
1429 /*
1430 * Getting file system access for reading is really cheating.
1431 * However we are getting called from sync so we do not
1432 * want to hang up if the cachefsd is not running.
1433 */
1434 error = cachefs_cd_access(fscp, 0, 0);
1435 if (error)
1436 break;
1437 held = 1;
1438
1439 /* if a regular file, write out the pages */
1440 if ((vp->v_type == VREG) && vn_has_cached_data(vp)) {
1441 ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
1442 error = cachefs_putpage_common(vp, (offset_t)0,
1443 0, 0, kcred);
1444 if (CFS_TIMEOUT(fscp, error)) {
1445 if (fscp->fs_cdconnected == CFS_CD_CONNECTED) {
1446 cachefs_cd_release(fscp);
1447 held = 0;
1448 cachefs_cd_timedout(fscp);
1449 continue;
1450 } else {
1451 /* cannot push, give up */
1452 break;
1453 }
1454 }
1455
1456 /* clear the cnode error if putpage worked */
1457 if ((error == 0) && cp->c_error) {
1458 mutex_enter(&cp->c_statelock);
1459 cp->c_error = 0;
1460 mutex_exit(&cp->c_statelock);
1461 }
1462
1463 if (error)
1464 break;
1465 }
1466
1467 /* if connected, sync the backvp */
1468 if ((fscp->fs_cdconnected == CFS_CD_CONNECTED) &&
1469 cp->c_backvp) {
1470 mutex_enter(&cp->c_statelock);
1471 if (cp->c_backvp) {
1472 error = VOP_FSYNC(cp->c_backvp, FSYNC, kcred,
1473 NULL);
1474 if (CFS_TIMEOUT(fscp, error)) {
1475 mutex_exit(&cp->c_statelock);
1476 cachefs_cd_release(fscp);
1477 held = 0;
1478 cachefs_cd_timedout(fscp);
1479 continue;
1480 } else if (error && (error != EINTR))
1481 cp->c_error = error;
1482 }
1483 mutex_exit(&cp->c_statelock);
1484 }
1485
1486 /* sync the metadata and the front file to the front fs */
1487 (void) cachefs_sync_metadata(cp);
1488 break;
1489 }
1490
1491 if (held)
1492 cachefs_cd_release(fscp);
1493 }
1494
1495 /*
1496 * Moves the specified file to the lost+found directory for the
1497 * cached file system.
1498 * Invalidates cached data and attributes.
1499 * Returns 0 or an error if could not perform operation.
1500 */
1501 int
cachefs_cnode_lostfound(cnode_t * cp,char * rname)1502 cachefs_cnode_lostfound(cnode_t *cp, char *rname)
1503 {
1504 int error = 0;
1505 fscache_t *fscp;
1506 cachefscache_t *cachep;
1507 char oname[CFS_FRONTFILE_NAME_SIZE];
1508 filegrp_t *fgp;
1509 char *namep, *strp;
1510 char *namebuf = NULL;
1511 vnode_t *nvp;
1512 int index;
1513 int len;
1514
1515 fscp = C_TO_FSCACHE(cp);
1516 cachep = fscp->fs_cache;
1517
1518 ASSERT(MUTEX_HELD(&cp->c_statelock));
1519 ASSERT((cachep->c_flags & (CACHE_NOCACHE|CACHE_NOFILL)) == 0);
1520 ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
1521
1522 fgp = cp->c_filegrp;
1523
1524 /* set up the file group if necessary */
1525 if (fgp->fg_flags & CFS_FG_ALLOC_ATTR) {
1526 error = filegrp_allocattr(fgp);
1527 if (error)
1528 goto out;
1529 }
1530 ASSERT(fgp->fg_dirvp);
1531
1532 namebuf = cachefs_kmem_alloc(MAXNAMELEN * 2, KM_SLEEP);
1533
1534 if ((cp->c_attr.va_type != VREG) ||
1535 (cp->c_metadata.md_rltype != CACHEFS_RL_MODIFIED) ||
1536 ((cp->c_metadata.md_flags & MD_POPULATED) == 0) ||
1537 ((cp->c_metadata.md_flags & MD_FILE) == 0) ||
1538 (cp->c_metadata.md_rlno == 0)) {
1539 #ifdef CFSDEBUG
1540 CFS_DEBUG(CFSDEBUG_CNODE)
1541 printf("cachefs_cnode_lostfound cp %p cannot save\n",
1542 (void *)cp);
1543 #endif
1544 error = EINVAL;
1545 goto out;
1546 }
1547
1548 /* lock out other users of the lost+found directory */
1549 mutex_enter(&cachep->c_contentslock);
1550
1551 /* find a name we can use in lost+found */
1552 if (rname)
1553 namep = rname;
1554 else
1555 namep = "lostfile";
1556 error = VOP_LOOKUP(cachep->c_lostfoundvp, namep, &nvp,
1557 NULL, 0, NULL, kcred, NULL, NULL, NULL);
1558 if (error == 0)
1559 VN_RELE(nvp);
1560 if (error != ENOENT) {
1561 #define MAXTRIES 1000
1562 strp = namep;
1563 for (index = 0; index < MAXTRIES; index++) {
1564 (void) sprintf(namebuf, "%s.%" PRIx64, strp,
1565 gethrestime_sec() * cp->c_id.cid_fileno * index);
1566 len = (int)strlen(namebuf) + 1;
1567 if (len > MAXNAMELEN)
1568 namep = &namebuf[len - MAXNAMELEN];
1569 else
1570 namep = namebuf;
1571 error = VOP_LOOKUP(cachep->c_lostfoundvp, namep, &nvp,
1572 NULL, 0, NULL, kcred, NULL, NULL, NULL);
1573 if (error == 0)
1574 VN_RELE(nvp);
1575 if (error == ENOENT)
1576 break;
1577 }
1578 if (index == MAXTRIES) {
1579 error = EIO;
1580 mutex_exit(&cachep->c_contentslock);
1581 goto out;
1582 }
1583 }
1584
1585 /* get the name of the front file */
1586 make_ascii_name(&cp->c_id, oname);
1587
1588 /* rename the file into the lost+found directory */
1589 error = VOP_RENAME(fgp->fg_dirvp, oname, cachep->c_lostfoundvp,
1590 namep, kcred, NULL, 0);
1591 if (error) {
1592 mutex_exit(&cachep->c_contentslock);
1593 goto out;
1594 }
1595 mutex_exit(&cachep->c_contentslock);
1596
1597 /* copy out the new name */
1598 if (rname)
1599 (void) strcpy(rname, namep);
1600
1601 out:
1602 /* clean up */
1603 cachefs_cnode_stale(cp);
1604
1605 if (namebuf)
1606 cachefs_kmem_free(namebuf, MAXNAMELEN * 2);
1607
1608 #if 0 /* XXX until we can put filesystem in read-only mode */
1609 if (error) {
1610 /* XXX put file system in read-only mode */
1611 }
1612 #endif
1613
1614 return (error);
1615 }
1616
1617 /*
1618 * Traverses the list of cnodes on the fscache and calls the
1619 * specified routine with the held cnode.
1620 */
1621 void
cachefs_cnode_traverse(fscache_t * fscp,void (* routinep)(cnode_t *))1622 cachefs_cnode_traverse(fscache_t *fscp, void (*routinep)(cnode_t *))
1623 {
1624 filegrp_t *fgp, *ofgp;
1625 cnode_t *cp, *ocp;
1626 int index;
1627
1628 /* lock the fscache while we traverse the file groups */
1629 mutex_enter(&fscp->fs_fslock);
1630
1631 /* for each bucket of file groups */
1632 for (index = 0; index < CFS_FS_FGP_BUCKET_SIZE; index++) {
1633 ofgp = NULL;
1634
1635 /* for each file group in a bucket */
1636 for (fgp = fscp->fs_filegrp[index];
1637 fgp != NULL;
1638 fgp = fgp->fg_next) {
1639
1640 /* hold the file group */
1641 filegrp_hold(fgp);
1642
1643 /* drop fscache lock so others can use it */
1644 mutex_exit(&fscp->fs_fslock);
1645
1646 /* drop hold on previous file group */
1647 if (ofgp)
1648 filegrp_rele(ofgp);
1649 ofgp = fgp;
1650
1651 /* lock the cnode list while we traverse it */
1652 mutex_enter(&fgp->fg_cnodelock);
1653 ocp = NULL;
1654
1655 /* for each cnode in this file group */
1656 for (cp = fgp->fg_cnodelist;
1657 cp != NULL;
1658 cp = cp->c_next) {
1659
1660 /* hold the cnode */
1661 VN_HOLD(CTOV(cp));
1662
1663 /* drop cnode list lock so others can use it */
1664 mutex_exit(&fgp->fg_cnodelock);
1665
1666 /* drop hold on previous cnode */
1667 if (ocp) {
1668 VN_RELE(CTOV(ocp));
1669 }
1670 ocp = cp;
1671
1672 /*
1673 * Execute routine for this cnode.
1674 * At this point no locks are held.
1675 */
1676 (routinep)(cp);
1677
1678 /* reacquire the cnode list lock */
1679 mutex_enter(&fgp->fg_cnodelock);
1680 }
1681
1682 /* drop cnode list lock */
1683 mutex_exit(&fgp->fg_cnodelock);
1684
1685 /* drop hold on last cnode */
1686 if (ocp) {
1687 VN_RELE(CTOV(ocp));
1688 }
1689
1690 /* reacquire the fscache lock */
1691 mutex_enter(&fscp->fs_fslock);
1692 }
1693
1694 /* drop hold on last file group */
1695 if (ofgp)
1696 filegrp_rele(ofgp);
1697 }
1698 mutex_exit(&fscp->fs_fslock);
1699 }
1700
1701 void
cachefs_cnode_disable_caching(struct cnode * cp)1702 cachefs_cnode_disable_caching(struct cnode *cp)
1703 {
1704 mutex_enter(&cp->c_statelock);
1705 cp->c_flags |= CN_NOCACHE;
1706 if (cp->c_frontvp != NULL) {
1707 VN_RELE(cp->c_frontvp);
1708 cp->c_frontvp = NULL;
1709 }
1710 mutex_exit(&cp->c_statelock);
1711 }
1712
1713 #define TIMEMATCH(a, b) ((a)->tv_sec == (b)->tv_sec && \
1714 (a)->tv_nsec == (b)->tv_nsec)
1715
1716 static void
cnode_enable_caching(struct cnode * cp)1717 cnode_enable_caching(struct cnode *cp)
1718 {
1719 struct vnode *iovp;
1720 struct filegrp *fgp;
1721 struct cachefs_metadata md;
1722 cachefscache_t *cachep = C_TO_FSCACHE(cp)->fs_cache;
1723 int error;
1724
1725 ASSERT((cachep->c_flags & (CACHE_NOFILL | CACHE_NOCACHE)) == 0);
1726 ASSERT(CFS_ISFS_BACKFS_NFSV4(C_TO_FSCACHE(cp)) == 0);
1727
1728 iovp = NULL;
1729 if (CTOV(cp)->v_type == VREG)
1730 iovp = cp->c_backvp;
1731 if (iovp) {
1732 (void) VOP_PUTPAGE(iovp, (offset_t)0,
1733 (uint_t)0, B_INVAL, kcred, NULL);
1734 }
1735 mutex_enter(&cp->c_statelock);
1736 if (cp->c_backvp) {
1737 VN_RELE(cp->c_backvp);
1738 cp->c_backvp = NULL;
1739 }
1740 fgp = cp->c_filegrp;
1741 ASSERT(fgp);
1742 error = filegrp_read_metadata(fgp, &cp->c_id, &md);
1743 if (error == 0) {
1744 if ((cachep->c_flags & CACHE_CHECK_RLTYPE) &&
1745 (md.md_rlno != 0) &&
1746 (md.md_rltype == CACHEFS_RL_ACTIVE)) {
1747 rl_entry_t *rlp, rl;
1748
1749 mutex_enter(&cachep->c_contentslock);
1750 error = cachefs_rl_entry_get(cachep, md.md_rlno, &rlp);
1751 if (error) {
1752 mutex_exit(&cachep->c_contentslock);
1753 goto out;
1754 }
1755
1756 rl = *rlp;
1757 mutex_exit(&cachep->c_contentslock);
1758
1759 if (rl.rl_current != md.md_rltype) {
1760 md.md_rltype = rl.rl_current;
1761 cp->c_flags |= CN_UPDATED;
1762 }
1763 }
1764
1765 /*
1766 * A rudimentary consistency check
1767 * here. If the cookie and mtime
1768 * from the cnode match those from the
1769 * cache metadata, we assume for now that
1770 * the cached data is OK.
1771 */
1772 if (bcmp(&md.md_cookie.fid_data, &cp->c_cookie.fid_data,
1773 (size_t)cp->c_cookie.fid_len) == 0 &&
1774 TIMEMATCH(&cp->c_attr.va_mtime, &md.md_vattr.va_mtime)) {
1775 cp->c_metadata = md;
1776 } else {
1777 /*
1778 * Here we're skeptical about the validity of
1779 * the front file.
1780 * We'll keep the attributes already present in
1781 * the cnode, and bring along the parts of the
1782 * metadata that we need to eventually nuke this
1783 * bogus front file -- in inactive or getfrontfile,
1784 * whichever comes first...
1785 */
1786 if (cp->c_frontvp != NULL) {
1787 VN_RELE(cp->c_frontvp);
1788 cp->c_frontvp = NULL;
1789 }
1790 cp->c_metadata.md_flags = md.md_flags;
1791 cp->c_metadata.md_flags |= MD_NEEDATTRS;
1792 cp->c_metadata.md_rlno = md.md_rlno;
1793 cp->c_metadata.md_rltype = md.md_rltype;
1794 cp->c_metadata.md_consttype = md.md_consttype;
1795 cp->c_metadata.md_fid = md.md_fid;
1796 cp->c_metadata.md_frontblks = md.md_frontblks;
1797 cp->c_metadata.md_timestamp.tv_sec = 0;
1798 cp->c_metadata.md_timestamp.tv_nsec = 0;
1799 bzero(&cp->c_metadata.md_allocinfo,
1800 cp->c_metadata.md_allocents *
1801 sizeof (struct cachefs_allocmap));
1802 cp->c_metadata.md_allocents = 0;
1803 cp->c_metadata.md_flags &= ~MD_POPULATED;
1804 if ((cp->c_metadata.md_rlno != 0) &&
1805 (cp->c_metadata.md_rltype == CACHEFS_RL_PACKED)) {
1806 cachefs_rlent_moveto(cachep,
1807 CACHEFS_RL_PACKED_PENDING,
1808 cp->c_metadata.md_rlno,
1809 cp->c_metadata.md_frontblks);
1810 cp->c_metadata.md_rltype =
1811 CACHEFS_RL_PACKED_PENDING;
1812 }
1813
1814 cp->c_flags |= CN_UPDATED;
1815 #ifdef CFSDEBUG
1816 CFS_DEBUG(CFSDEBUG_GENERAL) {
1817 printf(
1818 "fileno %lld ignores cached data due "
1819 "to cookie and/or mtime mismatch\n",
1820 (longlong_t)cp->c_id.cid_fileno);
1821 }
1822 #endif
1823 }
1824 if (cp->c_metadata.md_rltype == CACHEFS_RL_GC) {
1825 cachefs_rlent_moveto(cachep, CACHEFS_RL_ACTIVE,
1826 cp->c_metadata.md_rlno,
1827 cp->c_metadata.md_frontblks);
1828 cp->c_metadata.md_rltype = CACHEFS_RL_ACTIVE;
1829 cp->c_flags |= CN_UPDATED;
1830 }
1831 }
1832
1833 out:
1834 cp->c_flags &= ~CN_NOCACHE;
1835 mutex_exit(&cp->c_statelock);
1836
1837 (void) cachefs_pack_common(CTOV(cp), kcred);
1838 }
1839
1840 void
cachefs_enable_caching(struct fscache * fscp)1841 cachefs_enable_caching(struct fscache *fscp)
1842 {
1843
1844 /*
1845 * This function is only called when a remount occurs,
1846 * with "nocache" and "nofill" options configured
1847 * (currently these aren't supported). Since this
1848 * function can write into the cache, make sure that
1849 * its not in use with NFSv4.
1850 */
1851 if (CFS_ISFS_BACKFS_NFSV4(fscp))
1852 return;
1853
1854 /*
1855 * set up file groups so we can read them. Note that general
1856 * users (makecfsnode) will *not* start using them (i.e., all
1857 * newly created cnodes will be NOCACHE)
1858 * until we "enable_caching_rw" below.
1859 */
1860 mutex_enter(&fscp->fs_fslock);
1861 filegrp_list_enable_caching_ro(fscp);
1862 mutex_exit(&fscp->fs_fslock);
1863
1864 cachefs_cnode_traverse(fscp, cnode_enable_caching);
1865
1866 /* enable general use of the filegrps */
1867 mutex_enter(&fscp->fs_fslock);
1868 filegrp_list_enable_caching_rw(fscp);
1869 mutex_exit(&fscp->fs_fslock);
1870 }
1871
1872 /*
1873 * This function makes a cnode stale by performing the following tasks:
1874 * 1) remove the front file
1875 * 2) Remove any resource file entries
1876 * 3) Remove any metadata entry from the attrcache file
1877 * 4) Set the stale bit in the cnode flags field
1878 */
1879 void
cachefs_cnode_stale(cnode_t * cp)1880 cachefs_cnode_stale(cnode_t *cp)
1881 {
1882 fscache_t *fscp = C_TO_FSCACHE(cp);
1883 struct cachefs_metadata *mdp;
1884
1885 ASSERT(MUTEX_HELD(&cp->c_statelock));
1886
1887 /*
1888 * Remove a metadata entry if the file exists
1889 */
1890 mdp = &cp->c_metadata;
1891 if (mdp->md_rlno) {
1892
1893 ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
1894
1895 /*
1896 * destroy the frontfile
1897 */
1898 cachefs_removefrontfile(mdp, &cp->c_id, cp->c_filegrp);
1899 /*
1900 * Remove resource file entry
1901 */
1902 cachefs_rlent_moveto(fscp->fs_cache, CACHEFS_RL_FREE,
1903 mdp->md_rlno, 0);
1904 mdp->md_rlno = 0;
1905 mdp->md_rltype = CACHEFS_RL_NONE;
1906 }
1907
1908 /*
1909 * Remove attrcache metadata
1910 */
1911 if (CFS_ISFS_BACKFS_NFSV4(fscp) == 0)
1912 (void) filegrp_destroy_metadata(cp->c_filegrp, &cp->c_id);
1913 mdp->md_flags = 0;
1914
1915 if (cp->c_frontvp) {
1916 VN_RELE(cp->c_frontvp);
1917 cp->c_frontvp = NULL;
1918 }
1919
1920 /*
1921 * For NFSv4 need to hang on to the backvp until vn_rele()
1922 * frees this cnode.
1923 */
1924 if (cp->c_backvp && !CFS_ISFS_BACKFS_NFSV4(fscp)) {
1925 VN_RELE(cp->c_backvp);
1926 cp->c_backvp = NULL;
1927 }
1928 if (cp->c_acldirvp) {
1929 VN_RELE(cp->c_acldirvp);
1930 cp->c_acldirvp = NULL;
1931 }
1932
1933 cp->c_flags |= CN_STALE | CN_ALLOC_PENDING | CN_NOCACHE;
1934 }
1935
1936 /*
1937 * Sets up the local attributes in the metadata from the attributes.
1938 */
1939 void
cachefs_cnode_setlocalstats(cnode_t * cp)1940 cachefs_cnode_setlocalstats(cnode_t *cp)
1941 {
1942 fscache_t *fscp = C_TO_FSCACHE(cp);
1943 cachefs_metadata_t *mdp = &cp->c_metadata;
1944
1945 ASSERT(MUTEX_HELD(&cp->c_statelock));
1946
1947 /* allow over writing of local attributes if a remount occurred */
1948 if (fscp->fs_info.fi_resettimes != mdp->md_resettimes) {
1949 mdp->md_flags &= ~(MD_LOCALCTIME | MD_LOCALMTIME);
1950 mdp->md_resettimes = fscp->fs_info.fi_resettimes;
1951 }
1952 if (fscp->fs_info.fi_resetfileno != mdp->md_resetfileno) {
1953 mdp->md_flags &= ~MD_LOCALFILENO;
1954 mdp->md_resetfileno = fscp->fs_info.fi_resetfileno;
1955 }
1956
1957 /* overwrite old fileno and timestamps if not local versions */
1958 if ((mdp->md_flags & MD_LOCALFILENO) == 0)
1959 mdp->md_localfileno = mdp->md_vattr.va_nodeid;
1960 if ((mdp->md_flags & MD_LOCALCTIME) == 0)
1961 mdp->md_localctime = mdp->md_vattr.va_ctime;
1962 if ((mdp->md_flags & MD_LOCALMTIME) == 0)
1963 mdp->md_localmtime = mdp->md_vattr.va_mtime;
1964 cp->c_flags |= CN_UPDATED;
1965 }
1966