void dtree() { int32 changed = 0; char cmd_line[80]; dtpage_t *dtree; int32 field; char flag_names[64]; dinode_t inode; int64 inode_address; ino_t inum; char result; dtroot_t *root; char *token; ino_t which_table = FILESYSTEM_I; token = strtok(0, " "); if (token == 0) { fputs("dtree: Please enter: inum [fileset]\ndtree> ",stdout); gets(cmd_line); token=strtok(cmd_line, " "); if (token == 0) return; } errno = 0; inum = strtoul(token, 0, 0); if (inum == 0 && errno) { fputs("dtree: invalid inum\n\n", stderr); return; } token = strtok(0, " "); if (token) { if (token[0] != '0') { fputs("dtree: invalide fileset\n\n", stderr); return; } } if (strtok(0, " ")) { fputs("dtree: Too many arguments\n\n", stderr); return; } if (find_inode(inum, which_table, &inode_address) || xRead(inode_address, sizeof(dinode_t), (char *)&inode)) { fputs("dtree: error reading inode\n\n", stderr); return; } if ((inode.di_mode & IFMT) != IFDIR) { fputs("dtree: Not a directory!\n", stderr); return; } dtree = (dtpage_t *)&(inode.di_btroot); redisplay: if (!(dtree->header.flag & BT_ROOT)) fputs("dtree: Should be at root of dtree, but BTROOT not set!\n", stderr); root = (dtroot_t *)dtree; *flag_names = 0; if (root->header.flag & BT_ROOT) strcat(flag_names, "BT_ROOT "); if (root->header.flag & BT_LEAF) strcat(flag_names, "BT_LEAF "); if (root->header.flag & BT_INTERNAL) strcat(flag_names, "BT_INTERNAL "); if (root->header.flag & BT_RIGHTMOST) strcat(flag_names, "BT_RIGHTMOST "); if (root->header.flag & BT_LEFTMOST) strcat(flag_names, "BT_LEFTMOST "); printf("Root D-Tree Node of inode %d\n\n", inode.di_number); printf("[1] DASDlimit\t%lld\n", DASDLIMIT(&(root->header.DASD))); /* @F1 */ printf("[2] DASDused\t%lld\n", DASDUSED(&(root->header.DASD))); /* @F1 */ printf("[3] thresh (%%)\t%d\n", root->header.DASD.thresh ); /* @F1 */ printf("[4] delta (%%)\t%d\n", root->header.DASD.delta ); /* @F1 */ printf("\n"); /* @F1 */ printf("[5] flag\t0x%02x\t\t%s\n", root->header.flag, flag_names); /* @F1 */ printf("[6] nextindex\t%d\n", root->header.nextindex); /* @F1 */ printf("[7] freecnt\t%d\n", root->header.freecnt); /* @F1 */ printf("[8] freelist\t%d\n", root->header.freelist); /* @F1 */ printf("[9] idotdot\t%d\n", root->header.idotdot); /* @F1 */ printf("[10] stbl\t{%d,%d,%d,%d,%d,%d,%d,%d}\n", /* @F1 */ root->header.stbl[0], root->header.stbl[1], root->header.stbl[2], root->header.stbl[3], root->header.stbl[4], root->header.stbl[5], root->header.stbl[6], root->header.stbl[7]); retry: if (root->header.nextindex) { fputs("dtree: Hit enter to see entries, [m]odify, or e[x]it: ", stdout); } else { fputs("dtree: [m]odify, or e[x]it: ", stdout); } gets(cmd_line); token = strtok(cmd_line, " "); if (token) { if (*token == 'x') return; if (*token == 'm') { field = m_parse(cmd_line, 9, &token); if (field == 0) goto retry; switch (field) { case 1: /* @F1 */ setDASDLIMIT(&(root->header.DASD), strtoll(token, 0, 0) ); /* @F1 */ break; /* @F1 */ case 2: /* @F1 */ setDASDUSED(&(root->header.DASD), strtoll(token, 0, 0) ); /* @F1 */ break; /* @F1 */ case 3: /* @F1 */ root->header.DASD.thresh = strtoul(token, 0, 0); /* @F1 */ break; /* @F1 */ case 4: /* @F1 */ root->header.DASD.delta = strtoul(token, 0, 0); /* @F1 */ break; /* @F1 */ case 5: /* @F1 */ root->header.flag = strtoul(token, 0, 16); break; case 6: /* @F1 */ root->header.nextindex = strtoul(token, 0, 0); break; case 7: /* @F1 */ root->header.freecnt = strtoul(token, 0, 0); break; case 8: /* @F1 */ root->header.freelist = strtoul(token, 0, 0); break; case 9: /* @F1 */ root->header.idotdot = strtoul(token, 0, 0); break; } if (xWrite(inode_address, sizeof(dinode_t), (char *)&inode)) { fputs("dtree: error writing inode\n\n", stderr); return; } goto redisplay; } } if (root->header.nextindex == 0) return; if (root->header.flag & BT_LEAF) result = display_leaf_slots(root->slot, root->header.stbl, root->header.nextindex, &changed); else result = display_internal_slots(root->slot, root->header.stbl, root->header.nextindex, &changed); if (changed) { if (xWrite(inode_address, sizeof(dinode_t), (char *)&inode)) { fputs("dtree: error writing inode\n\n", stderr); return; } changed = 0; } if (result == 'u') goto redisplay; return; }
/* * NAME: jfs_mkdir(dvp, name, mode, crp) * * FUNCTION: create a child directory in the parent directory <dvp> * with name = <name> and mode = <mode> * * PARAMETER: dvp - parent directory vnode * name - name of child directory * mode - create mode (rwxrwxrwx). * crp - credential * * RETURN: Errors from subroutines * * note: * EACCESS: user needs search+write permission on the parent directory */ jfs_mkdir( struct vnode *dvp, UniChar *name, mode_t mode, #ifdef _JFS_OS2 EAOP *pEABuf, #endif /* _JFS_OS2 */ struct ucred *crp) { int32 rc = 0, rc1 = 0; int32 tid; /* transaction id */ struct vfs *vfsp = dvp->v_vfsp; inode_t *dip = VP2IP(dvp); /* parent directory inode */ struct dasd_usage *du; // F226941 inode_t *ip = NULL; /* child directory inode */ ino_t ino; component_t dname; /* child directory name */ btstack_t btstack; inode_t *iplist[2]; int64 orig_nblocks; // F226941 #ifdef _JFS_LAZYCOMMIT tblock_t *tblk; // D230860 #endif #ifdef _JFS_OS2 FEALIST *pfealist = NULL; #endif /* _JFS_OS2 */ NOISE(1,("jfs_mkdir: dip:0x%08x name:%s\n", dip, name)); /* * the named file exists for "." or ".." */ if (name[0] == '.') { if ((name[1] == '.' && name[2] == '\0') || name[1] == '\0') return EEXIST; } #ifdef _JFS_OS2 /* validate the EAOP buffer, FEALIST size storage location and the * entire FEALIST storage area. Once all the storage has been * validated, the entire FEALIST is validated for format and the size is * computed and compared against the limit. */ if (pEABuf) { if (rc = jfs_ValidateUserFEAList(pEABuf, &pfealist, &pEABuf->oError)) { /* something failed -- bail out */ return rc; } } #endif /* _JFS_OS2 */ if (dip->i_nlink == 0) { rc = ENOENT; goto out1; } /* link count overflow on parent directory ? */ if (dip->i_nlink >= LINK_MAX) { rc = EMLINK; goto out1; } /* * search parent directory for entry/freespace * (dtSearch() returns parent directory page pinned) */ dname.name = name; dname.namlen = UniStrlen(name); if (dname.namlen > JFS_NAME_MAX-1) { rc = ERROR_FILENAME_EXCED_RANGE; goto out1; } // BEGIN D233382 #ifdef _JFS_LAZYCOMMIT if (isReadOnly(dip)) { rc = EROFS; goto out1; } /* * Either iAlloc() or txBegin() may block. Deadlock can occur if we * block there while holding dtree page, so we allocate the inode & * begin the transaction before we search the directory. */ if (rc = iAlloc(vfsp, dip, IFDIR|mode|IDIRECTORY, &ip, crp)) goto out1; txBegin(dip->i_ipmnt, &tid, 0); if (rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE)) { ip->i_nlink = 0; ICACHE_LOCK(); iput(ip, vfsp); ICACHE_UNLOCK(); txEnd(tid); goto out1; } tblk = &TxBlock[tid]; // D230860 tblk->xflag |= COMMIT_CREATE; // D230860 tblk->ip = ip; // D230860 #else /* ! _JFS_LAZYCOMMIT */ // END D233382 if (rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE)) goto out1; if (isReadOnly(dip)) { rc = EROFS; /* release parent directory page */ BT_PUTSEARCH(&btstack); goto out1; } /* * allocate on-disk/in-memory inode for child directory: * (iAlloc() returns new, locked inode) */ if (rc = iAlloc(vfsp, dip, IFDIR|mode|IDIRECTORY, &ip, crp)) { /* release parent directory page */ BT_PUTSEARCH(&btstack); jEVENT(0,("jfs_mkdir: iAlloc error(%d)\n", rc)); goto out1; } txBegin(dip->i_ipmnt, &tid, 0); #endif /* _JFS_LAZYCOMMIT */ du = ip->i_dasdlim = dip->i_dasdlim; // F226941 orig_nblocks = dip->i_nblocks; // F226941 iplist[0] = dip; iplist[1] = ip; /* * initialize the child directory in-line in inode */ dtInitRoot(tid, ip, dip->i_number); /* * create entry in parent directory for child directory * (dtInsert() releases parent directory page) */ ino = ip->i_number; if (rc = dtInsert(tid, dip, &dname, &ino, &btstack)) { /* discard new directory inode */ ip->i_nlink = 0; if (rc == EIO) txAbort(tid, 1); /* Marks Filesystem dirty */ else txAbort(tid, 0); /* Filesystem full */ txEnd(tid); goto out3; } /* update child directory inode */ // BEGIN F226941 setDASDLIMIT(&ip->i_DASD, 0); setDASDUSED(&ip->i_DASD, 0); // END F226941 ip->i_nlink++; /* for '.' */ imark(ip, IACC|ICHG|IUPD|IFSYNC); /* update parent directory inode */ dip->i_nlink++; /* for '..' from child directory */ imark(dip, ICHG|IUPD|IFSYNC); /* * insert entry for the new file to dnlc */ ncEnter(dip->i_ipimap, dip->i_number, &dname, ino, NULL); #ifdef _JFS_OS2 if ((rc1 == 0) && pfealist) // F226941 rc1 = jfs_InitializeFEAList(ip, tid, pfealist); if ((rc1 == 0) && (dip->i_acl.flag) && (dip->i_acl.size)) rc1 = jfs_CopyACL(ip, dip, tid); #endif /* _JFS_OS2 */ // BEGIN FF226941 DLIM_UPDATE(tid, dip, dip->i_nblocks + ip->i_nblocks - orig_nblocks); setDASDUSED(&ip->i_DASD, ip->i_nblocks); // D233382 #ifndef _JFS_FASTDASD // D233382 /* * If the transaction modified the ancestors of the inode, the * parent will be in the dasd usage list. Otherwise, transaction * will only change new directory and parent. */ if (du && (du->flag & DLIM_LOGGED)) rc = dasd_commit(tid, ip, 0); else #endif /* _JFS_FASTDASD */ // D233382 // END FF226941 rc = txCommit(tid, 2, &iplist[0], 0); txEnd(tid); #ifdef _JFS_OS2 /* If we successfully added the directory, but failed adding the EA or * ACL, we must cleanup the created directory entry and return the * error. */ if (rc1) { // BEGIN D230860 if ((du) && (du->first_locked)) { /* * txCommit unlocked one or more inodes. * We need to unlock all the directories & * relock them. */ dip->i_dasdlim = 0; DLIM_WRITE_UNLOCK_DETACH(ip, du); DLIM_WRITE_LOCK_ATTACH(ip, du); dip->i_dasdlim = du; } // END D230860 jfs_xrmdir(dip, ip, name); rc = rc1; } #endif /* _JFS_OS2 */ out3: ip->i_dasdlim = 0; // F226941 IWRITE_UNLOCK(ip); ICACHE_LOCK(); iput(ip, vfsp); ICACHE_UNLOCK(); out1: #ifdef _JFS_OS2 /* * this buffer was allocated by * jfs_ValidateUserFEAList() at twice the * size of the given list to provide buffer * space for eliminating duplicate names */ if (pfealist) jfs_EABufFree((char *)pfealist, (pfealist->cbList << 1)); #endif /* _JFS_OS2 */ NOISE(1,("jfs_mkdir: rc:%d\n", rc)); return rc; }