Index: sys/dev/disk/vn/vn.c =================================================================== RCS file: /home/dcvs/src/sys/dev/disk/vn/vn.c,v retrieving revision 1.35 diff -u -r1.35 vn.c --- sys/dev/disk/vn/vn.c 19 May 2007 20:31:16 -0000 1.35 +++ sys/dev/disk/vn/vn.c 8 Jan 2008 16:38:44 -0000 @@ -140,6 +140,7 @@ static int vnsetcred (struct vn_softc *vn, struct ucred *cred); static void vnclear (struct vn_softc *vn); +static int vnget (cdev_t dev, struct vn_softc *vn , struct vn_user *vnu); static int vn_modevent (module_t, int, void *); static int vniocattach_file (struct vn_softc *, struct vn_ioctl *, cdev_t dev, int flag, struct ucred *cred); static int vniocattach_swap (struct vn_softc *, struct vn_ioctl *, cdev_t dev, int flag, struct ucred *cred); @@ -457,6 +458,7 @@ case VNIOCDETACH: case VNIOCGSET: case VNIOCGCLEAR: + case VNIOCGET: case VNIOCUSET: case VNIOCUCLEAR: goto vn_specific; @@ -511,6 +513,10 @@ kprintf("vnioctl: CLRed\n"); break; + case VNIOCGET: + error = vnget(dev, vn, (struct vn_user *) ap->a_data); + break; + case VNIOCGSET: vn_options |= *f; *f = vn_options; @@ -760,6 +766,88 @@ vn->sc_size = 0; } +/* + * vnget: + * + * populate a struct vn_user for the VNIOCGET ioctl. + * interface conventions defined in sys/sys/vnioctl.h. + */ + +static int +vnget(cdev_t dev, struct vn_softc *vn, struct vn_user *vnu) +{ + int error, found = 0; + char *freepath, *fullpath; + struct namecache *ncp; + struct nchandle nch; + struct vattr vattr; + + if (vnu->vnu_unit == -1) { + vnu->vnu_unit = dkunit(dev); + } + else if (vnu->vnu_unit < 0) + return (EINVAL); + + SLIST_FOREACH(vn, &vn_list, sc_list) { + + if(vn->sc_unit != vnu->vnu_unit) + continue; + + found = 1; + + if (vn->sc_flags & VNF_INITED && vn->sc_vp != NULL) { + + /* note: u_cred checked in vnioctl above */ + error = VOP_GETATTR(vn->sc_vp, &vattr); + if (error) + return (error); + + /* vfs_cache.c:vn_fullpath expects valid proc */ + TAILQ_FOREACH(ncp, &vn->sc_vp->v_namecache, nc_vnode) { + if (ncp->nc_nlen) + break; + } + if (ncp == NULL) + return (EINVAL); /* panic ? */ + + nch.ncp = ncp; + nch.mount = vn->sc_vp->v_mount; + error = cache_fullpath(NULL, &nch, + &fullpath, &freepath); + + if (error) { + kprintf("vnget: unable to resolve vp %p\n", + vn->sc_vp); + return(error); + } + + strlcpy(vnu->vnu_file, fullpath, + sizeof(vnu->vnu_file)); + kfree(freepath, M_TEMP); + vnu->vnu_dev = vattr.va_fsid; + vnu->vnu_ino = vattr.va_fileid; + + } + else if (vn->sc_flags & VNF_INITED && vn->sc_object != NULL){ + + strlcpy(vnu->vnu_file, _VN_USER_SWAP, + sizeof(vnu->vnu_file)); + vnu->vnu_size = vn->sc_size; + vnu->vnu_secsize = vn->sc_secsize; + } else { + bzero(vnu->vnu_file, sizeof(vnu->vnu_file)); + vnu->vnu_dev = 0; + vnu->vnu_ino = 0; + } + break; + } + + if (!found) + return(ENXIO); + + return(0); +} + static int vnsize(struct dev_psize_args *ap) { Index: sys/sys/vnioctl.h =================================================================== RCS file: /home/dcvs/src/sys/sys/vnioctl.h,v retrieving revision 1.3 diff -u -r1.3 vnioctl.h --- sys/sys/vnioctl.h 15 May 2007 22:44:19 -0000 1.3 +++ sys/sys/vnioctl.h 8 Jan 2008 00:26:54 -0000 @@ -46,6 +46,10 @@ #ifndef _SYS_VNIOCTL_H_ #define _SYS_VNIOCTL_H_ +#ifndef _SYS_PARAMH_H_ +#include /* PATH_MAX */ +#endif + /* * Ioctl definitions for file (vnode) disk pseudo-device. */ @@ -58,6 +62,39 @@ }; /* + * Structure used by userland to query vn devices. + * + * In file-backed configurations, vnu_file will contain the full path to + * the backing file, with vnu_dev and vnu_ino pointing to the appropriate + * filesystem entries for that file. + * + * In swap-backed configurations, vnu_file will contain the token "swap", + * with vnu_size and vnu_secsize indicating the portion of virtual memory + * in use by the vnode disk. + * + * Todo: verify vnu_file within a jail - path disclosure problem ? + */ + + +struct vn_user { + int vnu_unit; /* vn unit */ + char vnu_file[PATH_MAX]; /* vn description */ +#define _VN_USER_SWAP "swap" /* indicates swap-backed vn */ + union { + dev_t dev; /* vn device */ + u_int64_t size; /* size per vnu_secsize */ + } data1; + union { + ino_t ino; /* vn inode */ + int secsize; /* sector size */ + } data2; +}; +#define vnu_dev data1.dev +#define vnu_size data1.size +#define vnu_ino data2.ino +#define vnu_secsize data2.secsize + +/* * Before you can use a unit, it must be configured with VNIOCSET. * The configuration persists across opens and closes of the device; * an VNIOCCLR must be used to reset a configuration. An attempt to @@ -69,6 +106,7 @@ #define VNIOCGCLEAR _IOWR('F', 3, u_long ) /* reset --//-- */ #define VNIOCUSET _IOWR('F', 4, u_long ) /* set unit option */ #define VNIOCUCLEAR _IOWR('F', 5, u_long ) /* reset --//-- */ +#define VNIOCGET _IOWR('F', 6, struct vn_user) /* get disk info */ #define VN_LABELS 0x1 /* Use disk(/slice) labels */ #define VN_FOLLOW 0x2 /* Debug flow in vn driver */ Index: usr.sbin/vnconfig/vnconfig.8 =================================================================== RCS file: /home/dcvs/src/usr.sbin/vnconfig/vnconfig.8,v retrieving revision 1.5 diff -u -r1.5 vnconfig.8 --- usr.sbin/vnconfig/vnconfig.8 10 Aug 2007 18:28:27 -0000 1.5 +++ usr.sbin/vnconfig/vnconfig.8 7 Jan 2008 18:33:35 -0000 @@ -60,10 +60,13 @@ .Op Fl s Ar option .Op Fl r Ar option .Op Fl f Ar config_file +.Nm +.Fl l +.Op Ar special_file Ar ... .Sh DESCRIPTION The .Nm -command configures and enables vnode pseudo disk devices. +command configures, enables and lists vnode pseudo disk devices. The first form of the command will associate the special file .Ar special_file with the regular file @@ -102,6 +105,11 @@ as an alternate config file. .It Fl g Fiddle global options. +.It Fl l Ar special_file... +List the vn devices and indicate which ones are in use. +If a +.Ar special_file +list is given, only those devices will be described. .It Fl r Ar flag Reset .Ar flag . Index: usr.sbin/vnconfig/vnconfig.c =================================================================== RCS file: /home/dcvs/src/usr.sbin/vnconfig/vnconfig.c,v retrieving revision 1.12 diff -u -r1.12 vnconfig.c --- usr.sbin/vnconfig/vnconfig.c 19 Jun 2007 19:28:18 -0000 1.12 +++ usr.sbin/vnconfig/vnconfig.c 8 Jan 2008 17:27:47 -0000 @@ -90,12 +90,14 @@ int all = 0; int verbose = 0; int global = 0; +int listopt = 0; u_long setopt = 0; u_long resetopt = 0; char *configfile; int config(struct vndisk *); void getoptions(struct vndisk *, char *); +int getinfo(const char *vname); char *rawdevice(char *); void readconfig(int); static void usage(void); @@ -113,7 +115,7 @@ char *s; configfile = _PATH_VNTAB; - while ((i = getopt(argc, argv, "acdef:gr:s:S:TZL:uv")) != -1) + while ((i = getopt(argc, argv, "acdef:glr:s:S:TZL:uv")) != -1) switch (i) { /* all -- use config file */ @@ -158,6 +160,10 @@ flags |= VN_RESET; break; + case 'l': + listopt = 1; + break; + /* set options */ case 's': for (s = strtok(optarg, ","); s; s = strtok(NULL, ",")) { @@ -204,6 +210,16 @@ if (kldload("vn") < 0 || modfind("vn") < 0) warnx( "cannot find or load \"vn\" kernel module"); + if (listopt) { + if(argc > optind) + while(argc > optind) + rv += getinfo( argv[optind++]); + else { + rv = getinfo( NULL ); + } + exit(rv); + } + if (flags == 0) flags = VN_CONFIG; if (all) { @@ -240,6 +256,95 @@ return 1; } +/* + * + * GETINFO + * + * Print vnode disk information to stdout for the device at + * path 'vname', or all existing 'vn' devices if none is given. + * Any 'vn' devices must exist under /dev in order to be queried. + * + * Todo: correctly use vm_secsize for swap-backed vn's .. + */ + +int +getinfo( const char *vname ) +{ + int i, vd, printlim = 0; + char vnpath[PATH_MAX], *tmp; + + struct vn_user vnu; + struct stat sb; + + if (vname == NULL) { + i = 0; + printlim = 1024; + } + else { + tmp = (char *) vname; + while (*tmp != NULL) { + if(isdigit(*tmp)){ + i = atoi(tmp); + printlim = i + 1; + break; + } + tmp++; + } + if (tmp == NULL) { + printf("unknown vn device: %s", vname); + return 1; + } + } + + snprintf(vnpath, sizeof(vnpath), "/dev/vn%d", i); + + vd = open((char *)vnpath, O_RDONLY); + if (vd < 0) { + err(1, "open: %s", vnpath); + return 1; + } + + for (i; i