Commit | Line | Data |
---|---|---|
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 | */ | |
24 | swstrategy(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 | 72 | swapon() |
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 | */ | |
119 | swfree(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 | } |