summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2007-06-25 18:46:13 +0000
committerdelphij <delphij@FreeBSD.org>2007-06-25 18:46:13 +0000
commita78e2646a20f6b90a2414784899e11a72320701a (patch)
treed75982c3b0bd235189ed127edaf20c9ab228f399 /sys
parenta79676fb6d4640f4add118efa52a7ddb92c08245 (diff)
downloadFreeBSD-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.h13
-rw-r--r--sys/fs/tmpfs/tmpfs_subr.c65
-rw-r--r--sys/fs/tmpfs/tmpfs_uma.c24
-rw-r--r--sys/fs/tmpfs/tmpfs_uma.h22
-rw-r--r--sys/fs/tmpfs/tmpfs_vfsops.c93
-rw-r--r--sys/fs/tmpfs/tmpfs_vnops.c11
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();
OpenPOWER on IntegriCloud