Replace tmpfs_pool custom allocator code with a simpler layer for memory accounting. Use wired memory (which can be limited) for meta-data, and kmem(9) for string allocations. Close PR/31944. Fix PR/38361 while here. OK ad@.diff -r1.6 -r1.7 src/sys/fs/tmpfs/TODO
(rmind)
--- src/sys/fs/tmpfs/TODO 2006/11/09 15:06:03 1.6
+++ src/sys/fs/tmpfs/TODO 2010/06/22 18:32:07 1.7
@@ -1,18 +1,13 @@ | @@ -1,18 +1,13 @@ | |||
1 | - File meta-data is stored using memory pools. These use, at the moment, | |||
2 | wired kernel memory, which is not acceptable because it is easy to turn | |||
3 | the system unstable by exhausting it. Therefore, a pool allocator that | |||
4 | uses anonymous memory has to be written. | |||
5 | ||||
6 | - Verify that file holes work (they should, but must be checked). Add a | 1 | - Verify that file holes work (they should, but must be checked). Add a | |
7 | regression test for this feature. | 2 | regression test for this feature. | |
8 | 3 | |||
9 | - Fix and complete code marked with `XXX' and `TODO' tags. | 4 | - Fix and complete code marked with `XXX' and `TODO' tags. | |
10 | 5 | |||
11 | - Adjust code style - remove the /* ---- */ markers and use standard | 6 | - Adjust code style - remove the /* ---- */ markers and use standard | |
12 | struct vop_*_args assignment into *ap with comment like: | 7 | struct vop_*_args assignment into *ap with comment like: | |
13 | struct vop_link_args /* { | 8 | struct vop_link_args /* { | |
14 | struct vnode *a_dvp; | 9 | struct vnode *a_dvp; | |
15 | struct vnode *a_vp; | 10 | struct vnode *a_vp; | |
16 | struct componentname *a_cnp; | 11 | struct componentname *a_cnp; | |
17 | } */ *ap = v; | 12 | } */ *ap = v; | |
18 | 13 |
--- src/sys/fs/tmpfs/files.tmpfs 2010/03/02 16:43:48 1.3
+++ src/sys/fs/tmpfs/files.tmpfs 2010/06/22 18:32:07 1.4
@@ -1,10 +1,10 @@ | @@ -1,10 +1,10 @@ | |||
1 | # $NetBSD: files.tmpfs,v 1.3 2010/03/02 16:43:48 pooka Exp $ | 1 | # $NetBSD: files.tmpfs,v 1.4 2010/06/22 18:32:07 rmind Exp $ | |
2 | 2 | |||
3 | deffs TMPFS | 3 | deffs TMPFS | |
4 | 4 | |||
5 | file fs/tmpfs/tmpfs_fifoops.c tmpfs | 5 | file fs/tmpfs/tmpfs_fifoops.c tmpfs | |
6 | file fs/tmpfs/tmpfs_pool.c tmpfs | 6 | file fs/tmpfs/tmpfs_mem.c tmpfs | |
7 | file fs/tmpfs/tmpfs_specops.c tmpfs | 7 | file fs/tmpfs/tmpfs_specops.c tmpfs | |
8 | file fs/tmpfs/tmpfs_subr.c tmpfs | 8 | file fs/tmpfs/tmpfs_subr.c tmpfs | |
9 | file fs/tmpfs/tmpfs_vfsops.c tmpfs | 9 | file fs/tmpfs/tmpfs_vfsops.c tmpfs | |
10 | file fs/tmpfs/tmpfs_vnops.c tmpfs | 10 | file fs/tmpfs/tmpfs_vnops.c tmpfs |
--- src/sys/fs/tmpfs/tmpfs.h 2008/07/29 09:10:09 1.37
+++ src/sys/fs/tmpfs/tmpfs.h 2010/06/22 18:32:07 1.38
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: tmpfs.h,v 1.37 2008/07/29 09:10:09 pooka Exp $ */ | 1 | /* $NetBSD: tmpfs.h,v 1.38 2010/06/22 18:32:07 rmind Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Julio M. Merino Vidal, developed as part of Google's Summer of Code | 8 | * by Julio M. Merino Vidal, developed as part of Google's Summer of Code | |
9 | * 2005 program. | 9 | * 2005 program. | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
@@ -25,39 +25,30 @@ | @@ -25,39 +25,30 @@ | |||
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
30 | * POSSIBILITY OF SUCH DAMAGE. | 30 | * POSSIBILITY OF SUCH DAMAGE. | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | #ifndef _FS_TMPFS_TMPFS_H_ | 33 | #ifndef _FS_TMPFS_TMPFS_H_ | |
34 | #define _FS_TMPFS_TMPFS_H_ | 34 | #define _FS_TMPFS_TMPFS_H_ | |
35 | 35 | |||
36 | #include <sys/dirent.h> | 36 | #include <sys/dirent.h> | |
37 | #include <sys/mount.h> | 37 | #include <sys/mount.h> | |
38 | #include <sys/pool.h> | |||
38 | #include <sys/queue.h> | 39 | #include <sys/queue.h> | |
39 | #include <sys/vnode.h> | 40 | #include <sys/vnode.h> | |
40 | 41 | |||
41 | /* --------------------------------------------------------------------- */ | |||
42 | /* For the kernel and anyone who likes peeking into kernel memory */ | |||
43 | /* --------------------------------------------------------------------- */ | |||
44 | ||||
45 | #if defined(_KERNEL) | |||
46 | #include <fs/tmpfs/tmpfs_pool.h> | |||
47 | #endif /* defined(_KERNEL) */ | |||
48 | ||||
49 | /* --------------------------------------------------------------------- */ | |||
50 | ||||
51 | /* | 42 | /* | |
52 | * Internal representation of a tmpfs directory entry. | 43 | * Internal representation of a tmpfs directory entry. | |
53 | */ | 44 | */ | |
54 | struct tmpfs_dirent { | 45 | struct tmpfs_dirent { | |
55 | TAILQ_ENTRY(tmpfs_dirent) td_entries; | 46 | TAILQ_ENTRY(tmpfs_dirent) td_entries; | |
56 | 47 | |||
57 | /* Length of the name stored in this directory entry. This avoids | 48 | /* Length of the name stored in this directory entry. This avoids | |
58 | * the need to recalculate it every time the name is used. */ | 49 | * the need to recalculate it every time the name is used. */ | |
59 | uint16_t td_namelen; | 50 | uint16_t td_namelen; | |
60 | 51 | |||
61 | /* The name of the entry, allocated from a string pool. This | 52 | /* The name of the entry, allocated from a string pool. This | |
62 | * string is not required to be zero-terminated; therefore, the | 53 | * string is not required to be zero-terminated; therefore, the | |
63 | * td_namelen field must always be used when accessing its value. */ | 54 | * td_namelen field must always be used when accessing its value. */ | |
@@ -271,64 +262,56 @@ struct tmpfs_node { | @@ -271,64 +262,56 @@ struct tmpfs_node { | |||
271 | } tn_reg; | 262 | } tn_reg; | |
272 | } tn_spec; | 263 | } tn_spec; | |
273 | }; | 264 | }; | |
274 | 265 | |||
275 | #if defined(_KERNEL) | 266 | #if defined(_KERNEL) | |
276 | LIST_HEAD(tmpfs_node_list, tmpfs_node); | 267 | LIST_HEAD(tmpfs_node_list, tmpfs_node); | |
277 | 268 | |||
278 | /* --------------------------------------------------------------------- */ | 269 | /* --------------------------------------------------------------------- */ | |
279 | 270 | |||
280 | /* | 271 | /* | |
281 | * Internal representation of a tmpfs mount point. | 272 | * Internal representation of a tmpfs mount point. | |
282 | */ | 273 | */ | |
283 | struct tmpfs_mount { | 274 | struct tmpfs_mount { | |
284 | /* Maximum number of memory pages available for use by the file | 275 | /* Limit and number of bytes in use by the file system. */ | |
285 | * system, set during mount time. This variable must never be | 276 | uint64_t tm_mem_limit; | |
286 | * used directly as it may be bigger than the current amount of | 277 | uint64_t tm_bytes_used; | |
287 | * free memory; in the extreme case, it will hold the SIZE_MAX | 278 | kmutex_t tm_acc_lock; | |
288 | * value. Instead, use the TMPFS_PAGES_MAX macro. */ | |||
289 | unsigned int tm_pages_max; | |||
290 | ||||
291 | /* Number of pages in use by the file system. Cannot be bigger | |||
292 | * than the value returned by TMPFS_PAGES_MAX in any case. */ | |||
293 | unsigned int tm_pages_used; | |||
294 | 279 | |||
295 | /* Pointer to the node representing the root directory of this | 280 | /* Pointer to the node representing the root directory of this | |
296 | * file system. */ | 281 | * file system. */ | |
297 | struct tmpfs_node * tm_root; | 282 | struct tmpfs_node * tm_root; | |
298 | 283 | |||
299 | /* Maximum number of possible nodes for this file system; set | 284 | /* Maximum number of possible nodes for this file system; set | |
300 | * during mount time. We need a hard limit on the maximum number | 285 | * during mount time. We need a hard limit on the maximum number | |
301 | * of nodes to avoid allocating too much of them; their objects | 286 | * of nodes to avoid allocating too much of them; their objects | |
302 | * cannot be released until the file system is unmounted. | 287 | * cannot be released until the file system is unmounted. | |
303 | * Otherwise, we could easily run out of memory by creating lots | 288 | * Otherwise, we could easily run out of memory by creating lots | |
304 | * of empty files and then simply removing them. */ | 289 | * of empty files and then simply removing them. */ | |
305 | unsigned int tm_nodes_max; | 290 | unsigned int tm_nodes_max; | |
306 | 291 | |||
307 | /* Number of nodes currently allocated. This number only grows. | 292 | /* Number of nodes currently allocated. This number only grows. | |
308 | * When it reaches tm_nodes_max, no more new nodes can be allocated. | 293 | * When it reaches tm_nodes_max, no more new nodes can be allocated. | |
309 | * Of course, the old, unused ones can be reused. */ | 294 | * Of course, the old, unused ones can be reused. */ | |
310 | unsigned int tm_nodes_cnt; | 295 | unsigned int tm_nodes_cnt; | |
311 | 296 | |||
312 | /* Node list. */ | 297 | /* Node list. */ | |
313 | kmutex_t tm_lock; | 298 | kmutex_t tm_lock; | |
314 | struct tmpfs_node_list tm_nodes; | 299 | struct tmpfs_node_list tm_nodes; | |
315 | 300 | |||
316 | /* Pools used to store file system meta data. These are not shared | 301 | char tm_dwchan[32]; | |
317 | * across several instances of tmpfs for the reasons described in | 302 | struct pool tm_dirent_pool; | |
318 | * tmpfs_pool.c. */ | 303 | char tm_nwchan[32]; | |
319 | struct tmpfs_pool tm_dirent_pool; | 304 | struct pool tm_node_pool; | |
320 | struct tmpfs_pool tm_node_pool; | |||
321 | struct tmpfs_str_pool tm_str_pool; | |||
322 | }; | 305 | }; | |
323 | 306 | |||
324 | /* --------------------------------------------------------------------- */ | 307 | /* --------------------------------------------------------------------- */ | |
325 | 308 | |||
326 | /* | 309 | /* | |
327 | * This structure maps a file identifier to a tmpfs node. Used by the | 310 | * This structure maps a file identifier to a tmpfs node. Used by the | |
328 | * NFS code. | 311 | * NFS code. | |
329 | */ | 312 | */ | |
330 | struct tmpfs_fid { | 313 | struct tmpfs_fid { | |
331 | uint16_t tf_len; | 314 | uint16_t tf_len; | |
332 | uint16_t tf_pad; | 315 | uint16_t tf_pad; | |
333 | uint32_t tf_gen; | 316 | uint32_t tf_gen; | |
334 | ino_t tf_id; | 317 | ino_t tf_id; | |
@@ -351,41 +334,63 @@ void tmpfs_free_dirent(struct tmpfs_moun | @@ -351,41 +334,63 @@ void tmpfs_free_dirent(struct tmpfs_moun | |||
351 | int tmpfs_alloc_vp(struct mount *, struct tmpfs_node *, struct vnode **); | 334 | int tmpfs_alloc_vp(struct mount *, struct tmpfs_node *, struct vnode **); | |
352 | void tmpfs_free_vp(struct vnode *); | 335 | void tmpfs_free_vp(struct vnode *); | |
353 | int tmpfs_alloc_file(struct vnode *, struct vnode **, struct vattr *, | 336 | int tmpfs_alloc_file(struct vnode *, struct vnode **, struct vattr *, | |
354 | struct componentname *, char *); | 337 | struct componentname *, char *); | |
355 | void tmpfs_dir_attach(struct vnode *, struct tmpfs_dirent *); | 338 | void tmpfs_dir_attach(struct vnode *, struct tmpfs_dirent *); | |
356 | void tmpfs_dir_detach(struct vnode *, struct tmpfs_dirent *); | 339 | void tmpfs_dir_detach(struct vnode *, struct tmpfs_dirent *); | |
357 | struct tmpfs_dirent * tmpfs_dir_lookup(struct tmpfs_node *node, | 340 | struct tmpfs_dirent * tmpfs_dir_lookup(struct tmpfs_node *node, | |
358 | struct componentname *cnp); | 341 | struct componentname *cnp); | |
359 | int tmpfs_dir_getdotdent(struct tmpfs_node *, struct uio *); | 342 | int tmpfs_dir_getdotdent(struct tmpfs_node *, struct uio *); | |
360 | int tmpfs_dir_getdotdotdent(struct tmpfs_node *, struct uio *); | 343 | int tmpfs_dir_getdotdotdent(struct tmpfs_node *, struct uio *); | |
361 | struct tmpfs_dirent * tmpfs_dir_lookupbycookie(struct tmpfs_node *, off_t); | 344 | struct tmpfs_dirent * tmpfs_dir_lookupbycookie(struct tmpfs_node *, off_t); | |
362 | int tmpfs_dir_getdents(struct tmpfs_node *, struct uio *, off_t *); | 345 | int tmpfs_dir_getdents(struct tmpfs_node *, struct uio *, off_t *); | |
363 | int tmpfs_reg_resize(struct vnode *, off_t); | 346 | int tmpfs_reg_resize(struct vnode *, off_t); | |
364 | size_t tmpfs_mem_info(bool); | |||
365 | int tmpfs_chflags(struct vnode *, int, kauth_cred_t, struct lwp *); | 347 | int tmpfs_chflags(struct vnode *, int, kauth_cred_t, struct lwp *); | |
366 | int tmpfs_chmod(struct vnode *, mode_t, kauth_cred_t, struct lwp *); | 348 | int tmpfs_chmod(struct vnode *, mode_t, kauth_cred_t, struct lwp *); | |
367 | int tmpfs_chown(struct vnode *, uid_t, gid_t, kauth_cred_t, struct lwp *); | 349 | int tmpfs_chown(struct vnode *, uid_t, gid_t, kauth_cred_t, struct lwp *); | |
368 | int tmpfs_chsize(struct vnode *, u_quad_t, kauth_cred_t, struct lwp *); | 350 | int tmpfs_chsize(struct vnode *, u_quad_t, kauth_cred_t, struct lwp *); | |
369 | int tmpfs_chtimes(struct vnode *, const struct timespec *, | 351 | int tmpfs_chtimes(struct vnode *, const struct timespec *, | |
370 | const struct timespec *, const struct timespec *, int, kauth_cred_t, | 352 | const struct timespec *, const struct timespec *, int, kauth_cred_t, | |
371 | struct lwp *); | 353 | struct lwp *); | |
372 | void tmpfs_itimes(struct vnode *, const struct timespec *, | 354 | void tmpfs_itimes(struct vnode *, const struct timespec *, | |
373 | const struct timespec *, const struct timespec *); | 355 | const struct timespec *, const struct timespec *); | |
374 | 356 | |||
375 | void tmpfs_update(struct vnode *, const struct timespec *, | 357 | void tmpfs_update(struct vnode *, const struct timespec *, | |
376 | const struct timespec *, const struct timespec *, int); | 358 | const struct timespec *, const struct timespec *, int); | |
377 | int tmpfs_truncate(struct vnode *, off_t); | 359 | int tmpfs_truncate(struct vnode *, off_t); | |
378 | 360 | |||
361 | /* | |||
362 | * Prototypes for tmpfs_mem.c. | |||
363 | */ | |||
364 | ||||
365 | void tmpfs_mntmem_init(struct tmpfs_mount *, uint64_t); | |||
366 | void tmpfs_mntmem_destroy(struct tmpfs_mount *); | |||
367 | ||||
368 | size_t tmpfs_mem_info(bool); | |||
369 | uint64_t tmpfs_bytes_max(struct tmpfs_mount *); | |||
370 | size_t tmpfs_pages_avail(struct tmpfs_mount *); | |||
371 | bool tmpfs_mem_incr(struct tmpfs_mount *, size_t); | |||
372 | void tmpfs_mem_decr(struct tmpfs_mount *, size_t); | |||
373 | ||||
374 | struct tmpfs_dirent *tmpfs_dirent_get(struct tmpfs_mount *); | |||
375 | void tmpfs_dirent_put(struct tmpfs_mount *, struct tmpfs_dirent *); | |||
376 | ||||
377 | struct tmpfs_node *tmpfs_node_get(struct tmpfs_mount *); | |||
378 | void tmpfs_node_put(struct tmpfs_mount *, struct tmpfs_node *); | |||
379 | ||||
380 | char * tmpfs_strname_alloc(struct tmpfs_mount *, size_t); | |||
381 | void tmpfs_strname_free(struct tmpfs_mount *, char *, size_t); | |||
382 | bool tmpfs_strname_neqlen(struct componentname *, struct componentname *); | |||
383 | ||||
379 | /* --------------------------------------------------------------------- */ | 384 | /* --------------------------------------------------------------------- */ | |
380 | 385 | |||
381 | /* | 386 | /* | |
382 | * Convenience macros to simplify some logical expressions. | 387 | * Convenience macros to simplify some logical expressions. | |
383 | */ | 388 | */ | |
384 | #define IMPLIES(a, b) (!(a) || (b)) | 389 | #define IMPLIES(a, b) (!(a) || (b)) | |
385 | #define IFF(a, b) (IMPLIES(a, b) && IMPLIES(b, a)) | 390 | #define IFF(a, b) (IMPLIES(a, b) && IMPLIES(b, a)) | |
386 | 391 | |||
387 | /* --------------------------------------------------------------------- */ | 392 | /* --------------------------------------------------------------------- */ | |
388 | 393 | |||
389 | /* | 394 | /* | |
390 | * Checks that the directory entry pointed by 'de' matches the name 'name' | 395 | * Checks that the directory entry pointed by 'de' matches the name 'name' | |
391 | * with a length of 'len'. | 396 | * with a length of 'len'. | |
@@ -408,56 +413,26 @@ int tmpfs_truncate(struct vnode *, off_t | @@ -408,56 +413,26 @@ int tmpfs_truncate(struct vnode *, off_t | |||
408 | (node)->tn_spec.tn_dir.tn_readdir_lastn); | 413 | (node)->tn_spec.tn_dir.tn_readdir_lastn); | |
409 | 414 | |||
410 | /* --------------------------------------------------------------------- */ | 415 | /* --------------------------------------------------------------------- */ | |
411 | 416 | |||
412 | /* | 417 | /* | |
413 | * Memory management stuff. | 418 | * Memory management stuff. | |
414 | */ | 419 | */ | |
415 | 420 | |||
416 | /* Amount of memory pages to reserve for the system (e.g., to not use by | 421 | /* Amount of memory pages to reserve for the system (e.g., to not use by | |
417 | * tmpfs). | 422 | * tmpfs). | |
418 | * XXX: Should this be tunable through sysctl, for instance? */ | 423 | * XXX: Should this be tunable through sysctl, for instance? */ | |
419 | #define TMPFS_PAGES_RESERVED (4 * 1024 * 1024 / PAGE_SIZE) | 424 | #define TMPFS_PAGES_RESERVED (4 * 1024 * 1024 / PAGE_SIZE) | |
420 | 425 | |||
421 | /* Returns the maximum size allowed for a tmpfs file system. This macro | |||
422 | * must be used instead of directly retrieving the value from tm_pages_max. | |||
423 | * The reason is that the size of a tmpfs file system is dynamic: it lets | |||
424 | * the user store files as long as there is enough free memory (including | |||
425 | * physical memory and swap space). Therefore, the amount of memory to be | |||
426 | * used is either the limit imposed by the user during mount time or the | |||
427 | * amount of available memory, whichever is lower. To avoid consuming all | |||
428 | * the memory for a given mount point, the system will always reserve a | |||
429 | * minimum of TMPFS_PAGES_RESERVED pages, which is also taken into account | |||
430 | * by this macro (see above). */ | |||
431 | static __inline size_t | |||
432 | TMPFS_PAGES_MAX(struct tmpfs_mount *tmp) | |||
433 | { | |||
434 | size_t freepages; | |||
435 | ||||
436 | freepages = tmpfs_mem_info(false); | |||
437 | if (freepages < TMPFS_PAGES_RESERVED) | |||
438 | freepages = 0; | |||
439 | else | |||
440 | freepages -= TMPFS_PAGES_RESERVED; | |||
441 | ||||
442 | return MIN(tmp->tm_pages_max, freepages + tmp->tm_pages_used); | |||
443 | } | |||
444 | ||||
445 | /* Returns the available space for the given file system. */ | |||
446 | #define TMPFS_PAGES_AVAIL(tmp) \ | |||
447 | ((ssize_t)(TMPFS_PAGES_MAX(tmp) - (tmp)->tm_pages_used)) | |||
448 | ||||
449 | /* --------------------------------------------------------------------- */ | |||
450 | ||||
451 | /* | 426 | /* | |
452 | * Macros/functions to convert from generic data structures to tmpfs | 427 | * Macros/functions to convert from generic data structures to tmpfs | |
453 | * specific ones. | 428 | * specific ones. | |
454 | */ | 429 | */ | |
455 | 430 | |||
456 | static __inline | 431 | static __inline | |
457 | struct tmpfs_mount * | 432 | struct tmpfs_mount * | |
458 | VFS_TO_TMPFS(struct mount *mp) | 433 | VFS_TO_TMPFS(struct mount *mp) | |
459 | { | 434 | { | |
460 | struct tmpfs_mount *tmp; | 435 | struct tmpfs_mount *tmp; | |
461 | 436 | |||
462 | #ifdef KASSERT | 437 | #ifdef KASSERT | |
463 | KASSERT((mp) != NULL && (mp)->mnt_data != NULL); | 438 | KASSERT((mp) != NULL && (mp)->mnt_data != NULL); |
/* $NetBSD: tmpfs_mem.c,v 1.1 2010/06/22 18:32:07 rmind Exp $ */
/*
* Copyright (c) 2010 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* tmpfs memory allocation routines.
* Implements memory usage accounting and limiting.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: tmpfs_mem.c,v 1.1 2010/06/22 18:32:07 rmind Exp $");
#include <sys/param.h>
#include <sys/atomic.h>
#include <sys/kmem.h>
#include <sys/namei.h>
#include <sys/pool.h>
#include <fs/tmpfs/tmpfs.h>
void
tmpfs_mntmem_init(struct tmpfs_mount *mp, uint64_t memlimit)
{
sprintf(mp->tm_dwchan, "tmpfs_dirent_%p", mp);
pool_init(&mp->tm_dirent_pool, sizeof(struct tmpfs_dirent), 0, 0, 0,
mp->tm_dwchan, &pool_allocator_nointr, IPL_NONE);
sprintf(mp->tm_nwchan, "tmpfs_node_%p", mp);
pool_init(&mp->tm_node_pool, sizeof(struct tmpfs_node), 0, 0, 0,
mp->tm_dwchan, &pool_allocator_nointr, IPL_NONE);
mutex_init(&mp->tm_acc_lock, MUTEX_DEFAULT, IPL_NONE);
mp->tm_mem_limit = memlimit;
mp->tm_bytes_used = 0;
}
void
tmpfs_mntmem_destroy(struct tmpfs_mount *mp)
{
KASSERT(mp->tm_bytes_used == 0);
mutex_destroy(&mp->tm_acc_lock);
pool_destroy(&mp->tm_dirent_pool);
pool_destroy(&mp->tm_node_pool);
}
/*
* tmpfs_mem_info: return the number of available memory pages.
*
* => If 'total' is true, then return _total_ amount of pages.
* => If false, then return the amount of _free_ memory pages.
*
* Remember to remove TMPFS_PAGES_RESERVED from the returned value to avoid
* excessive memory usage.
*/
size_t
tmpfs_mem_info(bool total)
{
size_t size = 0;
/* XXX: unlocked */
size += uvmexp.swpgavail;
if (!total) {
size -= uvmexp.swpgonly;
}
size += uvmexp.free;
size += uvmexp.filepages;
if (size > uvmexp.wired) {
size -= uvmexp.wired;
} else {
size = 0;
}
return size;
}
uint64_t
tmpfs_bytes_max(struct tmpfs_mount *mp)
{
size_t freepages = tmpfs_mem_info(false);
uint64_t avail_mem;
if (freepages < TMPFS_PAGES_RESERVED) {
freepages = 0;
} else {
freepages -= TMPFS_PAGES_RESERVED;
}
avail_mem = round_page(mp->tm_bytes_used) + (freepages << PAGE_SHIFT);
return min(mp->tm_mem_limit, avail_mem);
}
size_t
tmpfs_pages_avail(struct tmpfs_mount *mp)
{
return (tmpfs_bytes_max(mp) - mp->tm_bytes_used) >> PAGE_SHIFT;
}
bool
tmpfs_mem_incr(struct tmpfs_mount *mp, size_t sz)
{
const uint64_t lim = tmpfs_bytes_max(mp);
mutex_enter(&mp->tm_acc_lock);
if (mp->tm_bytes_used + sz >= lim) {
mutex_exit(&mp->tm_acc_lock);
return false;
}
mp->tm_bytes_used += sz;
mutex_exit(&mp->tm_acc_lock);
return true;
}
void
tmpfs_mem_decr(struct tmpfs_mount *mp, size_t sz)
{
mutex_enter(&mp->tm_acc_lock);
KASSERT(mp->tm_bytes_used >= sz);
mp->tm_bytes_used -= sz;
mutex_exit(&mp->tm_acc_lock);
}
struct tmpfs_dirent *
tmpfs_dirent_get(struct tmpfs_mount *mp)
{
if (!tmpfs_mem_incr(mp, sizeof(struct tmpfs_dirent))) {
return NULL;
}
return pool_get(&mp->tm_dirent_pool, PR_WAITOK);
}
void
tmpfs_dirent_put(struct tmpfs_mount *mp, struct tmpfs_dirent *de)
{
tmpfs_mem_decr(mp, sizeof(struct tmpfs_dirent));
pool_put(&mp->tm_dirent_pool, de);
}
struct tmpfs_node *
tmpfs_node_get(struct tmpfs_mount *mp)
{
if (!tmpfs_mem_incr(mp, sizeof(struct tmpfs_node))) {
return NULL;
}
return pool_get(&mp->tm_node_pool, PR_WAITOK);
}
void
tmpfs_node_put(struct tmpfs_mount *mp, struct tmpfs_node *tn)
{
tmpfs_mem_decr(mp, sizeof(struct tmpfs_node));
pool_put(&mp->tm_node_pool, tn);
}
/*
* Quantum size to round-up the tmpfs names in order to reduce re-allocations.
*/
#define TMPFS_NAME_QUANTUM (32)
char *
tmpfs_strname_alloc(struct tmpfs_mount *mp, size_t len)
{
const size_t sz = roundup2(len, TMPFS_NAME_QUANTUM);
KASSERT(sz > 0 && sz <= 1024);
if (!tmpfs_mem_incr(mp, sz)) {
return NULL;
}
return kmem_alloc(sz, KM_SLEEP);
}
void
tmpfs_strname_free(struct tmpfs_mount *mp, char *str, size_t len)
{
const size_t sz = roundup2(len, TMPFS_NAME_QUANTUM);
KASSERT(sz > 0 && sz <= 1024);
tmpfs_mem_decr(mp, sz);
kmem_free(str, sz);
}
bool
tmpfs_strname_neqlen(struct componentname *fcnp, struct componentname *tcnp)
{
const size_t fln = roundup2(fcnp->cn_namelen, TMPFS_NAME_QUANTUM);
const size_t tln = roundup2(tcnp->cn_namelen, TMPFS_NAME_QUANTUM);
return (fln != tln) || memcmp(fcnp->cn_nameptr, tcnp->cn_nameptr, fln);
}
--- src/sys/fs/tmpfs/tmpfs_subr.c 2009/11/11 09:59:41 1.56
+++ src/sys/fs/tmpfs/tmpfs_subr.c 2010/06/22 18:32:08 1.57
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: tmpfs_subr.c,v 1.56 2009/11/11 09:59:41 rmind Exp $ */ | 1 | /* $NetBSD: tmpfs_subr.c,v 1.57 2010/06/22 18:32:08 rmind Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Julio M. Merino Vidal, developed as part of Google's Summer of Code | 8 | * by Julio M. Merino Vidal, developed as part of Google's Summer of Code | |
9 | * 2005 program. | 9 | * 2005 program. | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
@@ -25,27 +25,27 @@ | @@ -25,27 +25,27 @@ | |||
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
30 | * POSSIBILITY OF SUCH DAMAGE. | 30 | * POSSIBILITY OF SUCH DAMAGE. | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | /* | 33 | /* | |
34 | * Efficient memory file system supporting functions. | 34 | * Efficient memory file system supporting functions. | |
35 | */ | 35 | */ | |
36 | 36 | |||
37 | #include <sys/cdefs.h> | 37 | #include <sys/cdefs.h> | |
38 | __KERNEL_RCSID(0, "$NetBSD: tmpfs_subr.c,v 1.56 2009/11/11 09:59:41 rmind Exp $"); | 38 | __KERNEL_RCSID(0, "$NetBSD: tmpfs_subr.c,v 1.57 2010/06/22 18:32:08 rmind Exp $"); | |
39 | 39 | |||
40 | #include <sys/param.h> | 40 | #include <sys/param.h> | |
41 | #include <sys/dirent.h> | 41 | #include <sys/dirent.h> | |
42 | #include <sys/event.h> | 42 | #include <sys/event.h> | |
43 | #include <sys/kmem.h> | 43 | #include <sys/kmem.h> | |
44 | #include <sys/mount.h> | 44 | #include <sys/mount.h> | |
45 | #include <sys/namei.h> | 45 | #include <sys/namei.h> | |
46 | #include <sys/time.h> | 46 | #include <sys/time.h> | |
47 | #include <sys/stat.h> | 47 | #include <sys/stat.h> | |
48 | #include <sys/systm.h> | 48 | #include <sys/systm.h> | |
49 | #include <sys/swap.h> | 49 | #include <sys/swap.h> | |
50 | #include <sys/vnode.h> | 50 | #include <sys/vnode.h> | |
51 | #include <sys/kauth.h> | 51 | #include <sys/kauth.h> | |
@@ -97,27 +97,27 @@ tmpfs_alloc_node(struct tmpfs_mount *tmp | @@ -97,27 +97,27 @@ tmpfs_alloc_node(struct tmpfs_mount *tmp | |||
97 | KASSERT(IMPLIES(tmp->tm_root == NULL, parent == NULL && type == VDIR)); | 97 | KASSERT(IMPLIES(tmp->tm_root == NULL, parent == NULL && type == VDIR)); | |
98 | 98 | |||
99 | KASSERT(IFF(type == VLNK, target != NULL)); | 99 | KASSERT(IFF(type == VLNK, target != NULL)); | |
100 | KASSERT(IFF(type == VBLK || type == VCHR, rdev != VNOVAL)); | 100 | KASSERT(IFF(type == VBLK || type == VCHR, rdev != VNOVAL)); | |
101 | 101 | |||
102 | KASSERT(uid != VNOVAL && gid != VNOVAL && mode != VNOVAL); | 102 | KASSERT(uid != VNOVAL && gid != VNOVAL && mode != VNOVAL); | |
103 | 103 | |||
104 | nnode = NULL; | 104 | nnode = NULL; | |
105 | if (atomic_inc_uint_nv(&tmp->tm_nodes_cnt) >= tmp->tm_nodes_max) { | 105 | if (atomic_inc_uint_nv(&tmp->tm_nodes_cnt) >= tmp->tm_nodes_max) { | |
106 | atomic_dec_uint(&tmp->tm_nodes_cnt); | 106 | atomic_dec_uint(&tmp->tm_nodes_cnt); | |
107 | return ENOSPC; | 107 | return ENOSPC; | |
108 | } | 108 | } | |
109 | 109 | |||
110 | nnode = (struct tmpfs_node *)TMPFS_POOL_GET(&tmp->tm_node_pool, 0); | 110 | nnode = tmpfs_node_get(tmp); | |
111 | if (nnode == NULL) { | 111 | if (nnode == NULL) { | |
112 | atomic_dec_uint(&tmp->tm_nodes_cnt); | 112 | atomic_dec_uint(&tmp->tm_nodes_cnt); | |
113 | return ENOSPC; | 113 | return ENOSPC; | |
114 | } | 114 | } | |
115 | 115 | |||
116 | /* | 116 | /* | |
117 | * XXX Where the pool is backed by a map larger than (4GB * | 117 | * XXX Where the pool is backed by a map larger than (4GB * | |
118 | * sizeof(*nnode)), this may produce duplicate inode numbers | 118 | * sizeof(*nnode)), this may produce duplicate inode numbers | |
119 | * for applications that do not understand 64-bit ino_t. | 119 | * for applications that do not understand 64-bit ino_t. | |
120 | */ | 120 | */ | |
121 | nnode->tn_id = (ino_t)((uintptr_t)nnode / sizeof(*nnode)); | 121 | nnode->tn_id = (ino_t)((uintptr_t)nnode / sizeof(*nnode)); | |
122 | nnode->tn_gen = arc4random(); | 122 | nnode->tn_gen = arc4random(); | |
123 | 123 | |||
@@ -154,30 +154,30 @@ tmpfs_alloc_node(struct tmpfs_mount *tmp | @@ -154,30 +154,30 @@ tmpfs_alloc_node(struct tmpfs_mount *tmp | |||
154 | nnode->tn_spec.tn_dir.tn_readdir_lastp = NULL; | 154 | nnode->tn_spec.tn_dir.tn_readdir_lastp = NULL; | |
155 | nnode->tn_links++; | 155 | nnode->tn_links++; | |
156 | break; | 156 | break; | |
157 | 157 | |||
158 | case VFIFO: | 158 | case VFIFO: | |
159 | /* FALLTHROUGH */ | 159 | /* FALLTHROUGH */ | |
160 | case VSOCK: | 160 | case VSOCK: | |
161 | break; | 161 | break; | |
162 | 162 | |||
163 | case VLNK: | 163 | case VLNK: | |
164 | KASSERT(strlen(target) < MAXPATHLEN); | 164 | KASSERT(strlen(target) < MAXPATHLEN); | |
165 | nnode->tn_size = strlen(target); | 165 | nnode->tn_size = strlen(target); | |
166 | nnode->tn_spec.tn_lnk.tn_link = | 166 | nnode->tn_spec.tn_lnk.tn_link = | |
167 | tmpfs_str_pool_get(&tmp->tm_str_pool, nnode->tn_size, 0); | 167 | tmpfs_strname_alloc(tmp, nnode->tn_size); | |
168 | if (nnode->tn_spec.tn_lnk.tn_link == NULL) { | 168 | if (nnode->tn_spec.tn_lnk.tn_link == NULL) { | |
169 | atomic_dec_uint(&tmp->tm_nodes_cnt); | 169 | atomic_dec_uint(&tmp->tm_nodes_cnt); | |
170 | TMPFS_POOL_PUT(&tmp->tm_node_pool, nnode); | 170 | tmpfs_node_put(tmp, nnode); | |
171 | return ENOSPC; | 171 | return ENOSPC; | |
172 | } | 172 | } | |
173 | memcpy(nnode->tn_spec.tn_lnk.tn_link, target, nnode->tn_size); | 173 | memcpy(nnode->tn_spec.tn_lnk.tn_link, target, nnode->tn_size); | |
174 | break; | 174 | break; | |
175 | 175 | |||
176 | case VREG: | 176 | case VREG: | |
177 | nnode->tn_spec.tn_reg.tn_aobj = | 177 | nnode->tn_spec.tn_reg.tn_aobj = | |
178 | uao_create(INT32_MAX - PAGE_SIZE, 0); | 178 | uao_create(INT32_MAX - PAGE_SIZE, 0); | |
179 | nnode->tn_spec.tn_reg.tn_aobj_pages = 0; | 179 | nnode->tn_spec.tn_reg.tn_aobj_pages = 0; | |
180 | break; | 180 | break; | |
181 | 181 | |||
182 | default: | 182 | default: | |
183 | KASSERT(0); | 183 | KASSERT(0); | |
@@ -205,80 +205,84 @@ tmpfs_alloc_node(struct tmpfs_mount *tmp | @@ -205,80 +205,84 @@ tmpfs_alloc_node(struct tmpfs_mount *tmp | |||
205 | * kernel space. Furthermore, there is not need to provide such | 205 | * kernel space. Furthermore, there is not need to provide such | |
206 | * functionality (recursive removal) because the only primitives offered | 206 | * functionality (recursive removal) because the only primitives offered | |
207 | * to the user are the removal of empty directories and the deletion of | 207 | * to the user are the removal of empty directories and the deletion of | |
208 | * individual files. | 208 | * individual files. | |
209 | * | 209 | * | |
210 | * Note that nodes are not really deleted; in fact, when a node has been | 210 | * Note that nodes are not really deleted; in fact, when a node has been | |
211 | * allocated, it cannot be deleted during the whole life of the file | 211 | * allocated, it cannot be deleted during the whole life of the file | |
212 | * system. Instead, they are moved to the available list and remain there | 212 | * system. Instead, they are moved to the available list and remain there | |
213 | * until reused. | 213 | * until reused. | |
214 | */ | 214 | */ | |
215 | void | 215 | void | |
216 | tmpfs_free_node(struct tmpfs_mount *tmp, struct tmpfs_node *node) | 216 | tmpfs_free_node(struct tmpfs_mount *tmp, struct tmpfs_node *node) | |
217 | { | 217 | { | |
218 | size_t objsz; | |||
218 | 219 | |||
219 | if (node->tn_type == VREG) { | |||
220 | atomic_add_int(&tmp->tm_pages_used, | |||
221 | -node->tn_spec.tn_reg.tn_aobj_pages); | |||
222 | } | |||
223 | atomic_dec_uint(&tmp->tm_nodes_cnt); | |||
224 | mutex_enter(&tmp->tm_lock); | 220 | mutex_enter(&tmp->tm_lock); | |
225 | LIST_REMOVE(node, tn_entries); | 221 | LIST_REMOVE(node, tn_entries); | |
226 | mutex_exit(&tmp->tm_lock); | 222 | mutex_exit(&tmp->tm_lock); | |
223 | atomic_dec_uint(&tmp->tm_nodes_cnt); | |||
227 | 224 | |||
228 | switch (node->tn_type) { | 225 | switch (node->tn_type) { | |
229 | case VLNK: | 226 | case VLNK: | |
230 | tmpfs_str_pool_put(&tmp->tm_str_pool, | 227 | tmpfs_strname_free(tmp, node->tn_spec.tn_lnk.tn_link, | |
231 | node->tn_spec.tn_lnk.tn_link, node->tn_size); | 228 | node->tn_size); | |
232 | break; | 229 | break; | |
233 | ||||
234 | case VREG: | 230 | case VREG: | |
235 | if (node->tn_spec.tn_reg.tn_aobj != NULL) | 231 | /* | |
232 | * Calculate the size of node data, decrease the used-memory | |||
233 | * counter, and destroy the memory object (if any). | |||
234 | */ | |||
235 | objsz = PAGE_SIZE * node->tn_spec.tn_reg.tn_aobj_pages; | |||
236 | if (objsz != 0) { | |||
237 | tmpfs_mem_decr(tmp, objsz); | |||
238 | } | |||
239 | if (node->tn_spec.tn_reg.tn_aobj != NULL) { | |||
236 | uao_detach(node->tn_spec.tn_reg.tn_aobj); | 240 | uao_detach(node->tn_spec.tn_reg.tn_aobj); | |
241 | } | |||
237 | break; | 242 | break; | |
238 | ||||
239 | default: | 243 | default: | |
240 | break; | 244 | break; | |
241 | } | 245 | } | |
242 | 246 | |||
243 | mutex_destroy(&node->tn_vlock); | 247 | mutex_destroy(&node->tn_vlock); | |
244 | TMPFS_POOL_PUT(&tmp->tm_node_pool, node); | 248 | tmpfs_node_put(tmp, node); | |
245 | } | 249 | } | |
246 | 250 | |||
247 | /* --------------------------------------------------------------------- */ | 251 | /* --------------------------------------------------------------------- */ | |
248 | 252 | |||
249 | /* | 253 | /* | |
250 | * Allocates a new directory entry for the node node with a name of name. | 254 | * Allocates a new directory entry for the node node with a name of name. | |
251 | * The new directory entry is returned in *de. | 255 | * The new directory entry is returned in *de. | |
252 | * | 256 | * | |
253 | * The link count of node is increased by one to reflect the new object | 257 | * The link count of node is increased by one to reflect the new object | |
254 | * referencing it. This takes care of notifying kqueue listeners about | 258 | * referencing it. This takes care of notifying kqueue listeners about | |
255 | * this change. | 259 | * this change. | |
256 | * | 260 | * | |
257 | * Returns zero on success or an appropriate error code on failure. | 261 | * Returns zero on success or an appropriate error code on failure. | |
258 | */ | 262 | */ | |
259 | int | 263 | int | |
260 | tmpfs_alloc_dirent(struct tmpfs_mount *tmp, struct tmpfs_node *node, | 264 | tmpfs_alloc_dirent(struct tmpfs_mount *tmp, struct tmpfs_node *node, | |
261 | const char *name, uint16_t len, struct tmpfs_dirent **de) | 265 | const char *name, uint16_t len, struct tmpfs_dirent **de) | |
262 | { | 266 | { | |
263 | struct tmpfs_dirent *nde; | 267 | struct tmpfs_dirent *nde; | |
264 | 268 | |||
265 | nde = (struct tmpfs_dirent *)TMPFS_POOL_GET(&tmp->tm_dirent_pool, 0); | 269 | nde = tmpfs_dirent_get(tmp); | |
266 | if (nde == NULL) | 270 | if (nde == NULL) | |
267 | return ENOSPC; | 271 | return ENOSPC; | |
268 | 272 | |||
269 | nde->td_name = tmpfs_str_pool_get(&tmp->tm_str_pool, len, 0); | 273 | nde->td_name = tmpfs_strname_alloc(tmp, len); | |
270 | if (nde->td_name == NULL) { | 274 | if (nde->td_name == NULL) { | |
271 | TMPFS_POOL_PUT(&tmp->tm_dirent_pool, nde); | 275 | tmpfs_dirent_put(tmp, nde); | |
272 | return ENOSPC; | 276 | return ENOSPC; | |
273 | } | 277 | } | |
274 | nde->td_namelen = len; | 278 | nde->td_namelen = len; | |
275 | memcpy(nde->td_name, name, len); | 279 | memcpy(nde->td_name, name, len); | |
276 | nde->td_node = node; | 280 | nde->td_node = node; | |
277 | 281 | |||
278 | node->tn_links++; | 282 | node->tn_links++; | |
279 | if (node->tn_links > 1 && node->tn_vnode != NULL) | 283 | if (node->tn_links > 1 && node->tn_vnode != NULL) | |
280 | VN_KNOTE(node->tn_vnode, NOTE_LINK); | 284 | VN_KNOTE(node->tn_vnode, NOTE_LINK); | |
281 | *de = nde; | 285 | *de = nde; | |
282 | 286 | |||
283 | return 0; | 287 | return 0; | |
284 | } | 288 | } | |
@@ -307,28 +311,28 @@ tmpfs_free_dirent(struct tmpfs_mount *tm | @@ -307,28 +311,28 @@ tmpfs_free_dirent(struct tmpfs_mount *tm | |||
307 | 311 | |||
308 | node = de->td_node; | 312 | node = de->td_node; | |
309 | 313 | |||
310 | KASSERT(node->tn_links > 0); | 314 | KASSERT(node->tn_links > 0); | |
311 | node->tn_links--; | 315 | node->tn_links--; | |
312 | if (node->tn_vnode != NULL) | 316 | if (node->tn_vnode != NULL) | |
313 | VN_KNOTE(node->tn_vnode, node->tn_links == 0 ? | 317 | VN_KNOTE(node->tn_vnode, node->tn_links == 0 ? | |
314 | NOTE_DELETE : NOTE_LINK); | 318 | NOTE_DELETE : NOTE_LINK); | |
315 | if (node->tn_type == VDIR) | 319 | if (node->tn_type == VDIR) | |
316 | VN_KNOTE(node->tn_spec.tn_dir.tn_parent->tn_vnode, | 320 | VN_KNOTE(node->tn_spec.tn_dir.tn_parent->tn_vnode, | |
317 | NOTE_LINK); | 321 | NOTE_LINK); | |
318 | } | 322 | } | |
319 | 323 | |||
320 | tmpfs_str_pool_put(&tmp->tm_str_pool, de->td_name, de->td_namelen); | 324 | tmpfs_strname_free(tmp, de->td_name, de->td_namelen); | |
321 | TMPFS_POOL_PUT(&tmp->tm_dirent_pool, de); | 325 | tmpfs_dirent_put(tmp, de); | |
322 | } | 326 | } | |
323 | 327 | |||
324 | /* --------------------------------------------------------------------- */ | 328 | /* --------------------------------------------------------------------- */ | |
325 | 329 | |||
326 | /* | 330 | /* | |
327 | * Allocates a new vnode for the node node or returns a new reference to | 331 | * Allocates a new vnode for the node node or returns a new reference to | |
328 | * an existing one if the node had already a vnode referencing it. The | 332 | * an existing one if the node had already a vnode referencing it. The | |
329 | * resulting locked vnode is returned in *vpp. | 333 | * resulting locked vnode is returned in *vpp. | |
330 | * | 334 | * | |
331 | * Returns zero on success or an appropriate error code on failure. | 335 | * Returns zero on success or an appropriate error code on failure. | |
332 | */ | 336 | */ | |
333 | int | 337 | int | |
334 | tmpfs_alloc_vp(struct mount *mp, struct tmpfs_node *node, struct vnode **vpp) | 338 | tmpfs_alloc_vp(struct mount *mp, struct tmpfs_node *node, struct vnode **vpp) | |
@@ -845,128 +849,80 @@ tmpfs_dir_getdents(struct tmpfs_node *no | @@ -845,128 +849,80 @@ tmpfs_dir_getdents(struct tmpfs_node *no | |||
845 | * Resizes the aobj associated to the regular file pointed to by vp to | 849 | * Resizes the aobj associated to the regular file pointed to by vp to | |
846 | * the size newsize. 'vp' must point to a vnode that represents a regular | 850 | * the size newsize. 'vp' must point to a vnode that represents a regular | |
847 | * file. 'newsize' must be positive. | 851 | * file. 'newsize' must be positive. | |
848 | * | 852 | * | |
849 | * If the file is extended, the appropriate kevent is raised. This does | 853 | * If the file is extended, the appropriate kevent is raised. This does | |
850 | * not rise a write event though because resizing is not the same as | 854 | * not rise a write event though because resizing is not the same as | |
851 | * writing. | 855 | * writing. | |
852 | * | 856 | * | |
853 | * Returns zero on success or an appropriate error code on failure. | 857 | * Returns zero on success or an appropriate error code on failure. | |
854 | */ | 858 | */ | |
855 | int | 859 | int | |
856 | tmpfs_reg_resize(struct vnode *vp, off_t newsize) | 860 | tmpfs_reg_resize(struct vnode *vp, off_t newsize) | |
857 | { | 861 | { | |
858 | int error; | 862 | size_t newpages, oldpages; | |
859 | unsigned int newpages, oldpages; | |||
860 | struct tmpfs_mount *tmp; | 863 | struct tmpfs_mount *tmp; | |
861 | struct tmpfs_node *node; | 864 | struct tmpfs_node *node; | |
862 | off_t oldsize; | 865 | off_t oldsize; | |
863 | 866 | |||
864 | KASSERT(vp->v_type == VREG); | 867 | KASSERT(vp->v_type == VREG); | |
865 | KASSERT(newsize >= 0); | 868 | KASSERT(newsize >= 0); | |
866 | 869 | |||
867 | node = VP_TO_TMPFS_NODE(vp); | 870 | node = VP_TO_TMPFS_NODE(vp); | |
868 | tmp = VFS_TO_TMPFS(vp->v_mount); | 871 | tmp = VFS_TO_TMPFS(vp->v_mount); | |
869 | 872 | |||
870 | /* Convert the old and new sizes to the number of pages needed to | |||
871 | * store them. It may happen that we do not need to do anything | |||
872 | * because the last allocated page can accommodate the change on | |||
873 | * its own. */ | |||
874 | oldsize = node->tn_size; | 873 | oldsize = node->tn_size; | |
875 | oldpages = round_page(oldsize) / PAGE_SIZE; | 874 | oldpages = round_page(oldsize) >> PAGE_SHIFT; | |
875 | newpages = round_page(newsize) >> PAGE_SHIFT; | |||
876 | KASSERT(oldpages == node->tn_spec.tn_reg.tn_aobj_pages); | 876 | KASSERT(oldpages == node->tn_spec.tn_reg.tn_aobj_pages); | |
877 | newpages = round_page(newsize) / PAGE_SIZE; | |||
878 | 877 | |||
879 | if (newpages > oldpages && | 878 | if (newpages > oldpages) { | |
880 | (ssize_t)(newpages - oldpages) > TMPFS_PAGES_AVAIL(tmp)) { | 879 | /* Increase the used-memory counter if getting extra pages. */ | |
881 | error = ENOSPC; | 880 | if (!tmpfs_mem_incr(tmp, (newpages - oldpages) << PAGE_SHIFT)) { | |
882 | goto out; | 881 | return ENOSPC; | |
883 | } | 882 | } | |
884 | atomic_add_int(&tmp->tm_pages_used, newpages - oldpages); | 883 | } else if (newsize < oldsize) { | |
885 | ||||
886 | if (newsize < oldsize) { | |||
887 | int zerolen = MIN(round_page(newsize), node->tn_size) - newsize; | 884 | int zerolen = MIN(round_page(newsize), node->tn_size) - newsize; | |
888 | 885 | |||
889 | /* | 886 | /* Zero out the truncated part of the last page. */ | |
890 | * zero out the truncated part of the last page. | |||
891 | */ | |||
892 | ||||
893 | uvm_vnp_zerorange(vp, newsize, zerolen); | 887 | uvm_vnp_zerorange(vp, newsize, zerolen); | |
894 | } | 888 | } | |
895 | 889 | |||
896 | node->tn_spec.tn_reg.tn_aobj_pages = newpages; | 890 | node->tn_spec.tn_reg.tn_aobj_pages = newpages; | |
897 | node->tn_size = newsize; | 891 | node->tn_size = newsize; | |
898 | uvm_vnp_setsize(vp, newsize); | 892 | uvm_vnp_setsize(vp, newsize); | |
899 | 893 | |||
900 | /* | 894 | /* | |
901 | * free "backing store" | 895 | * Free "backing store". | |
902 | */ | 896 | */ | |
903 | ||||
904 | if (newpages < oldpages) { | 897 | if (newpages < oldpages) { | |
905 | struct uvm_object *uobj; | 898 | struct uvm_object *uobj; | |
906 | 899 | |||
907 | uobj = node->tn_spec.tn_reg.tn_aobj; | 900 | uobj = node->tn_spec.tn_reg.tn_aobj; | |
908 | 901 | |||
909 | mutex_enter(&uobj->vmobjlock); | 902 | mutex_enter(&uobj->vmobjlock); | |
910 | uao_dropswap_range(uobj, newpages, oldpages); | 903 | uao_dropswap_range(uobj, newpages, oldpages); | |
911 | mutex_exit(&uobj->vmobjlock); | 904 | mutex_exit(&uobj->vmobjlock); | |
912 | } | |||
913 | 905 | |||
914 | error = 0; | 906 | /* Decrease the used-memory counter. */ | |
907 | tmpfs_mem_decr(tmp, (oldpages - newpages) << PAGE_SHIFT); | |||
908 | } | |||
915 | 909 | |||
916 | if (newsize > oldsize) | 910 | if (newsize > oldsize) | |
917 | VN_KNOTE(vp, NOTE_EXTEND); | 911 | VN_KNOTE(vp, NOTE_EXTEND); | |
918 | 912 | |||
919 | out: | 913 | return 0; | |
920 | return error; | |||
921 | } | |||
922 | ||||
923 | /* --------------------------------------------------------------------- */ | |||
924 | ||||
925 | /* | |||
926 | * Returns information about the number of available memory pages, | |||
927 | * including physical and virtual ones. | |||
928 | * | |||
929 | * If 'total' is true, the value returned is the total amount of memory | |||
930 | * pages configured for the system (either in use or free). | |||
931 | * If it is FALSE, the value returned is the amount of free memory pages. | |||
932 | * | |||
933 | * Remember to remove TMPFS_PAGES_RESERVED from the returned value to avoid | |||
934 | * excessive memory usage. | |||
935 | * | |||
936 | */ | |||
937 | size_t | |||
938 | tmpfs_mem_info(bool total) | |||
939 | { | |||
940 | size_t size; | |||
941 | ||||
942 | size = 0; | |||
943 | size += uvmexp.swpgavail; | |||
944 | if (!total) { | |||
945 | size -= uvmexp.swpgonly; | |||
946 | } | |||
947 | size += uvmexp.free; | |||
948 | size += uvmexp.filepages; | |||
949 | if (size > uvmexp.wired) { | |||
950 | size -= uvmexp.wired; | |||
951 | } else { | |||
952 | size = 0; | |||
953 | } | |||
954 | ||||
955 | return size; | |||
956 | } | 914 | } | |
957 | 915 | |||
958 | /* --------------------------------------------------------------------- */ | |||
959 | ||||
960 | /* | 916 | /* | |
961 | * Change flags of the given vnode. | 917 | * Change flags of the given vnode. | |
962 | * Caller should execute tmpfs_update on vp after a successful execution. | 918 | * Caller should execute tmpfs_update on vp after a successful execution. | |
963 | * The vnode must be locked on entry and remain locked on exit. | 919 | * The vnode must be locked on entry and remain locked on exit. | |
964 | */ | 920 | */ | |
965 | int | 921 | int | |
966 | tmpfs_chflags(struct vnode *vp, int flags, kauth_cred_t cred, struct lwp *l) | 922 | tmpfs_chflags(struct vnode *vp, int flags, kauth_cred_t cred, struct lwp *l) | |
967 | { | 923 | { | |
968 | int error; | 924 | int error; | |
969 | struct tmpfs_node *node; | 925 | struct tmpfs_node *node; | |
970 | kauth_action_t action = KAUTH_VNODE_WRITE_FLAGS; | 926 | kauth_action_t action = KAUTH_VNODE_WRITE_FLAGS; | |
971 | int fs_decision = 0; | 927 | int fs_decision = 0; | |
972 | 928 |
--- src/sys/fs/tmpfs/tmpfs_vfsops.c 2008/07/29 09:10:09 1.44
+++ src/sys/fs/tmpfs/tmpfs_vfsops.c 2010/06/22 18:32:08 1.45
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: tmpfs_vfsops.c,v 1.44 2008/07/29 09:10:09 pooka Exp $ */ | 1 | /* $NetBSD: tmpfs_vfsops.c,v 1.45 2010/06/22 18:32:08 rmind Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Julio M. Merino Vidal, developed as part of Google's Summer of Code | 8 | * by Julio M. Merino Vidal, developed as part of Google's Summer of Code | |
9 | * 2005 program. | 9 | * 2005 program. | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
@@ -32,27 +32,27 @@ | @@ -32,27 +32,27 @@ | |||
32 | 32 | |||
33 | /* | 33 | /* | |
34 | * Efficient memory file system. | 34 | * Efficient memory file system. | |
35 | * | 35 | * | |
36 | * tmpfs is a file system that uses NetBSD's virtual memory sub-system | 36 | * tmpfs is a file system that uses NetBSD's virtual memory sub-system | |
37 | * (the well-known UVM) to store file data and metadata in an efficient | 37 | * (the well-known UVM) to store file data and metadata in an efficient | |
38 | * way. This means that it does not follow the structure of an on-disk | 38 | * way. This means that it does not follow the structure of an on-disk | |
39 | * file system because it simply does not need to. Instead, it uses | 39 | * file system because it simply does not need to. Instead, it uses | |
40 | * memory-specific data structures and algorithms to automatically | 40 | * memory-specific data structures and algorithms to automatically | |
41 | * allocate and release resources. | 41 | * allocate and release resources. | |
42 | */ | 42 | */ | |
43 | 43 | |||
44 | #include <sys/cdefs.h> | 44 | #include <sys/cdefs.h> | |
45 | __KERNEL_RCSID(0, "$NetBSD: tmpfs_vfsops.c,v 1.44 2008/07/29 09:10:09 pooka Exp $"); | 45 | __KERNEL_RCSID(0, "$NetBSD: tmpfs_vfsops.c,v 1.45 2010/06/22 18:32:08 rmind Exp $"); | |
46 | 46 | |||
47 | #include <sys/param.h> | 47 | #include <sys/param.h> | |
48 | #include <sys/types.h> | 48 | #include <sys/types.h> | |
49 | #include <sys/kmem.h> | 49 | #include <sys/kmem.h> | |
50 | #include <sys/mount.h> | 50 | #include <sys/mount.h> | |
51 | #include <sys/stat.h> | 51 | #include <sys/stat.h> | |
52 | #include <sys/systm.h> | 52 | #include <sys/systm.h> | |
53 | #include <sys/vnode.h> | 53 | #include <sys/vnode.h> | |
54 | #include <sys/proc.h> | 54 | #include <sys/proc.h> | |
55 | #include <sys/module.h> | 55 | #include <sys/module.h> | |
56 | 56 | |||
57 | #include <miscfs/genfs/genfs.h> | 57 | #include <miscfs/genfs/genfs.h> | |
58 | #include <fs/tmpfs/tmpfs.h> | 58 | #include <fs/tmpfs/tmpfs.h> | |
@@ -71,129 +71,116 @@ static int tmpfs_fhtovp(struct mount *, | @@ -71,129 +71,116 @@ static int tmpfs_fhtovp(struct mount *, | |||
71 | static int tmpfs_vptofh(struct vnode *, struct fid *, size_t *); | 71 | static int tmpfs_vptofh(struct vnode *, struct fid *, size_t *); | |
72 | static int tmpfs_statvfs(struct mount *, struct statvfs *); | 72 | static int tmpfs_statvfs(struct mount *, struct statvfs *); | |
73 | static int tmpfs_sync(struct mount *, int, kauth_cred_t); | 73 | static int tmpfs_sync(struct mount *, int, kauth_cred_t); | |
74 | static void tmpfs_init(void); | 74 | static void tmpfs_init(void); | |
75 | static void tmpfs_done(void); | 75 | static void tmpfs_done(void); | |
76 | static int tmpfs_snapshot(struct mount *, struct vnode *, | 76 | static int tmpfs_snapshot(struct mount *, struct vnode *, | |
77 | struct timespec *); | 77 | struct timespec *); | |
78 | 78 | |||
79 | /* --------------------------------------------------------------------- */ | 79 | /* --------------------------------------------------------------------- */ | |
80 | 80 | |||
81 | static int | 81 | static int | |
82 | tmpfs_mount(struct mount *mp, const char *path, void *data, size_t *data_len) | 82 | tmpfs_mount(struct mount *mp, const char *path, void *data, size_t *data_len) | |
83 | { | 83 | { | |
84 | struct lwp *l = curlwp; | |||
85 | int error; | |||
86 | ino_t nodes; | |||
87 | size_t pages; | |||
88 | struct tmpfs_mount *tmp; | 84 | struct tmpfs_mount *tmp; | |
89 | struct tmpfs_node *root; | 85 | struct tmpfs_node *root; | |
90 | struct tmpfs_args *args = data; | 86 | struct tmpfs_args *args = data; | |
87 | uint64_t memlimit; | |||
88 | ino_t nodes; | |||
89 | int error; | |||
91 | 90 | |||
92 | if (*data_len < sizeof *args) | 91 | if (*data_len < sizeof *args) | |
93 | return EINVAL; | 92 | return EINVAL; | |
94 | 93 | |||
95 | /* Handle retrieval of mount point arguments. */ | 94 | /* Handle retrieval of mount point arguments. */ | |
96 | if (mp->mnt_flag & MNT_GETARGS) { | 95 | if (mp->mnt_flag & MNT_GETARGS) { | |
97 | if (mp->mnt_data == NULL) | 96 | if (mp->mnt_data == NULL) | |
98 | return EIO; | 97 | return EIO; | |
99 | tmp = VFS_TO_TMPFS(mp); | 98 | tmp = VFS_TO_TMPFS(mp); | |
100 | 99 | |||
101 | args->ta_version = TMPFS_ARGS_VERSION; | 100 | args->ta_version = TMPFS_ARGS_VERSION; | |
102 | args->ta_nodes_max = tmp->tm_nodes_max; | 101 | args->ta_nodes_max = tmp->tm_nodes_max; | |
103 | args->ta_size_max = tmp->tm_pages_max * PAGE_SIZE; | 102 | args->ta_size_max = tmp->tm_mem_limit; | |
104 | 103 | |||
105 | root = tmp->tm_root; | 104 | root = tmp->tm_root; | |
106 | args->ta_root_uid = root->tn_uid; | 105 | args->ta_root_uid = root->tn_uid; | |
107 | args->ta_root_gid = root->tn_gid; | 106 | args->ta_root_gid = root->tn_gid; | |
108 | args->ta_root_mode = root->tn_mode; | 107 | args->ta_root_mode = root->tn_mode; | |
109 | 108 | |||
110 | *data_len = sizeof *args; | 109 | *data_len = sizeof(*args); | |
111 | return 0; | 110 | return 0; | |
112 | } | 111 | } | |
113 | 112 | |||
114 | if (mp->mnt_flag & MNT_UPDATE) { | 113 | if (mp->mnt_flag & MNT_UPDATE) { | |
115 | /* XXX: There is no support yet to update file system | 114 | /* XXX: There is no support yet to update file system | |
116 | * settings. Should be added. */ | 115 | * settings. Should be added. */ | |
117 | 116 | |||
118 | return EOPNOTSUPP; | 117 | return EOPNOTSUPP; | |
119 | } | 118 | } | |
120 | 119 | |||
121 | if (args->ta_version != TMPFS_ARGS_VERSION) | 120 | if (args->ta_version != TMPFS_ARGS_VERSION) | |
122 | return EINVAL; | 121 | return EINVAL; | |
123 | 122 | |||
124 | /* Do not allow mounts if we do not have enough memory to preserve | 123 | /* Do not allow mounts if we do not have enough memory to preserve | |
125 | * the minimum reserved pages. */ | 124 | * the minimum reserved pages. */ | |
126 | if (tmpfs_mem_info(true) < TMPFS_PAGES_RESERVED) | 125 | if (tmpfs_mem_info(true) < TMPFS_PAGES_RESERVED) | |
127 | return EINVAL; | 126 | return EINVAL; | |
128 | 127 | |||
129 | /* Get the maximum number of memory pages this file system is | 128 | /* Get the memory usage limit for this file-system. */ | |
130 | * allowed to use, based on the maximum size the user passed in | 129 | if (args->ta_size_max < PAGE_SIZE) { | |
131 | * the mount structure. A value of zero is treated as if the | 130 | memlimit = UINT64_MAX; | |
132 | * maximum available space was requested. */ | 131 | } else { | |
133 | if (args->ta_size_max < PAGE_SIZE || args->ta_size_max >= SIZE_MAX) | 132 | memlimit = args->ta_size_max; | |
134 | pages = SIZE_MAX; | 133 | } | |
135 | else | 134 | KASSERT(memlimit > 0); | |
136 | pages = args->ta_size_max / PAGE_SIZE + | 135 | ||
137 | (args->ta_size_max % PAGE_SIZE == 0 ? 0 : 1); | 136 | if (args->ta_nodes_max <= 3) { | |
138 | if (pages > INT_MAX) | 137 | nodes = 3 + (memlimit / 1024); | |
139 | pages = INT_MAX; | 138 | } else { | |
140 | KASSERT(pages > 0); | |||
141 | ||||
142 | if (args->ta_nodes_max <= 3) | |||
143 | nodes = 3 + pages * PAGE_SIZE / 1024; | |||
144 | else | |||
145 | nodes = args->ta_nodes_max; | 139 | nodes = args->ta_nodes_max; | |
146 | if (nodes > INT_MAX) | 140 | } | |
147 | nodes = INT_MAX; | 141 | nodes = MIN(nodes, INT_MAX); | |
148 | KASSERT(nodes >= 3); | 142 | KASSERT(nodes >= 3); | |
149 | 143 | |||
150 | /* Allocate the tmpfs mount structure and fill it. */ | 144 | /* Allocate the tmpfs mount structure and fill it. */ | |
151 | tmp = kmem_alloc(sizeof(struct tmpfs_mount), KM_SLEEP); | 145 | tmp = kmem_alloc(sizeof(struct tmpfs_mount), KM_SLEEP); | |
152 | if (tmp == NULL) | 146 | if (tmp == NULL) | |
153 | return ENOMEM; | 147 | return ENOMEM; | |
154 | 148 | |||
155 | tmp->tm_nodes_max = nodes; | 149 | tmp->tm_nodes_max = nodes; | |
156 | tmp->tm_nodes_cnt = 0; | 150 | tmp->tm_nodes_cnt = 0; | |
157 | LIST_INIT(&tmp->tm_nodes); | 151 | LIST_INIT(&tmp->tm_nodes); | |
158 | 152 | |||
159 | mutex_init(&tmp->tm_lock, MUTEX_DEFAULT, IPL_NONE); | 153 | mutex_init(&tmp->tm_lock, MUTEX_DEFAULT, IPL_NONE); | |
160 | 154 | tmpfs_mntmem_init(tmp, memlimit); | ||
161 | tmp->tm_pages_max = pages; | |||
162 | tmp->tm_pages_used = 0; | |||
163 | tmpfs_pool_init(&tmp->tm_dirent_pool, sizeof(struct tmpfs_dirent), | |||
164 | "dirent", tmp); | |||
165 | tmpfs_pool_init(&tmp->tm_node_pool, sizeof(struct tmpfs_node), | |||
166 | "node", tmp); | |||
167 | tmpfs_str_pool_init(&tmp->tm_str_pool, tmp); | |||
168 | 155 | |||
169 | /* Allocate the root node. */ | 156 | /* Allocate the root node. */ | |
170 | error = tmpfs_alloc_node(tmp, VDIR, args->ta_root_uid, | 157 | error = tmpfs_alloc_node(tmp, VDIR, args->ta_root_uid, | |
171 | args->ta_root_gid, args->ta_root_mode & ALLPERMS, NULL, NULL, | 158 | args->ta_root_gid, args->ta_root_mode & ALLPERMS, NULL, NULL, | |
172 | VNOVAL, &root); | 159 | VNOVAL, &root); | |
173 | KASSERT(error == 0 && root != NULL); | 160 | KASSERT(error == 0 && root != NULL); | |
174 | root->tn_links++; | 161 | root->tn_links++; | |
175 | tmp->tm_root = root; | 162 | tmp->tm_root = root; | |
176 | 163 | |||
177 | mp->mnt_data = tmp; | 164 | mp->mnt_data = tmp; | |
178 | mp->mnt_flag |= MNT_LOCAL; | 165 | mp->mnt_flag |= MNT_LOCAL; | |
179 | mp->mnt_stat.f_namemax = MAXNAMLEN; | 166 | mp->mnt_stat.f_namemax = MAXNAMLEN; | |
180 | mp->mnt_fs_bshift = PAGE_SHIFT; | 167 | mp->mnt_fs_bshift = PAGE_SHIFT; | |
181 | mp->mnt_dev_bshift = DEV_BSHIFT; | 168 | mp->mnt_dev_bshift = DEV_BSHIFT; | |
182 | mp->mnt_iflag |= IMNT_MPSAFE; | 169 | mp->mnt_iflag |= IMNT_MPSAFE; | |
183 | vfs_getnewfsid(mp); | 170 | vfs_getnewfsid(mp); | |
184 | 171 | |||
185 | return set_statvfs_info(path, UIO_USERSPACE, "tmpfs", UIO_SYSSPACE, | 172 | return set_statvfs_info(path, UIO_USERSPACE, "tmpfs", UIO_SYSSPACE, | |
186 | mp->mnt_op->vfs_name, mp, l); | 173 | mp->mnt_op->vfs_name, mp, curlwp); | |
187 | } | 174 | } | |
188 | 175 | |||
189 | /* --------------------------------------------------------------------- */ | 176 | /* --------------------------------------------------------------------- */ | |
190 | 177 | |||
191 | static int | 178 | static int | |
192 | tmpfs_start(struct mount *mp, int flags) | 179 | tmpfs_start(struct mount *mp, int flags) | |
193 | { | 180 | { | |
194 | 181 | |||
195 | return 0; | 182 | return 0; | |
196 | } | 183 | } | |
197 | 184 | |||
198 | /* --------------------------------------------------------------------- */ | 185 | /* --------------------------------------------------------------------- */ | |
199 | 186 | |||
@@ -235,33 +222,28 @@ tmpfs_unmount(struct mount *mp, int mntf | @@ -235,33 +222,28 @@ tmpfs_unmount(struct mount *mp, int mntf | |||
235 | 222 | |||
236 | nde = TAILQ_NEXT(de, td_entries); | 223 | nde = TAILQ_NEXT(de, td_entries); | |
237 | tmpfs_free_dirent(tmp, de, false); | 224 | tmpfs_free_dirent(tmp, de, false); | |
238 | de = nde; | 225 | de = nde; | |
239 | node->tn_size -= sizeof(struct tmpfs_dirent); | 226 | node->tn_size -= sizeof(struct tmpfs_dirent); | |
240 | } | 227 | } | |
241 | } | 228 | } | |
242 | 229 | |||
243 | next = LIST_NEXT(node, tn_entries); | 230 | next = LIST_NEXT(node, tn_entries); | |
244 | tmpfs_free_node(tmp, node); | 231 | tmpfs_free_node(tmp, node); | |
245 | node = next; | 232 | node = next; | |
246 | } | 233 | } | |
247 | 234 | |||
248 | tmpfs_pool_destroy(&tmp->tm_dirent_pool); | |||
249 | tmpfs_pool_destroy(&tmp->tm_node_pool); | |||
250 | tmpfs_str_pool_destroy(&tmp->tm_str_pool); | |||
251 | ||||
252 | KASSERT(tmp->tm_pages_used == 0); | |||
253 | ||||
254 | /* Throw away the tmpfs_mount structure. */ | 235 | /* Throw away the tmpfs_mount structure. */ | |
236 | tmpfs_mntmem_destroy(tmp); | |||
255 | mutex_destroy(&tmp->tm_lock); | 237 | mutex_destroy(&tmp->tm_lock); | |
256 | kmem_free(tmp, sizeof(*tmp)); | 238 | kmem_free(tmp, sizeof(*tmp)); | |
257 | mp->mnt_data = NULL; | 239 | mp->mnt_data = NULL; | |
258 | 240 | |||
259 | return 0; | 241 | return 0; | |
260 | } | 242 | } | |
261 | 243 | |||
262 | /* --------------------------------------------------------------------- */ | 244 | /* --------------------------------------------------------------------- */ | |
263 | 245 | |||
264 | static int | 246 | static int | |
265 | tmpfs_root(struct mount *mp, struct vnode **vpp) | 247 | tmpfs_root(struct mount *mp, struct vnode **vpp) | |
266 | { | 248 | { | |
267 | 249 | |||
@@ -330,43 +312,42 @@ tmpfs_vptofh(struct vnode *vp, struct fi | @@ -330,43 +312,42 @@ tmpfs_vptofh(struct vnode *vp, struct fi | |||
330 | node = VP_TO_TMPFS_NODE(vp); | 312 | node = VP_TO_TMPFS_NODE(vp); | |
331 | 313 | |||
332 | memset(&tfh, 0, sizeof(tfh)); | 314 | memset(&tfh, 0, sizeof(tfh)); | |
333 | tfh.tf_len = sizeof(struct tmpfs_fid); | 315 | tfh.tf_len = sizeof(struct tmpfs_fid); | |
334 | tfh.tf_gen = node->tn_gen; | 316 | tfh.tf_gen = node->tn_gen; | |
335 | tfh.tf_id = node->tn_id; | 317 | tfh.tf_id = node->tn_id; | |
336 | memcpy(fhp, &tfh, sizeof(tfh)); | 318 | memcpy(fhp, &tfh, sizeof(tfh)); | |
337 | 319 | |||
338 | return 0; | 320 | return 0; | |
339 | } | 321 | } | |
340 | 322 | |||
341 | /* --------------------------------------------------------------------- */ | 323 | /* --------------------------------------------------------------------- */ | |
342 | 324 | |||
343 | /* ARGSUSED2 */ | |||
344 | static int | 325 | static int | |
345 | tmpfs_statvfs(struct mount *mp, struct statvfs *sbp) | 326 | tmpfs_statvfs(struct mount *mp, struct statvfs *sbp) | |
346 | { | 327 | { | |
347 | fsfilcnt_t freenodes; | 328 | fsfilcnt_t freenodes; | |
348 | struct tmpfs_mount *tmp; | 329 | struct tmpfs_mount *tmp; | |
349 | 330 | |||
350 | tmp = VFS_TO_TMPFS(mp); | 331 | tmp = VFS_TO_TMPFS(mp); | |
351 | 332 | |||
352 | sbp->f_iosize = sbp->f_frsize = sbp->f_bsize = PAGE_SIZE; | 333 | sbp->f_iosize = sbp->f_frsize = sbp->f_bsize = PAGE_SIZE; | |
353 | 334 | |||
354 | sbp->f_blocks = TMPFS_PAGES_MAX(tmp); | 335 | sbp->f_blocks = (tmpfs_bytes_max(tmp) >> PAGE_SHIFT); | |
355 | sbp->f_bavail = sbp->f_bfree = TMPFS_PAGES_AVAIL(tmp); | 336 | sbp->f_bavail = sbp->f_bfree = tmpfs_pages_avail(tmp); | |
356 | sbp->f_bresvd = 0; | 337 | sbp->f_bresvd = 0; | |
357 | 338 | |||
358 | freenodes = MIN(tmp->tm_nodes_max - tmp->tm_nodes_cnt, | 339 | freenodes = MIN(tmp->tm_nodes_max - tmp->tm_nodes_cnt, | |
359 | TMPFS_PAGES_AVAIL(tmp) * PAGE_SIZE / sizeof(struct tmpfs_node)); | 340 | tmpfs_pages_avail(tmp) * PAGE_SIZE / sizeof(struct tmpfs_node)); | |
360 | 341 | |||
361 | sbp->f_files = tmp->tm_nodes_cnt + freenodes; | 342 | sbp->f_files = tmp->tm_nodes_cnt + freenodes; | |
362 | sbp->f_favail = sbp->f_ffree = freenodes; | 343 | sbp->f_favail = sbp->f_ffree = freenodes; | |
363 | sbp->f_fresvd = 0; | 344 | sbp->f_fresvd = 0; | |
364 | 345 | |||
365 | copy_statvfs_info(sbp, mp); | 346 | copy_statvfs_info(sbp, mp); | |
366 | 347 | |||
367 | return 0; | 348 | return 0; | |
368 | } | 349 | } | |
369 | 350 | |||
370 | /* --------------------------------------------------------------------- */ | 351 | /* --------------------------------------------------------------------- */ | |
371 | 352 | |||
372 | /* ARGSUSED0 */ | 353 | /* ARGSUSED0 */ |
--- src/sys/fs/tmpfs/tmpfs_vnops.c 2010/04/23 15:38:47 1.69
+++ src/sys/fs/tmpfs/tmpfs_vnops.c 2010/06/22 18:32:08 1.70
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: tmpfs_vnops.c,v 1.69 2010/04/23 15:38:47 pooka Exp $ */ | 1 | /* $NetBSD: tmpfs_vnops.c,v 1.70 2010/06/22 18:32:08 rmind Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Julio M. Merino Vidal, developed as part of Google's Summer of Code | 8 | * by Julio M. Merino Vidal, developed as part of Google's Summer of Code | |
9 | * 2005 program. | 9 | * 2005 program. | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
@@ -25,27 +25,27 @@ | @@ -25,27 +25,27 @@ | |||
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
30 | * POSSIBILITY OF SUCH DAMAGE. | 30 | * POSSIBILITY OF SUCH DAMAGE. | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | /* | 33 | /* | |
34 | * tmpfs vnode interface. | 34 | * tmpfs vnode interface. | |
35 | */ | 35 | */ | |
36 | 36 | |||
37 | #include <sys/cdefs.h> | 37 | #include <sys/cdefs.h> | |
38 | __KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.69 2010/04/23 15:38:47 pooka Exp $"); | 38 | __KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.70 2010/06/22 18:32:08 rmind Exp $"); | |
39 | 39 | |||
40 | #include <sys/param.h> | 40 | #include <sys/param.h> | |
41 | #include <sys/dirent.h> | 41 | #include <sys/dirent.h> | |
42 | #include <sys/fcntl.h> | 42 | #include <sys/fcntl.h> | |
43 | #include <sys/event.h> | 43 | #include <sys/event.h> | |
44 | #include <sys/malloc.h> | 44 | #include <sys/malloc.h> | |
45 | #include <sys/namei.h> | 45 | #include <sys/namei.h> | |
46 | #include <sys/proc.h> | 46 | #include <sys/proc.h> | |
47 | #include <sys/stat.h> | 47 | #include <sys/stat.h> | |
48 | #include <sys/uio.h> | 48 | #include <sys/uio.h> | |
49 | #include <sys/unistd.h> | 49 | #include <sys/unistd.h> | |
50 | #include <sys/vnode.h> | 50 | #include <sys/vnode.h> | |
51 | #include <sys/lockf.h> | 51 | #include <sys/lockf.h> | |
@@ -851,26 +851,36 @@ tmpfs_rename(void *v) | @@ -851,26 +851,36 @@ tmpfs_rename(void *v) | |||
851 | } | 851 | } | |
852 | 852 | |||
853 | fnode = VP_TO_TMPFS_NODE(fvp); | 853 | fnode = VP_TO_TMPFS_NODE(fvp); | |
854 | fdnode = VP_TO_TMPFS_DIR(fdvp); | 854 | fdnode = VP_TO_TMPFS_DIR(fdvp); | |
855 | tnode = (tvp == NULL) ? NULL : VP_TO_TMPFS_NODE(tvp); | 855 | tnode = (tvp == NULL) ? NULL : VP_TO_TMPFS_NODE(tvp); | |
856 | tdnode = VP_TO_TMPFS_DIR(tdvp); | 856 | tdnode = VP_TO_TMPFS_DIR(tdvp); | |
857 | tmp = VFS_TO_TMPFS(tdvp->v_mount); | 857 | tmp = VFS_TO_TMPFS(tdvp->v_mount); | |
858 | 858 | |||
859 | if (fdvp == tvp) { | 859 | if (fdvp == tvp) { | |
860 | error = 0; | 860 | error = 0; | |
861 | goto out_unlocked; | 861 | goto out_unlocked; | |
862 | } | 862 | } | |
863 | 863 | |||
864 | /* Allocate memory, if necessary, for a new name. */ | |||
865 | namelen = tcnp->cn_namelen; | |||
866 | if (tmpfs_strname_neqlen(fcnp, tcnp)) { | |||
867 | newname = tmpfs_strname_alloc(tmp, namelen); | |||
868 | if (newname == NULL) { | |||
869 | error = ENOSPC; | |||
870 | goto out_unlocked; | |||
871 | } | |||
872 | } | |||
873 | ||||
864 | /* If we need to move the directory between entries, lock the | 874 | /* If we need to move the directory between entries, lock the | |
865 | * source so that we can safely operate on it. */ | 875 | * source so that we can safely operate on it. */ | |
866 | 876 | |||
867 | /* XXX: this is a potential locking order violation! */ | 877 | /* XXX: this is a potential locking order violation! */ | |
868 | if (fdnode != tdnode) { | 878 | if (fdnode != tdnode) { | |
869 | vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY); | 879 | vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY); | |
870 | } | 880 | } | |
871 | 881 | |||
872 | /* | 882 | /* | |
873 | * If the node we were renaming has scarpered, just give up. | 883 | * If the node we were renaming has scarpered, just give up. | |
874 | */ | 884 | */ | |
875 | de = tmpfs_dir_lookup(fdnode, fcnp); | 885 | de = tmpfs_dir_lookup(fdnode, fcnp); | |
876 | if (de == NULL || de->td_node != fnode) { | 886 | if (de == NULL || de->td_node != fnode) { | |
@@ -900,38 +910,26 @@ tmpfs_rename(void *v) | @@ -900,38 +910,26 @@ tmpfs_rename(void *v) | |||
900 | } | 910 | } | |
901 | } else if (fnode->tn_type == VDIR && tnode->tn_type != VDIR) { | 911 | } else if (fnode->tn_type == VDIR && tnode->tn_type != VDIR) { | |
902 | error = ENOTDIR; | 912 | error = ENOTDIR; | |
903 | goto out; | 913 | goto out; | |
904 | } else if (fnode->tn_type != VDIR && tnode->tn_type == VDIR) { | 914 | } else if (fnode->tn_type != VDIR && tnode->tn_type == VDIR) { | |
905 | error = EISDIR; | 915 | error = EISDIR; | |
906 | goto out; | 916 | goto out; | |
907 | } else { | 917 | } else { | |
908 | KASSERT(fnode->tn_type != VDIR && | 918 | KASSERT(fnode->tn_type != VDIR && | |
909 | tnode->tn_type != VDIR); | 919 | tnode->tn_type != VDIR); | |
910 | } | 920 | } | |
911 | } | 921 | } | |
912 | 922 | |||
913 | /* Ensure that we have enough memory to hold the new name, if it | |||
914 | * has to be changed. */ | |||
915 | namelen = tcnp->cn_namelen; | |||
916 | if (fcnp->cn_namelen != tcnp->cn_namelen || | |||
917 | memcmp(fcnp->cn_nameptr, tcnp->cn_nameptr, fcnp->cn_namelen) != 0) { | |||
918 | newname = tmpfs_str_pool_get(&tmp->tm_str_pool, namelen, 0); | |||
919 | if (newname == NULL) { | |||
920 | error = ENOSPC; | |||
921 | goto out; | |||
922 | } | |||
923 | } | |||
924 | ||||
925 | /* If the node is being moved to another directory, we have to do | 923 | /* If the node is being moved to another directory, we have to do | |
926 | * the move. */ | 924 | * the move. */ | |
927 | if (fdnode != tdnode) { | 925 | if (fdnode != tdnode) { | |
928 | /* In case we are moving a directory, we have to adjust its | 926 | /* In case we are moving a directory, we have to adjust its | |
929 | * parent to point to the new parent. */ | 927 | * parent to point to the new parent. */ | |
930 | if (de->td_node->tn_type == VDIR) { | 928 | if (de->td_node->tn_type == VDIR) { | |
931 | struct tmpfs_node *n; | 929 | struct tmpfs_node *n; | |
932 | 930 | |||
933 | /* Ensure the target directory is not a child of the | 931 | /* Ensure the target directory is not a child of the | |
934 | * directory being moved. Otherwise, we'd end up | 932 | * directory being moved. Otherwise, we'd end up | |
935 | * with stale nodes. */ | 933 | * with stale nodes. */ | |
936 | n = tdnode; | 934 | n = tdnode; | |
937 | while (n != n->tn_spec.tn_dir.tn_parent) { | 935 | while (n != n->tn_spec.tn_dir.tn_parent) { | |
@@ -979,28 +977,27 @@ tmpfs_rename(void *v) | @@ -979,28 +977,27 @@ tmpfs_rename(void *v) | |||
979 | 977 | |||
980 | /* Free the directory entry we just deleted. Note that the | 978 | /* Free the directory entry we just deleted. Note that the | |
981 | * node referred by it will not be removed until the vnode is | 979 | * node referred by it will not be removed until the vnode is | |
982 | * really reclaimed. */ | 980 | * really reclaimed. */ | |
983 | tmpfs_free_dirent(VFS_TO_TMPFS(tvp->v_mount), de2, true); | 981 | tmpfs_free_dirent(VFS_TO_TMPFS(tvp->v_mount), de2, true); | |
984 | } | 982 | } | |
985 | 983 | |||
986 | /* If the name has changed, we need to make it effective by changing | 984 | /* If the name has changed, we need to make it effective by changing | |
987 | * it in the directory entry. */ | 985 | * it in the directory entry. */ | |
988 | if (newname != NULL) { | 986 | if (newname != NULL) { | |
989 | KASSERT(tcnp->cn_namelen < MAXNAMLEN); | 987 | KASSERT(tcnp->cn_namelen < MAXNAMLEN); | |
990 | KASSERT(tcnp->cn_namelen < 0xffff); | 988 | KASSERT(tcnp->cn_namelen < 0xffff); | |
991 | 989 | |||
992 | tmpfs_str_pool_put(&tmp->tm_str_pool, de->td_name, | 990 | tmpfs_strname_free(tmp, de->td_name, de->td_namelen); | |
993 | de->td_namelen); | |||
994 | de->td_namelen = (uint16_t)namelen; | 991 | de->td_namelen = (uint16_t)namelen; | |
995 | memcpy(newname, tcnp->cn_nameptr, namelen); | 992 | memcpy(newname, tcnp->cn_nameptr, namelen); | |
996 | de->td_name = newname; | 993 | de->td_name = newname; | |
997 | newname = NULL; | 994 | newname = NULL; | |
998 | 995 | |||
999 | fnode->tn_status |= TMPFS_NODE_CHANGED; | 996 | fnode->tn_status |= TMPFS_NODE_CHANGED; | |
1000 | tdnode->tn_status |= TMPFS_NODE_MODIFIED; | 997 | tdnode->tn_status |= TMPFS_NODE_MODIFIED; | |
1001 | } | 998 | } | |
1002 | out_ok: | 999 | out_ok: | |
1003 | /* Notify listeners of tdvp about the change in the directory (either | 1000 | /* Notify listeners of tdvp about the change in the directory (either | |
1004 | * because a new entry was added or because one was removed) and | 1001 | * because a new entry was added or because one was removed) and | |
1005 | * listeners of fvp about the rename. */ | 1002 | * listeners of fvp about the rename. */ | |
1006 | VN_KNOTE(tdvp, NOTE_WRITE); | 1003 | VN_KNOTE(tdvp, NOTE_WRITE); | |
@@ -1015,29 +1012,29 @@ tmpfs_rename(void *v) | @@ -1015,29 +1012,29 @@ tmpfs_rename(void *v) | |||
1015 | out_unlocked: | 1012 | out_unlocked: | |
1016 | /* Release target nodes. */ | 1013 | /* Release target nodes. */ | |
1017 | if (tdvp == tvp) | 1014 | if (tdvp == tvp) | |
1018 | vrele(tdvp); | 1015 | vrele(tdvp); | |
1019 | else | 1016 | else | |
1020 | vput(tdvp); | 1017 | vput(tdvp); | |
1021 | if (tvp != NULL) | 1018 | if (tvp != NULL) | |
1022 | vput(tvp); | 1019 | vput(tvp); | |
1023 | 1020 | |||
1024 | /* Release source nodes. */ | 1021 | /* Release source nodes. */ | |
1025 | vrele(fdvp); | 1022 | vrele(fdvp); | |
1026 | vrele(fvp); | 1023 | vrele(fvp); | |
1027 | 1024 | |||
1028 | if (newname != NULL) | 1025 | if (newname != NULL) { | |
1029 | tmpfs_str_pool_put(&tmp->tm_str_pool, newname, namelen); | 1026 | tmpfs_strname_free(tmp, newname, namelen); | |
1030 | 1027 | } | ||
1031 | return error; | 1028 | return error; | |
1032 | } | 1029 | } | |
1033 | 1030 | |||
1034 | /* --------------------------------------------------------------------- */ | 1031 | /* --------------------------------------------------------------------- */ | |
1035 | 1032 | |||
1036 | int | 1033 | int | |
1037 | tmpfs_mkdir(void *v) | 1034 | tmpfs_mkdir(void *v) | |
1038 | { | 1035 | { | |
1039 | struct vnode *dvp = ((struct vop_mkdir_args *)v)->a_dvp; | 1036 | struct vnode *dvp = ((struct vop_mkdir_args *)v)->a_dvp; | |
1040 | struct vnode **vpp = ((struct vop_mkdir_args *)v)->a_vpp; | 1037 | struct vnode **vpp = ((struct vop_mkdir_args *)v)->a_vpp; | |
1041 | struct componentname *cnp = ((struct vop_mkdir_args *)v)->a_cnp; | 1038 | struct componentname *cnp = ((struct vop_mkdir_args *)v)->a_cnp; | |
1042 | struct vattr *vap = ((struct vop_mkdir_args *)v)->a_vap; | 1039 | struct vattr *vap = ((struct vop_mkdir_args *)v)->a_vap; | |
1043 | 1040 |
--- src/sys/modules/tmpfs/Makefile 2008/06/28 16:11:36 1.1
+++ src/sys/modules/tmpfs/Makefile 2010/06/22 18:32:08 1.2
@@ -1,11 +1,11 @@ | @@ -1,11 +1,11 @@ | |||
1 | # $NetBSD: Makefile,v 1.1 2008/06/28 16:11:36 rumble Exp $ | 1 | # $NetBSD: Makefile,v 1.2 2010/06/22 18:32:08 rmind Exp $ | |
2 | 2 | |||
3 | .include "../Makefile.inc" | 3 | .include "../Makefile.inc" | |
4 | 4 | |||
5 | .PATH: ${S}/fs/tmpfs | 5 | .PATH: ${S}/fs/tmpfs | |
6 | 6 | |||
7 | KMOD= tmpfs | 7 | KMOD= tmpfs | |
8 | SRCS= tmpfs_fifoops.c tmpfs_pool.c tmpfs_specops.c tmpfs_subr.c \ | 8 | SRCS= tmpfs_fifoops.c tmpfs_mem.c tmpfs_specops.c tmpfs_subr.c \ | |
9 | tmpfs_vfsops.c tmpfs_vnops.c | 9 | tmpfs_vfsops.c tmpfs_vnops.c | |
10 | 10 | |||
11 | .include <bsd.kmodule.mk> | 11 | .include <bsd.kmodule.mk> |
--- src/sys/rump/fs/lib/libtmpfs/Makefile 2008/07/29 13:17:43 1.3
+++ src/sys/rump/fs/lib/libtmpfs/Makefile 2010/06/22 18:32:08 1.4
@@ -1,12 +1,12 @@ | @@ -1,12 +1,12 @@ | |||
1 | # $NetBSD: Makefile,v 1.3 2008/07/29 13:17:43 pooka Exp $ | 1 | # $NetBSD: Makefile,v 1.4 2010/06/22 18:32:08 rmind Exp $ | |
2 | # | 2 | # | |
3 | 3 | |||
4 | .PATH: ${.CURDIR}/../../../../fs/tmpfs | 4 | .PATH: ${.CURDIR}/../../../../fs/tmpfs | |
5 | 5 | |||
6 | LIB= rumpfs_tmpfs | 6 | LIB= rumpfs_tmpfs | |
7 | 7 | |||
8 | SRCS= tmpfs_fifoops.c tmpfs_specops.c tmpfs_vfsops.c tmpfs_pool.c \ | 8 | SRCS= tmpfs_fifoops.c tmpfs_specops.c tmpfs_vfsops.c tmpfs_mem.c \ | |
9 | tmpfs_subr.c tmpfs_vnops.c | 9 | tmpfs_subr.c tmpfs_vnops.c | |
10 | 10 | |||
11 | .include <bsd.lib.mk> | 11 | .include <bsd.lib.mk> | |
12 | .include <bsd.klinks.mk> | 12 | .include <bsd.klinks.mk> |