|
|
1.1 root 1: /*
2: * This file contains the routines which support mounted
3: * streams (file system type 3).
4: */
5: #include "sys/param.h"
6: #include "sys/systm.h"
7: #include "sys/inode.h"
8: #include "sys/stream.h"
9: #include "sys/user.h"
10: #include "sys/file.h"
11: #include "sys/stat.h"
12: #include "sys/conf.h"
13:
14: int msupdat(), msread(), mswrite(), msstat();
15: int msmount(), msioctl();
16: struct inode *msopen();
17: struct fstypsw msfs =
18: fsinit(nulldev, msupdat, msread, mswrite, nulldev, msstat,
19: nullnami, msmount, msioctl, msopen, nodev);
20:
21: /*
22: * The following definitions apply to all comments:
23: * - `locked' means that an inode has had `plock' applied to it
24: * - `reserved' means that the inode's i_count has been incremented to
25: * ensure that the inode will be freed during an operation.
26: */
27:
28: /*
29: * To ensure consistency
30: */
31: #define SETMOUNT(d,r) d->i_mroot = r
32: #define CLRMOUNT(d) d->i_mroot = NULL
33:
34: msmount(cip, dip, flag, mnt, fstyp)
35: struct inode *cip, *dip;
36: {
37:
38: if(accowner(dip) == 0) /* only owner can mount */
39: return; /* errno set by accowner */
40:
41: if (mnt) {
42: /*
43: * from fmount(), `dip' is locked and reserved
44: */
45: mson(cip, dip, flag, fstyp);
46: /*
47: * iput occurs in fmount();
48: */
49: } else {
50: /*
51: * from fmount(), nothing locked or reserved
52: */
53: msoff(dip, 0);
54: }
55: }
56:
57: /*
58: * Create an in core root node, mount it, and attach a communications inode.
59: * On entry, `dip' is locked and reserved. On exit, `dip' is still locked
60: * and reserved (i.e. shoud be iput).
61: */
62: mson(cip, dip, flag, fstyp)
63: register struct inode *cip; /* stream being mounted */
64: register struct inode *dip; /* mount point */
65: {
66: register struct inode *rip; /* root inode for new fs */
67:
68: /* must be mounting a stream */
69: if(cip->i_sptr == NULL) {
70: u.u_error = ENXIO;
71: return;
72: }
73:
74: /* already mounted? */
75: if(dip->i_fstyp == fstyp) {
76: u.u_error = EBUSY; /* in use */
77: return;
78: }
79:
80: /* create a new inode for the fs root */
81: rip = iuniq(fstyp);
82: if(rip == NULL)
83: return; /* errno already set */
84: rip->i_un.i_cip = cip;
85: rip->i_mpoint = dip;
86: rip->i_mode &= IFMT;
87: rip->i_mode |= dip->i_mode & ~IFMT;
88: rip->i_flag |= IACC; /* force update */
89: prele(rip);
90: cip->i_count++;
91:
92: /* mount the root */
93: SETMOUNT(dip,rip);
94: dip->i_count++;
95: }
96:
97: /*
98: * Unmount the stream and close it if approriate.
99: * On entry, `dip' is neither reserved or locked.
100: */
101: msoff(dip, rlocked)
102: register struct inode *dip; /* mount point */
103: {
104: register struct inode *rip; /* root inode */
105: register struct inode *cip; /* mounted stream */
106:
107: /* if not mounted, we're done */
108: if (dip->i_mroot==NULL)
109: return;
110:
111: /*
112: * To avoid deadlock, always lock the resources in the same order.
113: * Since the root may already be locked on the way in, it comes
114: * first.
115: */
116: rip = dip->i_mroot;
117: if (!rlocked)
118: plock(rip);
119: plock(dip);
120:
121: /* make sure nothing changed while we were locking the inodes */
122: if (dip->i_mroot!=rip) {
123: prele(dip);
124: if (!rlocked)
125: prele(rip);
126: return;
127: }
128:
129: /* disassociate the stream from the mount point */
130: cip = rip->i_un.i_cip;
131: rip->i_un.i_cip = NULL;
132: if(cip != NULL) {
133: if(cip->i_count==1)
134: stclose(cip, 1);
135: iput(cip);
136: }
137:
138: /* unmount root from file system */
139: rip->i_mpoint = NULL;
140: CLRMOUNT(dip);
141: iput(dip);
142: iput(rip);
143: }
144:
145: /*
146: * If the node is still mounted and the stream has hung up,
147: * unmount it. On entry, rip is locked.
148: * This is called by `update()'.
149: *
150: * This is called because IACC is set in rip in mson above.
151: * update routines are meant to clear IACC|IUPD|ICHG, but
152: * we don't, so the calls keep coming.
153: *
154: * stat and open should probably check the stream too.
155: */
156: msupdat(rip, ta, tm, waitfor)
157: register struct inode *rip;
158: time_t *ta, *tm;
159: {
160: register struct inode *cip;
161: register struct inode *dip;
162:
163: cip = rip->i_un.i_cip;
164: if (cip==NULL || cip->i_sptr==NULL || cip->i_sptr->flag&HUNGUP) {
165: dip = rip->i_mpoint;
166: if (dip != NULL) {
167: if (!(rip->i_flag&ILOCK))
168: panic("msupdate: inode not locked");
169: msoff(dip, 1);
170: }
171: }
172: }
173:
174: /*
175: * Pass read onto the stream's inode.
176: * `rip' is locked during this operation.
177: */
178: msread(rip)
179: struct inode *rip;
180: {
181: register struct inode *cip;
182:
183: cip = rip->i_un.i_cip;
184: if (cip!=NULL)
185: readi(cip);
186: else
187: u.u_error = EPIPE;
188: }
189:
190: /*
191: * Pass write onto the stream's inode.
192: * `rip' is locked during this operation.
193: */
194: mswrite(rip)
195: struct inode *rip;
196: {
197: register struct inode *cip;
198:
199: cip = rip->i_un.i_cip;
200: if (cip!=NULL)
201: writei(cip);
202: else
203: u.u_error = EPIPE;
204: }
205:
206: /*
207: * Pass ioctl onto the stream's inode.
208: * `rip' is locked during this operation.
209: */
210: msioctl(rip, cmd, cmarg, flag)
211: register struct inode *rip;
212: caddr_t cmarg;
213: {
214: register struct inode *cip;
215:
216: cip = rip->i_un.i_cip;
217: if (cip!=NULL)
218: stioctl(cip, cmd, cmarg);
219: else
220: u.u_error = EPIPE;
221: }
222:
223: /*
224: * stat `mounted' inode
225: */
226: msstat(rip, ub)
227: struct inode *rip;
228: struct stat *ub;
229: {
230: struct stat ds;
231:
232: ds.st_dev = rip->i_dev;
233: ds.st_ino = rip->i_number;
234: ds.st_mode = rip->i_mode;
235: ds.st_nlink = 0;
236: ds.st_uid = rip->i_uid;
237: ds.st_gid = rip->i_gid;
238: ds.st_rdev = (dev_t)0;
239: ds.st_size = 0;
240: ds.st_atime = time;
241: ds.st_mtime = time;
242: ds.st_ctime = time;
243: if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
244: u.u_error = EFAULT;
245: }
246:
247: /*
248: * Change an open of the root into a stopen of the communications inode.
249: */
250: struct inode *
251: msopen(rip, rw)
252: register struct inode *rip;
253: {
254: register struct inode *cip;
255: register struct inode *nip;
256:
257: /*
258: * Locking the root also locks out cip changes.
259: */
260: plock(rip);
261:
262: /* return error if stream is dead */
263: cip = rip->i_un.i_cip;
264: if (cip==NULL||cip->i_sptr==NULL||cip->i_sptr->flag&HUNGUP) {
265: u.u_error = ENXIO;
266: iput(rip);
267: return(NULL);
268: }
269:
270: /*
271: * Reopen stream, perhaps returning a fresh inode,
272: * or NULL on error, which is what we should do too.
273: * either this is a fresh reference to cip, or stopen will iput.
274: */
275: cip->i_count++;
276: nip = stopen((struct streamtab *)NULL, cip->i_un.i_rdev, rw, cip);
277: iput(rip);
278: return(nip);
279: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.