Пример #1
0
/*
 * Regenerates the dynroot contents from the current list of
 * cells.  Useful when the list of cells has changed due to
 * an AFSDB lookup, for instance.
 */
static void
afs_RebuildDynroot(void)
{
    int cellidx, maxcellidx, i;
    int aliasidx, maxaliasidx;
    struct cell *c;
    struct cell_alias *ca;
    int curChunk, curPage;
    int dirSize, dotLen;
    char *newDir, *dotCell;
    struct DirHeader *dirHeader;
    int linkCount = 0;
    struct afs_dynSymlink *ts;
    int newVersion;

    ObtainReadLock(&afs_dynrootDirLock);
    newVersion = afs_dynrootVersion;
    ReleaseReadLock(&afs_dynrootDirLock);

    /*
     * Compute the amount of space we need for the fake dir
     */
    curChunk = 13;
    curPage = 0;

    /* Reserve space for "." and ".." */
    curChunk += 2;

    /* Reserve space for the dynamic-mount directory */
    afs_dynroot_computeDirEnt(AFS_DYNROOT_MOUNTNAME, &curPage, &curChunk);

    for (cellidx = 0;; cellidx++) {
	c = afs_GetCellByIndex(cellidx, READ_LOCK);
	if (!c)
	    break;
	if (c->cellNum == afs_dynrootCell)
	    continue;

	dotLen = strlen(c->cellName) + 2;
	dotCell = afs_osi_Alloc(dotLen);
	strcpy(dotCell, ".");
	afs_strcat(dotCell, c->cellName);

	afs_dynroot_computeDirEnt(c->cellName, &curPage, &curChunk);
	afs_dynroot_computeDirEnt(dotCell, &curPage, &curChunk);

	afs_osi_Free(dotCell, dotLen);
	afs_PutCell(c, READ_LOCK);
    }
    maxcellidx = cellidx;

    for (aliasidx = 0;; aliasidx++) {
	ca = afs_GetCellAlias(aliasidx);
	if (!ca)
	    break;

	dotLen = strlen(ca->alias) + 2;
	dotCell = afs_osi_Alloc(dotLen);
	strcpy(dotCell, ".");
	afs_strcat(dotCell, ca->alias);

	afs_dynroot_computeDirEnt(ca->alias, &curPage, &curChunk);
	afs_dynroot_computeDirEnt(dotCell, &curPage, &curChunk);

	afs_osi_Free(dotCell, dotLen);
	afs_PutCellAlias(ca);
    }
    maxaliasidx = aliasidx;

    ObtainReadLock(&afs_dynSymlinkLock);
    ts = afs_dynSymlinkBase;
    while (ts) {
	afs_dynroot_computeDirEnt(ts->name, &curPage, &curChunk);
	ts = ts->next;
    }

    dirSize = (curPage + 1) * AFS_PAGESIZE;
    newDir = afs_osi_Alloc(dirSize);

    /*
     * Now actually construct the directory.
     */
    curChunk = 13;
    curPage = 0;
    dirHeader = (struct DirHeader *)newDir;

    dirHeader->header.pgcount = 0;
    dirHeader->header.tag = htons(1234);
    dirHeader->header.freecount = 0;

    dirHeader->header.freebitmap[0] = 0xff;
    dirHeader->header.freebitmap[1] = 0x1f;
    for (i = 2; i < EPP / 8; i++)
	dirHeader->header.freebitmap[i] = 0;
    dirHeader->alloMap[0] = EPP - DHE - 1;
    for (i = 1; i < MAXPAGES; i++)
	dirHeader->alloMap[i] = EPP;
    for (i = 0; i < NHASHENT; i++)
	dirHeader->hashTable[i] = 0;

    /* Install ".", "..", and the dynamic mount directory */
    afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, ".", 1);
    afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, "..", 1);
    afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk,
			  AFS_DYNROOT_MOUNTNAME, AFS_DYNROOT_MOUNT_VNODE);
    linkCount += 3;

    for (cellidx = 0; cellidx < maxcellidx; cellidx++) {
	c = afs_GetCellByIndex(cellidx, READ_LOCK);
	if (!c)
	    continue;
	if (c->cellNum == afs_dynrootCell)
	    continue;

	dotLen = strlen(c->cellName) + 2;
	dotCell = afs_osi_Alloc(dotLen);
	strcpy(dotCell, ".");
	afs_strcat(dotCell, c->cellName);
	afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, c->cellName,
			      VNUM_FROM_CIDX_RW(cellidx, 0));
	afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, dotCell,
			      VNUM_FROM_CIDX_RW(cellidx, 1));
	afs_osi_Free(dotCell, dotLen);

	linkCount += 2;
	afs_PutCell(c, READ_LOCK);
    }

    for (aliasidx = 0; aliasidx < maxaliasidx; aliasidx++) {
	ca = afs_GetCellAlias(aliasidx);
	if (!ca)
	    continue;

	dotLen = strlen(ca->alias) + 2;
	dotCell = afs_osi_Alloc(dotLen);
	strcpy(dotCell, ".");
	afs_strcat(dotCell, ca->alias);
	afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, ca->alias,
			      VNUM_FROM_CAIDX_RW(aliasidx, 0));
	afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, dotCell,
			      VNUM_FROM_CAIDX_RW(aliasidx, 1));
	afs_osi_Free(dotCell, dotLen);
	afs_PutCellAlias(ca);
    }

    ts = afs_dynSymlinkBase;
    while (ts) {
	int vnum = VNUM_FROM_TYPEID(VN_TYPE_SYMLINK, ts->index);
	afs_dynroot_addDirEnt(dirHeader, &curPage, &curChunk, ts->name, vnum);
	ts = ts->next;
    }

    ReleaseReadLock(&afs_dynSymlinkLock);

    ObtainWriteLock(&afs_dynrootDirLock, 549);
    if (afs_dynrootDir)
	afs_osi_Free(afs_dynrootDir, afs_dynrootDirLen);
    afs_dynrootDir = newDir;
    afs_dynrootDirLen = dirSize;
    afs_dynrootDirLinkcnt = linkCount;
    afs_dynrootDirVersion = newVersion;
    ReleaseWriteLock(&afs_dynrootDirLock);
}
Пример #2
0
static struct dentry *afs_decode_fh(struct super_block *sb, __u32 *fh,
				    int fh_len, int fh_type,
				    int (*acceptable)(void *, struct dentry *),
				    void *context)
#endif
{
    struct VenusFid fid;
    struct cell *tc;
    struct dentry *result;
#if defined(NEW_EXPORT_OPS)
    __u32 *fh = (__u32 *)fh_fid->raw;
#endif


    switch (fh_type) {
	case AFSFH_VENUSFID:
	    if (fh_len != 4)
		return NULL;
	    fid.Cell       = fh[0];
	    fid.Fid.Volume = fh[1];
	    fid.Fid.Vnode  = fh[2];
	    fid.Fid.Unique = fh[3];
	    break;

	case AFSFH_CELLFID:
	    if (fh_len != 7)
		return NULL;
	    AFS_GLOCK();
	    tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
	    if (!tc) {
		AFS_GUNLOCK();
		return NULL;
	    }
	    fid.Cell       = tc->cellNum;
	    fid.Fid.Volume = fh[4];
	    fid.Fid.Vnode  = fh[5];
	    fid.Fid.Unique = fh[6];
	    afs_PutCell(tc, READ_LOCK);
	    AFS_GUNLOCK();
	    break;

	case AFSFH_NET_VENUSFID:
	    fid.Cell       = ntohl(fh[0]);
	    fid.Fid.Volume = ntohl(fh[1]);
	    fid.Fid.Vnode  = ntohl(fh[2]);
	    fid.Fid.Unique = ntohl(fh[3]);
	    break;

	case AFSFH_NET_CELLFID:
	    if (fh_len != 7)
		return NULL;
	    AFS_GLOCK();
	    tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
	    if (!tc) {
		AFS_GUNLOCK();
		return NULL;
	    }
	    fid.Cell       = tc->cellNum;
	    fid.Fid.Volume = ntohl(fh[4]);
	    fid.Fid.Vnode  = ntohl(fh[5]);
	    fid.Fid.Unique = ntohl(fh[6]);
	    afs_PutCell(tc, READ_LOCK);
	    AFS_GUNLOCK();
	    break;

	case AFSFH_DYN_RO_CELL:
	case AFSFH_DYN_RW_CELL:
	    if (fh_len != 4)
		return NULL;
	    AFS_GLOCK();
	    tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
	    if (!tc) {
		AFS_GUNLOCK();
		return NULL;
	    }
	    afs_GetDynrootFid(&fid);
	    fid.Fid.Vnode  = VNUM_FROM_CIDX_RW(tc->cellIndex, fh_type & 1);
	    fid.Fid.Unique = 1;
	    afs_PutCell(tc, READ_LOCK);
	    AFS_GUNLOCK();
	    break;

	case AFSFH_DYN_RO_LINK:
	case AFSFH_DYN_RW_LINK:
	    if (fh_len != 4)
		return NULL;
	    AFS_GLOCK();
	    tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
	    if (!tc) {
		AFS_GUNLOCK();
		return NULL;
	    }
	    afs_GetDynrootFid(&fid);
	    fid.Fid.Vnode  = VNUM_FROM_CAIDX_RW(tc->cellIndex, fh_type & 1);
	    fid.Fid.Unique = 1;
	    afs_PutCell(tc, READ_LOCK);
	    AFS_GUNLOCK();
	    break;

	case AFSFH_DYN_MOUNT:
	    if (fh_len != 5)
		return NULL;
	    AFS_GLOCK();
	    tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
	    if (!tc) {
		AFS_GUNLOCK();
		return NULL;
	    }
	    afs_GetDynrootFid(&fid);
	    fid.Fid.Vnode  = VNUM_FROM_TYPEID(VN_TYPE_MOUNT,
					      tc->cellIndex << 2);
	    fid.Fid.Unique = ntohl(fh[4]);
	    afs_PutCell(tc, READ_LOCK);
	    AFS_GUNLOCK();
	    break;

	case AFSFH_DYN_SYMLINK:
	    /* XXX parse dynroot symlink filehandle */
	    /* break; */

	default:
	    return NULL;
    }

#if defined(NEW_EXPORT_OPS)
    result = afs_export_get_dentry(sb, &fid);
#else
    result = sb->s_export_op->find_exported_dentry(sb, &fid, 0,
						   acceptable, context);

#endif

#ifdef OSI_EXPORT_DEBUG
    if (!result) {
	printk("afs: decode_fh(0x%08x/%d/%d.%d): no dentry\n",
	       fid.Cell,      fid.Fid.Volume,
	       fid.Fid.Vnode, fid.Fid.Unique);
    } else if (IS_ERR(result)) {
	printk("afs: decode_fh(0x%08x/%d/%d.%d): error %ld\n",
	       fid.Cell,      fid.Fid.Volume,
	       fid.Fid.Vnode, fid.Fid.Unique, PTR_ERR(result));
    }
#endif
    return result;
}