7250: #
7251: #include "../param.h"
7252: #include "../systm.h"
7253: #include "../user.h"
7254: #include "../inode.h"
7255: #include "../filsys.h"
7256: #include "../conf.h"
7257: #include "../buf.h"
7258:
7259: /*
7260: * Look up an inode by device,inumber.
7261: * If it is in core (in the inode structure),
7262: * honor the locking protocol.
7263: * If it is not in core, read it in from the
7264: * specified device.
7265: * If the inode is mounted on, perform
7266: * the indicated indirection.
7267: * In all cases, a pointer to a locked
7268: * inode structure is returned.
7269: *
7270: * printf warning: no inodes -- if the inode
7271: * structure is full
7272: * panic: no imt -- if the mounted file
7273: * system is not in the mount table.
7274: * "cannot happen"
7275: */
7276: iget(dev, ino)
7277: {
7278: register struct inode *p;
7279: register *ip2;
7280: int *ip1;
7281: register struct mount *ip;
7282:
7283: loop:
7284: ip = NULL;
7285: for(p = &inode[0]; p < &inode[NINODE]; p++) {
7286: if(dev==p->i_dev && ino==p->i_number) {
7287: if((p->i_flag&ILOCK) != 0) {
7288: p->i_flag =| IWANT;
7289: sleep(p, PINOD);
7290: goto loop;
7291: }
7292: if((p->i_flag&IMOUNT) != 0) {
7293:
7294: for(ip = &mount[0]; ip < &mount[NMOUNT]; ip++)
7295: if(ip->m_inodp == p) {
7296: dev = ip->m_dev;
7297: ino = ROOTINO;
7298: goto loop;
7299: }
7300: panic("no imt");
7301: }
7302: p->i_count++;
7303: p->i_flag =| ILOCK;
7304: return(p);
7305: }
7306: if(ip==NULL && p->i_count==0)
7307: ip = p;
7308: }
7309: if((p=ip) == NULL) {
7310: printf("Inode table overflow\n");
7311: u.u_error = ENFILE;
7312: return(NULL);
7313: }
7314: p->i_dev = dev;
7315: p->i_number = ino;
7316: p->i_flag = ILOCK;
7317: p->i_count++;
7318: p->i_lastr = -1;
7319: ip = bread(dev, ldiv(ino+31,16));
7320: /*
7321: * Check I/O errors
7322: */
7323: if (ip->b_flags&B_ERROR) {
7324: brelse(ip);
7325: iput(p);
7326: return(NULL);
7327: }
7328: ip1 = ip->b_addr + 32*lrem(ino+31, 16);
7329: ip2 = &p->i_mode;
7330: while(ip2 < &p->i_addr[8])
7331: *ip2++ = *ip1++;
7332: brelse(ip);
7333: return(p);
7334: }
7335: /* --------------------------- */
7336:
7337: /*
7338: * Decrement reference count of
7339: * an inode structure.
7340: * On the last reference,
7341: * write the inode out and if necessary,
7342: * truncate and deallocate the file.
7343: */
7344: iput(p)
7345: struct inode *p;
7346: {
7347: register *rp;
7348:
7349: rp = p;
7350: if(rp->i_count == 1) {
7351: rp->i_flag =| ILOCK;
7352: if(rp->i_nlink <= 0) {
7353: itrunc(rp);
7354: rp->i_mode = 0;
7355: ifree(rp->i_dev, rp->i_number);
7356: }
7357: iupdat(rp, time);
7358: prele(rp);
7359: rp->i_flag = 0;
7360: rp->i_number = 0;
7361: }
7362: rp->i_count--;
7363: prele(rp);
7364: }
7365: /* --------------------------- */
7366:
7367: /*
7368: * Check accessed and update flags on
7369: * an inode structure.
7370: * If either is on, update the inode
7371: * with the corresponding dates
7372: * set to the argument tm.
7373: */
7374: iupdat(p, tm)
7375: int *p;
7376: int *tm;
7377: {
7378: register *ip1, *ip2, *rp;
7379: int *bp, i;
7380:
7381: rp = p;
7382: if((rp->i_flag&(IUPD|IACC)) != 0) {
7383: if(getfs(rp->i_dev)->s_ronly)
7384: return;
7385: i = rp->i_number+31;
7386: bp = bread(rp->i_dev, ldiv(i,16));
7387: ip1 = bp->b_addr + 32*lrem(i, 16);
7388: ip2 = &rp->i_mode;
7389: while(ip2 < &rp->i_addr[8])
7390: *ip1++ = *ip2++;
7391: if(rp->i_flag&IACC) {
7392: *ip1++ = time[0];
7393: *ip1++ = time[1];
7394: } else
7395: ip1 =+ 2;
7396: if(rp->i_flag&IUPD) {
7397: *ip1++ = *tm++;
7398: *ip1++ = *tm;
7399: }
7400: bwrite(bp);
7401: }
7402: }
7403: /* --------------------------- */
7404:
7405: /*
7406: * Free all the disk blocks associated
7407: * with the specified inode structure.
7408: * The blocks of the file are removed
7409: * in reverse order. This FILO
7410: * algorithm will tend to maintain
7411: * a contiguous free list much longer
7412: * than FIFO.
7413: */
7414: itrunc(ip)
7415: int *ip;
7416: {
7417: register *rp, *bp, *cp;
7418: int *dp, *ep;
7419:
7420: rp = ip;
7421: if((rp->i_mode&(IFCHR&IFBLK)) != 0)
7422: return;
7423: for(ip = &rp->i_addr[7]; ip >= &rp->i_addr[0]; ip--)
7424: if(*ip) {
7425: if((rp->i_mode&ILARG) != 0) {
7426: bp = bread(rp->i_dev, *ip);
7427:
7428: for(cp = bp->b_addr+512; cp >= bp->b_addr; cp--)
7429: if(*cp) {
7430: if(ip == &rp->i_addr[7]) {
7431: dp = bread(rp->i_dev, *cp);
7432:
7433: for(ep = dp->b_addr+512; ep >= dp->b_addr; ep--)
7434: if(*ep)
7435: free(rp->i_dev, *ep);
7436: brelse(dp);
7437: }
7438: free(rp->i_dev, *cp);
7439: }
7440: brelse(bp);
7441: }
7442: free(rp->i_dev, *ip);
7443: *ip = 0;
7444: }
7445: rp->i_mode =& ~ILARG;
7446: rp->i_size0 = 0;
7447: rp->i_size1 = 0;
7448: rp->i_flag =| IUPD;
7449: }
7450: /* --------------------------- */
7451:
7452: /*
7453: * Make a new file.
7454: */
7455: maknode(mode)
7456: {
7457: register *ip;
7458:
7459: ip = ialloc(u.u_pdir->i_dev);
7460: if (ip==NULL)
7461: return(NULL);
7462: ip->i_flag =| IACC|IUPD;
7463: ip->i_mode = mode|IALLOC;
7464: ip->i_nlink = 1;
7465: ip->i_uid = u.u_uid;
7466: ip->i_gid = u.u_gid;
7467: wdir(ip);
7468: return(ip);
7469: }
7470: /* --------------------------- */
7471:
7472: /*
7473: * Write a directory entry with
7474: * parameters left as side effects
7475: * to a call to namei.
7476: */
7477: wdir(ip)
7478: int *ip;
7479: {
7480: register char *cp1, *cp2;
7481:
7482: u.u_dent.u_ino = ip->i_number;
7483: cp1 = &u.u_dent.u_name[0];
7484: for(cp2 = &u.u_dbuf[0]; cp2 < &u.u_dbuf[DIRSIZ];)
7485: *cp1++ = *cp2++;
7486: u.u_count = DIRSIZ+2;
7487: u.u_segflg = 1;
7488: u.u_base = &u.u_dent;
7489: writei(u.u_pdir);
7490: iput(u.u_pdir);
7491: }
7492: /* --------------------------- */