/* write changes back to disk if nessary. */ void iupdate(struct inode *ip){ struct super *sp; struct d_inode *itab; struct buf *bp; uint lba; /* if ((ip->i_flag & I_DIRTY)==0){ return; } */ sp = getsp(ip->i_dev); if (sp==NULL){ panic("bad super"); } // get the blk number where this inode lies in. bp = bread(ip->i_dev, IBLK(sp, ip->i_num)); if (bp->b_flag & B_ERROR) { panic("error on reading an inode"); } itab = (struct d_inode*)bp->b_data; // which different from above. memcpy(&itab[(ip->i_num-1)%IPB], ip, sizeof(struct d_inode)); ip->i_flag &= ~I_DIRTY; bwrite(bp); brelse(bp); return 0; }
/* lock given inode with flag I_BUSY * read the inode form disk if necessary * non-ref inode can not be lock (ref = 0) */ void ilock(struct inode *ip) { struct buf *bp; struct d_inode *d_ip; struct super_block sb; read_sb(ip->dev, &sb); int timeout = 20000; while (ip->flags & I_BUSY) { timeout--; hlt(); } ip->flags |= I_BUSY; /* need to be read form disk */ if (!(ip->flags & I_VALID)) { bp = bread(ip->dev, IBLK(sb, ip->ino)); d_ip = (struct d_inode *)bp->data + (ip->ino - 1)%IPB; /* ip -> dip */ ip->mode = d_ip->mode; ip->uid = d_ip->uid; ip->size = d_ip->size; ip->mtime = d_ip->mtime; ip->gid = d_ip->gid; ip->nlinks = d_ip->nlinks; memcpy(ip->zone, d_ip->zone, sizeof(d_ip->zone)); brelse(bp); ip->flags |= I_VALID; } }
/* load a inode from disk * */ int iload(struct inode *ip){ struct super *sp; struct d_inode *itab; /* note this is an d_inode, 32 bytes. */ struct buf *bp; uint lba; sp = getsp(ip->i_dev); if (sp==NULL){ panic("error on reading a super"); } // get the blk number where this inode lies in. bp = bread(ip->i_dev, IBLK(sp, ip->i_num)); if (bp->b_flag & B_ERROR) { panic("error on reading an inode"); } itab = (struct d_inode*)bp->b_data; memcpy(ip, &itab[(ip->i_num-1)%IPB], sizeof(struct d_inode)); brelse(bp); return 0; }
/* copy a in-memory inode to disk */ void iupdate(struct inode *ip) { struct buf *bp; struct d_inode *d_ip; struct super_block sb; read_sb(ip->dev , &sb); bp = bread(ip->dev, IBLK(sb, ip->ino)); d_ip = (struct d_inode *)bp->data + (ip->ino - 1)%IPB; /* ip -> d_ip */ d_ip->mode = ip->mode; d_ip->uid = ip->uid; d_ip->size = ip->size; d_ip->mtime= ip->mtime; d_ip->gid = ip->gid; d_ip->nlinks = ip->nlinks; memcpy(d_ip->zone, ip->zone, sizeof(ip->zone)); bwrite(bp); brelse(bp); }
static int iblock(struct inodesc *idesc, long ilevel, off_t isize, int type) { struct bufarea *bp; int i, n, (*func)(struct inodesc *), nif; off_t sizepb; char buf[BUFSIZ]; char pathbuf[MAXPATHLEN + 1]; union dinode *dp; if (idesc->id_type != DATA) { func = idesc->id_func; if (((n = (*func)(idesc)) & KEEPON) == 0) return (n); } else func = dirscan; if (chkrange(idesc->id_blkno, idesc->id_numfrags)) return (SKIP); bp = getdatablk(idesc->id_blkno, sblock.fs_bsize, type); ilevel--; for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++) sizepb *= NINDIR(&sblock); if (howmany(isize, sizepb) > NINDIR(&sblock)) nif = NINDIR(&sblock); else nif = howmany(isize, sizepb); if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) { for (i = nif; i < NINDIR(&sblock); i++) { if (IBLK(bp, i) == 0) continue; (void)sprintf(buf, "PARTIALLY TRUNCATED INODE I=%lu", (u_long)idesc->id_number); if (preen) { pfatal("%s", buf); } else if (dofix(idesc, buf)) { IBLK_SET(bp, i, 0); dirty(bp); } } flush(fswritefd, bp); } for (i = 0; i < nif; i++) { if (ilevel == 0) idesc->id_lbn++; if (IBLK(bp, i)) { idesc->id_blkno = IBLK(bp, i); if (ilevel == 0) n = (*func)(idesc); else n = iblock(idesc, ilevel, isize, type); if (n & STOP) { bp->b_flags &= ~B_INUSE; return (n); } } else { if (idesc->id_type == DATA && isize > 0) { /* An empty block in a directory XXX */ getpathname(pathbuf, idesc->id_number, idesc->id_number); pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", pathbuf); if (reply("ADJUST LENGTH") == 1) { dp = ginode(idesc->id_number); DIP_SET(dp, di_size, DIP(dp, di_size) - isize); isize = 0; printf( "YOU MUST RERUN FSCK AFTERWARDS\n"); rerun = 1; inodirty(); bp->b_flags &= ~B_INUSE; return(STOP); } } } isize -= sizepb; } bp->b_flags &= ~B_INUSE; return (KEEPON); }