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 #pragma ident "%Z%%M% %I% %E% SMI"
26
27 #include <sys/param.h>
28 #include <sys/types.h>
29 #include <sys/systm.h>
30 #include <sys/cred.h>
31 #include <sys/proc.h>
32 #include <sys/user.h>
33 #include <sys/vfs.h>
34 #include <sys/vnode.h>
35 #include <sys/pathname.h>
36 #include <sys/uio.h>
37 #include <sys/tiuser.h>
38 #include <sys/sysmacros.h>
39 #include <sys/kmem.h>
40 #include <sys/mount.h>
41 #include <sys/ioctl.h>
42 #include <sys/statvfs.h>
43 #include <sys/errno.h>
44 #include <sys/debug.h>
45 #include <sys/cmn_err.h>
46 #include <sys/utsname.h>
47 #include <sys/bootconf.h>
48 #include <sys/modctl.h>
49 #include <sys/file.h>
50 #include <sys/stat.h>
51
52 #include <vm/hat.h>
53 #include <vm/as.h>
54 #include <vm/page.h>
55 #include <vm/pvn.h>
56 #include <vm/seg.h>
57 #include <vm/seg_map.h>
58 #include <vm/seg_vn.h>
59 #include <vm/rm.h>
60 #include <sys/fs/cachefs_fs.h>
61 #include <sys/fs/cachefs_log.h>
62
63 struct kmem_cache *cachefs_filegrp_cache = NULL;
64
65 #if (defined(_SYSCALL32_IMPL) || defined(_LP64))
66
67 #define CACHEFS_ALLOC_CFS_METADATA(p, inp) \
68 p = cachefs_kmem_zalloc(sizeof (struct cfs_cachefs_metadata), KM_SLEEP)
69
70 #define CACHEFS_FREE_CFS_METADATA(p) \
71 cachefs_kmem_free(p, sizeof (struct cfs_cachefs_metadata))
72
73 /* CACHEFS_COPY_COMMON_METADATA_FIELDS - common code for the metadata copy */
74 #define CACHEFS_COPY_COMMON_METADATA_FIELDS(inmdp, outmdp) \
75 (outmdp)->md_aclclass = (inmdp)->md_aclclass; \
76 CACHEFS_FID_COPY(&(inmdp)->md_cookie, &(outmdp)->md_cookie); \
77 (outmdp)->md_flags = (inmdp)->md_flags; \
78 (outmdp)->md_rlno = (inmdp)->md_rlno; \
79 (outmdp)->md_rltype = (inmdp)->md_rltype; \
80 (outmdp)->md_consttype = (inmdp)->md_consttype; \
81 CACHEFS_FID_COPY(&(inmdp)->md_fid, &(outmdp)->md_fid); \
82 (outmdp)->md_frontblks = (inmdp)->md_frontblks; \
83 (outmdp)->md_gen = (inmdp)->md_gen; \
84 (outmdp)->md_parent = (inmdp)->md_parent; \
85 (outmdp)->md_resettimes = (inmdp)->md_resettimes; \
86 (outmdp)->md_localfileno = (inmdp)->md_localfileno; \
87 (outmdp)->md_resetfileno = (inmdp)->md_resetfileno; \
88 (outmdp)->md_seq = (inmdp)->md_seq; \
89 (outmdp)->md_allocents = (inmdp)->md_allocents; \
90 bcopy(&(inmdp)->md_allocinfo, &(outmdp)->md_allocinfo, \
91 MIN(sizeof (inmdp)->md_allocinfo, sizeof (outmdp)->md_allocinfo))
92
93 #define CACHEFS_COPY_METADATA_TO_CFS_METADATA(inmdp, outmdp, error) \
94 CACHEFS_VATTR_TO_CFS_VATTR_COPY(&(inmdp)->md_vattr, \
95 &(outmdp)->md_vattr, error); \
96 CACHEFS_TS_TO_CFS_TS_COPY(&(inmdp)->md_timestamp, \
97 &(outmdp)->md_timestamp, error); \
98 CACHEFS_TS_TO_CFS_TS_COPY(&(inmdp)->md_x_time, \
99 &(outmdp)->md_x_time, error); \
100 CACHEFS_TS_TO_CFS_TS_COPY(&(inmdp)->md_localmtime, \
101 &(outmdp)->md_localmtime, error); \
102 CACHEFS_TS_TO_CFS_TS_COPY(&(inmdp)->md_localctime, \
103 &(outmdp)->md_localctime, error); \
104 CACHEFS_COPY_COMMON_METADATA_FIELDS(inmdp, outmdp)
105
106 #define CACHEFS_COPY_CFS_METADATA_TO_METADATA(inmdp, outmdp) \
107 CACHEFS_CFS_VATTR_TO_VATTR_COPY(&(inmdp)->md_vattr, \
108 &(outmdp)->md_vattr); \
109 CACHEFS_CFS_TS_TO_TS_COPY(&(inmdp)->md_timestamp, \
110 &(outmdp)->md_timestamp); \
111 CACHEFS_CFS_TS_TO_TS_COPY(&(inmdp)->md_x_time, \
112 &(outmdp)->md_x_time); \
113 CACHEFS_CFS_TS_TO_TS_COPY(&(inmdp)->md_localmtime, \
114 &(outmdp)->md_localmtime); \
115 CACHEFS_CFS_TS_TO_TS_COPY(&(inmdp)->md_localctime, \
116 &(outmdp)->md_localctime); \
117 CACHEFS_COPY_COMMON_METADATA_FIELDS(inmdp, outmdp)
118
119 #else /* not (_SYSCALL32_IMPL || _LP64) */
120
121 #define CACHEFS_ALLOC_CFS_METADATA(p, inp) \
122 p = (cfs_cachefs_metadata_t *)(inp)
123
124 #define CACHEFS_FREE_CFS_METADATA(p)
125
126 #define CACHEFS_COPY_METADATA_TO_CFS_METADATA(inmdp, outmdp, error)
127
128 #define CACHEFS_COPY_CFS_METADATA_TO_METADATA(inmdp, outmdp)
129
130 #endif /* _SYSCALL32_IMPL || _LP64 */
131
132 /* forward references */
133 int filegrp_write_space(vnode_t *vp, offset_t offset, ssize_t cnt);
134 int filegrpattr_find(struct filegrp *fgp);
135 int filegrpattr_create(struct filegrp *fgp);
136
137 int
138 /*ARGSUSED*/
filegrp_cache_create(void * voidp,void * cdrarg,int kmflags)139 filegrp_cache_create(void *voidp, void *cdrarg, int kmflags)
140 {
141 filegrp_t *fgp = (filegrp_t *)voidp;
142
143 mutex_init(&fgp->fg_mutex, NULL, MUTEX_DEFAULT, NULL);
144 mutex_init(&fgp->fg_cnodelock, NULL, MUTEX_DEFAULT, NULL);
145 return (0);
146 }
147
148 void
149 /*ARGSUSED*/
filegrp_cache_destroy(void * voidp,void * cdrarg)150 filegrp_cache_destroy(void *voidp, void *cdrarg)
151 {
152 filegrp_t *fgp = (filegrp_t *)voidp;
153
154 mutex_destroy(&fgp->fg_mutex);
155 mutex_destroy(&fgp->fg_cnodelock);
156 }
157
158 /*
159 * ------------------------------------------------------------------
160 *
161 * filegrp_create
162 *
163 * Description:
164 * Creates a filegrp object for the specified fscache.
165 * The CFS_FG_ALLOC_{ATTR, FILE} bits will be set in fg_flags
166 * if the cache is in NOCACHE and NOFILL mode or if
167 * the directory does not exist yet.
168 * The filegrp object maintains a reference to the specified
169 * fscache.
170 * Arguments:
171 * fscp fscache to create the file group in
172 * cidp start cid for the file group
173 * Returns:
174 * Returns the created filegrp object.
175 * Preconditions:
176 * precond(fscp)
177 * precond(cidp)
178 * precond(fscp->fs_info.fi_fgsize > 0)
179 */
180 #define Bugid_1249206_notfixed
181 #ifdef Bugid_1249206_notfixed
182 int bugid_1249206 = 0;
183 #endif
184 filegrp_t *
filegrp_create(struct fscache * fscp,cfs_cid_t * cidp)185 filegrp_create(struct fscache *fscp, cfs_cid_t *cidp)
186 {
187 filegrp_t *fgp;
188 int fgsize;
189 int flags;
190 ino64_t nfgsize;
191
192 fgsize = fscp->fs_info.fi_fgsize;
193
194 fgp = (filegrp_t *)
195 kmem_cache_alloc(cachefs_filegrp_cache, KM_SLEEP);
196
197 fgp->fg_flags = CFS_FG_ALLOC_ATTR | CFS_FG_ALLOC_FILE;
198 fgp->fg_count = 0;
199 fgp->fg_id = *cidp;
200 #ifdef Bugid_1249206_notfixed
201 if (bugid_1249206)
202 cmn_err(CE_CONT, "fg_id assigned value is %" PRId64 "\n",
203 fgp->fg_id.cid_fileno);
204 #endif
205 nfgsize = (fgp->fg_id.cid_fileno / (ino64_t)fgsize);
206 fgp->fg_id.cid_fileno = (ino64_t)(nfgsize * (ino64_t)fgsize);
207 #ifdef Bugid_1249206_notfixed
208 if (bugid_1249206) {
209 cmn_err(CE_CONT,
210 "cid_fileno for fscp %p fgp %p is %" PRId64 "\n",
211 (void *)fscp, (void *)fgp,
212 fgp->fg_id.cid_fileno);
213 cmn_err(CE_CONT,
214 "sent fileno is %" PRId64 " fgsize %d nfgsize %" PRId64
215 "\n", cidp->cid_fileno, fgsize, nfgsize);
216 }
217 #endif
218 fgp->fg_fscp = fscp;
219 fgp->fg_cnodelist = NULL;
220 fgp->fg_next = NULL;
221 fgp->fg_dirvp = NULL;
222 fgp->fg_attrvp = NULL;
223 fgp->fg_header = NULL;
224 fgp->fg_offsets = NULL;
225 fgp->fg_alloclist = NULL;
226
227 fgp->fg_headersize = (uint_t)sizeof (struct attrcache_header) +
228 (fgsize * (uint_t)sizeof (struct attrcache_index)) +
229 ((fgsize + 7) >> 3);
230
231 fgp->fg_filesize = fgp->fg_headersize +
232 (fgsize * (uint_t)sizeof (struct cfs_cachefs_metadata));
233
234 flags = fscp->fs_flags;
235 if (flags & CFS_FS_READ) {
236 fgp->fg_flags |= CFS_FG_READ;
237 if (flags & CFS_FS_WRITE) {
238 fgp->fg_flags |= CFS_FG_WRITE;
239 }
240 }
241
242 if (fgp->fg_flags & CFS_FG_READ) {
243 /* find the attrcache file and frontfile directory */
244 (void) filegrpattr_find(fgp);
245
246 /*
247 * XXX: we can tell from the file count in the attrcache
248 * whether we can expect to find a front file dir or
249 * not. If not, we can save the lookup here...
250 */
251 (void) filegrpdir_find(fgp);
252 }
253
254 return (fgp);
255 }
256
257 /*
258 * ------------------------------------------------------------------
259 *
260 * filegrp_destroy
261 *
262 * Description:
263 * Destroys the filegrp object and releases any kernel
264 * resource associated with it.
265 * Additionally if the on disk file group directory does
266 * not contain any front files it is removed.
267 * Arguments:
268 * fgp filegrp object to destroy
269 * Returns:
270 * Preconditions:
271 * precond(fgp is a valid filegrp object)
272 * precond(fgp->fg_count == 0)
273 * precond(fgp->fg_next == NULL)
274 */
275
276 void
filegrp_destroy(filegrp_t * fgp)277 filegrp_destroy(filegrp_t *fgp)
278 {
279 struct fscache *fscp = fgp->fg_fscp;
280 char name[CFS_FRONTFILE_NAME_SIZE];
281 char *fname;
282 int error;
283
284 ASSERT(fgp->fg_count == 0);
285 ASSERT(fgp->fg_next == NULL);
286
287 if (fgp->fg_attrvp) {
288 if (fgp->fg_flags & CFS_FG_UPDATED) {
289 error = filegrp_sync(fgp);
290 if (error)
291 cmn_err(CE_WARN,
292 "cachefs: UFS error on cache, "
293 "run fsck %d", error);
294 }
295 VN_RELE(fgp->fg_attrvp);
296 }
297 if (fgp->fg_header) {
298 /*
299 * If there are no attrcache entries in use and
300 * if we can modify the cache.
301 */
302 if ((fgp->fg_header->ach_count == 0) &&
303 (fgp->fg_flags & CFS_FG_WRITE)) {
304 ASSERT(fgp->fg_header->ach_nffs == 0);
305
306 /* remove attrcache file from the rl list */
307 ASSERT(fgp->fg_header->ach_rl_current ==
308 CACHEFS_RL_GC);
309 #ifdef CFSDEBUG
310 cachefs_rlent_verify(fscp->fs_cache, CACHEFS_RL_GC,
311 fgp->fg_header->ach_rlno);
312 #endif /* CFSDEBUG */
313
314 /*
315 * XXX sam: since we're blowing away the
316 * attrcache file, i guess i don't need to set
317 * ach_rl_current to CACHEFS_RL_NONE and
318 * sync the attrcache file, right?
319 *
320 * fgp->fg_header->ach_rl_current = CACHEFS_RL_NONE;
321 * fgp->fg_flags |= CFS_FG_UPDATED;
322 */
323
324 /* remove the attrcache file */
325 make_ascii_name(&fgp->fg_id, name);
326 fname = name;
327 error = VOP_REMOVE(fscp->fs_fsattrdir, fname, kcred,
328 NULL, 0);
329 if (error) {
330 cmn_err(CE_WARN,
331 "cachefs: error in cache, run fsck");
332 } else {
333 cachefs_freefile(fscp->fs_cache);
334 cachefs_freeblocks(fscp->fs_cache,
335 fgp->fg_header->ach_nblks, CACHEFS_RL_GC);
336 cachefs_rlent_moveto(fscp->fs_cache,
337 CACHEFS_RL_FREE, fgp->fg_header->ach_rlno,
338 0);
339 }
340 }
341 cachefs_kmem_free(fgp->fg_header, fgp->fg_headersize);
342 }
343 if (fgp->fg_dirvp) {
344 VN_RELE(fgp->fg_dirvp);
345 }
346 kmem_cache_free(cachefs_filegrp_cache, fgp);
347 }
348
349 /*
350 * ------------------------------------------------------------------
351 *
352 * filegrp_allocattr
353 *
354 * Description:
355 * Tries to find the attrcache file for the given filegroup.
356 * If the file does not yet exist it is created.
357 * Arguments:
358 * fgp filegrp object
359 * Returns:
360 * Returns 0 on success, an errno value on failure.
361 * Preconditions:
362 * precond(fgp is a valid filegrp object)
363 */
364
365 int
filegrp_allocattr(filegrp_t * fgp)366 filegrp_allocattr(filegrp_t *fgp)
367 {
368 int error = 0;
369
370 mutex_enter(&fgp->fg_mutex);
371
372 /* if we do not yet have the attrcache file */
373 if (fgp->fg_flags & CFS_FG_ALLOC_ATTR) {
374 /* fail if we tried to create it but failed previously */
375 if (fgp->fg_flags & CFS_FG_NOCACHE) {
376 error = ENOENT;
377 goto out;
378 }
379
380 /* fail if we cannot read from the cache */
381 if ((fgp->fg_flags & CFS_FG_READ) == 0) {
382 error = ENOENT;
383 goto out;
384 }
385
386 /* try to find the attrcache file in the cache */
387 error = filegrpattr_find(fgp);
388 if (error == ENOENT) {
389 /* fail if we cannot create the attrcache file */
390 if ((fgp->fg_flags & CFS_FG_WRITE) == 0) {
391 error = ENOENT;
392 goto out;
393 }
394
395 /* try to create the attrcache file */
396 error = filegrpattr_create(fgp);
397 }
398 }
399 out:
400 mutex_exit(&fgp->fg_mutex);
401
402 return (error);
403 }
404
405 /*
406 * ------------------------------------------------------------------
407 *
408 * filegrp_hold
409 *
410 * Description:
411 * Increments the number of references to this filegrp object.
412 * Arguments:
413 * fgp filegrp object to reference
414 * Returns:
415 * Preconditions:
416 * precond(fgp is a valid filegrp object)
417 */
418
419 void
filegrp_hold(filegrp_t * fgp)420 filegrp_hold(filegrp_t *fgp)
421 {
422 mutex_enter(&fgp->fg_mutex);
423
424 fgp->fg_count++;
425
426 /* remove attrcache file from the rl list if necessary */
427 if ((fgp->fg_flags & CFS_FG_WRITE) &&
428 (fgp->fg_header != NULL) &&
429 (fgp->fg_header->ach_rl_current == CACHEFS_RL_GC)) {
430 #ifdef CFSDEBUG
431 cachefs_rlent_verify(fgp->fg_fscp->fs_cache,
432 CACHEFS_RL_GC, fgp->fg_header->ach_rlno);
433 #endif /* CFSDEBUG */
434 cachefs_rlent_moveto(fgp->fg_fscp->fs_cache,
435 CACHEFS_RL_ATTRFILE, fgp->fg_header->ach_rlno,
436 fgp->fg_header->ach_nblks);
437 fgp->fg_header->ach_rl_current = CACHEFS_RL_ATTRFILE;
438 fgp->fg_flags |= CFS_FG_UPDATED;
439 }
440
441 mutex_exit(&fgp->fg_mutex);
442 }
443
444 /*
445 * ------------------------------------------------------------------
446 *
447 * filegrp_rele
448 *
449 * Description:
450 * Decrements the number of references to this filegrp object.
451 * Arguments:
452 * fgp filegrp object to dereference
453 * Returns:
454 * Preconditions:
455 * precond(fgp is a valid filegrp object)
456 * precond(number of references to filegrp is > 0)
457 */
458
459 void
filegrp_rele(filegrp_t * fgp)460 filegrp_rele(filegrp_t *fgp)
461 {
462 mutex_enter(&fgp->fg_mutex);
463 ASSERT(fgp->fg_count > 0);
464
465 /* move attrcache file to the rl list if necessary */
466 if (((fgp->fg_flags & CFS_FG_ALLOC_ATTR) == 0) &&
467 (fgp->fg_flags & CFS_FG_WRITE) &&
468 (fgp->fg_header->ach_rl_current != CACHEFS_RL_GC) &&
469 (fgp->fg_count == 1) &&
470 (fgp->fg_header->ach_nffs == 0)) {
471 #ifdef CFSDEBUG
472 cachefs_rlent_verify(fgp->fg_fscp->fs_cache,
473 CACHEFS_RL_ATTRFILE, fgp->fg_header->ach_rlno);
474 #endif /* CFSDEBUG */
475 cachefs_rlent_moveto(fgp->fg_fscp->fs_cache,
476 CACHEFS_RL_GC, fgp->fg_header->ach_rlno,
477 fgp->fg_header->ach_nblks);
478 fgp->fg_header->ach_rl_current = CACHEFS_RL_GC;
479 fgp->fg_flags |= CFS_FG_UPDATED;
480 }
481
482 fgp->fg_count--;
483
484 mutex_exit(&fgp->fg_mutex);
485
486 }
487
488 /*
489 * ------------------------------------------------------------------
490 *
491 * filegrp_ffhold
492 *
493 * Description:
494 * Increments the count of the number of front files for
495 * this filegrp by one.
496 * Arguments:
497 * fgp filegrp object to reference
498 * Returns:
499 * Returns 0 for success or a non-zero errno.
500 * Preconditions:
501 * precond(fgp is a valid filegrp object)
502 * precond(number of references to filegrp is > 0)
503 * precond(filegrp is writable)
504 */
505
506 int
filegrp_ffhold(filegrp_t * fgp)507 filegrp_ffhold(filegrp_t *fgp)
508 {
509 int error = 0;
510
511 cachefs_cache_dirty(fgp->fg_fscp->fs_cache, 1);
512
513 mutex_enter(&fgp->fg_mutex);
514 ASSERT(fgp->fg_flags & CFS_FG_WRITE);
515 ASSERT(fgp->fg_count > 0);
516
517 /* if the filegrp is no good, bail out with warning */
518 if (fgp->fg_flags & CFS_FG_NOCACHE) {
519 error = EINVAL;
520 goto out;
521 }
522
523 /* if we do not have the directory vp yet */
524 if (fgp->fg_flags & CFS_FG_ALLOC_FILE) {
525
526 /* create the directory if necessary */
527 if (fgp->fg_header->ach_nffs == 0) {
528 error = filegrpdir_create(fgp);
529 if (error)
530 goto out;
531 }
532
533 /* else find the directory */
534 else {
535 error = filegrpdir_find(fgp);
536 if (error) {
537 #ifdef CFSDEBUG
538 CFS_DEBUG(CFSDEBUG_FILEGRP)
539 printf("ffhold: no dir, errno %d, "
540 "fileno %llx\n",
541 error, (u_longlong_t)fgp->fg_id.cid_fileno);
542 #endif
543 goto out;
544 }
545 }
546 }
547 ASSERT(fgp->fg_dirvp);
548
549 #ifdef CFSDEBUG
550 if (fgp->fg_header->ach_nffs == 0) {
551 ASSERT(fgp->fg_header->ach_rl_current == CACHEFS_RL_ATTRFILE);
552 cachefs_rlent_verify(fgp->fg_fscp->fs_cache,
553 CACHEFS_RL_ATTRFILE, fgp->fg_header->ach_rlno);
554
555 /*
556 * XXX sam: this used to remove from the active list,
557 * and put on `NONE'. now, we're on
558 * CACHEFS_RL_ATTRFILE if either count or nffs is
559 * nonzero; CACHEFS_RL_GC otherwise. since we just
560 * asserted that we're not on CACHEFS_RL_GC, there's
561 * nothing more to do. right?
562 */
563 }
564 #endif /* CFSDEBUG */
565
566 fgp->fg_header->ach_nffs++;
567 fgp->fg_flags |= CFS_FG_UPDATED;
568 ASSERT(fgp->fg_header->ach_nffs <= fgp->fg_header->ach_count);
569
570 out:
571 mutex_exit(&fgp->fg_mutex);
572
573 return (error);
574 }
575
576 /*
577 * ------------------------------------------------------------------
578 *
579 * filegrp_ffrele
580 *
581 * Description:
582 * Decrements the count of the number of front files for
583 * this filegrp by one.
584 * Arguments:
585 * fgp filegrp object to dereference
586 * Returns:
587 * Preconditions:
588 * precond(fgp is a valid filegrp object)
589 * precond(filegrp is writable)
590 * precond(number of references to filegrp is > 0)
591 * precond(number of front file references is > 0)
592 */
593
594 void
filegrp_ffrele(filegrp_t * fgp)595 filegrp_ffrele(filegrp_t *fgp)
596 {
597 char name[CFS_FRONTFILE_NAME_SIZE];
598 char *fname;
599 struct fscache *fscp = fgp->fg_fscp;
600 int error = 0;
601
602 /* if the filegrp is corrupt, bail out with warning */
603 if (fgp->fg_flags & CFS_FG_NOCACHE) {
604 return;
605 }
606
607 cachefs_cache_dirty(fgp->fg_fscp->fs_cache, 1);
608
609 mutex_enter(&fgp->fg_mutex);
610 ASSERT(fgp->fg_flags & CFS_FG_WRITE);
611 ASSERT((fgp->fg_flags & CFS_FG_ALLOC_FILE) == 0);
612 ASSERT(fgp->fg_dirvp != NULL);
613 ASSERT(fgp->fg_count > 0);
614 ASSERT(fgp->fg_header->ach_nffs > 0);
615 ASSERT(fgp->fg_header->ach_nffs <= fgp->fg_header->ach_count);
616
617 fgp->fg_header->ach_nffs--;
618 fgp->fg_flags |= CFS_FG_UPDATED;
619
620 if (fgp->fg_header->ach_nffs == 0) {
621 make_ascii_name(&fgp->fg_id, name);
622 fname = name;
623 error = VOP_RMDIR(fscp->fs_fscdirvp, fname,
624 fscp->fs_fscdirvp, kcred, NULL, 0);
625 if (error == 0) {
626 cachefs_freefile(fscp->fs_cache);
627 cachefs_freeblocks(fscp->fs_cache, 1,
628 fgp->fg_header->ach_rl_current);
629 VN_RELE(fgp->fg_dirvp);
630 fgp->fg_dirvp = NULL;
631 fgp->fg_flags |= CFS_FG_ALLOC_FILE;
632 } else {
633 fgp->fg_flags |= CFS_FG_NOCACHE;
634 cmn_err(CE_WARN, "cachefs_ffrele:"
635 " frontfs cache error %d, run fsck", error);
636 }
637
638 /*
639 * XXX sam: this used to move from `NONE' to
640 * `CACHEFS_RL_ACTIVE'. now, we're on
641 * CACHEFS_RL_ATTRFILE if count and/or nffs is
642 * nonzero, and CACHEFS_RL_GC otherwise. since we
643 * just asserted that count > 0, there's nothing to
644 * do. right?
645 */
646 #ifdef CFSDEBUG
647 cachefs_rlent_verify(fgp->fg_fscp->fs_cache,
648 CACHEFS_RL_ATTRFILE, fgp->fg_header->ach_rlno);
649 #endif /* CFSDEBUG */
650 }
651 mutex_exit(&fgp->fg_mutex);
652 }
653
654 /*
655 * ------------------------------------------------------------------
656 *
657 * filegrp_sync
658 *
659 * Description:
660 * Writes the file group's attrcache header to the attrcache
661 * file if necessary and syncs it.
662 * Arguments:
663 * fgp filegrp object
664 * Returns:
665 * Returns 0 on success, an errno value on failure.
666 * Preconditions:
667 * precond(fgp is a valid filegrp object)
668 */
669
670 int
filegrp_sync(filegrp_t * fgp)671 filegrp_sync(filegrp_t *fgp)
672 {
673 int error = 0;
674
675 mutex_enter(&fgp->fg_mutex);
676
677 if (((fgp->fg_flags & CFS_FG_UPDATED) == 0) ||
678 (fgp->fg_flags & CFS_FG_ALLOC_ATTR) ||
679 CFS_ISFS_BACKFS_NFSV4(fgp->fg_fscp)) {
680 mutex_exit(&fgp->fg_mutex);
681 return (0);
682 }
683
684 ASSERT(fgp->fg_header->ach_nffs <= fgp->fg_header->ach_count);
685
686 error = vn_rdwr(UIO_WRITE, fgp->fg_attrvp, (caddr_t)fgp->fg_header,
687 fgp->fg_headersize, 0LL, UIO_SYSSPACE, 0, (rlim64_t)RLIM_INFINITY,
688 kcred, NULL);
689
690 if (error == 0)
691 error = VOP_FSYNC(fgp->fg_attrvp, FSYNC, kcred, NULL);
692
693 if (error == 0)
694 fgp->fg_flags &= ~CFS_FG_UPDATED;
695
696 mutex_exit(&fgp->fg_mutex);
697
698 return (error);
699 }
700
701 /*
702 * ------------------------------------------------------------------
703 *
704 * filegrp_read_metadata
705 *
706 * Description:
707 * Reads the metadata for the specified file from the attrcache
708 * file belonging to the filegrp object. Note that the md_rltype
709 * field may be incorrect if (cachep->c_flags & CACHE_CHECK_RLTYPE);
710 * in this case, if you care about md_rltype, you should double-check
711 * if rl_type is CACHEFS_RL_ACTIVE; cachefs_move_active_to_rl may have
712 * moved it without telling us.
713 * Arguments:
714 * fgp filegrp object
715 * cidp the file to search for
716 * mdp set to the metadata for the fileno
717 * Returns:
718 * Returns 0 on success, an errno value on failure.
719 * Preconditions:
720 * precond(fgp is a valid filegrp object)
721 * precond(mdp)
722 * precond(slotp)
723 */
724
725 int
filegrp_read_metadata(filegrp_t * fgp,cfs_cid_t * cidp,struct cachefs_metadata * mdp)726 filegrp_read_metadata(filegrp_t *fgp, cfs_cid_t *cidp,
727 struct cachefs_metadata *mdp)
728 {
729 int slot;
730 int error;
731 int index;
732 struct cfs_cachefs_metadata *tmpmdp;
733
734 ASSERT(CFS_ISFS_BACKFS_NFSV4(fgp->fg_fscp) == 0);
735
736 mutex_enter(&fgp->fg_mutex);
737 if (fgp->fg_flags & CFS_FG_ALLOC_ATTR) {
738 mutex_exit(&fgp->fg_mutex);
739 return (ENOENT);
740 }
741
742 slot = filegrp_cid_to_slot(fgp, cidp);
743 if (slot == 0) {
744 mutex_exit(&fgp->fg_mutex);
745 return (ENOENT);
746 }
747
748
749 /* see if metadata was ever written */
750 index = (int)(cidp->cid_fileno - fgp->fg_id.cid_fileno);
751 if (fgp->fg_offsets[index].ach_written == 0) {
752 mutex_exit(&fgp->fg_mutex);
753 return (ENOENT);
754 }
755
756 CACHEFS_ALLOC_CFS_METADATA(tmpmdp, mdp);
757
758 error = vn_rdwr(UIO_READ, fgp->fg_attrvp,
759 (caddr_t)tmpmdp, sizeof (struct cfs_cachefs_metadata),
760 (offset_t)slot,
761 UIO_SYSSPACE, 0, (long long)0, kcred, NULL);
762 if (error) {
763 cmn_err(CE_WARN,
764 "cachefs_read_metadata:"
765 " frontfs cache error %d, run fsck", error);
766 }
767 CACHEFS_COPY_CFS_METADATA_TO_METADATA(tmpmdp, mdp);
768 CACHEFS_FREE_CFS_METADATA(tmpmdp);
769
770 mutex_exit(&fgp->fg_mutex);
771 return (error);
772 }
773
774 /*
775 * ------------------------------------------------------------------
776 *
777 * filegrp_create_metadata
778 *
779 * Description:
780 * Allocates a slot for the specified fileno.
781 * Arguments:
782 * fgp filegrp object
783 * cidp the file to allocate a slot for
784 * Returns:
785 * Returns 0 on success, an errno value on failure.
786 * Preconditions:
787 * precond(fgp is a valid filegrp object)
788 */
789
790 int
filegrp_create_metadata(filegrp_t * fgp,struct cachefs_metadata * md,cfs_cid_t * cidp)791 filegrp_create_metadata(filegrp_t *fgp, struct cachefs_metadata *md,
792 cfs_cid_t *cidp)
793 {
794 struct fscache *fscp = fgp->fg_fscp;
795 cachefscache_t *cachep = fscp->fs_cache;
796 int slot;
797 int bitno;
798 uchar_t mask;
799 int last;
800 int xx;
801 int index;
802
803 ASSERT(CFS_ISFS_BACKFS_NFSV4(fgp->fg_fscp) == 0);
804
805 cachefs_cache_dirty(cachep, 1);
806
807 mutex_enter(&fgp->fg_mutex);
808
809 if (fgp->fg_flags & CFS_FG_ALLOC_ATTR) {
810 mutex_exit(&fgp->fg_mutex);
811 return (ENOENT);
812 }
813
814 slot = filegrp_cid_to_slot(fgp, cidp);
815 if (slot) {
816 mutex_exit(&fgp->fg_mutex);
817 return (0);
818 }
819
820 index = (int)(cidp->cid_fileno - fgp->fg_id.cid_fileno);
821
822 ASSERT(index < fgp->fg_fscp->fs_info.fi_fgsize);
823
824 last = (((fgp->fg_fscp->fs_info.fi_fgsize + 7) & ~(7)) / 8);
825 for (xx = 0; xx < last; xx++) {
826 if (fgp->fg_alloclist[xx] != (uchar_t)0xff) {
827 for (mask = 1, bitno = 0; bitno < 8; bitno++) {
828 if ((mask & fgp->fg_alloclist[xx]) == 0) {
829 slot = (xx * 8) + bitno;
830 goto found;
831 }
832 mask <<= 1;
833 }
834 }
835 }
836 found:
837 if (xx == last) {
838 cmn_err(CE_WARN, "cachefs: attrcache error, run fsck");
839 mutex_exit(&fgp->fg_mutex);
840 return (ENOMEM);
841 }
842
843 slot = (slot * (int)sizeof (struct cfs_cachefs_metadata)) +
844 fgp->fg_headersize;
845
846 ASSERT(fgp->fg_header->ach_nffs <= fgp->fg_header->ach_count);
847 fgp->fg_header->ach_count++;
848 fgp->fg_offsets[index].ach_offset = slot;
849 fgp->fg_offsets[index].ach_written = 0;
850 fgp->fg_alloclist[xx] |= mask;
851 fgp->fg_flags |= CFS_FG_UPDATED;
852
853 mutex_exit(&fgp->fg_mutex);
854
855 if (CACHEFS_LOG_LOGGING(cachep, CACHEFS_LOG_MDCREATE))
856 cachefs_log_mdcreate(cachep, 0,
857 fscp->fs_cfsvfsp, &md->md_cookie, cidp->cid_fileno,
858 fgp->fg_header->ach_count);
859
860 return (0);
861 }
862
863 /*
864 * ------------------------------------------------------------------
865 *
866 * filegrp_write_metadata
867 *
868 * Description:
869 * Writes metadata to the slot held by file.
870 * Arguments:
871 * fgp filegrp object
872 * cidp the file to write the metadata for
873 * mdp the metadata to write
874 * Returns:
875 * Returns 0 on success, an errno value on failure.
876 * Preconditions:
877 * precond(fgp is a valid filegrp object)
878 * precond(mdp)
879 */
880 int
filegrp_write_metadata(filegrp_t * fgp,cfs_cid_t * cidp,struct cachefs_metadata * mdp)881 filegrp_write_metadata(filegrp_t *fgp, cfs_cid_t *cidp,
882 struct cachefs_metadata *mdp)
883 {
884 int error = 0;
885 int slot;
886 blkcnt64_t nblks;
887 int index;
888 struct fscache *fscp = fgp->fg_fscp;
889 struct cfs_cachefs_metadata *tmpmdp;
890
891 ASSERT(CFS_ISFS_BACKFS_NFSV4(fgp->fg_fscp) == 0);
892
893 cachefs_cache_dirty(fscp->fs_cache, 1);
894 mutex_enter(&fgp->fg_mutex);
895
896 if (fgp->fg_flags & CFS_FG_ALLOC_ATTR) {
897 error = ENOENT;
898 goto out;
899 }
900
901 slot = filegrp_cid_to_slot(fgp, cidp);
902 if (slot == 0) {
903 error = ENOENT;
904 goto out;
905 }
906
907 /* allocate blocks for the data if necessary */
908 nblks = slot + sizeof (struct cfs_cachefs_metadata);
909 nblks = (nblks + MAXBSIZE - 1) / MAXBSIZE;
910 nblks -= fgp->fg_header->ach_nblks;
911 if (nblks > 0) {
912 error = cachefs_allocblocks(fscp->fs_cache, nblks,
913 fgp->fg_header->ach_rl_current);
914 if (error)
915 goto out;
916 error = filegrp_write_space(fgp->fg_attrvp,
917 (offset_t)fgp->fg_header->ach_nblks * MAXBSIZE,
918 nblks * MAXBSIZE);
919 if (error) {
920 cachefs_freeblocks(fscp->fs_cache, nblks,
921 fgp->fg_header->ach_rl_current);
922 goto out;
923 }
924 } else
925 nblks = 0;
926
927 CACHEFS_ALLOC_CFS_METADATA(tmpmdp, mdp);
928 CACHEFS_COPY_METADATA_TO_CFS_METADATA(mdp, tmpmdp, error);
929 /* write the metadata */
930 if (!error)
931 error = vn_rdwr(UIO_WRITE, fgp->fg_attrvp, (caddr_t)tmpmdp,
932 sizeof (struct cfs_cachefs_metadata), (offset_t)slot,
933 UIO_SYSSPACE, 0, (rlim64_t)RLIM_INFINITY, kcred, NULL);
934
935 CACHEFS_FREE_CFS_METADATA(tmpmdp);
936
937 if (error) {
938 if (error == EOVERFLOW) {
939 cmn_err(CE_WARN, "cachefs_write_metadata:"
940 " time/dev overflow error %d", error);
941 } else if (error != ENOSPC) {
942 cmn_err(CE_WARN,
943 "cachefs: UFS write error %d, run fsck",
944 error);
945 }
946 cachefs_freeblocks(fscp->fs_cache, nblks,
947 fgp->fg_header->ach_rl_current);
948 goto out;
949 }
950
951 /* mark metadata as having been written */
952 index = (int)(cidp->cid_fileno - fgp->fg_id.cid_fileno);
953 fgp->fg_offsets[index].ach_written = 1;
954
955 /* update number of blocks used by the attrcache file */
956 fgp->fg_header->ach_nblks += nblks;
957
958 /* force sync to be done eventually */
959 fgp->fg_flags |= CFS_FG_UPDATED;
960
961 out:
962 mutex_exit(&fgp->fg_mutex);
963 return (error);
964 }
965
966 /*
967 * ------------------------------------------------------------------
968 *
969 * filegrp_destroy_metadata
970 *
971 * Description:
972 * Destroys the metadata associated with the specified file.
973 * Arguments:
974 * fgp filegrp object
975 * cidp the file to destroy the metadata for
976 * Returns:
977 * Returns 0 on success, an errno value on failure.
978 * Preconditions:
979 * precond(fgp is a valid filegrp object)
980 */
981
982 int
filegrp_destroy_metadata(filegrp_t * fgp,cfs_cid_t * cidp)983 filegrp_destroy_metadata(filegrp_t *fgp, cfs_cid_t *cidp)
984 {
985 int i;
986 int bitno;
987 uchar_t mask = 1;
988
989 int slot;
990
991 ASSERT(CFS_ISFS_BACKFS_NFSV4(fgp->fg_fscp) == 0);
992
993 cachefs_cache_dirty(fgp->fg_fscp->fs_cache, 1);
994 mutex_enter(&fgp->fg_mutex);
995
996 if (fgp->fg_flags & CFS_FG_ALLOC_ATTR) {
997 mutex_exit(&fgp->fg_mutex);
998 return (ENOENT);
999 }
1000
1001 slot = filegrp_cid_to_slot(fgp, cidp);
1002 if (slot == 0) {
1003 mutex_exit(&fgp->fg_mutex);
1004 return (ENOENT);
1005 }
1006
1007 i = (int)(cidp->cid_fileno - fgp->fg_id.cid_fileno);
1008 fgp->fg_offsets[i].ach_offset = 0;
1009 fgp->fg_offsets[i].ach_written = 0;
1010 i = (slot - fgp->fg_headersize) /
1011 (int)sizeof (struct cfs_cachefs_metadata);
1012 bitno = i & 7;
1013 i = i >> 3;
1014 mask <<= bitno;
1015 if (fgp->fg_alloclist[i] & mask)
1016 fgp->fg_alloclist[i] &= ~mask;
1017 else
1018 cmn_err(CE_WARN,
1019 "filegrp_destroy_metadata:"
1020 " fileno %" PRId64 " slot %d-%d fgp %p not allocated",
1021 cidp->cid_fileno, i, bitno, (void *)fgp);
1022
1023 fgp->fg_header->ach_count--;
1024 ASSERT(fgp->fg_header->ach_nffs <= fgp->fg_header->ach_count);
1025 fgp->fg_flags |= CFS_FG_UPDATED;
1026 mutex_exit(&fgp->fg_mutex);
1027
1028 return (0);
1029 }
1030
1031 /*
1032 * ------------------------------------------------------------------
1033 *
1034 * filegrp_list_find
1035 *
1036 * Description:
1037 * Looks for the filegrp that owns the specified file
1038 * on the fscp filegrp lists.
1039 * The fscp->fs_fslock must be held while this routine is called.
1040 * By convention the filegrp object returned may be used as
1041 * long as the fs_fslock is held. To use the filegrp after
1042 * dropping fs_fslock, call filegrp_hold.
1043 * Arguments:
1044 * fscp fscache object
1045 * cidp the file to search on
1046 * Returns:
1047 * Returns the filegrp object if found, NULL if not.
1048 * Preconditions:
1049 * precond(fscp is a valid fscache object)
1050 */
1051
1052 filegrp_t *
filegrp_list_find(struct fscache * fscp,cfs_cid_t * cidp)1053 filegrp_list_find(struct fscache *fscp, cfs_cid_t *cidp)
1054 {
1055 int fgsize = fscp->fs_info.fi_fgsize;
1056 struct filegrp *fgp;
1057 ino64_t fxx;
1058 int findex;
1059 ino64_t fileno;
1060
1061 ASSERT(MUTEX_HELD(&fscp->fs_fslock));
1062
1063 /* get fileno of filegrp */
1064 fxx = (ino64_t)(cidp->cid_fileno / fgsize);
1065 fileno = fxx * fgsize;
1066
1067 /* hash into array of file groups */
1068 findex = (int)(fxx & (CFS_FS_FGP_BUCKET_SIZE - 1));
1069
1070 /* search set of file groups for this hash bucket */
1071 for (fgp = fscp->fs_filegrp[findex];
1072 fgp != NULL;
1073 fgp = fgp->fg_next) {
1074 if ((fgp->fg_id.cid_fileno == fileno) &&
1075 (fgp->fg_id.cid_flags == cidp->cid_flags))
1076 break;
1077 }
1078
1079 return (fgp);
1080 }
1081
1082 /*
1083 * ------------------------------------------------------------------
1084 *
1085 * filegrp_list_add
1086 *
1087 * Description:
1088 * Adds the filegrp to the list of filegrps in the fscp.
1089 * The fscp->fs_fslock must be held while this routine is called.
1090 * Arguments:
1091 * fscp fscache object
1092 * fgp filegrp object
1093 * Returns:
1094 * Preconditions:
1095 * precond(fscp is a valid fscache object)
1096 * precond(fgp is a valid filegrp object)
1097 * precond(fgp is not already on a list of filegrps)
1098 */
1099
1100 void
filegrp_list_add(struct fscache * fscp,filegrp_t * fgp)1101 filegrp_list_add(struct fscache *fscp, filegrp_t *fgp)
1102 {
1103 int findex;
1104 int fgsize = fscp->fs_info.fi_fgsize;
1105
1106 ASSERT(MUTEX_HELD(&fscp->fs_fslock));
1107 ASSERT(fgp->fg_next == NULL);
1108
1109 /* hash into array of file groups */
1110 findex = (int)((fgp->fg_id.cid_fileno / fgsize) &
1111 (CFS_FS_FGP_BUCKET_SIZE - 1));
1112
1113 fgp->fg_next = fscp->fs_filegrp[findex];
1114 fscp->fs_filegrp[findex] = fgp;
1115 fscp->fs_ref++;
1116 }
1117
1118 /*
1119 * ------------------------------------------------------------------
1120 *
1121 * filegrp_list_remove
1122 *
1123 * Description:
1124 * Removes the filegrp from the list of filegrps in the fscp.
1125 * The fscp->fs_fslock must be held while this routine is called.
1126 * Arguments:
1127 * fscp fscache object
1128 * fgp filegrp object
1129 * Returns:
1130 * Preconditions:
1131 * precond(fscp is a valid fscache object)
1132 * precond(fgp is a valid filegrp object)
1133 * precond(fgp is on the list of filegrps in fscp)
1134 */
1135
1136 void
filegrp_list_remove(struct fscache * fscp,filegrp_t * fgp)1137 filegrp_list_remove(struct fscache *fscp, filegrp_t *fgp)
1138 {
1139 struct filegrp *fp;
1140 struct filegrp **pfgp;
1141 int found = 0;
1142 int findex;
1143 int fgsize = fscp->fs_info.fi_fgsize;
1144
1145 ASSERT(MUTEX_HELD(&fscp->fs_fslock));
1146
1147 /* hash into array of file groups */
1148 findex = (int)((fgp->fg_id.cid_fileno / fgsize) &
1149 (CFS_FS_FGP_BUCKET_SIZE - 1));
1150 fp = fscp->fs_filegrp[findex];
1151 pfgp = &fscp->fs_filegrp[findex];
1152
1153 while (fp != NULL) {
1154 if (fp == fgp) {
1155 *pfgp = fp->fg_next;
1156 fp->fg_next = NULL;
1157 found++;
1158 break;
1159 }
1160 pfgp = &fp->fg_next;
1161 fp = fp->fg_next;
1162 }
1163 ASSERT(found);
1164 fscp->fs_ref--;
1165 }
1166
1167 /*
1168 * ------------------------------------------------------------------
1169 *
1170 * filegrp_list_gc
1171 *
1172 * Description:
1173 * Traverses the filegrp lists and throws away any filegrps that are
1174 * not in use.
1175 * The fscp->fs_fslock must be held while this routine is called.
1176 * Arguments:
1177 * fscp fscache object
1178 * Returns:
1179 * Preconditions:
1180 * precond(fscp is a valid fscache object)
1181 */
1182
1183 void
filegrp_list_gc(struct fscache * fscp)1184 filegrp_list_gc(struct fscache *fscp)
1185 {
1186 struct filegrp *next, *fgp;
1187 int xx;
1188
1189 ASSERT(MUTEX_HELD(&fscp->fs_fslock));
1190
1191 for (xx = 0; xx < CFS_FS_FGP_BUCKET_SIZE; xx++) {
1192 for (fgp = fscp->fs_filegrp[xx]; fgp != NULL; fgp = next) {
1193 next = fgp->fg_next;
1194 mutex_enter(&fgp->fg_mutex);
1195 if (fgp->fg_count > 0) {
1196 mutex_exit(&fgp->fg_mutex);
1197 continue;
1198 }
1199 mutex_exit(&fgp->fg_mutex);
1200 filegrp_list_remove(fscp, fgp);
1201 filegrp_destroy(fgp);
1202 }
1203 }
1204 }
1205
1206 /*
1207 * ------------------------------------------------------------------
1208 *
1209 * filegrp_setup
1210 *
1211 * Description:
1212 * Perform initialization actions on the given filegrp.
1213 * The fgp->fg_mutex must be held while this routine is called.
1214 * Arguments:
1215 * fgp filegrp object
1216 * flags flags to be OR'ed into the fgp flags field
1217 * dorl indicates whether filegrp should be removed from rl or not
1218 * Returns:
1219 * Preconditions:
1220 * precond(fgp is a valid filegrp object)
1221 */
1222 static void
filegrp_setup(struct filegrp * fgp,int flags,int dorl)1223 filegrp_setup(struct filegrp *fgp, int flags, int dorl)
1224 {
1225 ASSERT(MUTEX_HELD(&fgp->fg_mutex));
1226
1227 /* turn on the specified flags */
1228 if (flags)
1229 fgp->fg_flags |= flags;
1230
1231 /* if the attrcache file exists, find it */
1232 if (fgp->fg_flags & CFS_FG_ALLOC_ATTR)
1233 (void) filegrpattr_find(fgp);
1234
1235 /* if the attrcache directory exists, find it */
1236 if (((fgp->fg_flags & CFS_FG_ALLOC_ATTR) == 0) &&
1237 (fgp->fg_flags & CFS_FG_ALLOC_FILE) &&
1238 (fgp->fg_header->ach_nffs > 0)) {
1239 (void) filegrpdir_find(fgp);
1240 }
1241
1242 /* move from gc list to attrfile list if necessary */
1243 if ((dorl != 0) &&
1244 ((fgp->fg_flags & CFS_FG_ALLOC_ATTR) == 0) &&
1245 (fgp->fg_header->ach_rl_current == CACHEFS_RL_GC)) {
1246 ASSERT(fgp->fg_header->ach_nffs == 0);
1247 if (fgp->fg_count > 0) {
1248 #ifdef CFSDEBUG
1249 cachefs_rlent_verify(fgp->fg_fscp->fs_cache,
1250 CACHEFS_RL_GC, fgp->fg_header->ach_rlno);
1251 #endif /* CFSDEBUG */
1252 cachefs_rlent_moveto(fgp->fg_fscp->fs_cache,
1253 CACHEFS_RL_ATTRFILE, fgp->fg_header->ach_rlno,
1254 fgp->fg_header->ach_nblks);
1255 fgp->fg_header->ach_rl_current = CACHEFS_RL_ATTRFILE;
1256 fgp->fg_flags |= CFS_FG_UPDATED;
1257 }
1258 }
1259 }
1260
1261 /*
1262 * ------------------------------------------------------------------
1263 *
1264 * filegrp_list_enable_caching_ro
1265 *
1266 * Description:
1267 * Traverses the filegrp lists and enables the
1268 * use of the cache read-only.
1269 * The fscp->fs_fslock must be held while this routine is called.
1270 * Arguments:
1271 * fscp fscache object
1272 * Returns:
1273 * Preconditions:
1274 * precond(fscp is a valid fscache object)
1275 */
1276
1277 void
filegrp_list_enable_caching_ro(struct fscache * fscp)1278 filegrp_list_enable_caching_ro(struct fscache *fscp)
1279 {
1280 struct filegrp *fgp;
1281 int xx;
1282
1283 ASSERT(MUTEX_HELD(&fscp->fs_fslock));
1284
1285 for (xx = 0; xx < CFS_FS_FGP_BUCKET_SIZE; xx++) {
1286 for (fgp = fscp->fs_filegrp[xx]; fgp != NULL;
1287 fgp = fgp->fg_next) {
1288 mutex_enter(&fgp->fg_mutex);
1289 filegrp_setup(fgp, 0, 0);
1290 mutex_exit(&fgp->fg_mutex);
1291 }
1292 }
1293 }
1294
1295 /*
1296 * ------------------------------------------------------------------
1297 *
1298 * filegrp_list_enable_caching_rw
1299 *
1300 * Description:
1301 * Traverses the filegrp lists and enables the
1302 * use of the cache read-write.
1303 * The fscp->fs_fslock must be held while this routine is called.
1304 * Arguments:
1305 * fscp fscache object
1306 * Returns:
1307 * Preconditions:
1308 * precond(fscp is a valid fscache object)
1309 * precond(all filegrps must be in the read-only state)
1310 */
1311
1312 void
filegrp_list_enable_caching_rw(struct fscache * fscp)1313 filegrp_list_enable_caching_rw(struct fscache *fscp)
1314 {
1315 struct filegrp *fgp;
1316 int xx;
1317
1318 ASSERT(MUTEX_HELD(&fscp->fs_fslock));
1319
1320 for (xx = 0; xx < CFS_FS_FGP_BUCKET_SIZE; xx++) {
1321 for (fgp = fscp->fs_filegrp[xx]; fgp != NULL;
1322 fgp = fgp->fg_next) {
1323 mutex_enter(&fgp->fg_mutex);
1324 filegrp_setup(fgp, CFS_FG_READ|CFS_FG_WRITE, 1);
1325 mutex_exit(&fgp->fg_mutex);
1326 }
1327 }
1328 }
1329
1330 /*
1331 * ------------------------------------------------------------------
1332 *
1333 * filegrpdir_find
1334 *
1335 * Description:
1336 * Tries to find the filegrp frontfile directory in the cache.
1337 * If found CFS_FG_ALLOC_FILE is turned off.
1338 * This routine should not be called if CFS_FG_ALLOC_FILE is
1339 * already off.
1340 * Arguments:
1341 * fgp filegrp object
1342 * Returns:
1343 * Returns 0 on success, an errno value on failure.
1344 * Preconditions:
1345 * precond(fgp is a valid filegrp object)
1346 */
1347
1348 int
filegrpdir_find(filegrp_t * fgp)1349 filegrpdir_find(filegrp_t *fgp)
1350 {
1351 int error;
1352 vnode_t *dirvp;
1353 char name[CFS_FRONTFILE_NAME_SIZE];
1354 char *fname;
1355 struct fscache *fscp = fgp->fg_fscp;
1356
1357 if (fgp->fg_flags & CFS_FG_ALLOC_ATTR)
1358 return (ENOENT);
1359 ASSERT(fgp->fg_flags & CFS_FG_ALLOC_FILE);
1360
1361 make_ascii_name(&fgp->fg_id, name);
1362 fname = name;
1363 error = VOP_LOOKUP(fscp->fs_fscdirvp, fname, &dirvp, NULL,
1364 0, NULL, kcred, NULL, NULL, NULL);
1365 if (error == 0) {
1366 fgp->fg_dirvp = dirvp;
1367 fgp->fg_flags &= ~CFS_FG_ALLOC_FILE;
1368 #ifdef CFSDEBUG
1369 if (fgp->fg_header->ach_nffs == 0) {
1370 CFS_DEBUG(CFSDEBUG_FILEGRP)
1371 printf("filegrpdir_find: "
1372 "%s found but no front files\n", fname);
1373 }
1374 #endif
1375 }
1376 #ifdef CFSDEBUG
1377 else if (fgp->fg_header->ach_nffs != 0) {
1378 CFS_DEBUG(CFSDEBUG_FILEGRP)
1379 printf("filegrpdir_find: "
1380 "%s NOT found but %d front files\n",
1381 fname, fgp->fg_header->ach_nffs);
1382 }
1383 #endif
1384 return (error);
1385 }
1386
1387 /*
1388 * ------------------------------------------------------------------
1389 *
1390 * filegrparttr_find
1391 *
1392 * Description:
1393 * Tries to find the attrcache file for the given filegrp.
1394 * If found the header information is read in and
1395 * CFS_FG_ALLOC_ATTR is turned off.
1396 * This routine should not be called if CFS_FG_ALLOC_ATTR is
1397 * already off.
1398 * Arguments:
1399 * fgp filegrp object
1400 * Returns:
1401 * Returns 0 on success, an errno value on failure.
1402 * Preconditions:
1403 * precond(fgp is a valid filegrp object)
1404 * precond(fgp is readable)
1405 */
1406
1407 int
filegrpattr_find(struct filegrp * fgp)1408 filegrpattr_find(struct filegrp *fgp)
1409 {
1410 int error = 0;
1411 struct fscache *fscp = fgp->fg_fscp;
1412 cachefscache_t *cachep = fscp->fs_cache;
1413 vnode_t *attrvp;
1414 struct attrcache_header *ahp;
1415 char name[CFS_FRONTFILE_NAME_SIZE];
1416 char *fname;
1417
1418 if (fgp->fg_flags & CFS_FG_NOCACHE)
1419 return (ENOENT);
1420
1421 ASSERT(fgp->fg_flags & CFS_FG_ALLOC_ATTR);
1422 make_ascii_name(&fgp->fg_id, name);
1423 fname = name;
1424 error = VOP_LOOKUP(fscp->fs_fsattrdir, fname,
1425 &attrvp, NULL, 0, NULL, kcred, NULL, NULL, NULL);
1426 if (error) {
1427 return (error);
1428 }
1429 ahp = (struct attrcache_header *)cachefs_kmem_zalloc(
1430 fgp->fg_headersize, KM_SLEEP);
1431
1432 error = vn_rdwr(UIO_READ, attrvp, (caddr_t)ahp,
1433 fgp->fg_headersize, 0LL, UIO_SYSSPACE,
1434 0, (rlim64_t)RLIM_INFINITY, kcred, NULL);
1435 if (error) {
1436 cmn_err(CE_WARN, "cachefs: Read attrcache error %d, run fsck",
1437 error);
1438 cachefs_kmem_free(ahp, fgp->fg_headersize);
1439 fgp->fg_flags |= CFS_FG_NOCACHE;
1440 VN_RELE(attrvp);
1441 } else {
1442 ASSERT(ahp->ach_nffs <= ahp->ach_count);
1443 fgp->fg_attrvp = attrvp;
1444 fgp->fg_header = ahp;
1445 fgp->fg_offsets = (struct attrcache_index *)(ahp + 1);
1446 fgp->fg_alloclist = ((uchar_t *)fgp->fg_offsets) +
1447 (fscp->fs_info.fi_fgsize *
1448 sizeof (struct attrcache_index));
1449 fgp->fg_flags &= ~CFS_FG_ALLOC_ATTR;
1450
1451 if ((cachep->c_flags & CACHE_CHECK_RLTYPE) &&
1452 (ahp->ach_rl_current == CACHEFS_RL_ATTRFILE)) {
1453 rl_entry_t *rlp, rl;
1454
1455 mutex_enter(&cachep->c_contentslock);
1456 error = cachefs_rl_entry_get(cachep, ahp->ach_rlno,
1457 &rlp);
1458 if (error) {
1459 mutex_exit(&cachep->c_contentslock);
1460 cachefs_kmem_free(ahp, fgp->fg_headersize);
1461 fgp->fg_flags |= CFS_FG_NOCACHE;
1462 VN_RELE(attrvp);
1463 return (error);
1464 }
1465
1466 rl = *rlp;
1467 mutex_exit(&cachep->c_contentslock);
1468
1469 if (rl.rl_current != ahp->ach_rl_current) {
1470 ahp->ach_rl_current = rl.rl_current;
1471 fgp->fg_flags |= CFS_FG_UPDATED;
1472 }
1473 }
1474
1475 /* if the attr file is on the rl */
1476 if (fgp->fg_header->ach_rl_current == CACHEFS_RL_GC) {
1477 #ifdef CFSDEBUG
1478 if (fgp->fg_flags & CFS_FG_WRITE)
1479 cachefs_rlent_verify(fgp->fg_fscp->fs_cache,
1480 CACHEFS_RL_GC,
1481 fgp->fg_header->ach_rlno);
1482 #endif /* CFSDEBUG */
1483 if ((fgp->fg_count > 0) &&
1484 (fgp->fg_flags & CFS_FG_WRITE)) {
1485 /* remove from rl, put on active */
1486 cachefs_rlent_moveto(fgp->fg_fscp->fs_cache,
1487 CACHEFS_RL_ATTRFILE,
1488 fgp->fg_header->ach_rlno,
1489 fgp->fg_header->ach_nblks);
1490 fgp->fg_header->ach_rl_current =
1491 CACHEFS_RL_ATTRFILE;
1492 fgp->fg_flags |= CFS_FG_UPDATED;
1493 }
1494 } else {
1495 ASSERT(fgp->fg_header->ach_rl_current ==
1496 CACHEFS_RL_ATTRFILE);
1497 #ifdef CFSDEBUG
1498 if (fgp->fg_flags & CFS_FG_WRITE)
1499 cachefs_rlent_verify(fgp->fg_fscp->fs_cache,
1500 CACHEFS_RL_ATTRFILE,
1501 fgp->fg_header->ach_rlno);
1502 #endif /* CFSDEBUG */
1503 }
1504 }
1505
1506 return (error);
1507 }
1508
1509 /*
1510 * ------------------------------------------------------------------
1511 *
1512 * filegrpdir_create
1513 *
1514 * Description:
1515 * Creates the filegrp directory in the cache.
1516 * If created CFS_FG_ALLOC_FILE is turned off.
1517 * This routine should not be called if CFS_FG_ALLOC_FILE is
1518 * already off.
1519 * Arguments:
1520 * fgp filegrp object
1521 * Returns:
1522 * Returns 0 on success, an errno value on failure.
1523 * Preconditions:
1524 * precond(fgp is a valid filegrp object)
1525 * precond(filegrp is writeable)
1526 */
1527
1528 int
filegrpdir_create(filegrp_t * fgp)1529 filegrpdir_create(filegrp_t *fgp)
1530 {
1531 int error;
1532 vnode_t *dirvp = NULL;
1533 struct vattr *attrp = NULL;
1534 char name[CFS_FRONTFILE_NAME_SIZE];
1535 char *fname;
1536 struct fscache *fscp = fgp->fg_fscp;
1537
1538 ASSERT(fgp->fg_flags & CFS_FG_WRITE);
1539 ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
1540 ASSERT(MUTEX_HELD(&fgp->fg_mutex));
1541
1542 if (fgp->fg_flags & (CFS_FG_ALLOC_ATTR | CFS_FG_NOCACHE))
1543 return (ENOENT);
1544
1545 /* allocate a 1 block file for the directory */
1546 error = cachefs_allocfile(fscp->fs_cache);
1547 if (error) {
1548 return (error);
1549 }
1550 error = cachefs_allocblocks(fscp->fs_cache, 1,
1551 fgp->fg_header->ach_rl_current);
1552 if (error) {
1553 cachefs_freefile(fscp->fs_cache);
1554 return (error);
1555 }
1556
1557 /*
1558 * Construct a name for this file group directory and then do a mkdir
1559 */
1560 make_ascii_name(&fgp->fg_id, name);
1561 fname = name;
1562 attrp = (struct vattr *)cachefs_kmem_alloc(sizeof (struct vattr),
1563 KM_SLEEP);
1564 attrp->va_mode = S_IFDIR | 0777;
1565 attrp->va_uid = 0;
1566 attrp->va_gid = 0;
1567 attrp->va_type = VDIR;
1568 attrp->va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID;
1569 error = VOP_MKDIR(fscp->fs_fscdirvp, fname, attrp, &dirvp, kcred, NULL,
1570 0, NULL);
1571 if (error) {
1572 fgp->fg_flags |= CFS_FG_NOCACHE;
1573 cachefs_freefile(fscp->fs_cache);
1574 cachefs_freeblocks(fscp->fs_cache, 1,
1575 fgp->fg_header->ach_rl_current);
1576 } else {
1577 fgp->fg_dirvp = dirvp;
1578 fgp->fg_flags &= ~CFS_FG_ALLOC_FILE;
1579 }
1580
1581 if (attrp)
1582 cachefs_kmem_free(attrp, sizeof (*attrp));
1583
1584 return (error);
1585 }
1586
1587 /*
1588 * ------------------------------------------------------------------
1589 *
1590 * filegrpattr_create
1591 *
1592 * Description:
1593 * Creates the attrcache file for the given filegrp.
1594 * If created CFS_FG_ALLOC_ATTR is turned off.
1595 * This routine should not be called if CFS_FG_ALLOC_ATTR is
1596 * already off.
1597 * Arguments:
1598 * fgp filegrp object
1599 * Returns:
1600 * Returns 0 on success, an errno value on failure.
1601 * Preconditions:
1602 * precond(fgp is a valid filegrp object)
1603 * precond(filegrp is writable)
1604 */
1605
1606 int
filegrpattr_create(struct filegrp * fgp)1607 filegrpattr_create(struct filegrp *fgp)
1608 {
1609 int error;
1610 vnode_t *attrvp = NULL;
1611 struct attrcache_header *ahp = NULL;
1612 int nblks = 0;
1613 int gotrlent = 0;
1614 struct vattr *attrp = NULL;
1615 char name[CFS_FRONTFILE_NAME_SIZE];
1616 char *fname;
1617 struct fscache *fscp = fgp->fg_fscp;
1618 rl_entry_t rl_ent;
1619
1620 ASSERT(fgp->fg_flags & CFS_FG_WRITE);
1621
1622 if (fgp->fg_flags & CFS_FG_NOCACHE)
1623 return (ENOENT);
1624
1625 cachefs_cache_dirty(fscp->fs_cache, 1);
1626
1627 /* allocate a file for the attrcache */
1628 error = cachefs_allocfile(fscp->fs_cache);
1629 if (error) {
1630 goto out;
1631 }
1632
1633 make_ascii_name(&fgp->fg_id, name);
1634 fname = name;
1635 attrp = cachefs_kmem_alloc(sizeof (struct vattr), KM_SLEEP);
1636 attrp->va_mode = S_IFREG | 0666;
1637 attrp->va_uid = 0;
1638 attrp->va_gid = 0;
1639 attrp->va_type = VREG;
1640 attrp->va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID;
1641 error = VOP_CREATE(fscp->fs_fsattrdir, fname, attrp, EXCL, 0666,
1642 &attrvp, kcred, 0, NULL, NULL);
1643 if (error) {
1644 cachefs_freefile(fscp->fs_cache);
1645 goto out;
1646 }
1647
1648 /* alloc blocks for the attrcache header */
1649 nblks = (fgp->fg_headersize + MAXBSIZE - 1) / MAXBSIZE;
1650 error = cachefs_allocblocks(fscp->fs_cache, nblks, CACHEFS_RL_NONE);
1651 if (error) {
1652 nblks = 0;
1653 goto out;
1654 }
1655
1656 /* Construct an attrcache header */
1657 ahp = cachefs_kmem_zalloc(fgp->fg_headersize, KM_SLEEP);
1658
1659 /* write out the header to allocate space on ufs */
1660 error = vn_rdwr(UIO_WRITE, attrvp, (caddr_t)ahp,
1661 fgp->fg_headersize, 0LL, UIO_SYSSPACE, 0, (rlim64_t)RLIM_INFINITY,
1662 kcred, NULL);
1663 if (error)
1664 goto out;
1665 error = filegrp_write_space(attrvp, (offset_t)fgp->fg_headersize,
1666 (nblks * MAXBSIZE) - fgp->fg_headersize);
1667 if (error)
1668 goto out;
1669 error = VOP_FSYNC(attrvp, FSYNC, kcred, NULL);
1670 if (error)
1671 goto out;
1672
1673 /* allocate an rl entry and mark it as an attrcache entry */
1674 rl_ent.rl_fileno = fgp->fg_id.cid_fileno;
1675 rl_ent.rl_local = (fgp->fg_id.cid_flags & CFS_CID_LOCAL) ? 1 : 0;
1676 rl_ent.rl_fsid = fscp->fs_cfsid;
1677 rl_ent.rl_attrc = 1;
1678 error = cachefs_rl_alloc(fscp->fs_cache, &rl_ent, &ahp->ach_rlno);
1679 if (error)
1680 goto out;
1681 gotrlent = 1;
1682 if (fgp->fg_count == 0) {
1683 /* put on the gc */
1684 cachefs_rlent_moveto(fgp->fg_fscp->fs_cache, CACHEFS_RL_GC,
1685 ahp->ach_rlno, nblks);
1686 ahp->ach_rl_current = CACHEFS_RL_GC;
1687 } else {
1688 /* put on attrfile list */
1689 cachefs_rlent_moveto(fgp->fg_fscp->fs_cache,
1690 CACHEFS_RL_ATTRFILE, ahp->ach_rlno, nblks);
1691 ahp->ach_rl_current = CACHEFS_RL_ATTRFILE;
1692 }
1693
1694 out:
1695 if (error) {
1696 fgp->fg_flags |= CFS_FG_NOCACHE;
1697 if (attrvp) {
1698 VN_RELE(attrvp);
1699 (void) VOP_REMOVE(fscp->fs_fsattrdir, fname, kcred,
1700 NULL, 0);
1701 cachefs_freefile(fscp->fs_cache);
1702 }
1703 if (nblks)
1704 cachefs_freeblocks(fscp->fs_cache, nblks,
1705 CACHEFS_RL_NONE);
1706 if (gotrlent)
1707 cachefs_rlent_moveto(fscp->fs_cache,
1708 CACHEFS_RL_FREE, ahp->ach_rlno, 0);
1709 if (ahp)
1710 cachefs_kmem_free(ahp, fgp->fg_headersize);
1711 } else {
1712 fgp->fg_attrvp = attrvp;
1713 fgp->fg_header = ahp;
1714 fgp->fg_offsets = (struct attrcache_index *)(ahp + 1);
1715 fgp->fg_alloclist = ((uchar_t *)fgp->fg_offsets) +
1716 (fscp->fs_info.fi_fgsize *
1717 sizeof (struct attrcache_index));
1718 ahp->ach_count = 0;
1719 ahp->ach_nffs = 0;
1720 ahp->ach_nblks = nblks;
1721 fgp->fg_flags &= ~CFS_FG_ALLOC_ATTR;
1722 fgp->fg_flags |= CFS_FG_UPDATED;
1723 }
1724
1725 if (attrp)
1726 cachefs_kmem_free(attrp, sizeof (*attrp));
1727
1728 return (error);
1729 }
1730
1731 /*
1732 * ------------------------------------------------------------------
1733 *
1734 * filegrp_cid_to_slot
1735 *
1736 * Description:
1737 * Takes a file and returns the offset to the metadata
1738 * slot for the specified filegrp.
1739 * Arguments:
1740 * fgp filegrp object
1741 * cidp file to map to an offset
1742 * Returns:
1743 * Returns the offset or 0 if the slot is not allocated yet
1744 * or it is invalid.
1745 * Preconditions:
1746 * precond(fgp is a valid filegrp object)
1747 * precond(fgp is not ALLOC_PENDING or NOCACHE)
1748 */
1749
1750 int
filegrp_cid_to_slot(filegrp_t * fgp,cfs_cid_t * cidp)1751 filegrp_cid_to_slot(filegrp_t *fgp, cfs_cid_t *cidp)
1752 {
1753 int xx;
1754 int slot;
1755 int index;
1756
1757 index = (int)(cidp->cid_fileno - fgp->fg_id.cid_fileno);
1758
1759 if (index > fgp->fg_fscp->fs_info.fi_fgsize) {
1760 cmn_err(CE_WARN, "cachefs: attrcache error, run fsck");
1761 return (0);
1762 }
1763
1764 slot = fgp->fg_offsets[index].ach_offset;
1765 if (slot == 0)
1766 return (0);
1767
1768 xx = fgp->fg_filesize - (int)sizeof (struct cfs_cachefs_metadata);
1769 if ((slot < fgp->fg_headersize) || (xx < slot)) {
1770 cmn_err(CE_WARN, "cachefs: attrcache error, run fsck");
1771 return (0);
1772 }
1773
1774 return (slot);
1775 }
1776
1777 /*
1778 *
1779 * filegrp_write_space
1780 *
1781 * Description:
1782 * Writes garbage data to the specified file starting
1783 * at the specified location for the specified number of bytes.
1784 * slot for the specified filegrp.
1785 * Arguments:
1786 * vp vnode to write to
1787 * offset offset to write at
1788 * cnt number of bytes to write
1789 * Returns:
1790 * Returns 0 for success or on error the result of the
1791 * last vn_rdwr call.
1792 * Preconditions:
1793 * precond(vp)
1794 */
1795
1796 int
filegrp_write_space(vnode_t * vp,offset_t offset,ssize_t cnt)1797 filegrp_write_space(vnode_t *vp, offset_t offset, ssize_t cnt)
1798 {
1799 char *bufp;
1800 int xx;
1801 int error = 0;
1802
1803 bufp = (char *)cachefs_kmem_zalloc(MAXBSIZE, KM_SLEEP);
1804 while (cnt > 0) {
1805 if (cnt > MAXBSIZE)
1806 xx = MAXBSIZE;
1807 else
1808 xx = (int)cnt;
1809 error = vn_rdwr(UIO_WRITE, vp, (caddr_t)bufp,
1810 xx, offset, UIO_SYSSPACE, 0, (rlim64_t)RLIM_INFINITY,
1811 kcred, NULL);
1812 if (error)
1813 break;
1814 offset += xx;
1815 cnt -= xx;
1816 }
1817 cachefs_kmem_free(bufp, MAXBSIZE);
1818 return (error);
1819 }
1820