diff --git a/sbin/swapctl/swaplist.c b/sbin/swapctl/swaplist.c index 550c82057780..b644ba32aaa0 100644 --- a/sbin/swapctl/swaplist.c +++ b/sbin/swapctl/swaplist.c @@ -1,4 +1,4 @@ -/* $NetBSD: swaplist.c,v 1.5 1998/06/17 07:46:35 ross Exp $ */ +/* $NetBSD: swaplist.c,v 1.6 1998/08/29 13:27:51 mrg Exp $ */ /* * Copyright (c) 1997 Matthew R. Green @@ -60,8 +60,9 @@ list_swap(pri, kflag, pflag, tflag, dolong) struct swapent *sep, *fsep; long blocksize; char *header; - int hlen, totalsize, size, totalinuse, inuse, ncounted; - int rnswap, nswap = swapctl(SWAP_NSWAP, 0, 0); + size_t l; + int hlen, totalsize, size, totalinuse, inuse, ncounted, pathmax; + int rnswap, nswap = swapctl(SWAP_NSWAP, 0, 0), i; if (nswap < 1) { puts("no swap devices configured"); @@ -72,11 +73,13 @@ list_swap(pri, kflag, pflag, tflag, dolong) if (sep == NULL) err(1, "malloc"); rnswap = swapctl(SWAP_STATS, (void *)sep, nswap); - if (nswap < 0) + if (rnswap < 0) errx(1, "SWAP_STATS"); if (nswap != rnswap) - warnx("SWAP_STATS gave different value than SWAP_NSWAP"); + warnx("SWAP_STATS different to SWAP_NSWAP (%d != %d)", + rnswap, nswap); + pathmax = 11; if (dolong && tflag == 0) { if (kflag) { header = "1K-blocks"; @@ -84,8 +87,12 @@ list_swap(pri, kflag, pflag, tflag, dolong) hlen = strlen(header); } else header = getbsize(&hlen, &blocksize); - (void)printf("%-11s %*s %8s %8s %8s %s\n", - "Device", hlen, header, + for (i = rnswap; i-- > 0; sep++) + if (pathmax < (l = strlen(sep->se_path))) + pathmax = l; + sep = fsep; + (void)printf("%-*s %*s %8s %8s %8s %s\n", + pathmax, "Device", hlen, header, "Used", "Avail", "Capacity", "Priority"); } totalsize = totalinuse = ncounted = 0; @@ -99,10 +106,8 @@ list_swap(pri, kflag, pflag, tflag, dolong) totalinuse += inuse; if (dolong && tflag == 0) { - /* XXX handle se_dev == NODEV */ - (void)printf("/dev/%-6s %*ld ", - devname(sep->se_dev, S_IFBLK), - hlen, (long)(dbtoqb(size) / blocksize)); + (void)printf("%-*s %*ld ", pathmax, sep->se_path, hlen, + (long)(dbtoqb(size) / blocksize)); (void)printf("%8ld %8ld %5.0f%% %d\n", (long)(dbtoqb(inuse) / blocksize), @@ -122,7 +127,8 @@ list_swap(pri, kflag, pflag, tflag, dolong) (long)(dbtoqb(totalinuse) / 1024), (long)(dbtoqb(totalsize - totalinuse) / 1024)); else if (ncounted > 1) - printf("%-11s %*ld %8ld %8ld %5.0f%%\n", "Total", hlen, + (void)printf("%-*s %*ld %8ld %8ld %5.0f%%\n", pathmax, "Total", + hlen, (long)(dbtoqb(totalsize) / blocksize), (long)(dbtoqb(totalinuse) / blocksize), (long)(dbtoqb(totalsize - totalinuse) / blocksize), diff --git a/sys/uvm/uvm_swap.c b/sys/uvm/uvm_swap.c index 22c4538ba44a..c15c370f5c68 100644 --- a/sys/uvm/uvm_swap.c +++ b/sys/uvm/uvm_swap.c @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_swap.c,v 1.15 1998/08/13 02:11:03 eeh Exp $ */ +/* $NetBSD: uvm_swap.c,v 1.16 1998/08/29 13:27:51 mrg Exp $ */ /* * Copyright (c) 1995, 1996, 1997 Matthew R. Green @@ -33,6 +33,7 @@ #include "fs_nfs.h" #include "opt_uvmhist.h" +#include "opt_compat_netbsd.h" #include #include @@ -131,24 +132,26 @@ * swd_nblks <= swd_mapsize [because mapsize includes miniroot+disklabel] */ struct swapdev { - struct swapent swd_se; /* swap entry struct */ -#define swd_dev swd_se.se_dev /* dev_t for this dev */ -#define swd_flags swd_se.se_flags /* flags:inuse/enable/fake*/ -#define swd_priority swd_se.se_priority /* our priority */ - /* also: swd_se.se_nblks, swd_se.se_inuse */ - int swd_npages; /* #pages we can use */ - int swd_npginuse; /* #pages in use */ - int swd_drumoffset; /* page0 offset in drum */ - int swd_drumsize; /* #pages in drum */ - struct extent *swd_ex; /* extent for this swapdev*/ - struct vnode *swd_vp; /* backing vnode */ - CIRCLEQ_ENTRY(swapdev) swd_next; /* priority circleq */ + struct oswapent swd_ose; +#define swd_dev swd_ose.ose_dev /* device id */ +#define swd_flags swd_ose.ose_flags /* flags:inuse/enable/fake */ +#define swd_priority swd_ose.ose_priority /* our priority */ + /* also: swd_ose.ose_nblks, swd_ose.ose_inuse */ + char *swd_path; /* saved pathname of device */ + int swd_pathlen; /* length of pathname */ + int swd_npages; /* #pages we can use */ + int swd_npginuse; /* #pages in use */ + int swd_drumoffset; /* page0 offset in drum */ + int swd_drumsize; /* #pages in drum */ + struct extent *swd_ex; /* extent for this swapdev */ + struct vnode *swd_vp; /* backing vnode */ + CIRCLEQ_ENTRY(swapdev) swd_next; /* priority circleq */ #ifdef SWAP_TO_FILES - int swd_bsize; /* blocksize (bytes) */ - int swd_maxactive; /* max active i/o reqs */ - struct buf swd_tab; /* buffer list */ - struct ucred *swd_cred; /* cred for file access */ + int swd_bsize; /* blocksize (bytes) */ + int swd_maxactive; /* max active i/o reqs */ + struct buf swd_tab; /* buffer list */ + struct ucred *swd_cred; /* cred for file access */ #endif }; @@ -518,7 +521,8 @@ sys_swapctl(p, v, retval) struct swappri *spp; struct swapdev *sdp; struct swapent *sep; - int count, error, misc; + char userpath[PATH_MAX + 1]; + int count, error, misc, len; int priority; UVMHIST_FUNC("sys_swapctl"); UVMHIST_CALLED(pdhist); @@ -539,8 +543,8 @@ sys_swapctl(p, v, retval) UVMHIST_LOG(pdhist, "<- done SWAP_NSWAP=%d", uvmexp.nswapdev, 0, 0, 0); *retval = uvmexp.nswapdev; - lockmgr(&swap_syscall_lock, LK_RELEASE, (void *)0); - return (0); + error = 0; + goto out; } /* @@ -551,7 +555,11 @@ sys_swapctl(p, v, retval) * to grab the swap_data_lock because we may fault&sleep during * copyout() and we don't want to be holding that lock then! */ - if (SCARG(uap, cmd) == SWAP_STATS) { + if (SCARG(uap, cmd) == SWAP_STATS +#if defined(COMPAT_13) + || SCARG(uap, cmd) == SWAP_OSTATS +#endif + ) { sep = (struct swapent *)SCARG(uap, arg); count = 0; @@ -560,35 +568,53 @@ sys_swapctl(p, v, retval) for (sdp = spp->spi_swapdev.cqh_first; sdp != (void *)&spp->spi_swapdev && misc-- > 0; sdp = sdp->swd_next.cqe_next) { - /* backwards compatibility for system call */ - sdp->swd_se.se_inuse = - btodb(sdp->swd_npginuse * PAGE_SIZE); - error = copyout((caddr_t)&sdp->swd_se, - (caddr_t)sep, sizeof(struct swapent)); - if (error) { - lockmgr(&swap_syscall_lock, - LK_RELEASE, (void *)0); - return (error); - } + /* + * backwards compatibility for system call. + * note that we use 'struct oswapent' as an + * overlay into both 'struct swapdev' and + * the userland 'struct swapent', as we + * want to retain backwards compatibility + * with NetBSD 1.3. + */ + sdp->swd_ose.ose_inuse = + btodb(sdp->swd_npginuse * PAGE_SIZE); + error = copyout((caddr_t)&sdp->swd_ose, + (caddr_t)sep, sizeof(struct oswapent)); + + /* now copy out the path if necessary */ +#if defined(COMPAT_13) + if (error == 0 && SCARG(uap, cmd) == SWAP_STATS) +#else + if (error == 0) +#endif + error = copyout((caddr_t)sdp->swd_path, + (caddr_t)&sep->se_path, + sdp->swd_pathlen); + + if (error) + goto out; count++; - sep++; +#if defined(COMPAT_13) + if (SCARG(uap, cmd) == SWAP_OSTATS) + ((struct oswapent *)sep)++; + else +#endif + sep++; } } - UVMHIST_LOG(pdhist, "<-done SWAP_STATS", 0, 0, 0, 0); + UVMHIST_LOG(pdhist, "<- done SWAP_STATS", 0, 0, 0, 0); *retval = count; - lockmgr(&swap_syscall_lock, LK_RELEASE, (void *)0); - return (0); + error = 0; + goto out; } /* * all other requests require superuser privs. verify. */ - if ((error = suser(p->p_ucred, &p->p_acflag))) { - lockmgr(&swap_syscall_lock, LK_RELEASE, (void *)0); - return (error); - } + if ((error = suser(p->p_ucred, &p->p_acflag))) + goto out; /* * at this point we expect a path name in arg. we will @@ -596,23 +622,34 @@ sys_swapctl(p, v, retval) * the vnode (VOP_LOCK). * * XXX: a NULL arg means use the root vnode pointer (e.g. for - * miniroot + * miniroot) */ if (SCARG(uap, arg) == NULL) { vp = rootvp; /* miniroot */ if (vget(vp, LK_EXCLUSIVE)) { - lockmgr(&swap_syscall_lock, LK_RELEASE, - (void *)0); - return (EBUSY); + error = EBUSY; + goto out; } + if (SCARG(uap, cmd) == SWAP_ON && + copystr("miniroot", userpath, sizeof userpath, &len)) + panic("swapctl: miniroot copy failed"); } else { - NDINIT(&nd, LOOKUP, FOLLOW|LOCKLEAF, UIO_USERSPACE, - SCARG(uap, arg), p); - if ((error = namei(&nd))) { - lockmgr(&swap_syscall_lock, LK_RELEASE, - (void *)0); - return (error); + int space; + char *where; + + if (SCARG(uap, cmd) == SWAP_ON) { + if ((error = copyinstr(SCARG(uap, arg), userpath, + sizeof userpath, &len))) + goto out; + space = UIO_SYSSPACE; + where = userpath; + } else { + space = UIO_USERSPACE; + where = (char *)SCARG(uap, arg); } + NDINIT(&nd, LOOKUP, FOLLOW|LOCKLEAF, space, where, p); + if ((error = namei(&nd))) + goto out; vp = nd.ni_vp; } /* note: "vp" is referenced and locked */ @@ -652,7 +689,7 @@ sys_swapctl(p, v, retval) if ((sdp = swaplist_find(vp, 0)) != NULL) { error = EBUSY; simple_unlock(&swap_data_lock); - goto bad; + break; } sdp = (struct swapdev *) malloc(sizeof *sdp, M_VMSWAP, M_WAITOK); @@ -672,6 +709,11 @@ sys_swapctl(p, v, retval) swaplist_insert(sdp, spp, priority); simple_unlock(&swap_data_lock); + sdp->swd_pathlen = len; + sdp->swd_path = malloc(sdp->swd_pathlen, M_VMSWAP, M_WAITOK); + if ((error = copystr(userpath, sdp->swd_path, + sdp->swd_pathlen, 0))) + break; /* * we've now got a FAKE placeholder in the swap list. * now attempt to enable swap on it. if we fail, undo @@ -717,11 +759,11 @@ sys_swapctl(p, v, retval) if ((sdp->swd_flags & (SWF_INUSE|SWF_ENABLE)) == 0) { simple_unlock(&swap_data_lock); error = EBUSY; - goto bad; + break; } /* XXXCDC: should we call with list locked or unlocked? */ if ((error = swap_off(p, sdp)) != 0) - goto bad; + break; /* XXXCDC: might need relock here */ /* @@ -744,11 +786,11 @@ sys_swapctl(p, v, retval) error = EINVAL; } -bad: /* * done! use vput to drop our reference and unlock */ vput(vp); +out: lockmgr(&swap_syscall_lock, LK_RELEASE, (void *)0); UVMHIST_LOG(pdhist, "<- done! error=%d", error, 0, 0, 0); @@ -858,7 +900,7 @@ swap_on(p, sdp) * save nblocks in a safe place and convert to pages. */ - sdp->swd_se.se_nblks = nblocks; + sdp->swd_ose.ose_nblks = nblocks; npages = dbtob((u_int64_t)nblocks) / PAGE_SIZE; /* diff --git a/sys/vm/vm_swap.c b/sys/vm/vm_swap.c index 1d76af137179..8b51f4ca877a 100644 --- a/sys/vm/vm_swap.c +++ b/sys/vm/vm_swap.c @@ -1,4 +1,4 @@ -/* $NetBSD: vm_swap.c,v 1.58 1998/08/09 21:58:53 perry Exp $ */ +/* $NetBSD: vm_swap.c,v 1.59 1998/08/29 13:27:50 mrg Exp $ */ /* * Copyright (c) 1995, 1996, 1997 Matthew R. Green @@ -29,6 +29,7 @@ */ #include "fs_nfs.h" +#include "opt_compat_netbsd.h" #include #include @@ -112,12 +113,14 @@ int vmswapdebug = 0; #define SWAP_TO_FILES struct swapdev { - struct swapent swd_se; -#define swd_dev swd_se.se_dev -#define swd_flags swd_se.se_flags -#define swd_nblks swd_se.se_nblks -#define swd_inuse swd_se.se_inuse -#define swd_priority swd_se.se_priority + struct oswapent swd_ose; +#define swd_dev swd_ose.ose_dev +#define swd_flags swd_ose.ose_flags +#define swd_nblks swd_ose.ose_nblks +#define swd_inuse swd_ose.ose_inuse +#define swd_priority swd_ose.ose_priority + char *swd_path; + int swd_pathlen; daddr_t swd_mapoffset; int swd_mapsize; struct extent *swd_ex; @@ -347,7 +350,8 @@ sys_swapctl(p, v, retval) struct swappri *spp; struct swapdev *sdp; struct swapent *sep; - int count, error, misc; + char userpath[PATH_MAX + 1]; + int count, error, misc, len; int priority; misc = SCARG(uap, misc); @@ -362,7 +366,11 @@ sys_swapctl(p, v, retval) } /* stats on the swap devices. */ - if (SCARG(uap, cmd) == SWAP_STATS) { + if (SCARG(uap, cmd) == SWAP_STATS +#if defined(COMPAT_13) + || SCARG(uap, cmd) == SWAP_OSTATS +#endif + ) { sep = (struct swapent *)SCARG(uap, arg); count = 0; @@ -374,14 +382,38 @@ sys_swapctl(p, v, retval) for (sdp = spp->spi_swapdev.cqh_first; sdp != (void *)&spp->spi_swapdev && misc-- > 0; sdp = sdp->swd_next.cqe_next) { - error = copyout((caddr_t)&sdp->swd_se, - (caddr_t)sep, sizeof(struct swapent)); + /* + * backwards compatibility for system call. + * note that we use 'struct oswapent' as an + * overlay into both 'struct swapdev' and + * the userland 'struct swapent', as we + * want to retain backwards compatibility + * with NetBSD 1.3. + */ + error = copyout((caddr_t)&sdp->swd_ose, + (caddr_t)sep, sizeof(struct oswapent)); + + /* now copy out the path if necessary */ +#if defined(COMPAT_13) + if (error == 0 && SCARG(uap, cmd) == SWAP_STATS) +#else + if (error == 0) +#endif + error = copyout((caddr_t)sdp->swd_path, + (caddr_t)&sep->se_path, + sdp->swd_pathlen); if (error) - break; + goto out; count++; - sep++; +#if defined(COMPAT_13) + if (SCARG(uap, cmd) == SWAP_OSTATS) + ((struct oswapent *)sep)++; + else +#endif + sep++; } } +out: (void)lockmgr(&swaplist_change_lock, LK_RELEASE, (void *)0); if (error) return (error); @@ -399,9 +431,24 @@ sys_swapctl(p, v, retval) vp = rootvp; if (vget(vp, LK_EXCLUSIVE)) return (EBUSY); + if (SCARG(uap, cmd) == SWAP_ON && + copystr("miniroot", userpath, sizeof userpath, &len)) + panic("swapctl: miniroot copy failed"); } else { - NDINIT(&nd, LOOKUP, FOLLOW|LOCKLEAF, UIO_USERSPACE, - SCARG(uap, arg), p); + int space; + char *where; + + if (SCARG(uap, cmd) == SWAP_ON) { + if ((error = copyinstr(SCARG(uap, arg), userpath, + sizeof userpath, &len))) + return (error); + space = UIO_USERSPACE; + where = userpath; + } else { + space = UIO_SYSSPACE; + where = (char *)SCARG(uap, arg); + } + NDINIT(&nd, LOOKUP, FOLLOW|LOCKLEAF, space, where, p); if ((error = namei(&nd))) return (error); @@ -450,6 +497,11 @@ sys_swapctl(p, v, retval) if (vp->v_type == VREG) sdp->swd_cred = crdup(p->p_ucred); #endif + sdp->swd_pathlen = len; + sdp->swd_path = malloc(sdp->swd_pathlen, M_VMSWAP, M_WAITOK); + if ((error = copystr(userpath, sdp->swd_path, + sdp->swd_pathlen, 0))) + break; insert_swapdev(sdp, priority); /* Keep reference to vnode */ diff --git a/sys/vm/vm_swap.h b/sys/vm/vm_swap.h index 60f8a1f6e55c..980c983647f7 100644 --- a/sys/vm/vm_swap.h +++ b/sys/vm/vm_swap.h @@ -1,4 +1,4 @@ -/* $NetBSD: vm_swap.h,v 1.8 1998/02/10 14:09:08 mrg Exp $ */ +/* $NetBSD: vm_swap.h,v 1.9 1998/08/29 13:27:51 mrg Exp $ */ /* * Copyright (c) 1995, 1996 Matthew R. Green @@ -31,24 +31,43 @@ #ifndef _VM_VM_SWAP_H_ #define _VM_VM_SWAP_H_ +#include + #if defined(_KERNEL) && !defined(_LKM) #include "opt_uvm.h" #endif /* These structures are used to return swap information for userland */ + +/* + * NetBSD 1.3 swapctl(SWAP_STATS, ...) swapent structure; now used as an + * overlay for both the new swapent structure, and the hidden swapdev + * structure (see vm_swap.c). + */ +struct oswapent { + dev_t ose_dev; /* device id */ + int ose_flags; /* flags */ + int ose_nblks; /* total blocks */ + int ose_inuse; /* blocks in use */ + int ose_priority; /* priority of this device */ +}; + struct swapent { - dev_t se_dev; - int se_flags; - int se_nblks; - int se_inuse; - int se_priority; + struct oswapent se_ose; +#define se_dev se_ose.ose_dev +#define se_flags se_ose.ose_flags +#define se_nblks se_ose.ose_nblks +#define se_inuse se_ose.ose_inuse +#define se_priority se_ose.ose_priority + char se_path[PATH_MAX+1]; /* path name */ }; #define SWAP_ON 1 #define SWAP_OFF 2 #define SWAP_NSWAP 3 -#define SWAP_STATS 4 -#define SWAP_CTL 5 +#define SWAP_OSTATS 4 +#define SWAP_CTL 5 +#define SWAP_STATS 6 #define SWF_INUSE 0x00000001 #define SWF_ENABLE 0x00000002