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: /* --------------------------- */