/*===========================================================================* * fs_sync * *===========================================================================*/ PUBLIC int fs_sync() { /* Perform the sync() system call. Flush all the tables. * The order in which the various tables are flushed is critical. The * blocks must be flushed last, since rw_inode() leaves its results in * the block cache. */ struct inode *rip; struct buf *bp; int r; assert(nr_bufs > 0); assert(buf); if (superblock->s_rd_only) return(OK); /* nothing to sync */ /* Write all the dirty inodes to the disk. */ for(rip = &inode[0]; rip < &inode[NR_INODES]; rip++) if(rip->i_count > 0 && rip->i_dirt == DIRTY) rw_inode(rip, WRITING); /* Write all the dirty blocks to the disk, one drive at a time. */ for(bp = &buf[0]; bp < &buf[nr_bufs]; bp++) if(bp->b_dev != NO_DEV && bp->b_dirt == DIRTY) flushall(bp->b_dev); if (superblock->s_dev != NO_DEV) { superblock->s_wtime = clock_time(); write_super(superblock); } return(OK); /* sync() can't fail */ }
/*===========================================================================* * fs_newnode * *===========================================================================*/ int fs_newnode() { register int r; mode_t bits; struct minix_inode *rip; caller_uid = fs_m_in.REQ_UID; caller_gid = fs_m_in.REQ_GID; bits = fs_m_in.REQ_MODE; /* Try to allocate the inode */ if( (rip = alloc_inode(fs_dev, bits) ) == NIL_INODE) return err_code; switch (bits & S_IFMT) { case S_IFBLK: case S_IFCHR: rip->i_zone[0] = fs_m_in.REQ_DEV; /* major/minor dev numbers*/ break; } rw_inode(rip, WRITING); /* mark inode as allocated */ rip->i_update = ATIME | CTIME | MTIME; /* Fill in the fields of the response message */ fs_m_out.RES_INODE_NR = rip->i_num; fs_m_out.RES_MODE = rip->i_mode; fs_m_out.RES_FILE_SIZE_LO = rip->i_size; fs_m_out.RES_UID = rip->i_uid; fs_m_out.RES_GID = rip->i_gid; fs_m_out.RES_DEV = (dev_t) rip->i_zone[0]; return(0); }
/*===========================================================================* * do_pipe * *===========================================================================*/ PUBLIC int do_pipe() { /* Perform the pipe(fil_des) system call. */ register struct fproc *rfp; register struct inode *rip; int r; struct filp *fil_ptr0, *fil_ptr1; int fil_des[2]; /* reply goes here */ /* Acquire two file descriptors. */ rfp = fp; if ( (r = get_fd(0, R_BIT, &fil_des[0], &fil_ptr0)) != OK) return(r); rfp->fp_filp[fil_des[0]] = fil_ptr0; fil_ptr0->filp_count = 1; if ( (r = get_fd(0, W_BIT, &fil_des[1], &fil_ptr1)) != OK) { rfp->fp_filp[fil_des[0]] = NIL_FILP; fil_ptr0->filp_count = 0; return(r); } rfp->fp_filp[fil_des[1]] = fil_ptr1; fil_ptr1->filp_count = 1; /* Make the inode on the pipe device. */ if ( (rip = alloc_inode(root_dev, I_REGULAR) ) == NIL_INODE) { rfp->fp_filp[fil_des[0]] = NIL_FILP; fil_ptr0->filp_count = 0; rfp->fp_filp[fil_des[1]] = NIL_FILP; fil_ptr1->filp_count = 0; return(err_code); } if (read_only(rip) != OK) panic(__FILE__,"pipe device is read only", NO_NUM); rip->i_pipe = I_PIPE; rip->i_mode &= ~I_REGULAR; rip->i_mode |= I_NAMED_PIPE; /* pipes and FIFOs have this bit set */ fil_ptr0->filp_ino = rip; fil_ptr0->filp_flags = O_RDONLY; dup_inode(rip); /* for double usage */ fil_ptr1->filp_ino = rip; fil_ptr1->filp_flags = O_WRONLY; rw_inode(rip, WRITING); /* mark inode as allocated */ m_out.reply_i1 = fil_des[0]; m_out.reply_i2 = fil_des[1]; rip->i_update = ATIME | CTIME | MTIME; return(OK); }
/*===========================================================================* * fs_sync * *===========================================================================*/ int fs_sync() { /* Perform the sync() system call. Flush all the tables. * The order in which the various tables are flushed is critical. The * blocks must be flushed last, since rw_inode() leaves its results in * the block cache. */ struct inode *rip; assert(lmfs_nr_bufs() > 0); /* Write all the dirty inodes to the disk. */ for(rip = &inode[0]; rip < &inode[NR_INODES]; rip++) if(rip->i_count > 0 && IN_ISDIRTY(rip)) rw_inode(rip, WRITING); /* Write all the dirty blocks to the disk. */ lmfs_flushall(); return(OK); /* sync() can't fail */ }
/*===========================================================================* * fs_sync * *===========================================================================*/ PUBLIC int fs_sync() { /* Perform the sync() system call. Flush all the tables. * The order in which the various tables are flushed is critical. The * blocks must be flushed last, since rw_inode() leaves its results in * the block cache. */ register struct inode *rip; register struct buf *bp; /* Write all the dirty inodes to the disk. */ for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++) if (rip->i_count > 0 && rip->i_dirt == DIRTY) rw_inode(rip, WRITING); /* Write all the dirty blocks to the disk, one drive at a time. */ for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++) if (bp->b_dev != NO_DEV && bp->b_dirt == DIRTY) flushall(bp->b_dev); return(OK); /* sync() can't fail */ }
int fs_bitmapfixer() { /* m9_l1 dev m9_l3 fixertype */ if(fs_m_in.m9_l3 == 0) //fix inode bitmapblock { printf("enter mfs inode bitmap fixer!\n"); // int errorcount = 0; struct super_block* sp = get_super(fs_m_in.m9_l1); //read inodebitmap blocks int i; for(i = 0;i < sp->s_imap_blocks;i++) { struct buf* bitmapblock = get_block(sp->s_dev, 2+i, NORMAL); bitchunk_t* mapchunks = (bitchunk_t*)bitmapblock->data; int k = 0; if(i == 0) { k = 1; } for(;k < 32768;k++) { if(i*32768 + k > sp->s_ninodes) { break; } if((mapchunks[k / (sizeof(bitchunk_t) * 8)] & (bitchunk_t)1 << (k % (sizeof(bitchunk_t) * 8))) != 0) //used inode { struct inode inodetmp; inodetmp.i_dev = sp->s_dev; inodetmp.i_num = i*32768 + k; rw_inode(&inodetmp,READING); if(inodetmp.i_nlinks == 0) { mapchunks[k / (sizeof(bitchunk_t) * 8)] &= ~((bitchunk_t)1 << (k % (sizeof(bitchunk_t) * 8))); printf("Inode %d fixed!\n",i*32768 + k); } } else { struct inode inodetmp; inodetmp.i_dev = sp->s_dev; inodetmp.i_num = i*32768 + k; rw_inode(&inodetmp,READING); if(inodetmp.i_nlinks != 0) { mapchunks[k / (sizeof(bitchunk_t) * 8)] |= ((bitchunk_t)1 << (k % (sizeof(bitchunk_t) * 8))); printf("Inode %d fixed!\n",i*32768 + k); } } // struct inode inodetmp; // inodetmp.i_dev = sp->s_dev; // inodetmp.i_num = i*32768 + k; // rw_inode(&inodetmp,READING); // // if( // (inodetmp.i_nlinks !=0 && (mapchunks[k / (sizeof(bitchunk_t) * 8)] & (bitchunk_t)1 << (k % (sizeof(bitchunk_t) * 8))) == 0) || // (inodetmp.i_nlinks ==0 && (mapchunks[k / (sizeof(bitchunk_t) * 8)] & (bitchunk_t)1 << (k % (sizeof(bitchunk_t) * 8))) != 0) // ) // { // errorcount ++; // } } put_block(bitmapblock,0); } printf("inode bitmap fixer return\n"); // printf("error_count:%d\n",errorcount); return 0; } else if(fs_m_in.m9_l3 == 1) //fix zone bitmap { printf("enter mfs zone bitmap fixer!\n"); struct super_block* sp = get_super(fs_m_in.m9_l1); //first erase all zone bit map int logicalzonebitmapblockindex; for(logicalzonebitmapblockindex = 0;logicalzonebitmapblockindex < sp->s_zmap_blocks;logicalzonebitmapblockindex++) { struct buf* tmpbitmapblock = get_block(sp->s_dev,logicalzonebitmapblockindex + 2 + sp->s_imap_blocks,NORMAL); bitchunk_t* tmpchunktable = (bitchunk_t*)tmpbitmapblock->data; int chunkindex; for(chunkindex = 0;chunkindex < (sp->s_block_size / sizeof(bitchunk_t));chunkindex++) { if(logicalzonebitmapblockindex == 0 && chunkindex == 0) { tmpchunktable[chunkindex] &= (bitchunk_t) 1; } else { tmpchunktable[chunkindex] &= (bitchunk_t) 0; } } put_block(tmpbitmapblock,0); } //check all inode and fix zonebitmap // int i; // for(i = 0;i < sp->s_imap_blocks;i++) // { // struct buf* bitmapblock = get_block(sp->s_dev, 2+i, NORMAL); // bitchunk_t* mapchunks = (bitchunk_t*)bitmapblock->data; // int k = 0; // if(i == 0) // { // k = 1; // } // for(;k < 32768;k++) // { // if(i*32768 + k > sp->s_ninodes) // { // break; // } // if((mapchunks[k / (sizeof(bitchunk_t) * 8)] & (bitchunk_t)1 << (k % (sizeof(bitchunk_t) * 8))) != 0) //used inode // { // struct inode* inodetmp = NULL; // inodetmp = get_inode(sp->s_dev,i * 32768 + k); // int inodezoneindex; // printf("fix inode%d zones\n",i*32768 + k); // for(inodezoneindex = 0;inodezoneindex < V2_NR_TZONES;inodezoneindex++); // { // if(inodetmp->i_zone[inodezoneindex] != 0) // { // unsigned int bitsperblock = sp->s_block_size * 8; // unsigned int bitsperchunk = sizeof(bitchunk_t) * 8; // unsigned int logicalzoneindex = inodetmp->i_zone[inodezoneindex] - sp->s_firstdatazone; // unsigned int physicalblockindex = (logicalzoneindex / bitsperblock) + 2 + sp->s_imap_blocks; // unsigned int chunkindex = (logicalzoneindex % bitsperblock) / bitsperchunk; // unsigned int bitindex = logicalzoneindex % bitsperchunk; // struct buf* tmpzonebitmapblock = get_block(sp->s_dev,physicalblockindex,NORMAL); // bitchunk_t* tmpchunktable = (bitchunk_t*)tmpzonebitmapblock->data; // tmpchunktable[chunkindex] |= ((bitchunk_t)1 << bitindex); // printf("%u %u %u %u %u %u\n",bitsperblock,bitsperchunk,logicalzoneindex,physicalblockindex,chunkindex,bitindex); // put_block(tmpzonebitmapblock,0); // } // } // put_inode(inodetmp); // } // } // put_block(bitmapblock,0); // } int i; for(i = 1;i <= sp->s_ninodes;i++) { struct inode inodetmp; inodetmp.i_dev = sp->s_dev; inodetmp.i_num = i; rw_inode(&inodetmp,READING); if(inodetmp.i_nlinks != 0) { printf("inode%d used\t",inodetmp.i_num); int k; for(k = 0;k < V2_NR_TZONES;k++) { if(inodetmp.i_zone[k] != 0) { printf("fix zone %u\t",inodetmp.i_zone[k]); unsigned int bitsperblock = sp->s_block_size * 8; unsigned int bitsperchunk = sizeof(bitchunk_t) * 8; unsigned int logicalzoneindex = inodetmp.i_zone[k] - sp->s_firstdatazone + 1; unsigned int physicalblockindex = (logicalzoneindex / bitsperblock) + 2 + sp->s_imap_blocks; unsigned int chunkindex = (logicalzoneindex % bitsperblock) / bitsperchunk; unsigned int bitindex = logicalzoneindex % bitsperchunk; struct buf* tmpzonebitmapblock = get_block(sp->s_dev,physicalblockindex,NORMAL); bitchunk_t* tmpchunktable = (bitchunk_t*)tmpzonebitmapblock->data; tmpchunktable[chunkindex] |= ((bitchunk_t)1 << bitindex); put_block(tmpzonebitmapblock,0); } } printf("\n"); } } printf("zone bitmap fixer return\n"); return 0; } else { return 0; } }
/*===========================================================================* * new_node * *===========================================================================*/ PRIVATE struct inode *new_node(struct inode *ldirp, char *string, mode_t bits, zone_t z0) { /* New_node() is called by fs_open(), fs_mknod(), and fs_mkdir(). * In all cases it allocates a new inode, makes a directory entry for it in * the ldirp directory with string name, and initializes it. * It returns a pointer to the inode if it can do this; * otherwise it returns NULL. It always sets 'err_code' * to an appropriate value (OK or an error code). * * The parsed path rest is returned in 'parsed' if parsed is nonzero. It * has to hold at least NAME_MAX bytes. */ register struct inode *rip; register int r; if (ldirp->i_nlinks == NO_LINK) { /* Dir does not actually exist */ err_code = ENOENT; return(NULL); } /* Get final component of the path. */ rip = advance(ldirp, string, IGN_PERM); if (S_ISDIR(bits) && (ldirp->i_nlinks >= LINK_MAX)) { /* New entry is a directory, alas we can't give it a ".." */ put_inode(rip); err_code = EMLINK; return(NULL); } /* if creating a regular file, set it to be an immediate */ else if((bits & I_TYPE) == I_REGULAR) bits |= I_IMMEDIATE; /* printf("new_node() - mode bits: 0%6o\n", bits); */ if ( rip == NULL && err_code == ENOENT) { /* Last path component does not exist. Make new directory entry. */ if ( (rip = alloc_inode((ldirp)->i_dev, bits)) == NULL) { /* Can't creat new inode: out of inodes. */ return(NULL); } /* Force inode to the disk before making directory entry to make * the system more robust in the face of a crash: an inode with * no directory entry is much better than the opposite. */ rip->i_nlinks++; rip->i_zone[0] = z0; /* major/minor device numbers */ rw_inode(rip, WRITING); /* force inode to disk now */ /* New inode acquired. Try to make directory entry. */ if((r=search_dir(ldirp, string, &rip->i_num, ENTER, IGN_PERM)) != OK) { rip->i_nlinks--; /* pity, have to free disk inode */ rip->i_dirt = DIRTY; /* dirty inodes are written out */ put_inode(rip); /* this call frees the inode */ err_code = r; return(NULL); } } else if (err_code == EENTERMOUNT || err_code == ELEAVEMOUNT) { r = EEXIST; } else { /* Either last component exists, or there is some problem. */ if (rip != NULL) r = EEXIST; else r = err_code; } /* The caller has to return the directory inode (*ldirp). */ err_code = r; return(rip); }
/*===========================================================================* * new_node * *===========================================================================*/ static struct minix_inode *new_node(struct minix_inode *ldirp, char *string, mode_t bits, zone_t z0) { /* New_node() is called by fs_open(), fs_mknod(), and fs_mkdir(). * In all cases it allocates a new inode, makes a directory entry for it in * the ldirp directory with string name, and initializes it. * It returns a pointer to the inode if it can do this; * otherwise it returns NIL_INODE. It always sets 'err_code' * to an appropriate value (0 or an error code). * * The parsed path rest is returned in 'parsed' if parsed is nonzero. It * has to hold at least MINIXFS_NAME_MAX bytes. */ register struct minix_inode *rip; register int r; /* Get final component of the path. */ rip = advance(ldirp, string, IGN_PERM); if (S_ISDIR(bits) && (ldirp)->i_nlinks >= ((ldirp)->i_sp->s_version == 1 ? CHAR_MAX : LINK_MAX)) { /* New entry is a directory, alas we can't give it a ".." */ put_inode(rip); err_code = -EMLINK; return(NIL_INODE); } if ( rip == NIL_INODE && err_code == -ENOENT) { /* Last path component does not exist. Make new directory entry. */ if ( (rip = alloc_inode((ldirp)->i_dev, bits)) == NIL_INODE) { /* Can't creat new inode: out of inodes. */ return(NIL_INODE); } /* Force inode to the disk before making directory entry to make * the system more robust in the face of a crash: an inode with * no directory entry is much better than the opposite. */ rip->i_nlinks++; rip->i_zone[0] = z0; /* major/minor device numbers */ rw_inode(rip, WRITING); /* force inode to disk now */ /* New inode acquired. Try to make directory entry. */ if((r=search_dir(ldirp, string, &rip->i_num, ENTER, IGN_PERM)) != 0) { rip->i_nlinks--; /* pity, have to free disk inode */ rip->i_dirt = DIRTY; /* dirty inodes are written out */ put_inode(rip); /* this call frees the inode */ err_code = r; return(NIL_INODE); } } else if (err_code == -EENTERMOUNT || err_code == -ELEAVEMOUNT) { r = -EEXIST; } else { /* Either last component exists, or there is some problem. */ if (rip != NIL_INODE) r = -EEXIST; else r = err_code; } /* The caller has to return the directory inode (*ldirp). */ err_code = r; return(rip); }
/*===========================================================================* * new_node * *===========================================================================*/ static struct inode *new_node(struct inode *ldirp, char *string, mode_t bits, block_t b0) { /* New_node() is called by fs_open(), fs_mknod(), and fs_mkdir(). * In all cases it allocates a new inode, makes a directory entry for it in * the ldirp directory with string name, and initializes it. * It returns a pointer to the inode if it can do this; * otherwise it returns NULL. It always sets 'err_code' * to an appropriate value (OK or an error code). */ register struct inode *rip; register int r; if (ldirp->i_links_count == NO_LINK) { /* Dir does not actually exist */ err_code = ENOENT; return(NULL); } /* Get final component of the path. */ rip = advance(ldirp, string, IGN_PERM); if (S_ISDIR(bits) && (ldirp->i_links_count >= USHRT_MAX || ldirp->i_links_count >= LINK_MAX)) { /* New entry is a directory, alas we can't give it a ".." */ put_inode(rip); err_code = EMLINK; return(NULL); } if ( rip == NULL && err_code == ENOENT) { /* Last path component does not exist. Make new directory entry. */ if ( (rip = alloc_inode(ldirp, bits)) == NULL) { /* Can't creat new inode: out of inodes. */ return(NULL); } /* Force inode to the disk before making directory entry to make * the system more robust in the face of a crash: an inode with * no directory entry is much better than the opposite. */ rip->i_links_count++; rip->i_block[0] = b0; /* major/minor device numbers */ rw_inode(rip, WRITING); /* force inode to disk now */ /* New inode acquired. Try to make directory entry. */ if ((r=search_dir(ldirp, string, &rip->i_num, ENTER, IGN_PERM, rip->i_mode & I_TYPE)) != OK) { rip->i_links_count--; /* pity, have to free disk inode */ rip->i_dirt = IN_DIRTY; /* dirty inodes are written out */ put_inode(rip); /* this call frees the inode */ err_code = r; return(NULL); } } else if (err_code == EENTERMOUNT || err_code == ELEAVEMOUNT) { r = EEXIST; } else { /* Either last component exists, or there is some problem. */ if (rip != NULL) r = EEXIST; else r = err_code; } /* The caller has to return the directory inode (*ldirp). */ err_code = r; return(rip); }
/*===========================================================================* * common_open * *===========================================================================*/ PRIVATE int common_open(register int oflags, mode_t omode) { /* Common code from do_creat and do_open. */ struct inode *rip, *ldirp; int r, b, exist = TRUE; dev_t dev; mode_t bits; off_t pos; struct filp *fil_ptr, *filp2; /* Remap the bottom two bits of oflags. */ bits = (mode_t) mode_map[oflags & O_ACCMODE]; /* See if file descriptor and filp slots are available. */ if ( (r = get_fd(0, bits, &m_in.fd, &fil_ptr)) != OK) return(r); /* If O_CREATE is set, try to make the file. */ if (oflags & O_CREAT) { /* Create a new inode by calling new_node(). */ omode = I_REGULAR | (omode & ALL_MODES & fp->fp_umask); rip = new_node(&ldirp, user_path, omode, NO_ZONE, oflags&O_EXCL, NULL); r = err_code; put_inode(ldirp); if (r == OK) exist = FALSE; /* we just created the file */ else if (r != EEXIST) return(r); /* other error */ else exist = !(oflags & O_EXCL); /* file exists, if the O_EXCL flag is set this is an error */ } else { /* Scan path name. */ if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code); } /* Claim the file descriptor and filp slot and fill them in. */ fp->fp_filp[m_in.fd] = fil_ptr; FD_SET(m_in.fd, &fp->fp_filp_inuse); fil_ptr->filp_count = 1; fil_ptr->filp_ino = rip; fil_ptr->filp_flags = oflags; /* Only do the normal open code if we didn't just create the file. */ if (exist) { /* Check protections. */ if ((r = forbidden(rip, bits)) == OK) { /* Opening reg. files directories and special files differ. */ switch (rip->i_mode & I_TYPE) { case I_REGULAR: /* Truncate regular file if O_TRUNC. */ if (oflags & O_TRUNC) { if ((r = forbidden(rip, W_BIT)) !=OK) break; truncate_inode(rip, 0); wipe_inode(rip); /* Send the inode from the inode cache to the * block cache, so it gets written on the next * cache flush. */ rw_inode(rip, WRITING); } break; case I_DIRECTORY: /* Directories may be read but not written. */ r = (bits & W_BIT ? EISDIR : OK); break; case I_CHAR_SPECIAL: case I_BLOCK_SPECIAL: /* Invoke the driver for special processing. */ dev = (dev_t) rip->i_zone[0]; r = dev_open(dev, who_e, bits | (oflags & ~O_ACCMODE)); break; case I_NAMED_PIPE: oflags |= O_APPEND; /* force append mode */ fil_ptr->filp_flags = oflags; r = pipe_open(rip, bits, oflags); if (r != ENXIO) { /* See if someone else is doing a rd or wt on * the FIFO. If so, use its filp entry so the * file position will be automatically shared. */ b = (bits & R_BIT ? R_BIT : W_BIT); fil_ptr->filp_count = 0; /* don't find self */ if ((filp2 = find_filp(rip, b)) != NIL_FILP) { /* Co-reader or writer found. Use it.*/ fp->fp_filp[m_in.fd] = filp2; filp2->filp_count++; filp2->filp_ino = rip; filp2->filp_flags = oflags; /* i_count was incremented incorrectly * by eatpath above, not knowing that * we were going to use an existing * filp entry. Correct this error. */ rip->i_count--; } else { /* Nobody else found. Restore filp. */ fil_ptr->filp_count = 1; if (b == R_BIT) pos = rip->i_zone[V2_NR_DZONES+0]; else pos = rip->i_zone[V2_NR_DZONES+1]; fil_ptr->filp_pos = pos; } } break; } } } /* If error, release inode. */ if (r != OK) { if (r == SUSPEND) return(r); /* Oops, just suspended */ fp->fp_filp[m_in.fd] = NIL_FILP; FD_CLR(m_in.fd, &fp->fp_filp_inuse); fil_ptr->filp_count= 0; put_inode(rip); return(r); } return(m_in.fd); }
/*===========================================================================* * new_node * *===========================================================================*/ PRIVATE struct inode *new_node(struct inode **ldirp, char *path, mode_t bits, zone_t z0, int opaque, char *parsed) { /* New_node() is called by common_open(), do_mknod(), and do_mkdir(). * In all cases it allocates a new inode, makes a directory entry for it on * the path 'path', and initializes it. It returns a pointer to the inode if * it can do this; otherwise it returns NIL_INODE. It always sets 'err_code' * to an appropriate value (OK or an error code). * * The parsed path rest is returned in 'parsed' if parsed is nonzero. It * has to hold at least NAME_MAX bytes. */ register struct inode *rip; register int r; char string[NAME_MAX]; *ldirp = parse_path(path, string, opaque ? LAST_DIR : LAST_DIR_EATSYM); if (*ldirp == NIL_INODE) return(NIL_INODE); /* The final directory is accessible. Get final component of the path. */ rip = advance(ldirp, string); if (S_ISDIR(bits) && (*ldirp)->i_nlinks >= ((*ldirp)->i_sp->s_version == V1 ? CHAR_MAX : SHRT_MAX)) { /* New entry is a directory, alas we can't give it a ".." */ put_inode(rip); err_code = EMLINK; return(NIL_INODE); } if ( rip == NIL_INODE && err_code == ENOENT) { /* Last path component does not exist. Make new directory entry. */ if ( (rip = alloc_inode((*ldirp)->i_dev, bits)) == NIL_INODE) { /* Can't creat new inode: out of inodes. */ return(NIL_INODE); } /* Force inode to the disk before making directory entry to make * the system more robust in the face of a crash: an inode with * no directory entry is much better than the opposite. */ rip->i_nlinks++; rip->i_zone[0] = z0; /* major/minor device numbers */ rw_inode(rip, WRITING); /* force inode to disk now */ /* New inode acquired. Try to make directory entry. */ if ((r = search_dir(*ldirp, string, &rip->i_num,ENTER)) != OK) { rip->i_nlinks--; /* pity, have to free disk inode */ rip->i_dirt = DIRTY; /* dirty inodes are written out */ put_inode(rip); /* this call frees the inode */ err_code = r; return(NIL_INODE); } } else { /* Either last component exists, or there is some problem. */ if (rip != NIL_INODE) r = EEXIST; else r = err_code; } if(parsed) { /* Give the caller the parsed string if requested. */ strncpy(parsed, string, NAME_MAX-1); parsed[NAME_MAX-1] = '\0'; } /* The caller has to return the directory inode (*ldirp). */ err_code = r; return(rip); }