diff options
author | delphij <delphij@FreeBSD.org> | 2007-06-25 18:46:13 +0000 |
---|---|---|
committer | delphij <delphij@FreeBSD.org> | 2007-06-25 18:46:13 +0000 |
commit | a78e2646a20f6b90a2414784899e11a72320701a (patch) | |
tree | d75982c3b0bd235189ed127edaf20c9ab228f399 /sys | |
parent | a79676fb6d4640f4add118efa52a7ddb92c08245 (diff) | |
download | FreeBSD-src-a78e2646a20f6b90a2414784899e11a72320701a.zip FreeBSD-src-a78e2646a20f6b90a2414784899e11a72320701a.tar.gz |
MFp4: Several clean-ups and improvements over tmpfs:
- Remove tmpfs_zone_xxx KPI, the uma(9) wrapper, since
they does not bring any value now.
- Use |= instead of = when applying VV_ROOT flag.
- Remove tm_avariable_nodes list. Use uma to hold the
released nodes.
- init/destory interlock mutex of node when init/fini
instead of ctor/dtor.
- Change memory computing using u_int to fix negative
value in 2G mem machine.
- Remove unnecessary bzero's
- Rely uma logic to make file id allocation harder to
guess.
- Fix some unsigned/signed related things. Make sure
we respect -o size=xxxx
- Use wire instead of hold a page.
- Pass allocate_zero to obtain zeroed pages upon first
use.
Submitted by: Howard Su
Approved by: re (tmpfs blanket, kensmith)
Diffstat (limited to 'sys')
-rw-r--r-- | sys/fs/tmpfs/tmpfs.h | 13 | ||||
-rw-r--r-- | sys/fs/tmpfs/tmpfs_subr.c | 65 | ||||
-rw-r--r-- | sys/fs/tmpfs/tmpfs_uma.c | 24 | ||||
-rw-r--r-- | sys/fs/tmpfs/tmpfs_uma.h | 22 | ||||
-rw-r--r-- | sys/fs/tmpfs/tmpfs_vfsops.c | 93 | ||||
-rw-r--r-- | sys/fs/tmpfs/tmpfs_vnops.c | 11 |
6 files changed, 106 insertions, 122 deletions
diff --git a/sys/fs/tmpfs/tmpfs.h b/sys/fs/tmpfs/tmpfs.h index 2947b9b..61999e1 100644 --- a/sys/fs/tmpfs/tmpfs.h +++ b/sys/fs/tmpfs/tmpfs.h @@ -314,7 +314,6 @@ struct tmpfs_mount { * they will go into the available list, remaining alive until the * file system is unmounted. */ struct tmpfs_node_list tm_nodes_used; - struct tmpfs_node_list tm_nodes_avail; /* All node lock to protect the node list and tmp_pages_used */ struct mtx allnode_lock; @@ -470,10 +469,14 @@ TMPFS_PAGES_MAX(struct tmpfs_mount *tmp) } /* Returns the available space for the given file system. */ -#define TMPFS_META_SIZE(tmp) ((tmp)->tm_nodes_inuse * (sizeof(struct tmpfs_node) \ - + sizeof(struct dirent))) -#define TMPFS_PAGES_AVAIL(tmp) (TMPFS_PAGES_MAX(tmp) - (tmp)->tm_pages_used - \ - TMPFS_META_SIZE(tmp) / PAGE_SIZE - 1) +#define TMPFS_META_PAGES(tmp) ((tmp)->tm_nodes_inuse * (sizeof(struct tmpfs_node) \ + + sizeof(struct tmpfs_dirent))/PAGE_SIZE + 1) +#define TMPFS_FILE_PAGES(tmp) ((tmp)->tm_pages_used) + +#define TMPFS_PAGES_AVAIL(tmp) (TMPFS_PAGES_MAX(tmp) > \ + TMPFS_META_PAGES(tmp)+TMPFS_FILE_PAGES(tmp)? \ + TMPFS_PAGES_MAX(tmp) - TMPFS_META_PAGES(tmp) \ + - TMPFS_FILE_PAGES(tmp):0) #endif diff --git a/sys/fs/tmpfs/tmpfs_subr.c b/sys/fs/tmpfs/tmpfs_subr.c index a45febb..739747b 100644 --- a/sys/fs/tmpfs/tmpfs_subr.c +++ b/sys/fs/tmpfs/tmpfs_subr.c @@ -100,47 +100,23 @@ tmpfs_alloc_node(struct tmpfs_mount *tmp, enum vtype type, MPASS(IFF(type == VLNK, target != NULL)); MPASS(IFF(type == VBLK || type == VCHR, rdev != VNOVAL)); - nnode = NULL; + if (tmp->tm_nodes_inuse > tmp->tm_nodes_max) + return (ENOSPC); - TMPFS_LOCK(tmp); - if (LIST_EMPTY(&tmp->tm_nodes_avail)) { - MPASS(tmp->tm_nodes_last <= tmp->tm_nodes_max); - if (tmp->tm_nodes_last == tmp->tm_nodes_max) { - TMPFS_UNLOCK(tmp); - return ENOSPC; - } - TMPFS_UNLOCK(tmp); - nnode = (struct tmpfs_node *)tmpfs_zone_alloc( - tmp->tm_node_pool, M_WAITOK); - if (nnode == NULL) - return ENOSPC; - nnode->tn_id = tmp->tm_nodes_last++; - nnode->tn_gen = arc4random(); - } else { - nnode = LIST_FIRST(&tmp->tm_nodes_avail); - LIST_REMOVE(nnode, tn_entries); - TMPFS_UNLOCK(tmp); - nnode->tn_gen++; - } - MPASS(nnode != NULL); + nnode = (struct tmpfs_node *)uma_zalloc_arg( + tmp->tm_node_pool, tmp, M_WAITOK); + if (nnode == NULL) + return (ENOSPC); /* Generic initialization. */ nnode->tn_type = type; - nnode->tn_size = 0; - nnode->tn_status = 0; - nnode->tn_flags = 0; - nnode->tn_links = 0; nanotime(&nnode->tn_atime); nnode->tn_birthtime = nnode->tn_ctime = nnode->tn_mtime = nnode->tn_atime; nnode->tn_uid = uid; nnode->tn_gid = gid; nnode->tn_mode = mode; - nnode->tn_lockf = NULL; - nnode->tn_vnode = NULL; - nnode->tn_vpstate = 0; - mtx_init(&nnode->tn_interlock, "tmpfs node interlock", NULL, MTX_DEF); /* Type-specific initialization. */ switch (nnode->tn_type) { case VBLK: @@ -169,7 +145,7 @@ tmpfs_alloc_node(struct tmpfs_mount *tmp, enum vtype type, M_WAITOK, nnode->tn_size); if (nnode->tn_link == NULL) { nnode->tn_type = VNON; - tmpfs_free_node(tmp, nnode); + uma_zfree(tmp->tm_node_pool, nnode); return ENOSPC; } memcpy(nnode->tn_link, target, nnode->tn_size); @@ -216,9 +192,7 @@ tmpfs_alloc_node(struct tmpfs_mount *tmp, enum vtype type, void tmpfs_free_node(struct tmpfs_mount *tmp, struct tmpfs_node *node) { - ino_t id; - unsigned long gen; - size_t pages; + size_t pages = 0; TMPFS_LOCK(tmp); LIST_REMOVE(node, tn_entries); @@ -240,38 +214,28 @@ tmpfs_free_node(struct tmpfs_mount *tmp, struct tmpfs_node *node) case VFIFO: /* FALLTHROUGH */ case VSOCK: - pages = 0; break; case VLNK: tmpfs_str_zone_free(&tmp->tm_str_pool, node->tn_link, node->tn_size); - pages = 0; break; case VREG: if (node->tn_reg.tn_aobj != NULL) { vm_object_deallocate(node->tn_reg.tn_aobj); - node->tn_reg.tn_aobj = 0; } pages = node->tn_reg.tn_aobj_pages; break; default: MPASS(0); - pages = 0; /* Shut up gcc when !DIAGNOSTIC. */ break; } - id = node->tn_id; - gen = node->tn_gen; - memset(node, 0, sizeof(struct tmpfs_node)); - node->tn_id = id; - node->tn_type = VNON; - node->tn_gen = gen; + uma_zfree(tmp->tm_node_pool, node); TMPFS_LOCK(tmp); - LIST_INSERT_HEAD(&tmp->tm_nodes_avail, node, tn_entries); tmp->tm_pages_used -= pages; TMPFS_UNLOCK(tmp); } @@ -293,14 +257,14 @@ tmpfs_alloc_dirent(struct tmpfs_mount *tmp, struct tmpfs_node *node, { struct tmpfs_dirent *nde; - nde = (struct tmpfs_dirent *)tmpfs_zone_alloc( + nde = (struct tmpfs_dirent *)uma_zalloc( tmp->tm_dirent_pool, M_WAITOK); if (nde == NULL) return ENOSPC; nde->td_name = tmpfs_str_zone_alloc(&tmp->tm_str_pool, M_WAITOK, len); if (nde->td_name == NULL) { - tmpfs_zone_free(tmp->tm_dirent_pool, nde); + uma_zfree(tmp->tm_dirent_pool, nde); return ENOSPC; } nde->td_namelen = len; @@ -339,7 +303,7 @@ tmpfs_free_dirent(struct tmpfs_mount *tmp, struct tmpfs_dirent *de, } tmpfs_str_zone_free(&tmp->tm_str_pool, de->td_name, de->td_namelen); - tmpfs_zone_free(tmp->tm_dirent_pool, de); + uma_zfree(tmp->tm_dirent_pool, de); } /* --------------------------------------------------------------------- */ @@ -576,7 +540,6 @@ tmpfs_dir_attach(struct vnode *vp, struct tmpfs_dirent *de) dnode->tn_size += sizeof(struct tmpfs_dirent); dnode->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED | \ TMPFS_NODE_MODIFIED; - vnode_pager_setsize(vp, dnode->tn_size); } /* --------------------------------------------------------------------- */ @@ -602,8 +565,6 @@ tmpfs_dir_detach(struct vnode *vp, struct tmpfs_dirent *de) dnode->tn_size -= sizeof(struct tmpfs_dirent); dnode->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED | \ TMPFS_NODE_MODIFIED; - - vnode_pager_setsize(vp, dnode->tn_size); } /* --------------------------------------------------------------------- */ @@ -905,7 +866,7 @@ tmpfs_reg_resize(struct vnode *vp, off_t newsize) node->tn_size = newsize; vnode_pager_setsize(vp, newsize); if (newsize < oldsize) { - int zerolen = MIN(round_page(newsize), node->tn_size) - newsize; + size_t zerolen = MIN(round_page(newsize), node->tn_size) - newsize; struct vm_object *uobj = node->tn_reg.tn_aobj; vm_page_t m; diff --git a/sys/fs/tmpfs/tmpfs_uma.c b/sys/fs/tmpfs/tmpfs_uma.c index 73066e1..6f9e4db 100644 --- a/sys/fs/tmpfs/tmpfs_uma.c +++ b/sys/fs/tmpfs/tmpfs_uma.c @@ -32,29 +32,17 @@ __FBSDID("$FreeBSD$"); #include <fs/tmpfs/tmpfs.h> -uma_zone_t -tmpfs_zone_create(char *name, int size, int align, struct tmpfs_mount *tmp) -{ - uma_zone_t z; - z = uma_zcreate(name, size, NULL, NULL, NULL, NULL, align, M_WAITOK); - return z; -} - -void -tmpfs_zone_destroy(uma_zone_t zone) -{ - uma_zdestroy(zone); -} - void -tmpfs_str_zone_create(struct tmpfs_str_zone *tsz, struct tmpfs_mount *tmp) +tmpfs_str_zone_create(struct tmpfs_str_zone *tsz) { int i, len; len = TMPFS_STRZONE_STARTLEN; for (i = 0; i < TMPFS_STRZONE_ZONECOUNT; ++i) { - tsz->tsz_zone[i] = tmpfs_zone_create( - "TMPFS str", len, UMA_ALIGN_PTR, tmp); + tsz->tsz_zone[i] = uma_zcreate( + "TMPFS str", len, + NULL, NULL, NULL, NULL, + UMA_ALIGN_PTR, 0); len <<= 1; } } @@ -66,7 +54,7 @@ tmpfs_str_zone_destroy(struct tmpfs_str_zone *tsz) len = TMPFS_STRZONE_STARTLEN; for (i = 0; i < TMPFS_STRZONE_ZONECOUNT; ++i) { - tmpfs_zone_destroy(tsz->tsz_zone[i]); + uma_zdestroy(tsz->tsz_zone[i]); len <<= 1; } } diff --git a/sys/fs/tmpfs/tmpfs_uma.h b/sys/fs/tmpfs/tmpfs_uma.h index a402a4f..ceaf2ab 100644 --- a/sys/fs/tmpfs/tmpfs_uma.h +++ b/sys/fs/tmpfs/tmpfs_uma.h @@ -44,26 +44,14 @@ uma_zone_t tmpfs_zone_create(char *name, int size, int align, struct tmpfs_mount *m); void tmpfs_zone_destroy(uma_zone_t zone); -static __inline void* -tmpfs_zone_alloc(uma_zone_t zone, int flags) -{ - return uma_zalloc(zone, flags); -} - -static __inline void -tmpfs_zone_free(uma_zone_t zone, void *item) -{ - uma_zfree(zone, item); -} - -void tmpfs_str_zone_create(struct tmpfs_str_zone *, struct tmpfs_mount *); +void tmpfs_str_zone_create(struct tmpfs_str_zone *); void tmpfs_str_zone_destroy(struct tmpfs_str_zone *); static __inline char* tmpfs_str_zone_alloc(struct tmpfs_str_zone *tsz, int flags, size_t len) { - int i, zlen; + size_t i, zlen; char *ptr; MPASS(len <= (TMPFS_STRZONE_STARTLEN << (TMPFS_STRZONE_ZONECOUNT-1))); @@ -74,14 +62,14 @@ tmpfs_str_zone_alloc(struct tmpfs_str_zone *tsz, int flags, size_t len) ++i; zlen <<= 1; } - ptr = (char *)tmpfs_zone_alloc(tsz->tsz_zone[i], flags); + ptr = (char *)uma_zalloc(tsz->tsz_zone[i], flags); return ptr; } static __inline void tmpfs_str_zone_free(struct tmpfs_str_zone *tsz, char *item, size_t len) { - int i, zlen; + size_t i, zlen; MPASS(len <= (TMPFS_STRZONE_STARTLEN << (TMPFS_STRZONE_ZONECOUNT-1))); @@ -91,7 +79,7 @@ tmpfs_str_zone_free(struct tmpfs_str_zone *tsz, char *item, size_t len) ++i; zlen <<= 1; } - tmpfs_zone_free(tsz->tsz_zone[i], item); + uma_zfree(tsz->tsz_zone[i], item); } #endif diff --git a/sys/fs/tmpfs/tmpfs_vfsops.c b/sys/fs/tmpfs/tmpfs_vfsops.c index e5d3d6e..fe8f455 100644 --- a/sys/fs/tmpfs/tmpfs_vfsops.c +++ b/sys/fs/tmpfs/tmpfs_vfsops.c @@ -91,13 +91,13 @@ static const char *tmpfs_opts[] = { #define SWI_MAXMIB 3 -static int +static u_int get_swpgtotal(void) { struct xswdev xsd; char *sname = "vm.swap_info"; int soid[SWI_MAXMIB], oid[2]; - int unswdev, total, dmmax, nswapdev; + u_int unswdev, total, dmmax, nswapdev; size_t mibi, len; total = 0; @@ -139,6 +139,60 @@ get_swpgtotal(void) } /* --------------------------------------------------------------------- */ +static int +tmpfs_node_ctor(void *mem, int size, void *arg, int flags) +{ + struct tmpfs_node *node = (struct tmpfs_node *)mem; + + if (node->tn_id == 0) { + /* if this node structure first time used */ + struct tmpfs_mount *tmp = (struct tmpfs_mount *)arg; + TMPFS_LOCK(tmp); + node->tn_id = tmp->tm_nodes_last++; + TMPFS_UNLOCK(tmp); + node->tn_gen = arc4random(); + } + else { + node->tn_gen++; + } + + node->tn_size = 0; + node->tn_status = 0; + node->tn_flags = 0; + node->tn_links = 0; + node->tn_lockf = NULL; + node->tn_vnode = NULL; + node->tn_vpstate = 0; + node->tn_lookup_dirent = NULL; + + return (0); +} + +static void +tmpfs_node_dtor(void *mem, int size, void *arg) +{ + struct tmpfs_node *node = (struct tmpfs_node *)mem; + node->tn_type = VNON; +} + +static int +tmpfs_node_init(void *mem, int size, int flags) +{ + struct tmpfs_node *node = (struct tmpfs_node *)mem; + node->tn_id = 0; + + mtx_init(&node->tn_interlock, "tmpfs node interlock", NULL, MTX_DEF); + + return (0); +} + +static void +tmpfs_node_fini(void *mem, int size) +{ + struct tmpfs_node *node = (struct tmpfs_node *)mem; + + mtx_destroy(&node->tn_interlock); +} static int tmpfs_mount(struct mount *mp, struct thread *l) @@ -208,21 +262,23 @@ tmpfs_mount(struct mount *mp, struct thread *l) tmp->tm_nodes_inuse = 0; tmp->tm_maxfilesize = get_swpgtotal() * PAGE_SIZE; LIST_INIT(&tmp->tm_nodes_used); - LIST_INIT(&tmp->tm_nodes_avail); - + tmp->tm_pages_max = pages; tmp->tm_pages_used = 0; - tmp->tm_dirent_pool = tmpfs_zone_create( + tmp->tm_dirent_pool = uma_zcreate( "TMPFS dirent", sizeof(struct tmpfs_dirent), + NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, - tmp); - tmp->tm_node_pool = tmpfs_zone_create( + 0); + tmp->tm_node_pool = uma_zcreate( "TMPFS node", sizeof(struct tmpfs_node), + tmpfs_node_ctor, tmpfs_node_dtor, + tmpfs_node_init, tmpfs_node_fini, UMA_ALIGN_PTR, - tmp); - tmpfs_str_zone_create(&tmp->tm_str_pool, tmp); + 0); + tmpfs_str_zone_create(&tmp->tm_str_pool); /* Allocate the root node. */ error = tmpfs_alloc_node(tmp, VDIR, args.ta_root_uid, @@ -231,8 +287,8 @@ tmpfs_mount(struct mount *mp, struct thread *l) if (error != 0 || root == NULL) { tmpfs_str_zone_destroy(&tmp->tm_str_pool); - tmpfs_zone_destroy(tmp->tm_node_pool); - tmpfs_zone_destroy(tmp->tm_dirent_pool); + uma_zdestroy(tmp->tm_node_pool); + uma_zdestroy(tmp->tm_dirent_pool); free(tmp, M_TMPFSMNT); return error; } @@ -300,18 +356,9 @@ tmpfs_unmount(struct mount *mp, int mntflags, struct thread *l) tmpfs_free_node(tmp, node); node = next; } - node = LIST_FIRST(&tmp->tm_nodes_avail); - while (node != NULL) { - struct tmpfs_node *next; - - next = LIST_NEXT(node, tn_entries); - LIST_REMOVE(node, tn_entries); - tmpfs_zone_free(tmp->tm_node_pool, node); - node = next; - } - tmpfs_zone_destroy(tmp->tm_dirent_pool); - tmpfs_zone_destroy(tmp->tm_node_pool); + uma_zdestroy(tmp->tm_dirent_pool); + uma_zdestroy(tmp->tm_node_pool); tmpfs_str_zone_destroy(&tmp->tm_str_pool); mtx_destroy(&tmp->allnode_lock); @@ -336,7 +383,7 @@ tmpfs_root(struct mount *mp, int flags, struct vnode **vpp, struct thread *td) error = tmpfs_alloc_vp(mp, VFS_TO_TMPFS(mp)->tm_root, vpp, td); if (!error) - (*vpp)->v_vflag = VV_ROOT; + (*vpp)->v_vflag |= VV_ROOT; return error; } diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c index d7aea01..3527261 100644 --- a/sys/fs/tmpfs/tmpfs_vnops.c +++ b/sys/fs/tmpfs/tmpfs_vnops.c @@ -501,13 +501,10 @@ tmpfs_uio_xfer(struct tmpfs_mount *tmp, struct tmpfs_node *node, idx = OFF_TO_IDX(uio->uio_offset); d = uio->uio_offset - IDX_TO_OFF(idx); len = MIN(len, (PAGE_SIZE - d)); - m = vm_page_grab(uobj, idx, VM_ALLOC_NORMAL | VM_ALLOC_RETRY); + m = vm_page_grab(uobj, idx, VM_ALLOC_WIRED | VM_ALLOC_ZERO | + VM_ALLOC_NORMAL | VM_ALLOC_RETRY); if (uio->uio_rw == UIO_READ && m->valid != VM_PAGE_BITS_ALL) - if (vm_pager_get_pages(uobj, &m, 1, 0) != VM_PAGER_OK) - vm_page_zero_invalid(m, TRUE); - vm_page_lock_queues(); - vm_page_hold(m); - vm_page_unlock_queues(); + vm_page_zero_invalid(m, TRUE); VM_OBJECT_UNLOCK(uobj); sched_pin(); sf = sf_buf_alloc(m, SFB_CPUPRIVATE); @@ -521,7 +518,7 @@ tmpfs_uio_xfer(struct tmpfs_mount *tmp, struct tmpfs_node *node, vm_page_zero_invalid(m, TRUE); vm_page_dirty(m); } - vm_page_unhold(m); + vm_page_unwire(m, 0); vm_page_activate(m); vm_page_wakeup(m); vm_page_unlock_queues(); |