int32 jfs_strfromUCS( char * target, UniChar * source, int32 len, int32 source_len) { int32 rc; int32 newlen; char *pinned_string; pinned_string = (char *)allocpool(string_pool, 0); if (pinned_string == 0) return -1; rc = KernStrFromUcs(0, pinned_string, source, MIN(JFS_PATH_MAX+1, len), source_len); jEVENT((rc != 0), ("KernStrFromUcs returned %d\n", rc)); if (! rc) { newlen = strlen(pinned_string); rc = KernCopyOut(target, pinned_string, newlen+1); } freepool(string_pool, (caddr_t *)pinned_string); if (rc) return -1; else return newlen; }
int32 jfs_strtoUCS( UniChar * target, char * source, int32 len) { int32 rc; int32 source_len; int32 newlen; source_len = strlen(source); rc = KernStrToUcs(0, target, source, len+1, source_len); if (rc) { jEVENT(1, ("KernStrToUcs return %d\n", rc)); return -1; } else // return UniStrlen(target); /* Nobody uses this anyway */ return 0; }
/* * 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; }
/* * NAME: jfs_defragfs() * * FUNCTION: relocate specified extent for defragfs() * optionally commiting the operation. */ int32 jfs_defragfs( char *pData, /* pointer to buffer containing plist */ uint32 lenData, /* length of buffer */ uint16 *pbufsize) /* pointer of buffer length */ { int32 rc = 0; defragfs_t pList, *p = &pList; uint32 xtype; int64 offset, xoff, oxaddr, nxaddr; int32 xlen; inode_t *ipmnt, *ipimap, *ipbmap; inode_t *ip = NULL; xad_t oxad; pxd_t opxd; mode_t imode; int32 tid; inode_t *iplist[1]; struct vfs *vfsp; if (rc = KernCopyIn(&pList, pData, lenData)) return rc; /* get the 'mount' inode */ for (vfsp = vfs_anchor; vfsp != NULL; vfsp = vfsp->vfs_next) if (vfsp->vfs_vpfsi->vpi_drive == pList.dev) break; if (vfsp == NULL) return EINVAL; xtype = pList.flag; /* sync at start of defragfs ? */ if (xtype & DEFRAGFS_SYNC) { jEVENT(0,("jfs_defragfs: DEFRAGFS_SYNC\n")); if ((vfsp->vfs_flag & VFS_READONLY) || (vfsp->vfs_flag & VFS_ACCEPT)) return 0; ipimap = (inode_t *)vfsp->vfs_data; ipmnt = ipimap->i_ipmnt; ipbmap = ipmnt->i_ipbmap; /* sync the file system */ iSyncFS(vfsp); /* write dirty pages of imap */ diSync(ipimap); /* write dirty pages of bmap */ dbSync(ipbmap); return 0; } else if (!(xtype & DEFRAGFS_RELOCATE)) return EINVAL; if (vfsp->vfs_flag & VFS_READONLY) return EROFS; if (vfsp->vfs_flag & VFS_ACCEPT) return EINVAL; /* get the relocation parameter */ xoff = pList.xoff; oxaddr = pList.old_xaddr; nxaddr = pList.new_xaddr; xlen = pList.xlen; jEVENT(0,("jfs_defragfs: i:%d xtype:0x%08x xoff:%lld xlen:%d xaddr:%lld:%lld\n", pList.ino, xtype, xoff, xlen, oxaddr, nxaddr)); /* get the object inode if it exist */ ICACHE_LOCK(); rc = iget(vfsp, pList.ino, &ip, 0); ICACHE_UNLOCK(); if(rc) { jEVENT(0,("jfs_defragfs: stale target object.\n")); rc = ESTALE; /* stale object ENOENT */ goto out1; } IWRITE_LOCK(ip); /* validate inode */ if (ip->i_nlink == 0 || ip->i_gen != pList.gen || ip->i_fileset != pList.fileset || ip->i_inostamp != pList.inostamp) { jEVENT(0,("jfs_defragfs: stale target object.\n")); rc = ESTALE; /* stale object ENOENT */ goto out1; } /* validate object type: regular file or directory */ imode = ip->i_mode & IFMT; switch(imode) { case IFREG: case IFDIR: break; default: rc = ESTALE; /* invalid object type ENOENT */ goto out1; } /* * try to allocate new destination extent */ if (rc = dbAllocExact(ip, nxaddr, xlen)) { jEVENT(0,("jfs_defragfs: stale destination extent.\n")); rc = ENOSPC; goto out1; } iBindCache(ip); /* * regular file: */ if (imode == IFREG) { /* * automatic commit before and after each relocation * may be skipped after more experience; */ /* * commit any update before relocation */ if (ip->i_flag & IUPD) { ip->i_flag |= IFSYNC; txBegin(ip->i_ipmnt, &tid, 0); iplist[0] = ip; rc = txCommit(tid, 1, &iplist[0], 0); if (rc) goto out2; txEnd(tid); } /* * relocate either xtpage or data extent */ txBegin(ip->i_ipmnt, &tid, 0); /* source extent xad */ XADoffset(&oxad, xoff); XADaddress(&oxad, oxaddr); XADlength(&oxad, xlen); rc = xtRelocate(tid, ip, &oxad, nxaddr, xtype); if (rc) goto out2; iplist[0] = ip; rc = txCommit(tid, 1, &iplist[0], 0); if (rc) goto out2; txEnd(tid); goto out1; } /* * directory: */ else /* IFDIR */ { /* * relocate dtpage */ txBegin(ip->i_ipmnt, &tid, 0); /* source extent pxd */ PXDaddress(&opxd, oxaddr); PXDlength(&opxd, xlen); rc = dtRelocate(tid, ip, xoff, &opxd, nxaddr); if (rc) goto out2; iplist[0] = ip; rc = txCommit(tid, 1, &iplist[0], 0); if (rc) goto out2; txEnd(tid); goto out1; } out2: dbFree(ip, nxaddr, xlen) ; out1: if (ip) { IWRITE_UNLOCK(ip); ICACHE_LOCK(); iput(ip, NULL); ICACHE_UNLOCK(); } jEVENT(0,("jfs_defragfs: rc=%d\n", rc)); return (rc); }
/* * NAME: jfs_open(vp, flag, ext, vinfop, crp) * * FUNCTION: open a file <vp> with open flag <flag>. * * PARAMETER: vp - vnode to open * flag - open flags from the file pointer. * ext - external data for device driver. * vinfop - pointer to the vinfo field for the open file * crp - credential * * RETURN: ENOENT - non-positive link count * errors from subroutines * * note: silly story of open/type/mode flag ... * at user level, open flag (O_xxxx) is defined by fcntl.h, * file type and permission flags (S_xxxx defined by * sys/mode.h included in sys/stat.h); * in LFS, open flag is converted to file flag (Fxxxx defined * by fcntl.h) and to vnode type (Vxxxx defined by sys/vnode.h); * in PFS, file type and permission is defined by Ixxxx flag * (also defined by sys/mode.h) in addition to file flag and * vnode type; */ jfs_open( struct vnode *vp, /* object vnode */ int32 flag, /* open(2) flag */ uint32 oflag, /* file existence options */ EAOP *pcEABuf, struct ucred *crp) /* credential */ { int32 rc, rc1 = 0; inode_t *ip = VP2IP(vp); /* object inode */ int32 type; #ifdef _JFS_OS2 FEALIST *pfealist = NULL; inode_t *iplist[1]; #endif /* _JFS_OS2 */ jEVENT(0,("jfs_open(ip:0x%08x, flag:0x%08x)\n", ip, flag)); /* validate file type */ type = ip->i_mode & IFMT; if (! (type == IFREG || type == IFDIR)) { jEVENT(0,("jfs_open(ip:0x%08x, flag:0x%08x ERROR(EINVAL)\n", ip, flag)); return EINVAL; } #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 (pcEABuf && (oflag & OPEN_ACTION_REPLACE_IF_EXISTS)) { if (rc = jfs_ValidateUserFEAList(pcEABuf, &pfealist, &pcEABuf->oError)) { /* something failed -- bail out */ return rc; } } #endif /* _JFS_OS2 */ /* named file does not exist anymore ? */ if (ip->i_nlink == 0) { rc = ENOENT; goto out; } /* validate open access permission */ if (rc = iOpenAccess(ip, flag, crp)) goto out; #ifdef _JFS_OS2 rc = iOpen(ip, flag, oflag, pfealist, crp); #endif out: #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 */ /* If opening a file readonly, and we aren't explicitly told that * the access is random, perform readahead of first 32K */ if ((rc == 0) && ((flag & (OPEN_ACCESS_READWRITE | OPEN_ACCESS_WRITEONLY)) == OPEN_ACCESS_READONLY) && ((flag & OPEN_FLAGS_RANDOM) == 0)) { if (ip->i_size > 0) cmKickStart(ip); } jEVENT(0,("jfs_open(rc:%d)\n", rc)); return rc; }