diff --git a/sys/miscfs/devfs/devfs_proto.h b/sys/miscfs/devfs/devfs_proto.h index 5217e111d74f..ff9adcd6c3ce 100644 --- a/sys/miscfs/devfs/devfs_proto.h +++ b/sys/miscfs/devfs/devfs_proto.h @@ -1,21 +1,20 @@ /* THIS FILE PRODUCED AUTOMATICALLY */ void devfs_sinit(caddr_t junk) /*proto*/; +dn_p dev_findname(dn_p dir,char *name) /*proto*/; int dev_finddir(char *orig_path, dn_p dirnode, int create, dn_p *dn_pp) /*proto*/; -int dev_add_node(char *name, dn_p dirnode,devnm_p back, int entrytype, union typeinfo *by, devnm_p *devnm_pp) /*proto*/; -int dev_remove(devnm_p devnmp) /*proto*/; +int dev_add_name(char *name, dn_p dirnode,devnm_p back, int entrytype, union typeinfo *by, devnm_p *devnm_pp) /*proto*/; int dev_touch(devnm_p key) /* update the node for this dev */ /*proto*/; void devfs_dn_free(dn_p dnp) /*proto*/; -int get_cdev_major_num(caddr_t addr) /*proto*/; -int get_bdev_major_num(caddr_t addr) /*proto*/; int devfs_add_fronts(devnm_p parent,devnm_p child) /*proto*/; -dn_p dev_findname(dn_p dir,char *name) /*proto*/; -int dev_mk_front(dn_p parent, devnm_p back, devnm_p *dnm_pp, struct devfsmount *dvm) /*proto*/; -int devfs_make_plane(struct devfsmount *devfs_mp_p) /*proto*/; +void dev_remove_dev(devnm_p devnmp) /*proto*/; +int dev_dup_plane(struct devfsmount *devfs_mp_p) /*proto*/; void devfs_free_plane(struct devfsmount *devfs_mp_p) /*proto*/; -void devfs_remove_fronts(devnm_p devnmp) /*proto*/; +int dev_dup_name(dn_p parent, devnm_p back, devnm_p *dnm_pp, struct devfsmount *dvm) /*proto*/; void dev_free_name(devnm_p devnmp) /*proto*/; int devfs_vntodn(struct vnode *vn_p, dn_p *dn_pp) /*proto*/; int devfs_dntovn(dn_p dnp, struct vnode **vn_pp) /*proto*/; +int get_cdev_major_num(caddr_t addr) /*proto*/; +int get_bdev_major_num(caddr_t addr) /*proto*/; int devfs_init(void) /*proto*/; int devfs_mount( struct mount *mp, char *path, caddr_t data, struct nameidata *ndp, struct proc *p) /*proto*/; int mountdevfs( struct mount *mp, struct proc *p) /*proto*/; diff --git a/sys/miscfs/devfs/devfs_tree.c b/sys/miscfs/devfs/devfs_tree.c index 030bfd5742c1..e5b62ab82934 100644 --- a/sys/miscfs/devfs/devfs_tree.c +++ b/sys/miscfs/devfs/devfs_tree.c @@ -2,7 +2,7 @@ /* * Written by Julian Elischer (julian@DIALix.oz.au) * - * $Header: /home/ncvs/src/sys/miscfs/devfs/devfs_tree.c,v 1.2 1995/09/06 09:29:16 julian Exp $ + * $Header: /home/ncvs/src/sys/miscfs/devfs/devfs_tree.c,v 1.3 1995/09/06 23:15:53 julian Exp $ */ #include "param.h" @@ -39,9 +39,9 @@ void devfs_sinit(caddr_t junk) /*proto*/ /* * call the right routine at the right time with the right args.... */ - retval = dev_add_node("root",NULL,NULL,DEV_DIR,NULL,&dev_root); + retval = dev_add_name("root",NULL,NULL,DEV_DIR,NULL,&dev_root); #ifdef PARANOID - if(retval) panic("devfs_sinit: dev_add_node failed "); + if(retval) panic("devfs_sinit: dev_add_name failed "); #endif devfs_hidden_mount = (struct mount *)malloc(sizeof(struct mount), M_MOUNT,M_NOWAIT); @@ -56,8 +56,43 @@ void devfs_sinit(caddr_t junk) /*proto*/ } /***********************************************************************\ -* Routines used to add and remove nodes from the base tree * +************************************************************************* +* Routines used to find our way to a point in the tree * +************************************************************************* \***********************************************************************/ + + +/***************************************************************\ +* Search down the linked list off a dir to find "name" * +* return the dn_p for that node. +\***************************************************************/ +dn_p dev_findname(dn_p dir,char *name) /*proto*/ +{ + devnm_p newfp; + DBPRINT((" dev_findname(%s)\n",name)); + if(dir->type != DEV_DIR) return 0;/*XXX*/ /* printf?*/ + + if(name[0] == '.') + { + if(name[1] == 0) + { + return dir; + } + if((name[1] == '.') && (name[2] == 0)) + { + return dir->by.Dir.parent; /* for root, .. == . */ + } + } + newfp = dir->by.Dir.dirlist; + while(newfp) + { + if(!(strcmp(name,newfp->name))) + return newfp->dnp; + newfp = newfp->next; + } + return (dn_p)0; +} + /***********************************************************************\ * Given a starting node (0 for root) and a pathname, return the node * * for the end item on the path. It MUST BE A DIRECTORY. If the 'CREATE' * @@ -140,7 +175,7 @@ int dev_finddir(char *orig_path, dn_p dirnode, int create, dn_p *dn_pp) /*proto* \***************************************/ if(!create) return ENOENT; - if(retval = dev_add_node(name, dirnode, NULL ,DEV_DIR, + if(retval = dev_add_name(name, dirnode, NULL ,DEV_DIR, NULL, &devnmp)) { return retval; @@ -164,15 +199,17 @@ int dev_finddir(char *orig_path, dn_p dirnode, int create, dn_p *dn_pp) /*proto* * If we're creating a root node, then dirname is NULL * * If devnode is non zero, then we just want to create a link to it * * This implies that we are not at base level and it's a not a DIR * +* * +* Creates a name node, and (optionally) a new dev_node to go with it * \***********************************************************************/ -int dev_add_node(char *name, dn_p dirnode,devnm_p back, int entrytype, union typeinfo *by, devnm_p *devnm_pp) /*proto*/ +int dev_add_name(char *name, dn_p dirnode,devnm_p back, int entrytype, union typeinfo *by, devnm_p *devnm_pp) /*proto*/ { devnm_p devnmp; devnm_p realthing; /* needed to create an alias */ dn_p dnp; int retval; - DBPRINT(("dev_add_node\n")); + DBPRINT(("dev_add_name\n")); if(dirnode ) { if(dirnode->type != DEV_DIR) return(ENOTDIR); @@ -367,57 +404,12 @@ int dev_add_node(char *name, dn_p dirnode,devnm_p back, int entrytype, union typ *devnm_pp = devnmp; return 0 ; } - -/*********************************************************************** - * remove all fronts to this dev and also it's aliases, - * Then remove this node. - * For now only allow DEVICE nodes to go.. XXX - * directory nodes are more complicated and may need more work.. - ***********************************************************************/ -int dev_remove(devnm_p devnmp) /*proto*/ -{ - devnm_p alias; - - DBPRINT(("dev_remove\n")); - /* - * Check the type of the node.. for now don't allow dirs - */ - switch(devnmp->dnp->type) - { - case DEV_BDEV: - case DEV_CDEV: - case DEV_DDEV: - case DEV_ALIAS: - case DEV_SLNK: - break; - case DEV_DIR: - default: - return(EINVAL); - } - /* - * Free each alias - * Remember, aliases can't have front nodes - */ - while ( alias = devnmp->as.back.aliases) - { - devnmp->as.back.aliases = alias->dnp->by.Alias.next; - devfs_dn_free(alias->dnp); - free (alias, M_DEVFSNAME); - } - /* - * Now remove front items of the Main node itself - */ - devfs_remove_fronts(devnmp); - - /* - * now we should free the main node - */ - devfs_dn_free(devnmp->dnp); - free (devnmp, M_DEVFSNAME); - return 0; -} +/***************************************************************\ +* DEV_NODE reference count manipulations.. when a ref count * +* reaches 0, the node is to be deleted * +\***************************************************************/ int dev_touch(devnm_p key) /* update the node for this dev */ /*proto*/ { DBPRINT(("dev_touch\n")); @@ -435,104 +427,15 @@ void devfs_dn_free(dn_p dnp) /*proto*/ } if(--dnp->links == 0 ) { + /*probably need to do other cleanups XXX */ devfs_dropvnode(dnp); free (dnp, M_DEVFSNODE); } } - -/***********************************************************************\ -* UTILITY routine: * -* Return the major number for the cdevsw entry containing the given * -* address. * -\***********************************************************************/ -int get_cdev_major_num(caddr_t addr) /*proto*/ -{ - int index = 0; - - DBPRINT(("get_cdev_major_num\n")); - while (index < nchrdev) - { - if(((caddr_t)(cdevsw[index].d_open) == addr) - ||((caddr_t)(cdevsw[index].d_read) == addr) - ||((caddr_t)(cdevsw[index].d_ioctl) == addr)) - { - return index; - } - index++; - } - return -1; -} - -int get_bdev_major_num(caddr_t addr) /*proto*/ -{ - int index = 0; - - DBPRINT(("get_bdev_major_num\n")); - while (index < nblkdev) - { - if(((caddr_t)(bdevsw[index].d_open) == addr) - ||((caddr_t)(bdevsw[index].d_strategy) == addr) - ||((caddr_t)(bdevsw[index].d_ioctl) == addr)) - { - return index; - } - index++; - } - return -1; -} - -/***********************************************************************\ -* Add the named device entry into the given directory, and make it * -* The appropriate type... (called (sometimes indirectly) by drivers..) * -\***********************************************************************/ -void *dev_add(char *path, - char *name, - void *funct, - int minor, - int chrblk, - uid_t uid, - gid_t gid, - int perms) -{ - devnm_p new_dev; - dn_p dnp; /* devnode for parent directory */ - int retval; - int major ; - union typeinfo by; - - DBPRINT(("dev_add\n")); - retval = dev_finddir(path,NULL,1,&dnp); - if (retval) return 0; - switch(chrblk) - { - case DV_CHR: - major = get_cdev_major_num(funct); - by.Cdev.cdevsw = cdevsw + major; - by.Cdev.dev = makedev(major, minor); - if( dev_add_node(name, dnp, NULL, DEV_CDEV, - &by,&new_dev)) - return 0; - break; - case DV_BLK: - major = get_bdev_major_num(funct); - by.Bdev.bdevsw = bdevsw + major; - by.Bdev.dev = makedev(major, minor); - if( dev_add_node(name, dnp, NULL, DEV_BDEV, - &by, &new_dev)) - return 0; - break; - default: - return(0); - } - new_dev->dnp->gid = gid; - new_dev->dnp->uid = uid; - new_dev->dnp->mode |= perms; - return new_dev; -} - /***********************************************************************\ * Front Node Operations * +* Add or delete a chain of front nodes * \***********************************************************************/ /***********************************************************************\ @@ -544,6 +447,8 @@ void *dev_add(char *path, * front dir, however dirs completed will not be stripped of completed * * frontnodes on failure of a later frontnode * * * +* This allows a new node to be propogated through all mounted planes * +* * \***********************************************************************/ int devfs_add_fronts(devnm_p parent,devnm_p child) /*proto*/ { @@ -563,7 +468,7 @@ int devfs_add_fronts(devnm_p parent,devnm_p child) /*proto*/ child->name); continue; } - if (dev_add_node(child->name,parent->dnp,child, + if (dev_add_name(child->name,parent->dnp,child, type,NULL,&newnmp)) { printf("Device %s: allocation failed\n", @@ -574,46 +479,83 @@ int devfs_add_fronts(devnm_p parent,devnm_p child) /*proto*/ } return(0); /* for now always succeed */ } - -/***************************************************************\ -* Search down the linked list off a dir to find "name" * -* return the dn_p for that node. -\***************************************************************/ -dn_p dev_findname(dn_p dir,char *name) /*proto*/ -{ - devnm_p newfp; - DBPRINT((" dev_findname(%s)\n",name)); - if(dir->type != DEV_DIR) return 0;/*XXX*/ /* printf?*/ - if(name[0] == '.') + + + +/*********************************************************************** + * remove all instances of this devicename [for backing nodes..] + * note.. if there is another link to the node (non dir nodes only) + * then the devfs_node will still exist as the ref count will be non-0 + * removing a directory node will remove all sup-nodes on all planes (ZAP) + * + * Used be device drivers to remove nodes that are no longer relevant + ***********************************************************************/ +void dev_remove_dev(devnm_p devnmp) /*proto*/ +{ + DBPRINT(("dev_remove_dev\n")); + /* + * Keep removing the next front node till no more exist + */ + while(devnmp->next_front) { - if(name[1] == 0) - { - return dir; - } - if((name[1] == '.') && (name[2] == 0)) - { - return dir->by.Dir.parent; /* for root, .. == . */ - } + dev_free_name(devnmp->next_front); } - newfp = dir->by.Dir.dirlist; - while(newfp) - { - if(!(strcmp(name,newfp->name))) - return newfp->dnp; - newfp = newfp->next; + /* + * then free the main node + */ + dev_free_name(devnmp); + return ; +} + +/*************************************************************** + * duplicate the backing tree into a tree of nodes hung off the + * mount point given as the argument. Do this by + * calling dev_dup_name which recurses all the way + * up the tree.. + * If we are the first plane, just return the base root + **************************************************************/ +int dev_dup_plane(struct devfsmount *devfs_mp_p) /*proto*/ +{ + devnm_p new; + int error = 0; + + DBPRINT((" dev_dup_plane\n")); + if(devfs_up_and_going) { + if(error = dev_dup_name(NULL, dev_root, &new, devfs_mp_p)) { + return error; + } + } else { /* we are doing the dummy mount during initialisation.. */ + new = dev_root; } - return (dn_p)0; + devfs_mp_p->plane_root = new; + + return error; +} + + + +/***************************************************************\ +* Free a whole plane +\***************************************************************/ +void devfs_free_plane(struct devfsmount *devfs_mp_p) /*proto*/ +{ + devnm_p devnmp; + + DBPRINT((" devfs_free_plane\n")); + devnmp = devfs_mp_p->plane_root; + if(devnmp) dev_free_name(devnmp); + devfs_mp_p->plane_root = NULL; } /***************************************************************\ * Create and link in a new front element.. * * Parent can be 0 for a root node * * Not presently usable to make a symlink XXX * -* Must teach this to handle where there is no back node * -* maybe split into two bits? * +* recursively will create subnodes corresponding to equivalent * +* child nodes in the base level * \***************************************************************/ -int dev_mk_front(dn_p parent, devnm_p back, devnm_p *dnm_pp, struct devfsmount *dvm) /*proto*/ +int dev_dup_name(dn_p parent, devnm_p back, devnm_p *dnm_pp, struct devfsmount *dvm) /*proto*/ { devnm_p newnmp; struct devfsmount *dmt; @@ -622,11 +564,11 @@ int dev_mk_front(dn_p parent, devnm_p back, devnm_p *dnm_pp, struct devfsmount * int error; dn_p dnp = back->dnp; - DBPRINT((" dev_mk_front\n")); + DBPRINT((" dev_dup_name\n")); /* * go get the node made */ - error = dev_add_node(back->name,parent,back,dnp->type,NULL,&newnmp); + error = dev_add_name(back->name,parent,back,dnp->type,NULL,&newnmp); if ( error ) return error; /* @@ -647,7 +589,7 @@ int dev_mk_front(dn_p parent, devnm_p back, devnm_p *dnm_pp, struct devfsmount * for(newback = back->dnp->by.Dir.dirlist; newback; newback = newback->next) { - if(error = dev_mk_front(newnmp->dnp, + if(error = dev_dup_name(newnmp->dnp, newback, &newfront, NULL)) { break; /* back out with an error */ @@ -658,52 +600,10 @@ int dev_mk_front(dn_p parent, devnm_p back, devnm_p *dnm_pp, struct devfsmount * return error; } -/* - * duplicate the backing tree into a tree of nodes hung off the - * mount point given as the argument. Do this by - * calling dev_mk_front() which recurses all the way - * up the tree.. - */ -int devfs_make_plane(struct devfsmount *devfs_mp_p) /*proto*/ -{ - devnm_p new; - int error = 0; - - DBPRINT((" devfs_make_plane\n")); - if(devfs_up_and_going) { - if(error = dev_mk_front(NULL, dev_root, &new, devfs_mp_p)) { - return error; - } - } else { /* we are doing the dummy mount during initialisation.. */ - new = dev_root; - } - devfs_mp_p->plane_root = new; - - return error; -} - -void devfs_free_plane(struct devfsmount *devfs_mp_p) /*proto*/ -{ - devnm_p devnmp; - - DBPRINT((" devfs_free_plane\n")); - devnmp = devfs_mp_p->plane_root; - if(devnmp) dev_free_name(devnmp); - devfs_mp_p->plane_root = NULL; -} -/* - * Remove all the front nodes associated with a backing node - */ -void devfs_remove_fronts(devnm_p devnmp) /*proto*/ -{ - while(devnmp->next_front) - { - dev_free_name(devnmp->next_front); - } -} - /***************************************************************\ -* Free a front node (and any below it of it's a directory node) * +* Free a name node (and any below it of it's a directory node) * +* remember that if there are other names pointing to the * +* dev_node then it may not get freed yet * \***************************************************************/ void dev_free_name(devnm_p devnmp) /*proto*/ { @@ -768,6 +668,13 @@ void dev_free_name(devnm_p devnmp) /*proto*/ return; } +/*******************************************************\ +********************************************************* +* ROUTINES to control the connection between devfs * +* nodes and the system's vnodes * +********************************************************* +\*******************************************************/ + /*******************************************************\ * Theoretically this could be called for any kind of * * vnode, however in practice it must be a DEVFS vnode * @@ -899,3 +806,94 @@ DBPRINT(("(New vnode)")); } return error; } + +/***********************************************************************\ +* UTILITY routine: * +* Return the major number for the cdevsw entry containing the given * +* address. * +\***********************************************************************/ +int get_cdev_major_num(caddr_t addr) /*proto*/ +{ + int index = 0; + + DBPRINT(("get_cdev_major_num\n")); + while (index < nchrdev) + { + if(((caddr_t)(cdevsw[index].d_open) == addr) + ||((caddr_t)(cdevsw[index].d_read) == addr) + ||((caddr_t)(cdevsw[index].d_ioctl) == addr)) + { + return index; + } + index++; + } + return -1; +} + +int get_bdev_major_num(caddr_t addr) /*proto*/ +{ + int index = 0; + + DBPRINT(("get_bdev_major_num\n")); + while (index < nblkdev) + { + if(((caddr_t)(bdevsw[index].d_open) == addr) + ||((caddr_t)(bdevsw[index].d_strategy) == addr) + ||((caddr_t)(bdevsw[index].d_ioctl) == addr)) + { + return index; + } + index++; + } + return -1; +} + +/***********************************************************************\ +* Add the named device entry into the given directory, and make it * +* The appropriate type... (called (sometimes indirectly) by drivers..) * +\***********************************************************************/ +void *dev_add(char *path, + char *name, + void *funct, + int minor, + int chrblk, + uid_t uid, + gid_t gid, + int perms) +{ + devnm_p new_dev; + dn_p dnp; /* devnode for parent directory */ + int retval; + int major ; + union typeinfo by; + + DBPRINT(("dev_add\n")); + retval = dev_finddir(path,NULL,1,&dnp); + if (retval) return 0; + switch(chrblk) + { + case DV_CHR: + major = get_cdev_major_num(funct); + by.Cdev.cdevsw = cdevsw + major; + by.Cdev.dev = makedev(major, minor); + if( dev_add_name(name, dnp, NULL, DEV_CDEV, + &by,&new_dev)) + return 0; + break; + case DV_BLK: + major = get_bdev_major_num(funct); + by.Bdev.bdevsw = bdevsw + major; + by.Bdev.dev = makedev(major, minor); + if( dev_add_name(name, dnp, NULL, DEV_BDEV, + &by, &new_dev)) + return 0; + break; + default: + return(0); + } + new_dev->dnp->gid = gid; + new_dev->dnp->uid = uid; + new_dev->dnp->mode |= perms; + return new_dev; +} + diff --git a/sys/miscfs/devfs/devfs_vfsops.c b/sys/miscfs/devfs/devfs_vfsops.c index 4ac67f75d9c3..00b4933798fa 100644 --- a/sys/miscfs/devfs/devfs_vfsops.c +++ b/sys/miscfs/devfs/devfs_vfsops.c @@ -1,7 +1,7 @@ /* * Written by Julian Elischer (julian@DIALix.oz.au) * - * $Header: /home/ncvs/src/sys/miscfs/devfs/devfs_vfsops.c,v 1.4 1995/09/03 05:43:42 julian Exp $ + * $Header: /home/ncvs/src/sys/miscfs/devfs/devfs_vfsops.c,v 1.5 1995/09/06 09:29:17 julian Exp $ * * */ @@ -105,7 +105,7 @@ int mountdevfs( struct mount *mp, struct proc *p) /*proto*/ mp->mnt_stat.f_fsid.val[1] = MOUNT_DEVFS; mp->mnt_flag |= MNT_LOCAL; - if(error = devfs_make_plane(devfs_mp_p)) + if(error = dev_dup_plane(devfs_mp_p)) { mp->mnt_data = (qaddr_t)0; free((caddr_t)devfs_mp_p, M_DEVFSMNT); diff --git a/sys/miscfs/devfs/devfs_vnops.c b/sys/miscfs/devfs/devfs_vnops.c index 68ebd55b1acf..2aba6c1f79aa 100644 --- a/sys/miscfs/devfs/devfs_vnops.c +++ b/sys/miscfs/devfs/devfs_vnops.c @@ -1,7 +1,7 @@ /* * Written by Julian Elischer (julian@DIALix.oz.au) * - * $Header: /home/ncvs/src/sys/miscfs/devfs/devfs_vnops.c,v 1.9 1995/09/06 09:29:18 julian Exp $ + * $Header: /home/ncvs/src/sys/miscfs/devfs/devfs_vnops.c,v 1.10 1995/09/06 23:15:54 julian Exp $ * * symlinks can wait 'til later. */ @@ -683,7 +683,8 @@ DBPRINT(("read\n")); case VREG: return(EINVAL); case VDIR: - return VOP_READDIR(ap->a_vp,ap->a_uio,ap->a_cred); + return VOP_READDIR(ap->a_vp,ap->a_uio,ap->a_cred, + NULL,NULL,NULL); case VCHR: case VBLK: error = spec_read(ap); @@ -887,6 +888,9 @@ int devfs_readdir(struct vop_readdir_args *ap) /*proto*/ struct vnode *a_vp; struct uio *a_uio; struct ucred *a_cred; + int *eofflag; + int *ncookies; + u_int **cookies; } */ { struct vnode *vp = ap->a_vp; @@ -1196,15 +1200,13 @@ void devfs_dropvnode(dn_p dnp) /*proto*/ { struct vnode *vn_p; +#ifdef PARANOID if(!dnp) { printf("devfs: dn count dropped too early\n"); } +#endif vn_p = dnp->vn; - if(!vn_p) - { - printf("devfs: vn count dropped too early\n"); - } /* * check if we have a vnode....... */