summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJoel Sing <jsing@cvs.openbsd.org>2013-01-18 05:09:22 +0000
committerJoel Sing <jsing@cvs.openbsd.org>2013-01-18 05:09:22 +0000
commitfd9fe78e14c556c9623d71c9b952fa97b4b279c5 (patch)
tree7caebae67c45eab6a0fd20c8a1a80e89060ef910 /sys
parent6fc066f972e18a57fae0e5376f520e34678b363f (diff)
Constrain the amount of kernel memory used by NTFS. Keep a small cache of
loaded ntnodes and once the maximum is reached, unload the least recently used ntnode before loading a new one. This avoids leaving large data structures hanging around, which only get cleaned up when the vnode is reclaimed. Additionally, the buffer cache should contain the data needed to reload the ntnode. ok beck@
Diffstat (limited to 'sys')
-rw-r--r--sys/ntfs/ntfs.h13
-rw-r--r--sys/ntfs/ntfs_inode.h5
-rw-r--r--sys/ntfs/ntfs_subr.c56
-rw-r--r--sys/ntfs/ntfs_vfsops.c3
4 files changed, 63 insertions, 14 deletions
diff --git a/sys/ntfs/ntfs.h b/sys/ntfs/ntfs.h
index 8220e750d39..4a9f60b50fa 100644
--- a/sys/ntfs/ntfs.h
+++ b/sys/ntfs/ntfs.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ntfs.h,v 1.12 2010/12/21 20:14:43 thib Exp $ */
+/* $OpenBSD: ntfs.h,v 1.13 2013/01/18 05:09:21 jsing Exp $ */
/* $NetBSD: ntfs.h,v 1.5 2003/04/24 07:50:19 christos Exp $ */
/*-
@@ -240,6 +240,15 @@ typedef wchar (ntfs_wget_func_t)(const char **);
typedef int (ntfs_wput_func_t)(char *, size_t, wchar);
typedef int (ntfs_wcmp_func_t)(wchar, wchar);
+/*
+ * Maximum number of ntnodes to keep in memory. We do not want to leave
+ * large data structures hanging off vnodes indefinitely and the data
+ * needed to reload the ntnode should already be in the buffer cache.
+ */
+#define LOADED_NTNODE_HI 16
+struct ntnode;
+TAILQ_HEAD(ntnodeq, ntnode);
+
#define NTFS_SYSNODESNUM 0x0B
struct ntfsmount {
struct mount *ntm_mountp; /* filesystem vfs structure */
@@ -259,6 +268,8 @@ struct ntfsmount {
ntfs_wget_func_t *ntm_wget; /* decode string to Unicode string */
ntfs_wput_func_t *ntm_wput; /* encode Unicode string to string */
ntfs_wcmp_func_t *ntm_wcmp; /* compare to wide characters */
+ int ntm_ntnodes; /* Number of loaded ntnodes. */
+ struct ntnodeq ntm_ntnodeq; /* Queue of ntnodes (LRU). */
};
#define ntm_mftcn ntm_bootfile.bf_mftcn
diff --git a/sys/ntfs/ntfs_inode.h b/sys/ntfs/ntfs_inode.h
index 282303ba36a..7e255985e7a 100644
--- a/sys/ntfs/ntfs_inode.h
+++ b/sys/ntfs/ntfs_inode.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ntfs_inode.h,v 1.5 2009/08/13 16:00:53 jasper Exp $ */
+/* $OpenBSD: ntfs_inode.h,v 1.6 2013/01/18 05:09:21 jsing Exp $ */
/* $NetBSD: ntfs_inode.h,v 1.1 2002/12/23 17:38:33 jdolecek Exp $ */
/*-
@@ -38,8 +38,11 @@ struct ntnode {
dev_t i_dev; /* Device associated with the inode. */
LIST_ENTRY(ntnode) i_hash;
+ TAILQ_ENTRY(ntnode) i_loaded;
+
struct ntnode *i_next;
struct ntnode **i_prev;
+
struct ntfsmount *i_mp;
ino_t i_number;
u_int32_t i_flag;
diff --git a/sys/ntfs/ntfs_subr.c b/sys/ntfs/ntfs_subr.c
index 4a862470dc4..c214d3a6814 100644
--- a/sys/ntfs/ntfs_subr.c
+++ b/sys/ntfs/ntfs_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ntfs_subr.c,v 1.29 2013/01/14 02:41:03 jsing Exp $ */
+/* $OpenBSD: ntfs_subr.c,v 1.30 2013/01/18 05:09:21 jsing Exp $ */
/* $NetBSD: ntfs_subr.c,v 1.4 2003/04/10 21:37:32 jdolecek Exp $ */
/*-
@@ -115,6 +115,10 @@ ntfs_findvattr(struct ntfsmount *ntmp, struct ntnode *ip,
ip->i_number);
return (error);
}
+ } else {
+ /* Update LRU loaded list. */
+ TAILQ_REMOVE(&ntmp->ntm_ntnodeq, ip, i_loaded);
+ TAILQ_INSERT_HEAD(&ntmp->ntm_ntnodeq, ip, i_loaded);
}
*lvapp = NULL;
@@ -253,16 +257,35 @@ out:
int
ntfs_loadntnode(struct ntfsmount *ntmp, struct ntnode *ip)
{
- struct filerec *mfrp;
- daddr64_t bn;
- int error,off;
- struct attr *ap;
- struct ntvattr *nvap;
+ struct ntnode *oip;
+ struct ntvattr *vap;
+ struct filerec *mfrp;
+ struct attr *ap;
+ daddr64_t bn;
+ int error,off;
+
+ dprintf(("ntfs_loadntnode: loading ino: %d\n",ip->i_number));
+
+ KASSERT((ip->i_flag & IN_LOADED) == 0);
- dprintf(("ntfs_loadntnode: loading ino: %d\n",ip->i_number));
+ if (ntmp->ntm_ntnodes >= LOADED_NTNODE_HI) {
+ oip = TAILQ_LAST(&ntmp->ntm_ntnodeq, ntnodeq);
+ TAILQ_REMOVE(&ntmp->ntm_ntnodeq, oip, i_loaded);
+ ntmp->ntm_ntnodes--;
- mfrp = malloc(ntfs_bntob(ntmp->ntm_bpmftrec), M_TEMP, M_WAITOK);
+ dprintf(("ntfs_loadntnode: unloading ino: %d\n",
+ oip->i_number));
+
+ KASSERT((oip->i_flag & IN_LOADED));
+ oip->i_flag &= ~IN_LOADED;
+ while ((vap = LIST_FIRST(&oip->i_valist)) != NULL) {
+ LIST_REMOVE(vap, va_list);
+ ntfs_freentvattr(vap);
+ }
+ }
+ mfrp = malloc(ntfs_bntob(ntmp->ntm_bpmftrec), M_TEMP, M_WAITOK);
+
if (ip->i_number < NTFS_SYSNODESNUM) {
struct buf *bp;
@@ -309,12 +332,12 @@ ntfs_loadntnode(struct ntfsmount *ntmp, struct ntnode *ip)
LIST_INIT(&ip->i_valist);
while (ap->a_hdr.a_type != -1) {
- error = ntfs_attrtontvattr(ntmp, &nvap, ap);
+ error = ntfs_attrtontvattr(ntmp, &vap, ap);
if (error)
break;
- nvap->va_ip = ip;
+ vap->va_ip = ip;
- LIST_INSERT_HEAD(&ip->i_valist, nvap, va_list);
+ LIST_INSERT_HEAD(&ip->i_valist, vap, va_list);
off += ap->a_hdr.reclen;
ap = (struct attr *) ((caddr_t)mfrp + off);
@@ -331,6 +354,10 @@ ntfs_loadntnode(struct ntfsmount *ntmp, struct ntnode *ip)
ip->i_flag |= IN_LOADED;
+ /* Add to loaded list. */
+ TAILQ_INSERT_HEAD(&ntmp->ntm_ntnodeq, ip, i_loaded);
+ ntmp->ntm_ntnodes++;
+
out:
free(mfrp, M_TEMP);
return (error);
@@ -415,6 +442,7 @@ ntfs_ntlookup(struct ntfsmount *ntmp, ino_t ino, struct ntnode **ipp,
void
ntfs_ntput(struct ntnode *ip, struct proc *p)
{
+ struct ntfsmount *ntmp = ip->i_mp;
struct ntvattr *vap;
dprintf(("ntfs_ntput: rele ntnode %d: %p, usecount: %d\n",
@@ -441,6 +469,12 @@ ntfs_ntput(struct ntnode *ip, struct proc *p)
ntfs_nthashrem(ip);
+ /* Remove from loaded list. */
+ if (ip->i_flag & IN_LOADED) {
+ TAILQ_REMOVE(&ntmp->ntm_ntnodeq, ip, i_loaded);
+ ntmp->ntm_ntnodes--;
+ }
+
while ((vap = LIST_FIRST(&ip->i_valist)) != NULL) {
LIST_REMOVE(vap, va_list);
ntfs_freentvattr(vap);
diff --git a/sys/ntfs/ntfs_vfsops.c b/sys/ntfs/ntfs_vfsops.c
index 44cb3952c0e..fd08a45c480 100644
--- a/sys/ntfs/ntfs_vfsops.c
+++ b/sys/ntfs/ntfs_vfsops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ntfs_vfsops.c,v 1.32 2013/01/14 02:41:03 jsing Exp $ */
+/* $OpenBSD: ntfs_vfsops.c,v 1.33 2013/01/18 05:09:21 jsing Exp $ */
/* $NetBSD: ntfs_vfsops.c,v 1.7 2003/04/24 07:50:19 christos Exp $ */
/*-
@@ -343,6 +343,7 @@ ntfs_mountfs(struct vnode *devvp, struct mount *mp, struct ntfs_args *argsp,
ntmp->ntm_mode = argsp->mode;
ntmp->ntm_flag = argsp->flag;
mp->mnt_data = (qaddr_t) ntmp;
+ TAILQ_INIT(&ntmp->ntm_ntnodeq);
/* set file name encode/decode hooks XXX utf-8 only for now */
ntmp->ntm_wget = ntfs_utf8_wget;