Print this page
OS-1571 Placate gcc -Wparentheses
Reviewed by: Robert Mustacchi <rm@joyent.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/fs/hyprlofs/hyprlofs_vfsops.c
+++ new/usr/src/uts/common/fs/hyprlofs/hyprlofs_vfsops.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
23 23 */
24 24
25 25 /*
26 26 * Hyperlofs is a hybrid file system combining features of the tmpfs(7FS) and
27 27 * lofs(7FS) file systems. It is modeled on code from both of these file
28 28 * systems.
29 29 *
30 30 * The purpose is to create a high performance name space for files on which
31 31 * applications will compute. Given a large number of data files with various
32 32 * owners, we want to construct a view onto those files such that only a subset
33 33 * is visible to the applications and such that the view can be changed very
34 34 * quickly as compute progresses. Entries in the name space are not mounts and
35 35 * thus do not appear in the mnttab. Entries in the name space are allowed to
36 36 * refer to files on different backing file systems. Intermediate directories
37 37 * in the name space exist only in-memory, ala tmpfs. There are no leaf nodes
38 38 * in the name space except for entries that refer to backing files ala lofs.
39 39 *
40 40 * The name space is managed via ioctls issued on the mounted file system and
41 41 * is mostly read-only for the compute applications. That is, applications
42 42 * cannot create new files in the name space. If a file is unlinked by an
43 43 * application, that only removes the file from the name space, the backing
44 44 * file remains in place. It is possible for applications to write-through to
45 45 * the backing files if the file system is mounted read-write.
46 46 *
47 47 * The name space is managed via the HYPRLOFS_ADD_ENTRIES, HYPRLOFS_RM_ENTRIES,
48 48 * and HYPRLOFS_RM_ALL ioctls on the top-level mount.
49 49 *
50 50 * The HYPRLOFS_ADD_ENTRIES ioctl specifies path(s) to the backing file(s) and
51 51 * the name(s) for the file(s) in the name space. The name(s) may be path(s)
52 52 * which will be relative to the root of the mount and thus cannot begin with
53 53 * a /. If the name is a path, it does not have to correspond to any backing
54 54 * path. The intermediate directories will only exist in the name space. The
55 55 * entry(ies) will be added to the name space.
56 56 *
57 57 * The HYPRLOFS_RM_ENTRIES ioctl specifies the name(s) of the file(s) in the
58 58 * name space which should be removed. The name(s) may be path(s) which will
59 59 * be relative to the root of the mount and thus cannot begin with a /. The
60 60 * named entry(ies) will be removed.
61 61 *
62 62 * The HYPRLOFS_RM_ALL ioctl will remove all mappings from the name space.
63 63 */
64 64
65 65 #include <sys/types.h>
66 66 #include <sys/param.h>
67 67 #include <sys/sysmacros.h>
68 68 #include <sys/kmem.h>
69 69 #include <sys/time.h>
70 70 #include <sys/pathname.h>
71 71 #include <sys/vfs.h>
72 72 #include <sys/vfs_opreg.h>
73 73 #include <sys/vnode.h>
74 74 #include <sys/stat.h>
75 75 #include <sys/uio.h>
76 76 #include <sys/stat.h>
77 77 #include <sys/errno.h>
78 78 #include <sys/cmn_err.h>
79 79 #include <sys/cred.h>
80 80 #include <sys/statvfs.h>
81 81 #include <sys/mount.h>
82 82 #include <sys/debug.h>
83 83 #include <sys/systm.h>
84 84 #include <sys/mntent.h>
85 85 #include <fs/fs_subr.h>
86 86 #include <vm/page.h>
87 87 #include <vm/anon.h>
88 88 #include <sys/model.h>
89 89 #include <sys/policy.h>
90 90
91 91 #include <sys/fs/swapnode.h>
92 92 #include <sys/fs/hyprlofs_info.h>
93 93
94 94 static int hyprlofsfstype;
95 95
96 96 /*
97 97 * hyprlofs vfs operations.
98 98 */
99 99 static int hyprlofsinit(int, char *);
100 100 static int hyprlofs_mount(vfs_t *, vnode_t *, struct mounta *, cred_t *);
101 101 static int hyprlofs_unmount(vfs_t *, int, cred_t *);
102 102 static int hyprlofs_root(vfs_t *, vnode_t **);
103 103 static int hyprlofs_statvfs(vfs_t *, struct statvfs64 *);
104 104 static int hyprlofs_vget(vfs_t *, vnode_t **, struct fid *);
105 105
106 106 /*
107 107 * Loadable module wrapper
108 108 */
109 109 #include <sys/modctl.h>
110 110
111 111 static mntopts_t hyprlofs_mntopts;
112 112
113 113 static vfsdef_t vfw = {
114 114 VFSDEF_VERSION,
115 115 "hyprlofs",
116 116 hyprlofsinit,
117 117 VSW_HASPROTO|VSW_CANREMOUNT|VSW_STATS|VSW_ZMOUNT,
118 118 &hyprlofs_mntopts
119 119 };
120 120
121 121 static mntopts_t hyprlofs_mntopts = {
122 122 0, NULL
123 123 };
124 124
125 125 /*
126 126 * Module linkage information
127 127 */
128 128 static struct modlfs modlfs = {
129 129 &mod_fsops, "filesystem for hyprlofs", &vfw
130 130 };
131 131
132 132 static struct modlinkage modlinkage = {
133 133 MODREV_1, &modlfs, NULL
134 134 };
135 135
136 136 int
137 137 _init()
138 138 {
139 139 return (mod_install(&modlinkage));
140 140 }
141 141
142 142 int
143 143 _fini()
144 144 {
145 145 int error;
146 146
147 147 error = mod_remove(&modlinkage);
148 148 if (error)
149 149 return (error);
150 150 /*
151 151 * Tear down the operations vectors
152 152 */
153 153 (void) vfs_freevfsops_by_type(hyprlofsfstype);
154 154 vn_freevnodeops(hyprlofs_vnodeops);
155 155 return (0);
156 156 }
157 157
158 158 int
159 159 _info(struct modinfo *modinfop)
160 160 {
161 161 return (mod_info(&modlinkage, modinfop));
162 162 }
163 163
164 164 /*
165 165 * The following are patchable variables limiting the amount of system
166 166 * resources hyprlofs can use.
167 167 *
168 168 * hyprlofs_maxkmem limits the amount of kernel kmem_alloc memory hyprlofs can
169 169 * use for it's data structures (e.g. hlnodes, directory entries). It is set
170 170 * as a percentage of physical memory which is determined when hyprlofs is
171 171 * first used in the system.
172 172 *
173 173 * hyprlofs_minfree is the minimum amount of swap space that hyprlofs leaves for
174 174 * the rest of the system. If the amount of free swap space in the system
175 175 * (i.e. anoninfo.ani_free) drops below hyprlofs_minfree, hyprlofs anon
176 176 * allocations will fail.
177 177 */
178 178 size_t hyprlofs_maxkmem = 0;
179 179 size_t hyprlofs_minfree = 0;
180 180 size_t hyprlofs_kmemspace; /* bytes of kernel heap used by all hyprlofs */
181 181
182 182 static major_t hyprlofs_major;
183 183 static minor_t hyprlofs_minor;
184 184 static kmutex_t hyprlofs_minor_lock;
185 185
186 186 /*
187 187 * initialize global hyprlofs locks and hashes when loading hyprlofs module
188 188 */
189 189 static int
190 190 hyprlofsinit(int fstype, char *name)
191 191 {
192 192 static const fs_operation_def_t hl_vfsops_template[] = {
193 193 VFSNAME_MOUNT, { .vfs_mount = hyprlofs_mount },
194 194 VFSNAME_UNMOUNT, { .vfs_unmount = hyprlofs_unmount },
195 195 VFSNAME_ROOT, { .vfs_root = hyprlofs_root },
196 196 VFSNAME_STATVFS, { .vfs_statvfs = hyprlofs_statvfs },
197 197 VFSNAME_VGET, { .vfs_vget = hyprlofs_vget },
198 198 NULL, NULL
199 199 };
200 200 int error;
201 201 extern void hyprlofs_hash_init();
202 202
203 203 hyprlofs_hash_init();
204 204 hyprlofsfstype = fstype;
205 205 ASSERT(hyprlofsfstype != 0);
206 206
207 207 error = vfs_setfsops(fstype, hl_vfsops_template, NULL);
208 208 if (error != 0) {
209 209 cmn_err(CE_WARN, "hyprlofsinit: bad vfs ops template");
210 210 return (error);
211 211 }
212 212
213 213 error = vn_make_ops(name, hyprlofs_vnodeops_template,
214 214 &hyprlofs_vnodeops);
215 215 if (error != 0) {
216 216 (void) vfs_freevfsops_by_type(fstype);
217 217 cmn_err(CE_WARN, "hyprlofsinit: bad vnode ops template");
218 218 return (error);
219 219 }
220 220
221 221 /*
222 222 * hyprlofs_minfree is an absolute limit of swap space which still
223 223 * allows other processes to execute. Set it if its not patched.
224 224 */
225 225 if (hyprlofs_minfree == 0)
226 226 hyprlofs_minfree = btopr(HYPRLOFSMINFREE);
227 227
228 228 /*
229 229 * The maximum amount of space hyprlofs can allocate is
230 230 * HYPRLOFSMAXPROCKMEM percent of kernel memory
231 231 */
232 232 if (hyprlofs_maxkmem == 0)
233 233 hyprlofs_maxkmem =
234 234 MAX(PAGESIZE, kmem_maxavail() / HYPRLOFSMAXFRACKMEM);
235 235
236 236 if ((hyprlofs_major = getudev()) == (major_t)-1) {
237 237 cmn_err(CE_WARN,
238 238 "hyprlofsinit: Can't get unique device number.");
239 239 hyprlofs_major = 0;
240 240 }
241 241 mutex_init(&hyprlofs_minor_lock, NULL, MUTEX_DEFAULT, NULL);
242 242 return (0);
243 243 }
244 244
245 245 static int
246 246 hyprlofs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
247 247 {
248 248 hlfsmount_t *hm = NULL;
249 249 hlnode_t *hp;
250 250 struct pathname dpn;
251 251 int error;
252 252 vattr_t rattr;
253 253 int got_attrs;
254 254
255 255 if ((error = secpolicy_fs_mount(cr, mvp, vfsp)) != 0)
256 256 return (error);
257 257 if (secpolicy_hyprlofs_control(cr) != 0)
258 258 return (EPERM);
259 259
260 260 if (mvp->v_type != VDIR)
261 261 return (ENOTDIR);
262 262
263 263 if (uap->flags & MS_REMOUNT)
264 264 return (EBUSY);
265 265
266 266 mutex_enter(&mvp->v_lock);
↓ open down ↓ |
266 lines elided |
↑ open up ↑ |
267 267 if ((uap->flags & MS_OVERLAY) == 0 &&
268 268 (mvp->v_count != 1 || (mvp->v_flag & VROOT))) {
269 269 mutex_exit(&mvp->v_lock);
270 270 return (EBUSY);
271 271 }
272 272 mutex_exit(&mvp->v_lock);
273 273
274 274 /* Having the resource be anything but "swap" doesn't make sense. */
275 275 vfs_setresource(vfsp, "swap", 0);
276 276
277 - if (error = pn_get(uap->dir,
278 - (uap->flags & MS_SYSSPACE) ? UIO_SYSSPACE : UIO_USERSPACE, &dpn))
277 + if ((error = pn_get(uap->dir,
278 + (uap->flags & MS_SYSSPACE) ? UIO_SYSSPACE : UIO_USERSPACE,
279 + &dpn)) != 0)
279 280 goto out;
280 281
281 282 if ((hm = hyprlofs_memalloc(sizeof (hlfsmount_t), 0)) == NULL) {
282 283 pn_free(&dpn);
283 284 error = ENOMEM;
284 285 goto out;
285 286 }
286 287
287 288 /* Get an available minor device number for this mount */
288 289 mutex_enter(&hyprlofs_minor_lock);
289 290 do {
290 291 hyprlofs_minor = (hyprlofs_minor + 1) & L_MAXMIN32;
291 292 hm->hlm_dev = makedevice(hyprlofs_major, hyprlofs_minor);
292 293 } while (vfs_devismounted(hm->hlm_dev));
293 294 mutex_exit(&hyprlofs_minor_lock);
294 295
295 296 /*
296 297 * Set but don't bother entering the mutex since hlfsmount is not on
297 298 * the mount list yet.
298 299 */
299 300 mutex_init(&hm->hlm_contents, NULL, MUTEX_DEFAULT, NULL);
300 301
301 302 hm->hlm_vfsp = vfsp;
302 303
303 304 vfsp->vfs_data = (caddr_t)hm;
304 305 vfsp->vfs_fstype = hyprlofsfstype;
305 306 vfsp->vfs_dev = hm->hlm_dev;
306 307 vfsp->vfs_bsize = PAGESIZE;
307 308 vfsp->vfs_flag |= VFS_NOTRUNC;
308 309 vfs_make_fsid(&vfsp->vfs_fsid, hm->hlm_dev, hyprlofsfstype);
309 310 hm->hlm_mntpath = hyprlofs_memalloc(dpn.pn_pathlen + 1, HL_MUSTHAVE);
310 311 (void) strcpy(hm->hlm_mntpath, dpn.pn_path);
311 312
312 313 /* allocate and initialize root hlnode structure */
313 314 bzero(&rattr, sizeof (vattr_t));
314 315 rattr.va_mode = (mode_t)(S_IFDIR | 0777);
315 316 rattr.va_type = VDIR;
316 317 rattr.va_rdev = 0;
317 318 hp = hyprlofs_memalloc(sizeof (hlnode_t), HL_MUSTHAVE);
318 319 hyprlofs_node_init(hm, hp, &rattr, cr);
319 320
320 321 /* Get the mode, uid, and gid from the underlying mount point. */
321 322 rattr.va_mask = AT_MODE|AT_UID|AT_GID;
322 323 got_attrs = VOP_GETATTR(mvp, &rattr, 0, cr, NULL);
323 324
324 325 rw_enter(&hp->hln_rwlock, RW_WRITER);
325 326 HLNTOV(hp)->v_flag |= VROOT;
326 327
327 328 /*
328 329 * If the getattr succeeded, use its results, otherwise allow the
329 330 * previously set defaults to prevail.
330 331 */
331 332 if (got_attrs == 0) {
332 333 hp->hln_mode = rattr.va_mode;
333 334 hp->hln_uid = rattr.va_uid;
334 335 hp->hln_gid = rattr.va_gid;
335 336 }
336 337
337 338 /*
338 339 * Initialize linked list of hlnodes so that the back pointer of the
339 340 * root hlnode always points to the last one on the list and the
340 341 * forward pointer of the last node is null
341 342 */
342 343 hp->hln_back = hp;
343 344 hp->hln_forw = NULL;
344 345 hp->hln_nlink = 0;
345 346 hm->hlm_rootnode = hp;
346 347
347 348 hyprlofs_dirinit(hp, hp);
348 349
349 350 rw_exit(&hp->hln_rwlock);
350 351
351 352 pn_free(&dpn);
352 353 error = 0;
353 354
354 355 out:
355 356 return (error);
356 357 }
357 358
358 359 static int
359 360 hyprlofs_unmount(vfs_t *vfsp, int flag, cred_t *cr)
360 361 {
361 362 hlfsmount_t *hm = (hlfsmount_t *)VFSTOHLM(vfsp);
362 363 hlnode_t *hnp, *cancel;
363 364 vnode_t *vp;
364 365 int error;
365 366
366 367 if ((error = secpolicy_fs_unmount(cr, vfsp)) != 0)
367 368 return (error);
368 369 if (secpolicy_hyprlofs_control(cr) != 0)
369 370 return (EPERM);
370 371
371 372 /*
372 373 * forced unmount is not supported by this file system
373 374 * and thus, ENOTSUP, is being returned.
374 375 */
375 376 if (flag & MS_FORCE)
376 377 return (ENOTSUP);
377 378
378 379 mutex_enter(&hm->hlm_contents);
379 380
380 381 /*
381 382 * If there are no open files, only the root node should have a ref cnt.
382 383 * With hlm_contents held, nothing can be added or removed. There may
383 384 * be some dirty pages. To prevent fsflush from disrupting the unmount,
384 385 * put a hold on each node while scanning. If we find a previously
385 386 * referenced node, undo the holds we have placed and fail EBUSY.
386 387 */
387 388 hnp = hm->hlm_rootnode;
388 389 if (HLNTOV(hnp)->v_count > 1) {
389 390 mutex_exit(&hm->hlm_contents);
390 391 return (EBUSY);
391 392 }
392 393
393 394 for (hnp = hnp->hln_forw; hnp; hnp = hnp->hln_forw) {
394 395 if ((vp = HLNTOV(hnp))->v_count > 0) {
395 396 cancel = hm->hlm_rootnode->hln_forw;
396 397 while (cancel != hnp) {
397 398 vp = HLNTOV(cancel);
398 399 ASSERT(vp->v_count > 0);
399 400 VN_RELE(vp);
400 401 cancel = cancel->hln_forw;
401 402 }
402 403 mutex_exit(&hm->hlm_contents);
403 404 return (EBUSY);
404 405 }
405 406 VN_HOLD(vp);
406 407 }
407 408
408 409 /* We can drop the mutex now because no one can find this mount */
409 410 mutex_exit(&hm->hlm_contents);
410 411
411 412 /*
412 413 * Free all alloc'd memory associated with this FS. To do this, we go
413 414 * through the file list twice, once to remove all the dir entries, and
414 415 * then to remove all the files.
415 416 */
416 417
417 418 /* Remove all directory entries */
418 419 for (hnp = hm->hlm_rootnode; hnp; hnp = hnp->hln_forw) {
419 420 rw_enter(&hnp->hln_rwlock, RW_WRITER);
420 421 if (hnp->hln_type == VDIR)
421 422 hyprlofs_dirtrunc(hnp);
422 423 rw_exit(&hnp->hln_rwlock);
423 424 }
424 425
425 426 ASSERT(hm->hlm_rootnode);
426 427
427 428 /*
428 429 * All links are gone, v_count is keeping nodes in place. VN_RELE
429 430 * should make the node disappear, unless somebody is holding pages
430 431 * against it. Wait and retry until it disappears.
431 432 *
432 433 * We re-acquire the lock to prevent others who have a HOLD on a hlnode
433 434 * from blowing it away (in hyprlofs_inactive) while we're trying to
434 435 * get to it here. Once we have a HOLD on it we know it'll stick around.
435 436 */
436 437 mutex_enter(&hm->hlm_contents);
437 438
438 439 /* Remove all the files (except the rootnode) backwards. */
439 440 while ((hnp = hm->hlm_rootnode->hln_back) != hm->hlm_rootnode) {
440 441 mutex_exit(&hm->hlm_contents);
441 442 /* Note we handled the link count in pass 2 above. */
442 443 vp = HLNTOV(hnp);
443 444 VN_RELE(vp);
444 445 mutex_enter(&hm->hlm_contents);
445 446 /*
446 447 * It's still there after the RELE. Someone else like pageout
447 448 * has a hold on it so wait a bit and then try again.
448 449 */
449 450 if (hnp == hm->hlm_rootnode->hln_back) {
450 451 VN_HOLD(vp);
451 452 mutex_exit(&hm->hlm_contents);
452 453 delay(hz / 4);
453 454 mutex_enter(&hm->hlm_contents);
454 455 }
455 456 }
456 457 mutex_exit(&hm->hlm_contents);
457 458
458 459 VN_RELE(HLNTOV(hm->hlm_rootnode));
459 460
460 461 ASSERT(hm->hlm_mntpath);
461 462
462 463 hyprlofs_memfree(hm->hlm_mntpath, strlen(hm->hlm_mntpath) + 1);
463 464
464 465 mutex_destroy(&hm->hlm_contents);
465 466 hyprlofs_memfree(hm, sizeof (hlfsmount_t));
466 467
467 468 return (0);
468 469 }
469 470
470 471 /* Return root hlnode for given vnode */
471 472 static int
472 473 hyprlofs_root(vfs_t *vfsp, vnode_t **vpp)
473 474 {
474 475 hlfsmount_t *hm = (hlfsmount_t *)VFSTOHLM(vfsp);
475 476 hlnode_t *hp = hm->hlm_rootnode;
476 477 vnode_t *vp;
477 478
478 479 ASSERT(hp);
479 480
480 481 vp = HLNTOV(hp);
481 482 VN_HOLD(vp);
482 483 *vpp = vp;
483 484 return (0);
484 485 }
485 486
486 487 static int
487 488 hyprlofs_statvfs(vfs_t *vfsp, struct statvfs64 *sbp)
488 489 {
489 490 hlfsmount_t *hm = (hlfsmount_t *)VFSTOHLM(vfsp);
490 491 ulong_t blocks;
491 492 dev32_t d32;
492 493 zoneid_t eff_zid;
493 494 struct zone *zp;
494 495
495 496 /*
496 497 * The FS may have been mounted by the GZ on behalf of the NGZ. In
497 498 * that case, the hlfsmount zone_id will be the global zone. We want
498 499 * to show the swap cap inside the zone in this case, even though the
499 500 * FS was mounted by the GZ.
500 501 */
501 502 if (curproc->p_zone->zone_id != GLOBAL_ZONEUNIQID)
502 503 zp = curproc->p_zone;
503 504 else
504 505 zp = hm->hlm_vfsp->vfs_zone;
505 506
506 507 if (zp == NULL)
507 508 eff_zid = GLOBAL_ZONEUNIQID;
508 509 else
509 510 eff_zid = zp->zone_id;
510 511
511 512 sbp->f_bsize = PAGESIZE;
512 513 sbp->f_frsize = PAGESIZE;
513 514
514 515 /*
515 516 * Find the amount of available physical and memory swap
516 517 */
517 518 mutex_enter(&anoninfo_lock);
518 519 ASSERT(k_anoninfo.ani_max >= k_anoninfo.ani_phys_resv);
519 520 blocks = (ulong_t)CURRENT_TOTAL_AVAILABLE_SWAP;
520 521 mutex_exit(&anoninfo_lock);
521 522
522 523 if (blocks > hyprlofs_minfree)
523 524 sbp->f_bfree = blocks - hyprlofs_minfree;
524 525 else
525 526 sbp->f_bfree = 0;
526 527
527 528 sbp->f_bavail = sbp->f_bfree;
528 529
529 530 /*
530 531 * Total number of blocks is what's available plus what's been used
531 532 */
532 533 sbp->f_blocks = (fsblkcnt64_t)(sbp->f_bfree);
533 534
534 535 if (eff_zid != GLOBAL_ZONEUNIQID &&
535 536 zp->zone_max_swap_ctl != UINT64_MAX) {
536 537 /*
537 538 * If the fs is used by a NGZ with a swap cap, then report the
538 539 * capped size.
539 540 */
540 541 rctl_qty_t cap, used;
541 542 pgcnt_t pgcap, pgused;
542 543
543 544 mutex_enter(&zp->zone_mem_lock);
544 545 cap = zp->zone_max_swap_ctl;
545 546 used = zp->zone_max_swap;
546 547 mutex_exit(&zp->zone_mem_lock);
547 548
548 549 pgcap = btop(cap);
549 550 pgused = btop(used);
550 551
551 552 sbp->f_bfree = MIN(pgcap - pgused, sbp->f_bfree);
552 553 sbp->f_bavail = sbp->f_bfree;
553 554 sbp->f_blocks = MIN(pgcap, sbp->f_blocks);
554 555 }
555 556
556 557 /*
557 558 * This is fairly inaccurate since it doesn't take into account the
558 559 * names stored in the directory entries.
559 560 */
560 561 if (hyprlofs_maxkmem > hyprlofs_kmemspace)
561 562 sbp->f_ffree = (hyprlofs_maxkmem - hyprlofs_kmemspace) /
562 563 (sizeof (hlnode_t) + sizeof (hldirent_t));
563 564 else
564 565 sbp->f_ffree = 0;
565 566
566 567 sbp->f_files = hyprlofs_maxkmem /
567 568 (sizeof (hlnode_t) + sizeof (hldirent_t));
568 569 sbp->f_favail = (fsfilcnt64_t)(sbp->f_ffree);
569 570 (void) cmpldev(&d32, vfsp->vfs_dev);
570 571 sbp->f_fsid = d32;
571 572 (void) strcpy(sbp->f_basetype, vfssw[hyprlofsfstype].vsw_name);
572 573 (void) strncpy(sbp->f_fstr, hm->hlm_mntpath, sizeof (sbp->f_fstr));
573 574 /*
574 575 * ensure null termination
575 576 */
576 577 sbp->f_fstr[sizeof (sbp->f_fstr) - 1] = '\0';
577 578 sbp->f_flag = vf_to_stf(vfsp->vfs_flag);
578 579 sbp->f_namemax = MAXNAMELEN - 1;
579 580 return (0);
580 581 }
581 582
582 583 static int
583 584 hyprlofs_vget(vfs_t *vfsp, vnode_t **vpp, struct fid *fidp)
584 585 {
585 586 hlfid_t *hfid;
586 587 hlfsmount_t *hm = (hlfsmount_t *)VFSTOHLM(vfsp);
587 588 hlnode_t *hp = NULL;
588 589
589 590 hfid = (hlfid_t *)fidp;
590 591 *vpp = NULL;
591 592
592 593 mutex_enter(&hm->hlm_contents);
593 594 for (hp = hm->hlm_rootnode; hp; hp = hp->hln_forw) {
594 595 mutex_enter(&hp->hln_tlock);
595 596 if (hp->hln_nodeid == hfid->hlfid_ino) {
596 597 /*
597 598 * If the gen numbers don't match we know the file
598 599 * won't be found since only one hlnode can have this
599 600 * number at a time.
600 601 */
601 602 if (hp->hln_gen != hfid->hlfid_gen ||
602 603 hp->hln_nlink == 0) {
603 604 mutex_exit(&hp->hln_tlock);
604 605 mutex_exit(&hm->hlm_contents);
605 606 return (0);
606 607 }
607 608 *vpp = (vnode_t *)HLNTOV(hp);
608 609
609 610 VN_HOLD(*vpp);
610 611
611 612 if ((hp->hln_mode & S_ISVTX) &&
612 613 !(hp->hln_mode & (S_IXUSR | S_IFDIR))) {
613 614 mutex_enter(&(*vpp)->v_lock);
614 615 (*vpp)->v_flag |= VISSWAP;
615 616 mutex_exit(&(*vpp)->v_lock);
616 617 }
617 618 mutex_exit(&hp->hln_tlock);
618 619 mutex_exit(&hm->hlm_contents);
619 620 return (0);
620 621 }
621 622 mutex_exit(&hp->hln_tlock);
622 623 }
623 624 mutex_exit(&hm->hlm_contents);
624 625 return (0);
625 626 }
↓ open down ↓ |
337 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX