Thread: [Libsysio-commit] HEAD: libsysio/src chdir.c inode.c mount.c
Brought to you by:
lward
From: Lee W. <lw...@us...> - 2003-08-26 15:54:04
|
Update of /cvsroot/libsysio/libsysio/src In directory sc8-pr-cvs1:/tmp/cvs-serv10929/src Modified Files: chdir.c inode.c mount.c Log Message: Fixed the bug in get{c}wd where names of sub-mounts were ommitted from the returned string. Path alias nodes now have their parent pointing at the parent of the bottom-most, covered node. No need to look for mount-point crossing when ascending the tree. Index: chdir.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/src/chdir.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -w -b -B -p -r1.4 -r1.5 --- chdir.c 14 Aug 2003 18:39:33 -0000 1.4 +++ chdir.c 26 Aug 2003 15:53:59 -0000 1.5 @@ -98,62 +98,6 @@ chdir(const char *path) return 0; } -char * -getwd(char *buf) -{ - size_t len, n; - struct pnode *tmp; - char *cp; - - /* - * First pass: Traverse to the root of the sub-tree, remembering - * lengths. - */ - len = 0; - tmp = _sysio_cwd; - do { - n = tmp->p_base->pb_name.len; - len += tmp->p_base->pb_name.len; - if (n) - len++; - tmp = tmp->p_parent; - /* - * Traverse mount points. - */ - while (tmp->p_mount->mnt_root == tmp && - tmp != tmp->p_mount->mnt_covers) - tmp = tmp->p_mount->mnt_root; - } while (tmp != tmp->p_parent); - if (!len) - len++; - /* - * Fill in the path buffer -- Backwards, since we're starting - * from the end. - */ - cp = buf; - *cp = PATH_SEPARATOR; - cp += len; - *cp = '\0'; /* NUL term */ - tmp = _sysio_cwd; - do { - cp -= tmp->p_base->pb_name.len; - n = tmp->p_base->pb_name.len; - if (n) { - (void )strncpy(cp, tmp->p_base->pb_name.name, n); - *--cp = PATH_SEPARATOR; - } - tmp = tmp->p_parent; - /* - * Traverse mount points. - */ - while (tmp->p_mount->mnt_root == tmp && - tmp != tmp->p_mount->mnt_covers) - tmp = tmp->p_mount->mnt_root; - } while (tmp != tmp->p_parent); - - return buf; -} - /* * Return path tracked by the path ancestor chain. * @@ -178,12 +122,6 @@ _sysio_p_path(struct pnode *pno, char ** n = 0; do { /* - * Traverse back through mounts. - */ - while (pno->p_mount->mnt_root == pno && - pno != pno->p_mount->mnt_covers) - pno = pno->p_mount->mnt_root; - /* * Add length of this component to running sum and * account for this vertex. */ @@ -217,12 +155,6 @@ _sysio_p_path(struct pnode *pno, char ** *cp = '\0'; /* NUL terminate */ do { /* - * Traverse back through mounts. - */ - while (pno->p_mount->mnt_root == pno && - pno != pno->p_mount->mnt_covers) - pno = pno->p_mount->mnt_root; - /* * Add component and separator. */ cp -= pno->p_base->pb_name.len; @@ -257,3 +189,14 @@ __getcwd(char *buf, size_t size) } #endif +#ifdef PATH_MAX +char * +getwd(char *buf) +{ + + if (!buf) + return -EFAULT; + + return getcwd(buf, PATH_MAX); +} +#endif Index: inode.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/src/inode.c,v retrieving revision 1.8 retrieving revision 1.9 diff -u -w -b -B -p -r1.8 -r1.9 --- inode.c 25 Jul 2003 14:45:34 -0000 1.8 +++ inode.c 26 Aug 2003 15:53:59 -0000 1.9 @@ -497,43 +497,19 @@ _sysio_p_gone(struct pnode *pno) int _sysio_p_validate(struct pnode *pno, struct intent *intnt, const char *path) { - struct pnode *parent; - int err; struct inode *ino; + struct pnode_base *rootpb; + int err; - err = 0; - - /* - * Make sure we can use the parent. We don't validate that - * unless we have to. Beware of this! It's assuming the caller - * recently revalidated. Namei will do this for instance. - */ - parent = pno->p_parent; - if (!parent->p_base->pb_ino) { - err = _sysio_p_validate(parent, NULL, NULL); - if (err) { + ino = pno->p_base->pb_ino; /* - * I really, really want to smash the association - * of the passed path node with it's i-node. Can't - * do it, though, since at least one FS driver can - * still accomplish IO accesses to the currently - * held i-node. For now, the driver needs to - * record that the i-node has become (semi) invalid - * and return appropriate errors itself. - * - * We *might* be able to do this, now, with the - * recent changes to the open file table. Must check - * on it. It is so annoying to have these half - * dead i-nodes hanging around. + * An invalid pnode will not have an associated inode. We'll use + * the FS root inode, then -- It *must* be valid. */ - return err; - } - } - - ino = pno->p_base->pb_ino; - if (!err) + rootpb = pno->p_mount->mnt_root->p_base; + assert(rootpb->pb_ino); err = - parent->p_base->pb_ino->i_ops.inop_lookup(pno, + rootpb->pb_ino->i_ops.inop_lookup(pno, &ino, intnt, path); Index: mount.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/src/mount.c,v retrieving revision 1.6 retrieving revision 1.7 diff -u -w -b -B -p -r1.6 -r1.7 --- mount.c 26 Aug 2003 13:17:20 -0000 1.6 +++ mount.c 26 Aug 2003 15:53:59 -0000 1.7 @@ -106,8 +106,8 @@ _sysio_do_mount(struct filesys *fs, struct inode *ino; /* - * It's really poor form to allow the new root to be - * descendant of the pnode being covered.the one being covered. + * It's really poor form to allow the new root to be a + * descendant of the pnode being covered. */ if (tocover) { struct pnode_base *pb; @@ -142,7 +142,8 @@ _sysio_do_mount(struct filesys *fs, /* * Get alias for the new root. */ - mnt->mnt_root = _sysio_p_new_alias(NULL, rootpb, mnt); + mnt->mnt_root = + _sysio_p_new_alias(tocover ? tocover->p_parent : NULL, rootpb, mnt); if (!mnt->mnt_root) { err = -ENOMEM; goto error; |
From: Lee W. <lw...@us...> - 2007-09-21 19:41:41
|
Update of /cvsroot/libsysio/libsysio/src In directory sc8-pr-cvs6.sourceforge.net:/tmp/cvs-serv759/src Modified Files: chdir.c inode.c mount.c Log Message: The pnode base name cache is now maintained as a hashed table of trees, instead of lists. The pnode base record was re-organized. The qstr name record and parent were grouped under a pnodE_base_key sub-record and the new field named pb_key. As well, the LIST_ENTRY for pb_names was removed and a struct tree record added, reflecting the conversion to trees from lists in the hash table slots. + Fixed an issue in inode.c where the pnode base nodes were being reclaimed wholesale, instead of partially, on every call to the garbage collector. Index: chdir.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/src/chdir.c,v retrieving revision 1.30 retrieving revision 1.31 diff -u -w -b -B -p -r1.30 -r1.31 --- chdir.c 2 Jul 2007 18:58:15 -0000 1.30 +++ chdir.c 21 Sep 2007 19:41:37 -0000 1.31 @@ -183,10 +183,10 @@ _sysio_p_path(struct pnode *pno, char ** * Add length of this component to running sum and * account for this vertex. */ - assert((len >= pno->p_base->pb_name.len && - (size_t )~0 - pno->p_base->pb_name.len > len) || - (size_t )~0 - len > pno->p_base->pb_name.len); - len += pno->p_base->pb_name.len; + assert((len >= pno->p_base->pb_key.pbk_name.len && + (size_t )~0 - pno->p_base->pb_key.pbk_name.len > len) || + (size_t )~0 - len > pno->p_base->pb_key.pbk_name.len); + len += pno->p_base->pb_key.pbk_name.len; n++; assert(n); pno = pno->p_parent; @@ -226,9 +226,9 @@ _sysio_p_path(struct pnode *pno, char ** /* * Add component and separator. */ - cp -= pno->p_base->pb_name.len; - (void )memcpy(cp, pno->p_base->pb_name.name, - pno->p_base->pb_name.len); + cp -= pno->p_base->pb_key.pbk_name.len; + (void )memcpy(cp, pno->p_base->pb_key.pbk_name.name, + pno->p_base->pb_key.pbk_name.len); *--cp = PATH_SEPARATOR; pno = pno->p_parent; Index: inode.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/src/inode.c,v retrieving revision 1.28 retrieving revision 1.29 diff -u -w -b -B -p -r1.28 -r1.29 --- inode.c 28 Aug 2007 17:41:56 -0000 1.28 +++ inode.c 21 Sep 2007 19:41:37 -0000 1.29 @@ -41,6 +41,9 @@ * le...@sa... */ +#include <stdio.h> + +#include <stddef.h> #include <stdlib.h> #include <string.h> #include <errno.h> @@ -55,6 +58,8 @@ #include "inode.h" #include "dev.h" +/* #define I_STATS */ + /* * Support for path and index nodes. */ @@ -67,25 +72,16 @@ #endif /* - * Desired i-nodes cache size is MAX_INODES_MULTIPLIER times the number - * of slots in the names hash table. - */ -#define MAX_INODES_MULTIPLIER 3 - -/* * Active i-nodes in the system and the number of same. */ struct inodes_head _sysio_inodes; static size_t n_inodes = 0; -/* - * Desired number of active i-nodes. - */ -static size_t max_inodes = (MAX_INODES_MULTIPLIER * NAMES_TABLE_LEN); /* * System table for rapid access to component names. */ -static LIST_HEAD(, pnode_base) names[NAMES_TABLE_LEN]; +static struct tree_node *names[NAMES_TABLE_LEN]; + /* * Number of names tracked by the system. */ @@ -93,7 +89,8 @@ static size_t n_names = 0; /* * Desired number of base path nodes to maintain. */ -static size_t max_names = (2 * NAMES_TABLE_LEN); +static size_t desired_names = (3 * NAMES_TABLE_LEN); +static size_t max_names; /* * List of all path-nodes (aliases) referenced by any tree. @@ -105,6 +102,12 @@ struct pnodes_head _sysio_pnodes; */ struct pnode *_sysio_root = NULL; +#ifdef I_STATS +static unsigned long i_probes, i_hits; +static unsigned long pb_probes, pb_hits; +static unsigned long p_reclaims, p_examined, p_dismissed; +#endif + /* * Initialize path and i-node support. Must be called before any other * routine in this module. @@ -117,16 +120,23 @@ _sysio_i_init() TAILQ_INIT(&_sysio_inodes); for (i = 0; i < NAMES_TABLE_LEN; i++) - LIST_INIT(&names[i]); + names[i] = NULL; TAILQ_INIT(&_sysio_pnodes); + max_names = desired_names; + +#ifdef I_STATS + i_probes = i_hits = 0; + pb_probes = pb_hits = 0; + p_reclaims = p_examined = p_dismissed = 0; +#endif + return 0; } /* - * Garbage-collect idle i-nodes. We try to keep resource use limited to - * MAX_INODES_MULTIPLIER * max_names. + * Garbage-collect idle i-nodes. */ static void i_reclaim() @@ -134,35 +144,17 @@ i_reclaim() struct inode *next, *ino; size_t t; - /* - * I just can't figure out a good way to reclaim these well without - * getting really fancy and using complex algorithms. The - * base nodes hold references on them for a long time and then - * release them. Those will age to the front of the queue and - * we have to skip over them. Oh well... - */ - t = MAX_INODES_MULTIPLIER * max_names; - if (max_inodes < t) { - /* - * Oops. Nope. We want more inodes than names entries. - */ - max_inodes = t; - return; - } + t = n_inodes / 2; next = _sysio_inodes.tqh_first; - if (!next) - return; - t = max_inodes / 2; - do { + while (next) { ino = next; next = ino->i_nodes.tqe_next; if (ino->i_ref || ino->i_immune) continue; _sysio_i_gone(ino); - } while (next && n_inodes > t); - - if (n_inodes > t) - max_inodes += t; + if (n_inodes < t) + break; + } } static unsigned @@ -200,9 +192,11 @@ _sysio_i_new(struct filesys *fs, struct itable_entry *head; struct inode_ops operations; - if (n_inodes > max_inodes) { + if (n_inodes > n_names) { /* - * Try to limit growth. + * This has become pretty badly skewed relative to + * the number of active nodes in the system. Try to + * correct that, now. */ i_reclaim(); } @@ -264,9 +258,15 @@ _sysio_i_find(struct filesys *fs, struct fid->fid_data, fid->fid_len) == 0) { I_REF(ino); +#ifdef I_STATS + i_hits++; +#endif break; } +#ifdef I_STATS + i_probes++; +#endif return ino; } @@ -303,31 +303,111 @@ _sysio_i_undead(struct inode *ino) } /* + * Destroy path node and, if path base node is no longer referenced that + * node as well. + */ +static void +_sysio_p_kill(struct pnode *pno) +{ + struct pnode_base *pb; + + pb = pno->p_base; + _sysio_p_gone(pno); + if (!(pb->pb_aliases.lh_first || pb->pb_children.lh_first)) + _sysio_pb_gone(pb); +} + +/* * Garbage collect idle path (and base path) nodes tracked by the system. */ static void -p_reclaim() +p_reclaim(unsigned count) { + int adjust; struct pnode *next, *pno; size_t t; + struct pnode_base *nxtpb, *pb; + + adjust = 0; + if (count) + adjust = 1; +#ifdef I_STATS + p_reclaims++; +#endif next = _sysio_pnodes.tqh_first; if (!next) return; - t = max_names / 2; + t = n_names / 2; do { +#ifdef I_STATS + p_examined++; +#endif pno = next; next = pno->p_nodes.tqe_next; if (pno->p_ref) continue; - next->p_ref++; - assert(next->p_ref); - (void )_sysio_p_prune(pno); - next->p_ref--; - } while (n_names > t && next); + if (pno->p_mount->mnt_root == pno) { + /* + * We never reclaim mount points, here. + */ + continue; + } + nxtpb = pno->p_base; +#ifdef I_STATS + p_dismissed++; +#endif + _sysio_p_gone(pno); + /* + * Have to run up the tree, too. We might + * have removed the last child from the parent + * as well. + */ + while ((pb = nxtpb)) { + nxtpb = NULL; + if (!(pb->pb_aliases.lh_first || + pb->pb_children.lh_first)) { + nxtpb = pb->pb_key.pbk_parent; + _sysio_pb_gone(pb); + } + } + } while ((!count || --count) && n_names > t && next); + + if (!adjust) + return; if (n_names > t) max_names += t; + else { + max_names = t; + if (max_names < desired_names) + max_names = desired_names; + } +} + +static int +compar_pb_key(const struct pnode_base_key *pbk1, + const struct pnode_base_key *pbk2) +{ + + if (pbk1->pbk_parent < pbk2->pbk_parent) + return -1; + if (pbk1->pbk_parent > pbk2->pbk_parent) + return 1; + + if (pbk1->pbk_name.len < pbk2->pbk_name.len) + return -1; + if (pbk1->pbk_name.len > pbk2->pbk_name.len) + return 1; + + if (pbk1->pbk_name.hashval < pbk2->pbk_name.hashval) + return -1; + if (pbk1->pbk_name.hashval > pbk2->pbk_name.hashval) + return 1; + + return strncmp(pbk1->pbk_name.name, + pbk2->pbk_name.name, + pbk1->pbk_name.len); } /* @@ -342,18 +422,20 @@ _sysio_pb_new(struct qstr *name, struct /* * Try to limit growth. */ - p_reclaim(); + p_reclaim(0); } pb = malloc(sizeof(struct pnode_base) + name->len); if (!pb) return NULL; - pb->pb_name.name = NULL; - pb->pb_name.len = name->len; - if (pb->pb_name.len) { + pb->pb_key.pbk_name = *name; + pb->pb_key.pbk_parent = parent; + if (pb->pb_key.pbk_name.len) { char *cp; + pb->pb_tentry.tn_key = &pb->pb_key; + pb->pb_tentry.tn_left = pb->pb_tentry.tn_right = NULL; /* * Copy the passed name. * @@ -362,11 +444,15 @@ _sysio_pb_new(struct qstr *name, struct */ cp = (char *)pb + sizeof(struct pnode_base); (void )strncpy(cp, name->name, name->len); - pb->pb_name.name = cp; - pb->pb_name.hashval = name->hashval; - LIST_INSERT_HEAD(&names[name->hashval % NAMES_TABLE_LEN], - pb, - pb_names); + pb->pb_key.pbk_name.name = cp; + pb->pb_key.pbk_name.hashval = name->hashval; + if (_sysio_tree_search(&pb->pb_tentry, + &names[pb->pb_key.pbk_name.hashval % + NAMES_TABLE_LEN], + (int (*)(const void *, + const void *))compar_pb_key) != + &pb->pb_tentry) + abort(); } pb->pb_ino = ino; @@ -374,7 +460,6 @@ _sysio_pb_new(struct qstr *name, struct LIST_INIT(&pb->pb_aliases); if (parent) LIST_INSERT_HEAD(&parent->pb_children, pb, pb_sibs); - pb->pb_parent = parent; n_names++; assert(n_names); @@ -390,6 +475,7 @@ _sysio_pb_new(struct qstr *name, struct static void pb_destroy(struct pnode_base *pb) { + struct tree_node *tn; assert(n_names); n_names--; @@ -397,9 +483,17 @@ pb_destroy(struct pnode_base *pb) assert(!pb->pb_aliases.lh_first); assert(!pb->pb_children.lh_first); assert(!pb->pb_ino); - if (pb->pb_name.len) - LIST_REMOVE(pb, pb_names); - if (pb->pb_parent) + if (pb->pb_key.pbk_name.len) { + tn = + _sysio_tree_delete(&pb->pb_key, + &names[pb->pb_key.pbk_name.hashval % + NAMES_TABLE_LEN], + (int (*)(const void *, + const void *))compar_pb_key); + if (TREE_ENTRY(tn, pnode_base, pb_tentry) != pb) + abort(); + } + if (pb->pb_key.pbk_parent) LIST_REMOVE(pb, pb_sibs); free(pb); @@ -412,8 +506,11 @@ void _sysio_pb_gone(struct pnode_base *pb) { - if (pb->pb_ino) + if (pb->pb_ino) { I_RELE(pb->pb_ino); + if (!pb->pb_ino->i_ref) + _sysio_i_gone(pb->pb_ino); + } pb->pb_ino = NULL; pb_destroy(pb); @@ -426,6 +523,7 @@ static void _sysio_pb_disconnect(struct pnode_base *pb) { struct pnode *pno; + struct tree_node *tn; /* * Disconnect all aliases associated with the referenced base node. @@ -438,9 +536,17 @@ _sysio_pb_disconnect(struct pnode_base * * Remove name from the names cache so that it can't * be found anymore. */ - if (pb->pb_name.len) - LIST_REMOVE(pb, pb_names); - pb->pb_name.len = 0; + if (pb->pb_key.pbk_name.len) { + tn = + _sysio_tree_delete(&pb->pb_tentry, + &names[pb->pb_key.pbk_name.hashval % + NAMES_TABLE_LEN], + (int (*)(const void *, + const void *))compar_pb_key); + if (TREE_ENTRY(tn, pnode_base, pb_tentry) != pb) + abort(); + } + pb->pb_key.pbk_name.len = 0; } #ifdef ZERO_SUM_MEMORY @@ -451,6 +557,8 @@ void _sysio_i_shutdown() { + max_names = desired_names; + return; } #endif @@ -541,6 +649,8 @@ _sysio_p_find_alias(struct pnode *parent struct pnode **pnop) { struct pnode_base *pb; + struct pnode_base_key key; + struct tree_node *tn; int err; struct pnode *pno; @@ -555,15 +665,22 @@ _sysio_p_find_alias(struct pnode *parent /* * Try the names table. */ - pb = names[name->hashval % NAMES_TABLE_LEN].lh_first; - while (pb) { - if (pb->pb_parent == parent->p_base && - pb->pb_name.len == name->len && - strncmp(pb->pb_name.name, - name->name, - name->len) == 0) - break; - pb = pb->pb_names.le_next; +#ifdef I_STATS + pb_probes++; +#endif + key.pbk_name = *name; + key.pbk_parent = parent->p_base; + tn = + _sysio_tree_find(&key, + &names[key.pbk_name.hashval % + NAMES_TABLE_LEN], + (int (*)(const void *, + const void *))compar_pb_key); + if (tn) { + pb = TREE_ENTRY(tn, pnode_base, pb_tentry); +#ifdef I_STATS + pb_hits++; +#endif } } if (!pb) { @@ -683,7 +800,7 @@ _sysio_p_prune(struct pnode *root) #else /* * This is an automount-point. Must - * unmount before relcaim. + * unmount before reclaim. */ P_REF(pno); if (_sysio_do_unmount(pno->p_mount) != 0) { @@ -693,10 +810,7 @@ _sysio_p_prune(struct pnode *root) continue; #endif } - _sysio_p_gone(pno); - if (!(pb->pb_aliases.lh_first || - pb->pb_children.lh_first)) - _sysio_pb_gone(pb); + _sysio_p_kill(pno); } } @@ -728,13 +842,8 @@ _sysio_p_prune(struct pnode *root) count++; } #endif - } else { - pb = root->p_base; - _sysio_p_gone(root); - if (!(pb->pb_aliases.lh_first || - pb->pb_children.lh_first)) - _sysio_pb_gone(pb); - } + } else + _sysio_p_kill(root); return count; } @@ -761,13 +870,13 @@ _sysio_pb_pathof(struct pnode_base *pb, len = 0; tmp = pb; do { - n = tmp->pb_name.len; - len += tmp->pb_name.len; + n = tmp->pb_key.pbk_name.len; + len += tmp->pb_key.pbk_name.len; if (n) len++; - tmp = tmp->pb_parent; + tmp = tmp->pb_key.pbk_parent; } while (tmp); - if (tmp && !tmp->pb_name.len) + if (tmp && !tmp->pb_key.pbk_name.len) return -ENOENT; if (!len) len++; @@ -787,13 +896,13 @@ _sysio_pb_pathof(struct pnode_base *pb, *cp = '\0'; /* NUL term */ tmp = pb; do { - cp -= tmp->pb_name.len; - n = tmp->pb_name.len; + cp -= tmp->pb_key.pbk_name.len; + n = tmp->pb_key.pbk_name.len; if (n) { - (void )strncpy(cp, tmp->pb_name.name, n); + (void )strncpy(cp, tmp->pb_key.pbk_name.name, n); *--cp = separator; } - tmp = tmp->pb_parent; + tmp = tmp->pb_key.pbk_parent; } while (tmp); *pathp = buf; @@ -931,7 +1040,7 @@ _sysio_p_rename(struct pnode *old, struc nxtpb = new->p_base; do { pb = nxtpb; - nxtpb = pb->pb_parent; + nxtpb = pb->pb_key.pbk_parent; if (pb == old->p_base) return -EINVAL; } while (nxtpb); Index: mount.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/src/mount.c,v retrieving revision 1.24 retrieving revision 1.25 diff -u -w -b -B -p -r1.24 -r1.25 --- mount.c 2 Jul 2007 18:58:17 -0000 1.24 +++ mount.c 21 Sep 2007 19:41:37 -0000 1.25 @@ -131,7 +131,7 @@ _sysio_do_mount(struct filesys *fs, for (pb = rootpb; pb && pb != tocover->p_base; - pb = pb->pb_parent) + pb = pb->pb_key.pbk_parent) ; if (pb == tocover->p_base) return -EBUSY; |