예제 #1
0
/**
 *   Note that areq may be null, in which case we don't bother to set any
 * request status information.
 * @param afid Volume FID.
 * @param areq Request type.
 * @param locktype Lock to be used.
 * @return Volume or NULL if no result.
 */
struct volume *
afs_GetVolume(struct VenusFid *afid, struct vrequest *areq,
	      afs_int32 locktype)
{
    struct volume *tv;
    char *bp, tbuf[CVBS];
    AFS_STATCNT(afs_GetVolume);

    tv = afs_FindVolume(afid, locktype);
    if (!tv) {
	/* Do a dynroot check and add dynroot volume if found. */
	if (afs_IsDynrootAnyFid(afid)) {
	    tv = afs_NewDynrootVolume(afid);
	} else {
	    bp = afs_cv2string(&tbuf[CVBS], afid->Fid.Volume);
	    tv = afs_NewVolumeByName(bp, afid->Cell, 0, areq, locktype);
	}
    }
    return tv;
}				/*afs_GetVolume */
예제 #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;
}
예제 #3
0
int
afs_IsDynrootAny(struct vcache *avc)
{
    return afs_IsDynrootAnyFid(&avc->f.fid);
}
예제 #4
0
static int afs_export_get_name(struct dentry *parent, char *name,
			       struct dentry *child)
{
    struct afs_fakestat_state fakestate;
    struct get_name_data data;
    struct vrequest treq;
    struct volume *tvp;
    struct vcache *vcp;
    struct dcache *tdc;
    cred_t *credp;
    afs_size_t dirOffset, dirLen;
    afs_int32 code = 0;

    if (!parent->d_inode) {
#ifdef OSI_EXPORT_DEBUG
	/* can't lookup name in a negative dentry */
	printk("afs: get_name(%s, %s): no parent inode\n",
	       parent->d_name.name ? (char *)parent->d_name.name : "?",
	       child->d_name.name  ? (char *)child->d_name.name  : "?");
#endif
	return -EIO;
    }
    if (!child->d_inode) {
#ifdef OSI_EXPORT_DEBUG
	/* can't find the FID of negative dentry */
	printk("afs: get_name(%s, %s): no child inode\n",
	       parent->d_name.name ? (char *)parent->d_name.name : "?",
	       child->d_name.name  ? (char *)child->d_name.name  : "?");
#endif
	return -ENOENT;
    }

    afs_InitFakeStat(&fakestate);

    credp = crref();
    AFS_GLOCK();

    vcp = VTOAFS(child->d_inode);

    /* special case dynamic mount directory */
    if (afs_IsDynrootMount(vcp)) {
#ifdef OSI_EXPORT_DEBUG
	printk("afs: get_name(%s, 0x%08x/%d/%d.%d): this is the dynmount dir\n",
	       parent->d_name.name ? (char *)parent->d_name.name : "?",
	       vcp->f.fid.Cell,      vcp->f.fid.Fid.Volume,
	       vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
#endif
	data.fid = vcp->f.fid;
	if (VTOAFS(parent->d_inode) == afs_globalVp)
	    strcpy(name, AFS_DYNROOT_MOUNTNAME);
	else
	    code = -ENOENT;
	goto done;
    }

    /* Figure out what FID to look for */
    if (vcp->mvstat == 2) { /* volume root */
	tvp = afs_GetVolume(&vcp->f.fid, 0, READ_LOCK);
	if (!tvp) {
#ifdef OSI_EXPORT_DEBUG
	    printk("afs: get_name(%s, 0x%08x/%d/%d.%d): no volume for root\n",
		   parent->d_name.name ? (char *)parent->d_name.name : "?",
		   vcp->f.fid.Cell,      vcp->f.fid.Fid.Volume,
		   vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
#endif
	    code = ENOENT;
	    goto done;
	}
	data.fid = tvp->mtpoint;
	afs_PutVolume(tvp, READ_LOCK);
    } else {
	data.fid = vcp->f.fid;
    }

    vcp = VTOAFS(parent->d_inode);
#ifdef OSI_EXPORT_DEBUG
    printk("afs: get_name(%s, 0x%08x/%d/%d.%d): parent is 0x%08x/%d/%d.%d\n",
	   parent->d_name.name ? (char *)parent->d_name.name : "?",
	   data.fid.Cell,      data.fid.Fid.Volume,
	   data.fid.Fid.Vnode, data.fid.Fid.Unique,
	   vcp->f.fid.Cell,      vcp->f.fid.Fid.Volume,
	   vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
#endif

    code = afs_InitReq(&treq, credp);
    if (code) {
#ifdef OSI_EXPORT_DEBUG
	printk("afs: get_name(%s, 0x%08x/%d/%d.%d): afs_InitReq: %d\n",
	       parent->d_name.name ? (char *)parent->d_name.name : "?",
	       data.fid.Cell,      data.fid.Fid.Volume,
	       data.fid.Fid.Vnode, data.fid.Fid.Unique, code);
#endif
	goto done;
    }

    /* a dynamic mount point in the dynamic mount directory */
    if (afs_IsDynrootMount(vcp) && afs_IsDynrootAnyFid(&data.fid)
	&& VNUM_TO_VNTYPE(data.fid.Fid.Vnode) == VN_TYPE_MOUNT) {
#ifdef OSI_EXPORT_DEBUG
	printk("afs: get_name(%s, 0x%08x/%d/%d.%d): dynamic mount point\n",
	       parent->d_name.name ? (char *)parent->d_name.name : "?",
	       data.fid.Cell,      data.fid.Fid.Volume,
	       data.fid.Fid.Vnode, data.fid.Fid.Unique);
#endif
	vcp = afs_GetVCache(&data.fid, &treq, NULL, NULL);
	if (vcp) {
	    ObtainReadLock(&vcp->lock);
	    if (strlen(vcp->linkData + 1) <= NAME_MAX)
		strcpy(name, vcp->linkData + 1);
	    else
		code = ENOENT;
	    ReleaseReadLock(&vcp->lock);
	    afs_PutVCache(vcp);
	} else {
#ifdef OSI_EXPORT_DEBUG
	    printk("afs: get_name(%s, 0x%08x/%d/%d.%d): no vcache\n",
		   parent->d_name.name ? (char *)parent->d_name.name : "?",
		   data.fid.Cell,      data.fid.Fid.Volume,
		   data.fid.Fid.Vnode, data.fid.Fid.Unique);
#endif
	    code = ENOENT;
	}
	goto done;
    }

    code = afs_EvalFakeStat(&vcp, &fakestate, &treq);
    if (code)
	goto done;

    if (vcp->f.fid.Cell != data.fid.Cell ||
	vcp->f.fid.Fid.Volume != data.fid.Fid.Volume) {
	/* parent is not the expected cell and volume; thus it
	 * cannot possibly contain the fid we are looking for */
#ifdef OSI_EXPORT_DEBUG
	printk("afs: get_name(%s, 0x%08x/%d/%d.%d): wrong parent 0x%08x/%d\n",
	       parent->d_name.name ? (char *)parent->d_name.name : "?",
	       data.fid.Cell,      data.fid.Fid.Volume,
	       data.fid.Fid.Vnode, data.fid.Fid.Unique,
	       vcp->f.fid.Cell,      vcp->f.fid.Fid.Volume);
#endif
	code = ENOENT;
	goto done;
    }


redo:
    if (!(vcp->f.states & CStatd)) {
	if ((code = afs_VerifyVCache2(vcp, &treq))) {
#ifdef OSI_EXPORT_DEBUG
	    printk("afs: get_name(%s, 0x%08x/%d/%d.%d): VerifyVCache2(0x%08x/%d/%d.%d): %d\n",
		   parent->d_name.name ? (char *)parent->d_name.name : "?",
		   data.fid.Cell,      data.fid.Fid.Volume,
		   data.fid.Fid.Vnode, data.fid.Fid.Unique,
		   vcp->f.fid.Cell,      vcp->f.fid.Fid.Volume,
		   vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
#endif
	    goto done;
	}
    }

    tdc = afs_GetDCache(vcp, (afs_size_t) 0, &treq, &dirOffset, &dirLen, 1);
    if (!tdc) {
#ifdef OSI_EXPORT_DEBUG
	printk("afs: get_name(%s, 0x%08x/%d/%d.%d): GetDCache(0x%08x/%d/%d.%d): %d\n",
	       parent->d_name.name ? (char *)parent->d_name.name : "?",
	       data.fid.Cell,      data.fid.Fid.Volume,
	       data.fid.Fid.Vnode, data.fid.Fid.Unique,
	       vcp->f.fid.Cell,      vcp->f.fid.Fid.Volume,
	       vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
#endif
	code = EIO;
	goto done;
    }

    ObtainReadLock(&vcp->lock);
    ObtainReadLock(&tdc->lock);

    /*
     * Make sure that the data in the cache is current. There are two
     * cases we need to worry about:
     * 1. The cache data is being fetched by another process.
     * 2. The cache data is no longer valid
     */
    while ((vcp->f.states & CStatd)
	   && (tdc->dflags & DFFetching)
	   && hsame(vcp->f.m.DataVersion, tdc->f.versionNo)) {
	ReleaseReadLock(&tdc->lock);
	ReleaseReadLock(&vcp->lock);
	afs_osi_Sleep(&tdc->validPos);
	ObtainReadLock(&vcp->lock);
	ObtainReadLock(&tdc->lock);
    }
    if (!(vcp->f.states & CStatd)
	|| !hsame(vcp->f.m.DataVersion, tdc->f.versionNo)) {
	ReleaseReadLock(&tdc->lock);
	ReleaseReadLock(&vcp->lock);
	afs_PutDCache(tdc);
#ifdef OSI_EXPORT_DEBUG
	printk("afs: get_name(%s, 0x%08x/%d/%d.%d): dir (0x%08x/%d/%d.%d) changed; retrying\n",
	       parent->d_name.name ? (char *)parent->d_name.name : "?",
	       data.fid.Cell,      data.fid.Fid.Volume,
	       data.fid.Fid.Vnode, data.fid.Fid.Unique,
	       vcp->f.fid.Cell,      vcp->f.fid.Fid.Volume,
	       vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique);
#endif
	goto redo;
    }

    data.name  = name;
    data.found = 0;
    code = afs_dir_EnumerateDir(tdc, get_name_hook, &data);
    if (!code && !data.found) {
#ifdef OSI_EXPORT_DEBUG
	printk("afs: get_name(%s, 0x%08x/%d/%d.%d): not found\n",
	       parent->d_name.name ? (char *)parent->d_name.name : "?",
	       data.fid.Cell,      data.fid.Fid.Volume,
	       data.fid.Fid.Vnode, data.fid.Fid.Unique);
#endif
	code = ENOENT;
    } else if (code) {
#ifdef OSI_EXPORT_DEBUG
	printk("afs: get_name(%s, 0x%08x/%d/%d.%d): Enumeratedir(0x%08x/%d/%d.%d): %d\n",
	       parent->d_name.name ? (char *)parent->d_name.name : "?",
	       data.fid.Cell,      data.fid.Fid.Volume,
	       data.fid.Fid.Vnode, data.fid.Fid.Unique,
	       vcp->f.fid.Cell,      vcp->f.fid.Fid.Volume,
	       vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code);
#endif
    }

    ReleaseReadLock(&tdc->lock);
    ReleaseReadLock(&vcp->lock);
    afs_PutDCache(tdc);

done:
    if (!code) {
	printk("afs: get_name(%s, 0x%08x/%d/%d.%d) => %s\n",
	       parent->d_name.name ? (char *)parent->d_name.name : "?",
	       data.fid.Cell,      data.fid.Fid.Volume,
	       data.fid.Fid.Vnode, data.fid.Fid.Unique, name);
    }
    afs_PutFakeStat(&fakestate);
    AFS_GUNLOCK();
    crfree(credp);
    code = afs_CheckCode(code, &treq, 102);
    return -code;
}