BSD 4_3_Tahoe release
[unix-history] / usr / src / sys / sys / vm_sw.c
CommitLineData
da7c5cc6 1/*
0880b18e 2 * Copyright (c) 1982, 1986 Regents of the University of California.
da7c5cc6
KM
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
ca67e7b4 6 * @(#)vm_sw.c 7.3 (Berkeley) 5/6/88
da7c5cc6 7 */
013037be 8
94368568
JB
9#include "param.h"
10#include "systm.h"
11#include "buf.h"
12#include "conf.h"
13#include "dir.h"
14#include "user.h"
15#include "inode.h"
16#include "map.h"
17#include "uio.h"
18#include "file.h"
ec67a3ce 19#include "stat.h"
013037be 20
013037be
BJ
21/*
22 * Indirect driver for multi-controller paging.
23 */
24swstrategy(bp)
25 register struct buf *bp;
26{
ec67a3ce
MK
27 int sz, off, seg, index;
28 register struct swdevt *sp;
013037be 29
b9ee5d20
BJ
30#ifdef GENERIC
31 /*
32 * A mini-root gets copied into the front of the swap
33 * and we run over top of the swap area just long
34 * enough for us to do a mkfs and restor of the real
35 * root (sure beats rewriting standalone restor).
36 */
8c5046eb 37#define MINIROOTSIZE 4096
b9ee5d20
BJ
38 if (rootdev == dumpdev)
39 bp->b_blkno += MINIROOTSIZE;
40#endif
ca1f746a 41 sz = howmany(bp->b_bcount, DEV_BSIZE);
d668d9ba 42 if (bp->b_blkno+sz > nswap) {
013037be 43 bp->b_flags |= B_ERROR;
ec67a3ce 44 biodone(bp);
013037be
BJ
45 return;
46 }
d668d9ba
SL
47 if (nswdev > 1) {
48 off = bp->b_blkno % dmmax;
49 if (off+sz > dmmax) {
50 bp->b_flags |= B_ERROR;
ec67a3ce 51 biodone(bp);
d668d9ba
SL
52 return;
53 }
54 seg = bp->b_blkno / dmmax;
ec67a3ce 55 index = seg % nswdev;
d668d9ba
SL
56 seg /= nswdev;
57 bp->b_blkno = seg*dmmax + off;
58 } else
ec67a3ce
MK
59 index = 0;
60 sp = &swdevt[index];
ec67a3ce
MK
61 bp->b_dev = sp->sw_dev;
62 if (bp->b_dev == 0)
013037be 63 panic("swstrategy");
ec67a3ce 64 (*bdevsw[major(bp->b_dev)].d_strategy)(bp);
013037be
BJ
65}
66
67/*
68 * System call swapon(name) enables swapping on device name,
69 * which must be in the swdevsw. Return EBUSY
70 * if already swapping on this device.
71 */
2dfa06c1 72swapon()
013037be 73{
2dfa06c1
SL
74 struct a {
75 char *name;
715baff1 76 } *uap = (struct a *)u.u_ap;
013037be
BJ
77 register struct inode *ip;
78 dev_t dev;
79 register struct swdevt *sp;
715baff1 80 register struct nameidata *ndp = &u.u_nd;
013037be 81
dca9bb95
KM
82 if (!suser())
83 return;
715baff1
KM
84 ndp->ni_nameiop = LOOKUP | FOLLOW;
85 ndp->ni_segflg = UIO_USERSPACE;
86 ndp->ni_dirp = uap->name;
87 ip = namei(ndp);
013037be
BJ
88 if (ip == NULL)
89 return;
90 if ((ip->i_mode&IFMT) != IFBLK) {
91 u.u_error = ENOTBLK;
92 iput(ip);
93 return;
94 }
76e9203a 95 dev = (dev_t)ip->i_rdev;
013037be
BJ
96 iput(ip);
97 if (major(dev) >= nblkdev) {
98 u.u_error = ENXIO;
99 return;
100 }
ae0ffeb1 101 for (sp = &swdevt[0]; sp->sw_dev; sp++)
013037be
BJ
102 if (sp->sw_dev == dev) {
103 if (sp->sw_freed) {
104 u.u_error = EBUSY;
105 return;
106 }
ec67a3ce 107 u.u_error = swfree(sp - swdevt);
013037be
BJ
108 return;
109 }
ae0ffeb1 110 u.u_error = EINVAL;
013037be
BJ
111}
112
113/*
114 * Swfree(index) frees the index'th portion of the swap map.
115 * Each of the nswdev devices provides 1/nswdev'th of the swap
d668d9ba 116 * space, which is laid out with blocks of dmmax pages circularly
013037be
BJ
117 * among the devices.
118 */
119swfree(index)
120 int index;
121{
ec67a3ce 122 register struct swdevt *sp;
013037be 123 register swblk_t vsbase;
39d536e6 124 register long blk;
e438ed8e 125 dev_t dev;
d668d9ba
SL
126 register swblk_t dvbase;
127 register int nblks;
ec67a3ce 128 int error;
013037be 129
ec67a3ce
MK
130 sp = &swdevt[index];
131 dev = sp->sw_dev;
132 if (error = (*bdevsw[major(dev)].d_open)(dev, FREAD|FWRITE, S_IFBLK))
133 return (error);
134 sp->sw_freed = 1;
135 nblks = sp->sw_nblks;
d668d9ba
SL
136 for (dvbase = 0; dvbase < nblks; dvbase += dmmax) {
137 blk = nblks - dvbase;
138 if ((vsbase = index*dmmax + dvbase*nswdev) >= nswap)
139 panic("swfree");
140 if (blk > dmmax)
141 blk = dmmax;
013037be
BJ
142 if (vsbase == 0) {
143 /*
144 * Can't free a block starting at 0 in the swapmap
c84ff1f9 145 * but need some space for argmap so use 1/2 this
013037be
BJ
146 * hunk which needs special treatment anyways.
147 */
ec67a3ce 148 argdev = sp->sw_dev;
e438ed8e
BJ
149 rminit(argmap, (long)(blk/2-ctod(CLSIZE)),
150 (long)ctod(CLSIZE), "argmap", ARGMAPSIZE);
c84ff1f9
BJ
151 /*
152 * First of all chunks... initialize the swapmap
153 * the second half of the hunk.
154 */
a29f7995
BJ
155 rminit(swapmap, (long)blk/2, (long)blk/2,
156 "swap", nswapmap);
ec67a3ce
MK
157 } else if (dvbase == 0) {
158 /*
159 * Don't use the first cluster of the device
160 * in case it starts with a label or boot block.
161 */
162 rmfree(swapmap, blk - ctod(CLSIZE),
163 vsbase + ctod(CLSIZE));
013037be 164 } else
c84ff1f9 165 rmfree(swapmap, blk, vsbase);
013037be 166 }
ec67a3ce 167 return (0);
013037be 168}