📄 nfshash.c
字号:
if (lseek (pTbl->fd, (pTbl->numBlocks + 1) * HASH_BKT_SZ - 1, SEEK_SET) == ERROR) { return (BAD_OFFSET); } pTbl->numBlocks ++; return ((pTbl->numBlocks - 1) * HASH_BKT_SZ); } else { /* existing free block available */ /* scan byte wise then bit wise */ pIx = (char *) pBits; for (; *pIx == 0; ++pIx) {}; for (ix = 0; ix < CHAR_BIT_LEN; ++ix) { if (*pIx & (0x1 << ix)) { bitPos = (pIx - (char*)pTbl->allocBits) * CHAR_BIT_LEN + (CHAR_BIT_LEN - ix) - 1; *pIx &= ~(0x1 << ix); return (bitPos * HASH_BKT_SZ); } } /* impossible to reach here */ } return (BAD_OFFSET); }/******************************************************************************* * namehashFn - hash by name function** RETURNS: index into hash table*/LOCAL int nameHashFn ( char * pName ) { int i = strlen (pName); return (pName[i - 2] + pName[i - 1]) % NAME_HASH_TBL_LEN; }/******************************************************************************* * namehashFn - hash by file handle function** Index into hash table, must be multiplies by the hash file bucket size* to get the actual file offset.** RETURNS: index into hash table*/LOCAL int fhHashFn ( int fh ) { return fh % FH_HASH_TBL_LEN; }/******************************************************************************* * name2Fh - convert name to file handle ** Given a file name <pName>, convert that to a file handle, using the hash * table given by <ptbl>. We only do a lookup, so if the name does not exist * in the lookup structure we do not create the file handle for it. ** RETURNS: N/A*/LOCAL int name2Fh ( TBL_DESC * pTbl, char * pName ) { off_t off_1 = 0; char buf [NFS_MAXPATHLEN + 1 + sizeof (HNDL_NAME)]; HNDL_NAME * pEnt; int nameLen = strlen (pName); semTake (pTbl->sem, WAIT_FOREVER); for (off_1 = pTbl->nameHash [nameHashFn(pName)]; off_1 != BAD_OFFSET; off_1 = pEnt->next ) { if (blkRead (pTbl->fd, off_1, buf, sizeof buf) == ERROR) { semGive (pTbl->sem); return (ERROR); } pEnt = (HNDL_NAME*)buf; if (pEnt->nameLen == nameLen && (strcmp (pEnt->name, pName) == 0)) { semGive (pTbl->sem); return (pEnt->fh); } } semGive (pTbl->sem); return (ERROR); }/******************************************************************************* * fh2Name - convert file handle to name** Find the file name corresponding to a file handle <fh> using hahs table* <pTbl> and return name in <pName>.** RETURNS: OK else ERROR if name not found.*/LOCAL STATUS fh2Name ( TBL_DESC * pTbl, /* hash file descriptor ptr */ int fh, /* file handle */ char * pName /* name output buffer */ ) { off_t off_1 ; HNDL_NAME * pEnt; HASH_BKT * pBlk; char buf [HASH_BKT_SZ]; struct stat statBuf; HNDL_NAME * pTmpEnt; char entBuf [NFS_MAXPATHLEN + 1 + sizeof (HNDL_NAME)]; semTake (pTbl->sem, WAIT_FOREVER); for (off_1 = fhHashFn(fh) * HASH_BKT_SZ; off_1 != BAD_OFFSET; off_1 = pBlk->next ) { if (blkRead (pTbl->fd, off_1, buf, sizeof buf) == ERROR) { semGive (pTbl->sem); return (ERROR); } pBlk = (HASH_BKT *) buf; pEnt = (HNDL_NAME*) pBlk->entries; for (pEnt = (HNDL_NAME *)pBlk->entries; (char*)pEnt < (buf + sizeof(buf) - MIN_ENTRY_SZ); pEnt = (HNDL_NAME*) ((char *)pEnt + pEnt->totalLen)) { if (pEnt->fh == fh) { strcpy (pName, pEnt->name); semGive (pTbl->sem); if (stat(pName, &statBuf) == ERROR) { /* delete from hash file since handle is not valid */ if (blkRead (pTbl->fd, pEnt->next, entBuf, sizeof (entBuf)) == ERROR) { return (ERROR); } pTmpEnt = (HNDL_NAME*)entBuf; pTmpEnt->prev = pEnt->prev; if (blkWrite (pTbl->fd, pEnt->next, entBuf, sizeof (entBuf)) == ERROR) { return (ERROR); } if (blkRead (pTbl->fd, pEnt->prev, entBuf, sizeof (entBuf)) == ERROR) { return (ERROR); } pTmpEnt->next = pEnt->next; if (blkWrite (pTbl->fd, pEnt->prev, entBuf, sizeof (entBuf)) == ERROR) { return (ERROR); } pEnt->nameLen = 0; pBlk->freeSpace += pEnt->totalLen; /* if all entries in a block are gone then we could free * the block however that is not done currently since the * space will most likely be used up again unless * the hash table gets unbalanced. */ } return (OK); } } } semGive (pTbl->sem); return (ERROR); }/******************************************************************************* * fhInsert - insert a file handle and name pair into hash table* Inser the file handle <fh> and name <pName> into the hash table* <pTbl>.** RETURNS: OK or ERROR if unable to insert entry.*/LOCAL STATUS fhInsert ( TBL_DESC * pTbl, int fh, char * pName ) { /* first select block based on hash by fh , insert into blk then onto list of entries by name */ off_t offPrev = 0; off_t offNow ; HNDL_NAME * pEnt = 0; HNDL_NAME * pTmpEnt; HASH_BKT * pBlk = (HASH_BKT *) NULL; char buf [HASH_BKT_SZ]; int need; int ix; int newEntryLen; char entBuf [NFS_MAXPATHLEN + 1 + sizeof (HNDL_NAME)]; need = ENTRY_HDR_SZ + STR_ALIGN_LEN (pName) ; semTake (pTbl->sem, WAIT_FOREVER); for (offNow = fhHashFn (fh) * HASH_BKT_SZ ; offNow != BAD_OFFSET; offPrev = offNow, offNow = pBlk->next ) { if (blkRead (pTbl->fd, offNow, buf, sizeof buf) == ERROR) { semGive (pTbl->sem); return (ERROR); } pBlk = (HASH_BKT *)buf; if (pBlk->freeSpace < need) { continue; } for (pEnt = (HNDL_NAME *)pBlk->entries; (char*)pEnt <= (buf + sizeof(buf) - need); pEnt = (HNDL_NAME*) ((char *)pEnt + pEnt->totalLen)) { if (pEnt->nameLen == 0 && pEnt->totalLen >= need) { /* found an empty entry big enough */ goto scanDone; } } } /* At this point we may need to allocate a new blk */ /* allocate new block and link it in then set pEnt and offNow * as in earlier case */scanDone: if (offNow == BAD_OFFSET) { offNow = blockAlloc (pTbl); /* link new block into prev block */ if (blkRead (pTbl->fd, offPrev, buf, sizeof buf) == ERROR) { semGive (pTbl->sem); return (ERROR); } pBlk = (HASH_BKT*)buf; pBlk->next = offNow; if (blkWrite (pTbl->fd, offPrev, buf, sizeof buf) == ERROR) { semGive (pTbl->sem); return (ERROR); } /* Now convert buf into a new empty block. initially the whole block is just one full sized empty entry */ pBlk->next = BAD_OFFSET; pBlk->freeSpace = HASH_BKT_SZ - HASH_BKT_HDR_SZ; pEnt = (HNDL_NAME*) (pBlk->entries); pEnt->totalLen = HASH_BKT_SZ - HASH_BKT_HDR_SZ ; pEnt->nameLen = 0; } /* At this point offNow points to the block to be updated and pEnt points to the correct entry in the buffered bucket */ ix = nameHashFn (pName); pEnt->next = pTbl->nameHash [ix]; pEnt->prev = BAD_OFFSET; pTbl->nameHash[ix] = offNow + ((char *)pEnt - buf); /* update back ptr of next entry if there is one */ if (pEnt->next != BAD_OFFSET) { if (blkRead (pTbl->fd, pEnt->next, entBuf, sizeof (entBuf) == ERROR)) { return (ERROR); }; pTmpEnt = (HNDL_NAME*)entBuf; pTmpEnt->prev = pTbl->nameHash[ix]; if (blkWrite (pTbl->fd, pEnt->next, entBuf, sizeof (entBuf) == ERROR)) { return (ERROR); }; } /* if there is sufficient space in this entry to accomodate * another entry at this end then divide this to get an empty entry * at the end of first entry */ newEntryLen = ENTRY_HDR_SZ + STR_ALIGN_LEN (pName); if (pEnt->totalLen - newEntryLen >= MIN_ENTRY_SZ) { pTmpEnt = (HNDL_NAME*) ((char*)pEnt + newEntryLen); pTmpEnt->totalLen = pEnt->totalLen - newEntryLen; pTmpEnt->nameLen = 0; pEnt->totalLen = newEntryLen; } pBlk->freeSpace -= pEnt->totalLen; strcpy (pEnt->name, pName); pEnt->fh = fh; pEnt->nameLen = strlen (pName); if (blkWrite (pTbl->fd, offNow, buf, sizeof buf) == ERROR) { return (ERROR); } semGive (pTbl->sem); return (OK); }/******************************************************************************* * blkRead - read block from file* * Read block from file with file descriptor <fd>, offset <offset>* buffer <buf> and buffer len <len>* * RETURNS: num chars read or ERROR.*/LOCAL int blkRead ( int fd, off_t offset, char * buf, int len ) { if (lseek (fd, offset, SEEK_SET) == ERROR) { return (ERROR); } return (read ( fd, buf, len)); }/******************************************************************************* * blkWrite - write block to file* * Write block to file with file descriptor <fd>, offset <offset>* buffer <buf> and buffer len <len>* * RETURNS: num chars written or ERROR. */LOCAL int blkWrite ( int fd, off_t offset, char * buf, int len ) { if (lseek (fd, offset, SEEK_SET) == ERROR) { return (ERROR); } return (write ( fd, buf, len)); }/******************************************************************************* * nfsFhLkup - find name corresponding to file handle ** using file handle <fh> as the key get corresponding file name* in <pName>.** RETURNS: OK or ERROR if name not found*/STATUS nfsFhLkup ( NFS_FILE_HANDLE * pFh, /* key for lookup */ char * pName /* output name */ ) { TBL_DESC * pT; pT = tblDescGet (pFh->volumeId); if (pT == NULL) { return (ERROR); } if (fh2Name (pT, pFh->inode, pName) == ERROR) { return (ERROR); } else { return OK; } }/******************************************************************************* * nfsNmLkupIns - find fh corresponding to file name** Find the file handle corresponding to the given file name <Pname> with* nfs mount volume id <mntId> and create and insert an entry in the table* if not found.** RETURNS: file handle or ERROR;* NOMANUAL*/int nfsNmLkupIns ( int mntId, /* mount id no */ char * pName /* seach key */ ) { TBL_DESC * pT; int in; pT = tblDescGet (mntId); if (pT == NULL) return (ERROR); if ((in = name2Fh (pT, pName)) == ERROR) { in = ++pT->nextInode; if (fhInsert (pT, pT->nextInode, pName)== ERROR) return (ERROR); } return (in); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -