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)
This commit is contained in:
Xin LI 2007-06-25 18:46:13 +00:00
parent 16dbcac063
commit 7adb177693
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=171029
6 changed files with 106 additions and 122 deletions

View file

@ -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

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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

View file

@ -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;
}

View file

@ -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();