Exemple #1
0
/*
 * Inform dynroot that a new vnode is being created.  Return value
 * is non-zero if this vnode is handled by dynroot, in which case
 * FetchStatus will be filled in.
 */
int
afs_DynrootNewVnode(struct vcache *avc, struct AFSFetchStatus *status)
{
    char *bp, tbuf[CVBS];

    if (_afs_IsDynrootFid(&avc->f.fid)) {
	if (!afs_dynrootEnable)
	    return 0;
	afs_GetDynroot(0, 0, status);
	afs_PutDynroot();
	return 1;
    }

    if (afs_IsDynrootMount(avc)) {
	afs_GetDynrootMount(0, 0, status);
	afs_PutDynroot();
	return 1;
    }

    /*
     * Check if this is an entry under /afs, e.g. /afs/cellname.
     */
    if (avc->f.fid.Cell == afs_dynrootCell
	&& avc->f.fid.Fid.Volume == AFS_DYNROOT_VOLUME) {

	struct cell *c;
	struct cell_alias *ca;
	int namelen, linklen, cellidx, rw;

	memset(status, 0, sizeof(struct AFSFetchStatus));

	status->FileType = SymbolicLink;
	status->LinkCount = 1;
	status->DataVersion = 1;
	status->CallerAccess = PRSFS_LOOKUP | PRSFS_READ;
	status->AnonymousAccess = PRSFS_LOOKUP | PRSFS_READ;
	status->ParentVnode = 1;
	status->ParentUnique = 1;

	if (VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode) == VN_TYPE_SYMLINK) {
	    struct afs_dynSymlink *ts;
	    int index = VNUM_TO_VNID(avc->f.fid.Fid.Vnode);

	    ObtainReadLock(&afs_dynSymlinkLock);
	    ts = afs_dynSymlinkBase;
	    while (ts) {
		if (ts->index == index)
		    break;
		ts = ts->next;
	    }

	    if (ts) {
		linklen = strlen(ts->target);
		avc->linkData = afs_osi_Alloc(linklen + 1);
		strcpy(avc->linkData, ts->target);

		status->Length = linklen;
		status->UnixModeBits = 0755;
	    }
	    ReleaseReadLock(&afs_dynSymlinkLock);

	    return ts ? 1 : 0;
	}

	if (VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode) != VN_TYPE_CELL
	    && VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode) != VN_TYPE_ALIAS
	    && VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode) != VN_TYPE_MOUNT) {
	    afs_warn("dynroot vnode inconsistency, unknown VNTYPE %d\n",
		     VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode));
	    return 0;
	}

	cellidx = VNUM_TO_CIDX(avc->f.fid.Fid.Vnode);
	rw = VNUM_TO_RW(avc->f.fid.Fid.Vnode);

	if (VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode) == VN_TYPE_ALIAS) {
	    char *realName;

	    ca = afs_GetCellAlias(cellidx);
	    if (!ca) {
		afs_warn("dynroot vnode inconsistency, can't find alias %d\n",
			 cellidx);
		return 0;
	    }

	    /*
	     * linkData needs to contain the name of the cell
	     * we're aliasing for.
	     */
	    realName = ca->cell;
	    if (!realName) {
		afs_warn("dynroot: alias %s missing real cell name\n",
			 ca->alias);
		avc->linkData = afs_strdup("unknown");
		linklen = 7;
	    } else {
		int namelen = strlen(realName);
		linklen = rw + namelen;
		avc->linkData = afs_osi_Alloc(linklen + 1);
		strcpy(avc->linkData, rw ? "." : "");
		afs_strcat(avc->linkData, realName);
	    }

	    status->UnixModeBits = 0755;
	    afs_PutCellAlias(ca);

	} else if (VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode) == VN_TYPE_MOUNT) {
	    c = afs_GetCellByIndex(cellidx, READ_LOCK);
	    if (!c) {
		afs_warn("dynroot vnode inconsistency, can't find cell %d\n",
			 cellidx);
		return 0;
	    }

	    /*
	     * linkData needs to contain "%cell:volumeid"
	     */
	    namelen = strlen(c->cellName);
	    bp = afs_cv2string(&tbuf[CVBS], avc->f.fid.Fid.Unique);
	    linklen = 2 + namelen + strlen(bp);
	    avc->linkData = afs_osi_Alloc(linklen + 1);
	    strcpy(avc->linkData, "%");
	    afs_strcat(avc->linkData, c->cellName);
	    afs_strcat(avc->linkData, ":");
	    afs_strcat(avc->linkData, bp);

	    status->UnixModeBits = 0644;
	    status->ParentVnode = AFS_DYNROOT_MOUNT_VNODE;
	    afs_PutCell(c, READ_LOCK);

	} else {
	    c = afs_GetCellByIndex(cellidx, READ_LOCK);
	    if (!c) {
		afs_warn("dynroot vnode inconsistency, can't find cell %d\n",
			 cellidx);
		return 0;
	    }

	    /*
	     * linkData needs to contain "#cell:root.cell" or "%cell:root.cell"
	     */
	    namelen = strlen(c->cellName);
	    linklen = 1 + namelen + 10;
	    avc->linkData = afs_osi_Alloc(linklen + 1);
	    strcpy(avc->linkData, rw ? "%" : "#");
	    afs_strcat(avc->linkData, c->cellName);
	    afs_strcat(avc->linkData, ":root.cell");

	    status->UnixModeBits = 0644;
	    afs_PutCell(c, READ_LOCK);
	}

	status->Length = linklen;
	return 1;
    }

    return 0;
}
Exemple #2
0
static int afs_encode_fh(struct dentry *de, __u32 *fh, int *max_len,
			 int connectable)
{
    struct vcache *tvc;
    struct cell *tc;
    int vntype;

    if (!de->d_inode) /* encode a negative dentry?! */
	return 255;
    if (*max_len < 4)  /* not enough space */
	return 255;

    tvc = VTOAFS(de->d_inode);

#ifdef OSI_EXPORT_DEBUG
    printk("afs: encode_fh(0x%08x/%d/%d.%d)\n",
	   tvc->f.fid.Cell,      tvc->f.fid.Fid.Volume,
	   tvc->f.fid.Fid.Vnode, tvc->f.fid.Fid.Unique);
#endif
    if (afs_IsDynrootAnyFid(&tvc->f.fid)) {
	vntype = VNUM_TO_VNTYPE(tvc->f.fid.Fid.Vnode);
	switch (vntype) {
	    case 0:
		/* encode as a normal filehandle */
		break;

	    case VN_TYPE_MOUNT:
		if (*max_len < 5) {
		    return 255;
		}
		/* fall through */

	    case VN_TYPE_CELL:
	    case VN_TYPE_ALIAS:
		AFS_GLOCK();
		tc = afs_GetCellByIndex(VNUM_TO_CIDX(tvc->f.fid.Fid.Vnode),
					READ_LOCK);
		if (!tc) {
		    AFS_GUNLOCK();
		    return 255;
		}
		memcpy((void *)fh, tc->cellHandle, 16);
		afs_PutCell(tc, READ_LOCK);
		AFS_GUNLOCK();
		if (vntype == VN_TYPE_MOUNT) {
		    fh[4] = htonl(tvc->f.fid.Fid.Unique);
		    *max_len = 5;
		    return AFSFH_DYN_MOUNT;
		}
		*max_len = 4;
		if (vntype == VN_TYPE_CELL) {
		    return AFSFH_DYN_RO_CELL | VNUM_TO_RW(tvc->f.fid.Fid.Vnode);
		} else {
		    return AFSFH_DYN_RO_LINK | VNUM_TO_RW(tvc->f.fid.Fid.Vnode);
		}

	    case VN_TYPE_SYMLINK:
		/* XXX fill in filehandle for dynroot symlink */
		/* XXX return AFSFH_DYN_SYMLINK; */

	    default:
		return 255;
	}
    }

    if (*max_len < 7) {
	/* not big enough for a migratable filehandle */
	/* always encode in network order */
	fh[0] = htonl(tvc->f.fid.Cell);
	fh[1] = htonl(tvc->f.fid.Fid.Volume);
	fh[2] = htonl(tvc->f.fid.Fid.Vnode);
	fh[3] = htonl(tvc->f.fid.Fid.Unique);
	*max_len = 4;
	return AFSFH_NET_VENUSFID;
    }

    AFS_GLOCK();
    tc = afs_GetCell(tvc->f.fid.Cell, READ_LOCK);
    if (!tc) {
	AFS_GUNLOCK();
	return 255;
    }
    memcpy((void *)fh, tc->cellHandle, 16);
    afs_PutCell(tc, READ_LOCK);
    AFS_GUNLOCK();
    /* always encode in network order */
    fh[4] = htonl(tvc->f.fid.Fid.Volume);
    fh[5] = htonl(tvc->f.fid.Fid.Vnode);
    fh[6] = htonl(tvc->f.fid.Fid.Unique);

    *max_len = 7;
    return AFSFH_NET_CELLFID;
}