|
|
1.1 root 1: /*
2: * indirect driver for swapping
3: */
4:
5: #include "sys/param.h"
6: #include "sys/systm.h"
7: #include "sys/buf.h"
8: #include "sys/conf.h"
9: #include "sys/user.h"
10: #include "sys/inode.h"
11: #include "sys/map.h"
12:
13: struct buf rswbuf;
14: extern struct map swapmap[];
15: extern int swmapcnt;
16: extern struct map argmap[];
17: extern int argcnt;
18:
19: int swopen(), swstrategy(), swread(), swwrite();
20:
21: struct bdevsw swbdev = bdinit(swopen, nulldev, swstrategy, 0);
22:
23: struct cdevsw swcdev = cdinit(swopen, nulldev, swread, swwrite, nodev);
24:
25: /*
26: * presumably called for the first time on boot
27: */
28: swopen(dev, flag)
29: dev_t dev;
30: int flag;
31: {
32: static int opened;
33:
34: if (opened)
35: return;
36: opened++;
37: swfree(0);
38: }
39:
40: swstrategy(bp)
41: register struct buf *bp;
42: {
43: register clicks_t sz;
44: register daddr_t off;
45: register int seg;
46: dev_t dev;
47:
48: sz = btoc(bp->b_bcount);
49: off = bp->b_blkno % dmmax;
50: seg = bp->b_blkno / dmmax;
51: dev = swdevt[seg % nswdevt].sw_dev;
52: if (bdevsw[major(dev)] == 0)
53: panic("swstrategy");
54: bp->b_blkno = seg / nswdevt;
55: bp->b_blkno *= dmmax;
56: bp->b_blkno += off;
57: bp->b_dev = dev;
58: if (bp->b_blkno+sz > swdevt[seg % nswdevt].sw_size
59: || off+sz > dmmax) {
60: bp->b_flags |= B_ERROR;
61: iodone(bp);
62: return;
63: }
64: (*bdevsw[major(dev)]->d_strategy)(bp);
65: }
66:
67: swread(dev)
68: {
69:
70: physio(swstrategy, &rswbuf, dev, B_READ, minphys);
71: }
72:
73: swwrite(dev)
74: {
75:
76: physio(swstrategy, &rswbuf, dev, B_WRITE, minphys);
77: }
78:
79: /*
80: * System call swapon(name) enables swapping on device name,
81: * which must be in the swdevsw. Return EBUSY
82: * if already swapping on this device.
83: * silly; this should just be an ioctl.
84: *
85: * -- assume swapping on a regular filesystem,
86: * so directly calling thought bdevsw is what we want.
87: * some day this will be unfortunate.
88: */
89: vswapon()
90: {
91: struct a {
92: char *fname;
93: };
94: register struct inode *ip;
95: dev_t dev;
96: register int i;
97:
98: ip = namei(((struct a *)u.u_ap)->fname, SEGUDATA, &nilargnamei, 1);
99: if (ip == NULL)
100: return;
101: if ((ip->i_mode&IFMT) != IFBLK || ip->i_fstyp != 0) {
102: u.u_error = EINVAL;
103: iput(ip);
104: return;
105: }
106: dev = (dev_t)ip->i_un.i_rdev;
107: iput(ip);
108: for (i = 0; i < nswdevt; i++) {
109: if (swdevt[i].sw_dev != dev)
110: continue;
111: if (swdevt[i].sw_freed) {
112: u.u_error = EBUSY;
113: return;
114: }
115: swfree(i);
116: return;
117: }
118: u.u_error = ENODEV;
119: }
120:
121: /*
122: * Swfree(index) frees the index'th portion of the swap map.
123: * Each of the nswdevt devices provides 1/nswdev'th of the swap
124: * space, which is laid out with blocks of dmmax pages circularly
125: * among the devices.
126: * rmalloc starts at 1, so give the first dmmax/2 pages of the first device
127: * to the arg device.
128: * quietly opens the device, with no trace in inode table
129: * subsequently really opening and closing the device may cause trouble?
130: */
131: swfree(index)
132: register int index;
133: {
134: register swblk_t bno;
135: register int nblk;
136: register int xsize;
137: extern int argcnt, swmapcnt;
138:
139: bdevopen(swdevt[index].sw_dev);
140: if (u.u_error)
141: return;
142: xsize = swdevt[index].sw_size * nswdevt;
143: xsize += index * dmmax;
144: xsize -= (nswdevt - 1) * (swdevt[index].sw_size % dmmax);
145: for (bno = dmmax * index; bno < xsize; bno += dmmax * nswdevt) {
146: nblk = xsize - bno;
147: if (nblk > dmmax)
148: nblk = dmmax;
149: if (bno)
150: rmfree(swapmap, nblk, (int)bno);
151: else {
152: argdev = swdevt[0].sw_dev;
153: rminit(argmap, argcnt, nblk/2-CLSIZE, CLSIZE);
154: rminit(swapmap, swmapcnt, nblk/2, nblk/2);
155: }
156: }
157: swdevt[index].sw_freed = 1;
158: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.