convert to new syscall convention
[unix-history] / usr / src / sys / vm / vm_swap.c
CommitLineData
da7c5cc6 1/*
c4ec2128
KM
2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3 * All rights reserved.
da7c5cc6 4 *
c4ec2128
KM
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 *
0f93ba7b 17 * @(#)vm_swap.c 7.11 (Berkeley) %G%
da7c5cc6 18 */
013037be 19
94368568
JB
20#include "param.h"
21#include "systm.h"
22#include "buf.h"
23#include "conf.h"
94368568 24#include "user.h"
c4ec2128 25#include "vnode.h"
0f93ba7b 26#include "specdev.h"
94368568 27#include "map.h"
94368568 28#include "file.h"
ec67a3ce 29#include "stat.h"
013037be 30
013037be
BJ
31/*
32 * Indirect driver for multi-controller paging.
33 */
34swstrategy(bp)
35 register struct buf *bp;
36{
ec67a3ce
MK
37 int sz, off, seg, index;
38 register struct swdevt *sp;
013037be 39
b9ee5d20
BJ
40#ifdef GENERIC
41 /*
42 * A mini-root gets copied into the front of the swap
43 * and we run over top of the swap area just long
44 * enough for us to do a mkfs and restor of the real
45 * root (sure beats rewriting standalone restor).
46 */
8c5046eb 47#define MINIROOTSIZE 4096
b9ee5d20
BJ
48 if (rootdev == dumpdev)
49 bp->b_blkno += MINIROOTSIZE;
50#endif
ca1f746a 51 sz = howmany(bp->b_bcount, DEV_BSIZE);
d668d9ba 52 if (bp->b_blkno+sz > nswap) {
013037be 53 bp->b_flags |= B_ERROR;
ec67a3ce 54 biodone(bp);
013037be
BJ
55 return;
56 }
d668d9ba
SL
57 if (nswdev > 1) {
58 off = bp->b_blkno % dmmax;
59 if (off+sz > dmmax) {
60 bp->b_flags |= B_ERROR;
ec67a3ce 61 biodone(bp);
d668d9ba
SL
62 return;
63 }
64 seg = bp->b_blkno / dmmax;
ec67a3ce 65 index = seg % nswdev;
d668d9ba
SL
66 seg /= nswdev;
67 bp->b_blkno = seg*dmmax + off;
68 } else
ec67a3ce
MK
69 index = 0;
70 sp = &swdevt[index];
71#ifdef SECSIZE
72 bp->b_blkno <<= sp->sw_bshift;
73 bp->b_blksize = sp->sw_blksize;
74#endif SECSIZE
75 bp->b_dev = sp->sw_dev;
76 if (bp->b_dev == 0)
013037be 77 panic("swstrategy");
ec67a3ce 78 (*bdevsw[major(bp->b_dev)].d_strategy)(bp);
013037be
BJ
79}
80
013037be
BJ
81/*
82 * System call swapon(name) enables swapping on device name,
83 * which must be in the swdevsw. Return EBUSY
84 * if already swapping on this device.
85 */
2dfa06c1 86swapon()
013037be 87{
2dfa06c1
SL
88 struct a {
89 char *name;
715baff1 90 } *uap = (struct a *)u.u_ap;
c4ec2128 91 register struct vnode *vp;
013037be
BJ
92 dev_t dev;
93 register struct swdevt *sp;
715baff1 94 register struct nameidata *ndp = &u.u_nd;
013037be 95
849cbd39 96 if (u.u_error = suser(u.u_cred, &u.u_acflag))
dca9bb95 97 return;
715baff1
KM
98 ndp->ni_nameiop = LOOKUP | FOLLOW;
99 ndp->ni_segflg = UIO_USERSPACE;
100 ndp->ni_dirp = uap->name;
c4ec2128 101 if (u.u_error = namei(ndp))
013037be 102 return;
c4ec2128
KM
103 vp = ndp->ni_vp;
104 if (vp->v_type != VBLK) {
105 vrele(vp);
013037be 106 u.u_error = ENOTBLK;
013037be
BJ
107 return;
108 }
c4ec2128 109 dev = (dev_t)vp->v_rdev;
013037be 110 if (major(dev) >= nblkdev) {
c4ec2128 111 vrele(vp);
013037be
BJ
112 u.u_error = ENXIO;
113 return;
114 }
ae0ffeb1 115 for (sp = &swdevt[0]; sp->sw_dev; sp++)
013037be
BJ
116 if (sp->sw_dev == dev) {
117 if (sp->sw_freed) {
c4ec2128 118 vrele(vp);
013037be
BJ
119 u.u_error = EBUSY;
120 return;
121 }
ec67a3ce 122 u.u_error = swfree(sp - swdevt);
013037be
BJ
123 return;
124 }
c4ec2128 125 vrele(vp);
ae0ffeb1 126 u.u_error = EINVAL;
013037be
BJ
127}
128
ec67a3ce
MK
129#ifdef SECSIZE
130long argdbsize; /* XXX */
131
132#endif SECSIZE
013037be
BJ
133/*
134 * Swfree(index) frees the index'th portion of the swap map.
135 * Each of the nswdev devices provides 1/nswdev'th of the swap
d668d9ba 136 * space, which is laid out with blocks of dmmax pages circularly
013037be
BJ
137 * among the devices.
138 */
139swfree(index)
140 int index;
141{
609e7cfa 142 register struct swdevt *sp;
ec67a3ce 143 register struct swdevt *sp;
013037be 144 register swblk_t vsbase;
39d536e6 145 register long blk;
c4ec2128 146 struct vnode *vp;
d668d9ba
SL
147 register swblk_t dvbase;
148 register int nblks;
ec67a3ce 149 int error;
609e7cfa 150 int error;
013037be 151
ec67a3ce
MK
152 sp = &swdevt[index];
153 dev = sp->sw_dev;
154 if (error = (*bdevsw[major(dev)].d_open)(dev, FREAD|FWRITE, S_IFBLK))
155 return (error);
156 sp->sw_freed = 1;
157 nblks = sp->sw_nblks;
d668d9ba
SL
158 for (dvbase = 0; dvbase < nblks; dvbase += dmmax) {
159 blk = nblks - dvbase;
160 if ((vsbase = index*dmmax + dvbase*nswdev) >= nswap)
161 panic("swfree");
162 if (blk > dmmax)
163 blk = dmmax;
013037be
BJ
164 if (vsbase == 0) {
165 /*
166 * Can't free a block starting at 0 in the swapmap
c84ff1f9 167 * but need some space for argmap so use 1/2 this
013037be
BJ
168 * hunk which needs special treatment anyways.
169 */
ec67a3ce
MK
170 argdev = sp->sw_dev;
171#ifdef SECSIZE
172 argdbsize = sp->sw_blksize;
173 rminit(argmap,
174 ((blk / 2) * DEV_BSIZE - CLBYTES) / argdbsize,
175 CLBYTES / argdbsize, "argmap", ARGMAPSIZE);
176#else SECSIZE
e438ed8e
BJ
177 rminit(argmap, (long)(blk/2-ctod(CLSIZE)),
178 (long)ctod(CLSIZE), "argmap", ARGMAPSIZE);
ec67a3ce 179#endif SECSIZE
c84ff1f9
BJ
180 /*
181 * First of all chunks... initialize the swapmap
182 * the second half of the hunk.
183 */
c4ec2128 184 rminit(swapmap, (long)(blk/2), (long)(blk/2),
a29f7995 185 "swap", nswapmap);
ec67a3ce
MK
186 } else if (dvbase == 0) {
187 /*
188 * Don't use the first cluster of the device
189 * in case it starts with a label or boot block.
190 */
191 rmfree(swapmap, blk - ctod(CLSIZE),
192 vsbase + ctod(CLSIZE));
609e7cfa
MK
193 } else if (dvbase == 0) {
194 /*
195 * Don't use the first cluster of the device
196 * in case it starts with a label or boot block.
197 */
198 rmfree(swapmap, blk - ctod(CLSIZE),
199 vsbase + ctod(CLSIZE));
013037be 200 } else
c84ff1f9 201 rmfree(swapmap, blk, vsbase);
013037be 202 }
ec67a3ce 203 return (0);
609e7cfa 204 return (0);
013037be 205}