[Libsysio-commit] HEAD: libsysio/src inode.c
Brought to you by:
lward
From: Lee W. <lw...@us...> - 2008-04-23 00:24:53
|
Update of /cvsroot/libsysio/libsysio/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11947/src Modified Files: inode.c Log Message: Lots of changes to try to eliminate the potential for dangling references. Notable changes in the way the pnode graphs are maintained; 1) Now, mnt->mnt_root->p_parent == mnt->mnt_root->p_parent 2) An automount now causes mnt->mnt_root to be referenced, meaning automounts have to be unmounted by hand, currently -- Will fix that. 3) Disconnects do not make pno->p_parent NULL any longer as we must maintain the chain to the root. 4) One must not blindly release a pnode, please. They should only be removed from the leaves, up. Index: inode.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/src/inode.c,v retrieving revision 1.40 retrieving revision 1.41 diff -u -w -b -B -p -r1.40 -r1.41 --- inode.c 15 Apr 2008 16:26:19 -0000 1.40 +++ inode.c 23 Apr 2008 00:24:50 -0000 1.41 @@ -332,21 +332,6 @@ _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 @@ -355,7 +340,7 @@ p_reclaim(unsigned count) int adjust; struct pnode *next, *pno; size_t t; - struct pnode_base *nxtpb, *pb; + struct pnode_base *pb; adjust = 0; if (count) @@ -378,22 +363,19 @@ p_reclaim(unsigned count) */ continue; } - nxtpb = pno->p_base; - INO_CST_UPDCNT(pdismissed); - _sysio_p_gone(pno); + if (pno->p_base->pb_children.lh_first) { /* - * Have to run up the tree, too. We might - * have removed the last child from the parent - * as well. + * Must not dismiss from interior nodes. There + * might be aliases on the child pointing + * at this one. */ - 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); - } + continue; } + INO_CST_UPDCNT(pdismissed); + pb = pno->p_base; + _sysio_p_gone(pno); + if (!(pb->pb_children.lh_first || pb->pb_aliases.lh_first)) + _sysio_pb_gone(pb); } while ((!count || --count) && n_names > t && next); if (!adjust) @@ -576,24 +558,14 @@ _sysio_pb_gone(struct pnode_base *pb) static void _sysio_pb_disconnect(struct pnode_base *pb) { - struct pnode *pno; /* - * Disconnect all aliases associated with the referenced base node. - */ - pno = pb->pb_aliases.lh_first; - do { - assert(pno->p_parent != pno); - pno->p_parent = NULL; - } while ((pno = pno->p_links.le_next)); - /* * Remove name from the names cache so that it can't * be found anymore. */ - if (pb->pb_key.pbk_name.len) - ncache_delete(pb); - else + if (!pb->pb_key.pbk_name.len) abort(); + ncache_delete(pb); pb->pb_key.pbk_name.len = 0; } @@ -656,8 +628,10 @@ _sysio_p_path(struct pnode *pno, char ** * the root of the name-space. */ while (pno == pno->p_mount->mnt_root && - pno != pno->p_parent) + pno != pno->p_mount->mnt_covers) { pno = pno->p_mount->mnt_covers; + assert(pno); + } /* * Add length of this component to running sum and @@ -670,9 +644,10 @@ _sysio_p_path(struct pnode *pno, char ** n++; assert(n); pno = pno->p_parent; - } while (pno && pno != pno->p_parent); - if (!pno) - return -ENOENT; + assert(pno); + } while (pno != pno->p_parent || + (pno != pno->p_mount->mnt_covers && + pno->p_mount->mnt_covers)); if (!*bufp) size = len + n + 1; @@ -700,8 +675,9 @@ _sysio_p_path(struct pnode *pno, char ** * the root of the name-space. */ while (pno == pno->p_mount->mnt_root && - pno != pno->p_parent ) + pno != pno->p_mount->mnt_covers) { pno = pno->p_mount->mnt_covers; + } /* * Add component and separator. @@ -712,7 +688,9 @@ _sysio_p_path(struct pnode *pno, char ** *--cp = PATH_SEPARATOR; pno = pno->p_parent; - } while (pno != pno->p_parent); + } while (pno != pno->p_parent || + (pno != pno->p_mount->mnt_covers && + pno->p_mount->mnt_covers)); return 0; } @@ -740,6 +718,9 @@ _sysio_p_new_alias(struct pnode *parent, pno->p_mount = mnt; pno->p_cover = NULL; LIST_INSERT_HEAD(&pb->pb_aliases, pno, p_links); +#ifdef P_DEBUG + _sysio_p_show("P_CREATE_ALIAS", pno); +#endif return pno; } @@ -835,12 +816,12 @@ _sysio_p_gone(struct pnode *pno) assert(!pno->p_ref); assert(!pno->p_cover); -#ifdef P_DEBUG - _sysio_p_show("P_GONE", pno); -#endif TAILQ_REMOVE(&_sysio_idle_pnodes, pno, p_idle); LIST_REMOVE(pno, p_links); +#ifdef P_DEBUG + _sysio_p_show("P_GONE", pno); +#endif free(pno); } @@ -890,6 +871,9 @@ _sysio_p_find_alias(struct pnode *parent struct pnode_base_key key; int err; struct pnode *pno; +#ifdef P_DEBUG + int isnew; +#endif if (!parent) return -ENOENT; @@ -930,7 +914,13 @@ _sysio_p_find_alias(struct pnode *parent } pno = pno->p_links.le_next; } +#ifdef P_DEBUG + isnew = 0; +#endif if (!pno) { +#ifdef P_DEBUG + isnew = 1; +#endif /* * Hmm. No alias. Create one. */ @@ -940,6 +930,7 @@ _sysio_p_find_alias(struct pnode *parent } if (!err) { #ifdef P_DEBUG + if (!isnew) _sysio_p_show("P_FIND_ALIAS", pno); #endif *pnop = pno; @@ -973,45 +964,22 @@ _sysio_prune(struct pnode_base *rpb) } #endif -/* - * Prune idle nodes from the passed sub-tree, including the root. - * - * Returns the number of aliases on the same mount that could not be pruned. - * i.e. a zero return means the entire sub-tree is gone. - */ -size_t -_sysio_p_prune(struct pnode *root) +static size_t +p_remove_aliases(struct mount *mnt, struct pnode_base *pb) { size_t count; - struct pnode_base *nxtpb, *pb; struct pnode *nxtpno, *pno; count = 0; - nxtpb = root->p_base->pb_children.lh_first; - while ((pb = nxtpb)) { - nxtpb = pb->pb_sibs.le_next; nxtpno = pb->pb_aliases.lh_first; -#if 0 - if (!nxtpno) { - _sysio_prune(pb); - continue; - } -#endif while ((pno = nxtpno)) { nxtpno = pno->p_links.le_next; - if (pno->p_mount != root->p_mount) { + if (pno->p_mount != mnt) { /* * Not the alias we were looking for. */ continue; } - if (pno->p_base->pb_children.lh_first) { - /* - * Node is interior. Recurse. - */ - count += _sysio_p_prune(pno); - continue; - } if (pno->p_ref) { /* * Can't prune; It's active. @@ -1019,63 +987,55 @@ _sysio_p_prune(struct pnode *root) count++; continue; } - assert(!pno->p_cover); /* covered => ref'd! */ + if (pno->p_cover) { /* - * Ok to prune. + * Mounted on. */ - if (pno->p_mount->mnt_root == pno) { -#ifndef AUTOMOUNT_FILE_NAME count++; continue; -#else - /* - * This is an automount-point. Must - * unmount before reclaim. - */ - P_REF(pno); - if (_sysio_do_unmount(pno->p_mount) != 0) { - P_RELE(pno); - count++; } +#ifdef AUTOMOUNT_FILE_NAME + if (pno->p_mount->mnt_root == pno) { + count++; continue; -#endif } - _sysio_p_kill(pno); +#endif + _sysio_p_gone(pno); } + + return count; } - if (count) { - /* - * Can't get the root or we disconnect the sub-trees. - */ - if (root->p_ref) - count++; +static size_t +pb_prune(struct mount *mnt, struct pnode_base *pb) +{ + size_t count; + struct pnode_base *nxt, *child; + + count = 0; + nxt = pb->pb_children.lh_first; + while ((child = nxt)) { + nxt = child->pb_sibs.le_next; + count += pb_prune(mnt, child); + } + if (!count) { + count += p_remove_aliases(mnt, pb); + if (!(pb->pb_aliases.lh_first || pb->pb_children.lh_first)) + _sysio_pb_gone(pb); + } return count; } /* - * All that is left is the root. Try for it too. - */ - if (root->p_ref) { - count++; - } else if (root->p_mount->mnt_root == root) { -#ifndef AUTOMOUNT_FILE_NAME - count++; -#else - /* - * This is an automount-point. Must - * unmount before reclaim. + * Prune idle nodes from the passed sub-tree, including the root. + * + * Returns the number of aliases on the same mount that could not be pruned. + * i.e. a zero return means the entire sub-tree is gone. */ - P_REF(root); - if (_sysio_do_unmount(root->p_mount) != 0) { - P_RELE(root); - count++; - } -#endif - } else - _sysio_p_kill(root); - - return count; +size_t +_sysio_p_prune(struct pnode *pno) +{ + return pb_prune(pno->p_mount, pno->p_base); } /* |