|
|
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.