Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/fs/tmpfs/tmp_vfsops.c
+++ new/usr/src/uts/common/fs/tmpfs/tmp_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) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 * Copyright (c) 2011, Joyent, Inc. All rights reserved.
24 24 */
25 25
26 26 #include <sys/types.h>
27 27 #include <sys/param.h>
28 28 #include <sys/sysmacros.h>
29 29 #include <sys/kmem.h>
30 30 #include <sys/time.h>
31 31 #include <sys/pathname.h>
32 32 #include <sys/vfs.h>
33 33 #include <sys/vfs_opreg.h>
34 34 #include <sys/vnode.h>
35 35 #include <sys/stat.h>
36 36 #include <sys/uio.h>
37 37 #include <sys/stat.h>
38 38 #include <sys/errno.h>
39 39 #include <sys/cmn_err.h>
40 40 #include <sys/cred.h>
41 41 #include <sys/statvfs.h>
42 42 #include <sys/mount.h>
43 43 #include <sys/debug.h>
44 44 #include <sys/systm.h>
45 45 #include <sys/mntent.h>
46 46 #include <fs/fs_subr.h>
47 47 #include <vm/page.h>
48 48 #include <vm/anon.h>
49 49 #include <sys/model.h>
50 50 #include <sys/policy.h>
51 51
52 52 #include <sys/fs/swapnode.h>
53 53 #include <sys/fs/tmp.h>
54 54 #include <sys/fs/tmpnode.h>
55 55
56 56 static int tmpfsfstype;
57 57
58 58 /*
59 59 * tmpfs vfs operations.
60 60 */
61 61 static int tmpfsinit(int, char *);
62 62 static int tmp_mount(struct vfs *, struct vnode *,
63 63 struct mounta *, struct cred *);
64 64 static int tmp_unmount(struct vfs *, int, struct cred *);
65 65 static int tmp_root(struct vfs *, struct vnode **);
66 66 static int tmp_statvfs(struct vfs *, struct statvfs64 *);
67 67 static int tmp_vget(struct vfs *, struct vnode **, struct fid *);
68 68
69 69 /*
70 70 * Loadable module wrapper
71 71 */
72 72 #include <sys/modctl.h>
73 73
74 74 static mntopts_t tmpfs_proto_opttbl;
75 75
76 76 static vfsdef_t vfw = {
77 77 VFSDEF_VERSION,
78 78 "tmpfs",
79 79 tmpfsinit,
80 80 VSW_HASPROTO|VSW_CANREMOUNT|VSW_STATS|VSW_ZMOUNT,
81 81 &tmpfs_proto_opttbl
82 82 };
83 83
84 84 /*
85 85 * in-kernel mnttab options
86 86 */
87 87 static char *xattr_cancel[] = { MNTOPT_NOXATTR, NULL };
88 88 static char *noxattr_cancel[] = { MNTOPT_XATTR, NULL };
89 89
90 90 static mntopt_t tmpfs_options[] = {
91 91 /* Option name Cancel Opt Arg Flags Data */
92 92 { MNTOPT_XATTR, xattr_cancel, NULL, MO_DEFAULT, NULL},
93 93 { MNTOPT_NOXATTR, noxattr_cancel, NULL, NULL, NULL},
94 94 { "size", NULL, "0", MO_HASVALUE, NULL}
95 95 };
96 96
97 97
98 98 static mntopts_t tmpfs_proto_opttbl = {
99 99 sizeof (tmpfs_options) / sizeof (mntopt_t),
100 100 tmpfs_options
↓ open down ↓ |
100 lines elided |
↑ open up ↑ |
101 101 };
102 102
103 103 /*
104 104 * Module linkage information
105 105 */
106 106 static struct modlfs modlfs = {
107 107 &mod_fsops, "filesystem for tmpfs", &vfw
108 108 };
109 109
110 110 static struct modlinkage modlinkage = {
111 - MODREV_1, &modlfs, NULL
111 + MODREV_1, { &modlfs, NULL }
112 112 };
113 113
114 114 int
115 115 _init()
116 116 {
117 117 return (mod_install(&modlinkage));
118 118 }
119 119
120 120 int
121 121 _fini()
122 122 {
123 123 int error;
124 124
125 125 error = mod_remove(&modlinkage);
126 126 if (error)
127 127 return (error);
128 128 /*
129 129 * Tear down the operations vectors
130 130 */
131 131 (void) vfs_freevfsops_by_type(tmpfsfstype);
132 132 vn_freevnodeops(tmp_vnodeops);
133 133 return (0);
134 134 }
135 135
136 136 int
137 137 _info(struct modinfo *modinfop)
138 138 {
139 139 return (mod_info(&modlinkage, modinfop));
140 140 }
141 141
142 142 /*
143 143 * The following are patchable variables limiting the amount of system
144 144 * resources tmpfs can use.
145 145 *
146 146 * tmpfs_maxkmem limits the amount of kernel kmem_alloc memory
147 147 * tmpfs can use for it's data structures (e.g. tmpnodes, directory entries)
148 148 * It is not determined by setting a hard limit but rather as a percentage of
149 149 * physical memory which is determined when tmpfs is first used in the system.
150 150 *
151 151 * tmpfs_minfree is the minimum amount of swap space that tmpfs leaves for
152 152 * the rest of the system. In other words, if the amount of free swap space
153 153 * in the system (i.e. anoninfo.ani_free) drops below tmpfs_minfree, tmpfs
154 154 * anon allocations will fail.
155 155 *
156 156 * There is also a per mount limit on the amount of swap space
157 157 * (tmount.tm_anonmax) settable via a mount option.
158 158 */
159 159 size_t tmpfs_maxkmem = 0;
160 160 size_t tmpfs_minfree = 0;
161 161 size_t tmp_kmemspace; /* bytes of kernel heap used by all tmpfs */
162 162
163 163 static major_t tmpfs_major;
164 164 static minor_t tmpfs_minor;
↓ open down ↓ |
43 lines elided |
↑ open up ↑ |
165 165 static kmutex_t tmpfs_minor_lock;
166 166
167 167 /*
168 168 * initialize global tmpfs locks and such
169 169 * called when loading tmpfs module
170 170 */
171 171 static int
172 172 tmpfsinit(int fstype, char *name)
173 173 {
174 174 static const fs_operation_def_t tmp_vfsops_template[] = {
175 - VFSNAME_MOUNT, { .vfs_mount = tmp_mount },
176 - VFSNAME_UNMOUNT, { .vfs_unmount = tmp_unmount },
177 - VFSNAME_ROOT, { .vfs_root = tmp_root },
178 - VFSNAME_STATVFS, { .vfs_statvfs = tmp_statvfs },
179 - VFSNAME_VGET, { .vfs_vget = tmp_vget },
180 - NULL, NULL
175 + { VFSNAME_MOUNT, { .vfs_mount = tmp_mount } },
176 + { VFSNAME_UNMOUNT, { .vfs_unmount = tmp_unmount } },
177 + { VFSNAME_ROOT, { .vfs_root = tmp_root } },
178 + { VFSNAME_STATVFS, { .vfs_statvfs = tmp_statvfs } },
179 + { VFSNAME_VGET, { .vfs_vget = tmp_vget } },
180 + { NULL, { NULL } }
181 181 };
182 182 int error;
183 183 extern void tmpfs_hash_init();
184 184
185 185 tmpfs_hash_init();
186 186 tmpfsfstype = fstype;
187 187 ASSERT(tmpfsfstype != 0);
188 188
189 189 error = vfs_setfsops(fstype, tmp_vfsops_template, NULL);
190 190 if (error != 0) {
191 191 cmn_err(CE_WARN, "tmpfsinit: bad vfs ops template");
192 192 return (error);
193 193 }
194 194
195 195 error = vn_make_ops(name, tmp_vnodeops_template, &tmp_vnodeops);
196 196 if (error != 0) {
197 197 (void) vfs_freevfsops_by_type(fstype);
198 198 cmn_err(CE_WARN, "tmpfsinit: bad vnode ops template");
199 199 return (error);
200 200 }
201 201
202 202 /*
203 203 * tmpfs_minfree doesn't need to be some function of configured
204 204 * swap space since it really is an absolute limit of swap space
205 205 * which still allows other processes to execute.
206 206 */
207 207 if (tmpfs_minfree == 0) {
208 208 /*
209 209 * Set if not patched
210 210 */
211 211 tmpfs_minfree = btopr(TMPMINFREE);
212 212 }
213 213
214 214 /*
215 215 * The maximum amount of space tmpfs can allocate is
216 216 * TMPMAXPROCKMEM percent of kernel memory
217 217 */
218 218 if (tmpfs_maxkmem == 0)
219 219 tmpfs_maxkmem = MAX(PAGESIZE, kmem_maxavail() / TMPMAXFRACKMEM);
220 220
221 221 if ((tmpfs_major = getudev()) == (major_t)-1) {
222 222 cmn_err(CE_WARN, "tmpfsinit: Can't get unique device number.");
223 223 tmpfs_major = 0;
224 224 }
225 225 mutex_init(&tmpfs_minor_lock, NULL, MUTEX_DEFAULT, NULL);
226 226 return (0);
227 227 }
228 228
229 229 static int
230 230 tmp_mount(
231 231 struct vfs *vfsp,
232 232 struct vnode *mvp,
233 233 struct mounta *uap,
234 234 struct cred *cr)
235 235 {
236 236 struct tmount *tm = NULL;
237 237 struct tmpnode *tp;
238 238 struct pathname dpn;
239 239 int error;
240 240 pgcnt_t anonmax;
241 241 struct vattr rattr;
242 242 int got_attrs;
243 243
244 244 char *sizestr;
245 245
246 246 if ((error = secpolicy_fs_mount(cr, mvp, vfsp)) != 0)
247 247 return (error);
248 248
249 249 if (mvp->v_type != VDIR)
250 250 return (ENOTDIR);
251 251
252 252 mutex_enter(&mvp->v_lock);
253 253 if ((uap->flags & MS_REMOUNT) == 0 && (uap->flags & MS_OVERLAY) == 0 &&
254 254 (mvp->v_count != 1 || (mvp->v_flag & VROOT))) {
255 255 mutex_exit(&mvp->v_lock);
256 256 return (EBUSY);
257 257 }
258 258 mutex_exit(&mvp->v_lock);
259 259
260 260 /*
261 261 * Having the resource be anything but "swap" doesn't make sense.
262 262 */
263 263 vfs_setresource(vfsp, "swap", 0);
264 264
265 265 /*
266 266 * now look for options we understand...
267 267 */
268 268
269 269 /* tmpfs doesn't support read-only mounts */
270 270 if (vfs_optionisset(vfsp, MNTOPT_RO, NULL)) {
271 271 error = EINVAL;
272 272 goto out;
273 273 }
274 274
275 275 /*
276 276 * tm_anonmax is set according to the mount arguments
277 277 * if any. Otherwise, it is set to a maximum value.
278 278 */
279 279 if (vfs_optionisset(vfsp, "size", &sizestr)) {
280 280 if ((error = tmp_convnum(sizestr, &anonmax)) != 0)
281 281 goto out;
282 282 } else {
283 283 anonmax = ULONG_MAX;
284 284 }
285 285
286 286 if (error = pn_get(uap->dir,
287 287 (uap->flags & MS_SYSSPACE) ? UIO_SYSSPACE : UIO_USERSPACE, &dpn))
288 288 goto out;
289 289
290 290 if (uap->flags & MS_REMOUNT) {
291 291 tm = (struct tmount *)VFSTOTM(vfsp);
292 292
293 293 /*
294 294 * If we change the size so its less than what is currently
295 295 * being used, we allow that. The file system will simply be
296 296 * full until enough files have been removed to get below the
297 297 * new max.
298 298 */
299 299 mutex_enter(&tm->tm_contents);
300 300 tm->tm_anonmax = anonmax;
301 301 mutex_exit(&tm->tm_contents);
302 302 goto out;
303 303 }
304 304
305 305 if ((tm = tmp_memalloc(sizeof (struct tmount), 0)) == NULL) {
306 306 pn_free(&dpn);
307 307 error = ENOMEM;
308 308 goto out;
309 309 }
310 310
311 311 /*
312 312 * find an available minor device number for this mount
313 313 */
314 314 mutex_enter(&tmpfs_minor_lock);
315 315 do {
316 316 tmpfs_minor = (tmpfs_minor + 1) & L_MAXMIN32;
317 317 tm->tm_dev = makedevice(tmpfs_major, tmpfs_minor);
318 318 } while (vfs_devismounted(tm->tm_dev));
319 319 mutex_exit(&tmpfs_minor_lock);
320 320
321 321 /*
322 322 * Set but don't bother entering the mutex
323 323 * (tmount not on mount list yet)
324 324 */
325 325 mutex_init(&tm->tm_contents, NULL, MUTEX_DEFAULT, NULL);
326 326 mutex_init(&tm->tm_renamelck, NULL, MUTEX_DEFAULT, NULL);
327 327
328 328 tm->tm_vfsp = vfsp;
329 329 tm->tm_anonmax = anonmax;
330 330
331 331 vfsp->vfs_data = (caddr_t)tm;
332 332 vfsp->vfs_fstype = tmpfsfstype;
333 333 vfsp->vfs_dev = tm->tm_dev;
334 334 vfsp->vfs_bsize = PAGESIZE;
335 335 vfsp->vfs_flag |= VFS_NOTRUNC;
336 336 vfs_make_fsid(&vfsp->vfs_fsid, tm->tm_dev, tmpfsfstype);
337 337 tm->tm_mntpath = tmp_memalloc(dpn.pn_pathlen + 1, TMP_MUSTHAVE);
338 338 (void) strcpy(tm->tm_mntpath, dpn.pn_path);
339 339
340 340 /*
341 341 * allocate and initialize root tmpnode structure
342 342 */
343 343 bzero(&rattr, sizeof (struct vattr));
344 344 rattr.va_mode = (mode_t)(S_IFDIR | 0777); /* XXX modes */
345 345 rattr.va_type = VDIR;
346 346 rattr.va_rdev = 0;
347 347 tp = tmp_memalloc(sizeof (struct tmpnode), TMP_MUSTHAVE);
348 348 tmpnode_init(tm, tp, &rattr, cr);
349 349
350 350 /*
351 351 * Get the mode, uid, and gid from the underlying mount point.
352 352 */
353 353 rattr.va_mask = AT_MODE|AT_UID|AT_GID; /* Hint to getattr */
354 354 got_attrs = VOP_GETATTR(mvp, &rattr, 0, cr, NULL);
355 355
356 356 rw_enter(&tp->tn_rwlock, RW_WRITER);
357 357 TNTOV(tp)->v_flag |= VROOT;
358 358
359 359 /*
360 360 * If the getattr succeeded, use its results. Otherwise allow
361 361 * the previously set hardwired defaults to prevail.
362 362 */
363 363 if (got_attrs == 0) {
364 364 tp->tn_mode = rattr.va_mode;
365 365 tp->tn_uid = rattr.va_uid;
366 366 tp->tn_gid = rattr.va_gid;
367 367 }
368 368
369 369 /*
370 370 * initialize linked list of tmpnodes so that the back pointer of
371 371 * the root tmpnode always points to the last one on the list
372 372 * and the forward pointer of the last node is null
373 373 */
374 374 tp->tn_back = tp;
375 375 tp->tn_forw = NULL;
376 376 tp->tn_nlink = 0;
377 377 tm->tm_rootnode = tp;
378 378
379 379 tdirinit(tp, tp);
380 380
381 381 rw_exit(&tp->tn_rwlock);
382 382
383 383 pn_free(&dpn);
384 384 error = 0;
385 385
386 386 out:
387 387 if (error == 0)
388 388 vfs_set_feature(vfsp, VFSFT_SYSATTR_VIEWS);
389 389
390 390 return (error);
391 391 }
392 392
393 393 static int
394 394 tmp_unmount(struct vfs *vfsp, int flag, struct cred *cr)
395 395 {
396 396 struct tmount *tm = (struct tmount *)VFSTOTM(vfsp);
397 397 struct tmpnode *tnp, *cancel;
398 398 struct vnode *vp;
399 399 int error;
400 400
401 401 if ((error = secpolicy_fs_unmount(cr, vfsp)) != 0)
402 402 return (error);
403 403
404 404 /*
405 405 * forced unmount is not supported by this file system
406 406 * and thus, ENOTSUP, is being returned.
407 407 */
408 408 if (flag & MS_FORCE)
409 409 return (ENOTSUP);
410 410
411 411 mutex_enter(&tm->tm_contents);
412 412
413 413 /*
414 414 * If there are no open files, only the root node should have
415 415 * a reference count.
416 416 * With tm_contents held, nothing can be added or removed.
417 417 * There may be some dirty pages. To prevent fsflush from
418 418 * disrupting the unmount, put a hold on each node while scanning.
419 419 * If we find a previously referenced node, undo the holds we have
420 420 * placed and fail EBUSY.
421 421 */
422 422 tnp = tm->tm_rootnode;
423 423 if (TNTOV(tnp)->v_count > 1) {
424 424 mutex_exit(&tm->tm_contents);
425 425 return (EBUSY);
426 426 }
427 427
428 428 for (tnp = tnp->tn_forw; tnp; tnp = tnp->tn_forw) {
429 429 if ((vp = TNTOV(tnp))->v_count > 0) {
430 430 cancel = tm->tm_rootnode->tn_forw;
431 431 while (cancel != tnp) {
432 432 vp = TNTOV(cancel);
433 433 ASSERT(vp->v_count > 0);
434 434 VN_RELE(vp);
435 435 cancel = cancel->tn_forw;
436 436 }
437 437 mutex_exit(&tm->tm_contents);
438 438 return (EBUSY);
439 439 }
440 440 VN_HOLD(vp);
441 441 }
442 442
443 443 /*
444 444 * We can drop the mutex now because no one can find this mount
445 445 */
446 446 mutex_exit(&tm->tm_contents);
447 447
448 448 /*
449 449 * Free all kmemalloc'd and anonalloc'd memory associated with
450 450 * this filesystem. To do this, we go through the file list twice,
451 451 * once to remove all the directory entries, and then to remove
452 452 * all the files. We do this because there is useful code in
453 453 * tmpnode_free which assumes that the directory entry has been
454 454 * removed before the file.
455 455 */
456 456 /*
457 457 * Remove all directory entries
458 458 */
459 459 for (tnp = tm->tm_rootnode; tnp; tnp = tnp->tn_forw) {
460 460 rw_enter(&tnp->tn_rwlock, RW_WRITER);
461 461 if (tnp->tn_type == VDIR)
462 462 tdirtrunc(tnp);
463 463 if (tnp->tn_vnode->v_flag & V_XATTRDIR) {
464 464 /*
465 465 * Account for implicit attrdir reference.
466 466 */
467 467 ASSERT(tnp->tn_nlink > 0);
468 468 DECR_COUNT(&tnp->tn_nlink, &tnp->tn_tlock);
469 469 }
470 470 rw_exit(&tnp->tn_rwlock);
471 471 }
472 472
473 473 ASSERT(tm->tm_rootnode);
474 474
475 475 /*
476 476 * All links are gone, v_count is keeping nodes in place.
477 477 * VN_RELE should make the node disappear, unless somebody
478 478 * is holding pages against it. Nap and retry until it disappears.
479 479 *
480 480 * We re-acquire the lock to prevent others who have a HOLD on
481 481 * a tmpnode via its pages or anon slots from blowing it away
482 482 * (in tmp_inactive) while we're trying to get to it here. Once
483 483 * we have a HOLD on it we know it'll stick around.
484 484 *
485 485 */
486 486 mutex_enter(&tm->tm_contents);
487 487 /*
488 488 * Remove all the files (except the rootnode) backwards.
489 489 */
490 490 while ((tnp = tm->tm_rootnode->tn_back) != tm->tm_rootnode) {
491 491 mutex_exit(&tm->tm_contents);
492 492 /*
493 493 * Inhibit tmp_inactive from touching attribute directory
494 494 * as all nodes will be released here.
495 495 * Note we handled the link count in pass 2 above.
496 496 */
497 497 rw_enter(&tnp->tn_rwlock, RW_WRITER);
498 498 tnp->tn_xattrdp = NULL;
499 499 rw_exit(&tnp->tn_rwlock);
500 500 vp = TNTOV(tnp);
501 501 VN_RELE(vp);
502 502 mutex_enter(&tm->tm_contents);
503 503 /*
504 504 * It's still there after the RELE. Someone else like pageout
505 505 * has a hold on it so wait a bit and then try again - we know
506 506 * they'll give it up soon.
507 507 */
508 508 if (tnp == tm->tm_rootnode->tn_back) {
509 509 VN_HOLD(vp);
510 510 mutex_exit(&tm->tm_contents);
511 511 delay(hz / 4);
512 512 mutex_enter(&tm->tm_contents);
513 513 }
514 514 }
515 515 mutex_exit(&tm->tm_contents);
516 516
517 517 tm->tm_rootnode->tn_xattrdp = NULL;
518 518 VN_RELE(TNTOV(tm->tm_rootnode));
519 519
520 520 ASSERT(tm->tm_mntpath);
521 521
522 522 tmp_memfree(tm->tm_mntpath, strlen(tm->tm_mntpath) + 1);
523 523
524 524 ASSERT(tm->tm_anonmem == 0);
525 525
526 526 mutex_destroy(&tm->tm_contents);
527 527 mutex_destroy(&tm->tm_renamelck);
528 528 tmp_memfree(tm, sizeof (struct tmount));
529 529
530 530 return (0);
531 531 }
532 532
533 533 /*
534 534 * return root tmpnode for given vnode
535 535 */
536 536 static int
537 537 tmp_root(struct vfs *vfsp, struct vnode **vpp)
538 538 {
539 539 struct tmount *tm = (struct tmount *)VFSTOTM(vfsp);
540 540 struct tmpnode *tp = tm->tm_rootnode;
541 541 struct vnode *vp;
542 542
543 543 ASSERT(tp);
544 544
545 545 vp = TNTOV(tp);
546 546 VN_HOLD(vp);
547 547 *vpp = vp;
548 548 return (0);
549 549 }
550 550
551 551 static int
552 552 tmp_statvfs(struct vfs *vfsp, struct statvfs64 *sbp)
553 553 {
554 554 struct tmount *tm = (struct tmount *)VFSTOTM(vfsp);
555 555 ulong_t blocks;
556 556 dev32_t d32;
557 557 zoneid_t eff_zid;
558 558 struct zone *zp;
559 559
560 560 /*
561 561 * The file system may have been mounted by the global zone on
562 562 * behalf of the non-global zone. In that case, the tmount zone_id
563 563 * will be the global zone. We still want to show the swap cap inside
564 564 * the zone in this case, even though the file system was mounted by
565 565 * the global zone.
566 566 */
567 567 if (curproc->p_zone->zone_id != GLOBAL_ZONEUNIQID)
568 568 zp = curproc->p_zone;
569 569 else
570 570 zp = tm->tm_vfsp->vfs_zone;
571 571
572 572 if (zp == NULL)
573 573 eff_zid = GLOBAL_ZONEUNIQID;
574 574 else
575 575 eff_zid = zp->zone_id;
576 576
577 577 sbp->f_bsize = PAGESIZE;
578 578 sbp->f_frsize = PAGESIZE;
579 579
580 580 /*
581 581 * Find the amount of available physical and memory swap
582 582 */
583 583 mutex_enter(&anoninfo_lock);
584 584 ASSERT(k_anoninfo.ani_max >= k_anoninfo.ani_phys_resv);
585 585 blocks = (ulong_t)CURRENT_TOTAL_AVAILABLE_SWAP;
586 586 mutex_exit(&anoninfo_lock);
587 587
588 588 /*
589 589 * If tm_anonmax for this mount is less than the available swap space
590 590 * (minus the amount tmpfs can't use), use that instead
591 591 */
592 592 if (blocks > tmpfs_minfree)
593 593 sbp->f_bfree = MIN(blocks - tmpfs_minfree,
594 594 tm->tm_anonmax - tm->tm_anonmem);
595 595 else
596 596 sbp->f_bfree = 0;
597 597
598 598 sbp->f_bavail = sbp->f_bfree;
599 599
600 600 /*
601 601 * Total number of blocks is what's available plus what's been used
602 602 */
603 603 sbp->f_blocks = (fsblkcnt64_t)(sbp->f_bfree + tm->tm_anonmem);
604 604
605 605 if (eff_zid != GLOBAL_ZONEUNIQID &&
606 606 zp->zone_max_swap_ctl != UINT64_MAX) {
607 607 /*
608 608 * If the fs is used by a non-global zone with a swap cap,
609 609 * then report the capped size.
610 610 */
611 611 rctl_qty_t cap, used;
612 612 pgcnt_t pgcap, pgused;
613 613
614 614 mutex_enter(&zp->zone_mem_lock);
615 615 cap = zp->zone_max_swap_ctl;
616 616 used = zp->zone_max_swap;
617 617 mutex_exit(&zp->zone_mem_lock);
618 618
619 619 pgcap = btop(cap);
620 620 pgused = btop(used);
621 621
622 622 sbp->f_bfree = MIN(pgcap - pgused, sbp->f_bfree);
623 623 sbp->f_bavail = sbp->f_bfree;
624 624 sbp->f_blocks = MIN(pgcap, sbp->f_blocks);
625 625 }
626 626
627 627 /*
628 628 * The maximum number of files available is approximately the number
629 629 * of tmpnodes we can allocate from the remaining kernel memory
630 630 * available to tmpfs. This is fairly inaccurate since it doesn't
631 631 * take into account the names stored in the directory entries.
632 632 */
633 633 if (tmpfs_maxkmem > tmp_kmemspace)
634 634 sbp->f_ffree = (tmpfs_maxkmem - tmp_kmemspace) /
635 635 (sizeof (struct tmpnode) + sizeof (struct tdirent));
636 636 else
637 637 sbp->f_ffree = 0;
638 638
639 639 sbp->f_files = tmpfs_maxkmem /
640 640 (sizeof (struct tmpnode) + sizeof (struct tdirent));
641 641 sbp->f_favail = (fsfilcnt64_t)(sbp->f_ffree);
642 642 (void) cmpldev(&d32, vfsp->vfs_dev);
643 643 sbp->f_fsid = d32;
644 644 (void) strcpy(sbp->f_basetype, vfssw[tmpfsfstype].vsw_name);
645 645 (void) strncpy(sbp->f_fstr, tm->tm_mntpath, sizeof (sbp->f_fstr));
646 646 /*
647 647 * ensure null termination
648 648 */
649 649 sbp->f_fstr[sizeof (sbp->f_fstr) - 1] = '\0';
650 650 sbp->f_flag = vf_to_stf(vfsp->vfs_flag);
651 651 sbp->f_namemax = MAXNAMELEN - 1;
652 652 return (0);
653 653 }
654 654
655 655 static int
656 656 tmp_vget(struct vfs *vfsp, struct vnode **vpp, struct fid *fidp)
657 657 {
658 658 struct tfid *tfid;
659 659 struct tmount *tm = (struct tmount *)VFSTOTM(vfsp);
660 660 struct tmpnode *tp = NULL;
661 661
662 662 tfid = (struct tfid *)fidp;
663 663 *vpp = NULL;
664 664
665 665 mutex_enter(&tm->tm_contents);
666 666 for (tp = tm->tm_rootnode; tp; tp = tp->tn_forw) {
667 667 mutex_enter(&tp->tn_tlock);
668 668 if (tp->tn_nodeid == tfid->tfid_ino) {
669 669 /*
670 670 * If the gen numbers don't match we know the
671 671 * file won't be found since only one tmpnode
672 672 * can have this number at a time.
673 673 */
674 674 if (tp->tn_gen != tfid->tfid_gen || tp->tn_nlink == 0) {
675 675 mutex_exit(&tp->tn_tlock);
676 676 mutex_exit(&tm->tm_contents);
677 677 return (0);
678 678 }
679 679 *vpp = (struct vnode *)TNTOV(tp);
680 680
681 681 VN_HOLD(*vpp);
682 682
683 683 if ((tp->tn_mode & S_ISVTX) &&
684 684 !(tp->tn_mode & (S_IXUSR | S_IFDIR))) {
685 685 mutex_enter(&(*vpp)->v_lock);
686 686 (*vpp)->v_flag |= VISSWAP;
687 687 mutex_exit(&(*vpp)->v_lock);
688 688 }
689 689 mutex_exit(&tp->tn_tlock);
690 690 mutex_exit(&tm->tm_contents);
691 691 return (0);
692 692 }
693 693 mutex_exit(&tp->tn_tlock);
694 694 }
695 695 mutex_exit(&tm->tm_contents);
696 696 return (0);
697 697 }
↓ open down ↓ |
507 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX