Ejemplo n.º 1
0
static int
do_volop(struct fssync_state * state, afs_int32 command, SYNC_response * res)
{
    afs_int32 code;
    SYNC_PROTO_BUF_DECL(res_buf);
    SYNC_response res_l;

    if (!res) {
	res = &res_l;
	res->payload.len = SYNC_PROTO_MAX_LEN;
	res->payload.buf = res_buf;
    }

    fprintf(stderr, "calling FSYNC_VolOp with command code %d (%s)\n",
	    command, FSYNC_com2string(command));

    code = FSYNC_VolOp(state->vop->volume,
		       state->vop->partName,
		       command,
		       state->reason,
		       res);

    debug_response(code, res);

    VDisconnectFS();

    return 0;

}
Ejemplo n.º 2
0
/* Try to detect if the fileserver is DAFS, and if so, re-exec as the
 * DAFS-enabled fssync-debug (dafssync_debug). If we fail to detect or
 * exec, just try to proceed anyway as if the server is not DAFS */
static void
dafs_prolog(void)
{
    SYNC_response res;
    SYNC_PROTO_BUF_DECL(res_buf);
    afs_int32 code;
    char *dfssd;

    res.payload.len = SYNC_PROTO_MAX_LEN;
    res.payload.buf = res_buf;

    /* LISTVOLUMES is a no-op; we just want to get the response header flags
     * to see if the server reports itself as DAFS or not */
    code = FSYNC_VolOp(0, NULL, FSYNC_VOL_LISTVOLUMES, FSYNC_WHATEVER, &res);
    if (code) {
	/* probably failed to contact the fileserver; later code will provide
	 * some warning/error indication */
	return;
    }

    if (!(res.hdr.flags & SYNC_FLAG_DAFS_EXTENSIONS)) {
	/* fileserver is not DAFS, so we don't need to do anything */
	return;
    }

    dfssd = afs_exec_alt(fssd_argc, fssd_argv, "da", NULL);

    fprintf(stderr, "\n*** server asserted demand attach extensions, but we failed\n"
                    "*** to exec a DAFS-enabled fssync-debug '%s' (errno=%d);\n"
                    "*** attempting to proceed without it.\n\n", dfssd, errno);

    free(dfssd);
}
Ejemplo n.º 3
0
/* No lock needed. Only the volserver will call this, and only one transaction
 * can have a given volume (volid/partition pair) in use at a time 
 */
void
VPurgeVolume(Error * ec, Volume * vp)
{
    struct DiskPartition64 *tpartp = vp->partition;
    char purgePath[MAXPATHLEN];

    /* so VCheckDetach doesn't try to update the volume header and
     * dump spurious errors into the logs */
    V_inUse(vp) = 0;

    /* N.B.  it's important here to use the partition pointed to by the
     * volume header. This routine can, under some circumstances, be called
     * when two volumes with the same id exist on different partitions.
     */
    (void)afs_snprintf(purgePath, sizeof purgePath, "%s/%s",
		       VPartitionPath(vp->partition),
		       VolumeExternalName(V_id(vp)));
    PurgeIndex_r(vp, vLarge);
    PurgeIndex_r(vp, vSmall);
    PurgeHeader_r(vp);
    unlink(purgePath);
    /*
     * Call the fileserver to break all call backs for that volume
     */
    FSYNC_VolOp(V_id(vp), tpartp->name, FSYNC_VOL_BREAKCBKS, 0, NULL);
}
Ejemplo n.º 4
0
/**
 * perform an asynchronous volume group scan.
 *
 * @param[in] partition   vice partition string
 * @param[in] reason      FSSYNC reason code
 *
 * @note if partition is NULL, all vice partitions will be scanned.
 *
 * @return operation status
 *    @retval SYNC_OK success
 */
afs_int32
FSYNC_VGCScan(char * partition, int reason)
{
    int command;

    if (partition == NULL) {
        command = FSYNC_VG_SCAN_ALL;
        partition = "";
    } else {
        command = FSYNC_VG_SCAN;
    }

    return FSYNC_VolOp(0, partition, command, reason, NULL);
}
Ejemplo n.º 5
0
/**
 * query the volume group cache.
 *
 * @param[in]  part     vice partition path
 * @param[in]  volid    volume id
 * @param[out] qry      query response object
 * @param[out] res      SYNC response message
 *
 * @return operation status
 *    @retval SYNC_OK success
 */
afs_int32
FSYNC_VGCQuery(char * part,
               VolumeId volid,
               FSSYNC_VGQry_response_t * qry,
               SYNC_response *res)
{
    SYNC_response lres;

    if (!res) {
        res = &lres;
    }

    res->hdr.response_len = sizeof(res->hdr);
    res->payload.buf = qry;
    res->payload.len = sizeof(*qry);

    return FSYNC_VolOp(volid, part, FSYNC_VG_QUERY, 0, res);
}
Ejemplo n.º 6
0
static int
do_volop(struct state * state, afs_int32 command, SYNC_response * res)
{
    afs_int32 code;
    SYNC_PROTO_BUF_DECL(res_buf);
    SYNC_response res_l;

    if (!res) {
	res = &res_l;
	res->payload.len = SYNC_PROTO_MAX_LEN;
	res->payload.buf = res_buf;
    }

    fprintf(stderr, "calling FSYNC_VolOp with command code %d (%s)\n", 
	    command, command_code_to_string(command));

    code = FSYNC_VolOp(state->vop->volume,
		       state->vop->partName,
		       command,
		       state->reason,
		       res);

    switch (code) {
    case SYNC_OK:
    case SYNC_DENIED:
	break;
    default:
	fprintf(stderr, "possible sync protocol error. return code was %d\n", code);
    }

    fprintf(stderr, "FSYNC_VolOp returned %d (%s)\n", code, response_code_to_string(code));
    fprintf(stderr, "protocol response code was %d (%s)\n", 
	    res->hdr.response, response_code_to_string(res->hdr.response));
    fprintf(stderr, "protocol reason code was %d (%s)\n", 
	    res->hdr.reason, reason_code_to_string(res->hdr.reason));

    VDisconnectFS();
}
Ejemplo n.º 7
0
/**
 * verify that the fileserver still thinks we have a volume checked out.
 *
 * In DAFS, a non-fileserver program accesses a volume by checking it out from
 * the fileserver (FSYNC_VOL_OFF or FSYNC_VOL_NEEDVOLUME), and then locks the
 * volume. There is a possibility that the fileserver crashes or restarts for
 * some reason between volume checkout and locking; if this happens, the
 * fileserver could attach the volume before we had a chance to lock it. This
 * function serves to detect if this has happened; it must be called after
 * volume checkout and locking to make sure the fileserver still thinks we
 * have the volume. (If it doesn't, we should try to check it out again.)
 *
 * @param[in] volume    volume ID
 * @param[in] partition partition name string
 * @param[in] command   the command that was used to checkout the volume
 * @param[in] reason    the reason code used to checkout the volume
 *
 * @return operation status
 *  @retval SYNC_OK the fileserver could not have attached the volume since
 *                  it was checked out (either it thinks it is still checked
 *                  out, or it doesn't know about the volume)
 *  @retval SYNC_DENIED fileserver may have restarted since checkout; checkout
 *                      should be reattempted
 *  @retval SYNC_COM_ERROR internal/fatal error
 */
afs_int32
FSYNC_VerifyCheckout(VolumeId volume, char * partition,
                     afs_int32 command, afs_int32 reason)
{
    SYNC_response res;
    FSSYNC_VolOp_info vop;
    afs_int32 code;
    afs_int32 pid;

    res.hdr.response_len = sizeof(res.hdr);
    res.payload.buf = &vop;
    res.payload.len = sizeof(vop);

    code = FSYNC_VolOp(volume, partition, FSYNC_VOL_QUERY_VOP, FSYNC_WHATEVER, &res);
    if (code != SYNC_OK) {
        if (res.hdr.reason == FSYNC_NO_PENDING_VOL_OP) {
            Log("FSYNC_VerifyCheckout: fileserver claims no vop for vol %lu "
                "part %s; fileserver may have restarted since checkout\n",
                afs_printable_uint32_lu(volume), partition);
            return SYNC_DENIED;
        }

        if (res.hdr.reason == FSYNC_UNKNOWN_VOLID ||
                res.hdr.reason == FSYNC_WRONG_PART) {
            /* if the fileserver does not know about this volume on this
             * partition, there's no way it could have attached it, so we're
             * fine */
            return SYNC_OK;
        }

        Log("FSYNC_VerifyCheckout: FSYNC_VOL_QUERY_VOP failed for vol %lu "
            "part %s with code %ld reason %ld\n",
            afs_printable_uint32_lu(volume), partition,
            afs_printable_int32_ld(code),
            afs_printable_int32_ld(res.hdr.reason));
        return SYNC_COM_ERROR;
    }

    pid = getpid();

    /* Check if the current vol op is us. Checking pid is probably enough, but
     * be a little bit paranoid. We could also probably check tid, but I'm not
     * completely confident of its reliability on all platforms (on pthread
     * envs, we coerce a pthread_t to an afs_int32, which is not guaranteed
     * to mean anything significant). */

    if (vop.com.programType == programType && vop.com.pid == pid &&
            vop.com.command == command && vop.com.reason == reason) {

        /* looks like the current pending vol op is the same one as the one
         * with which we checked it out. success. */
        return SYNC_OK;
    }

    Log("FSYNC_VerifyCheckout: vop for vol %lu part %s does not match "
        "expectations (got pt %ld pid %ld cmd %ld reason %ld, but expected "
        "pt %ld pid %ld cmd %ld reason %ld); fileserver may have restarted "
        "since checkout\n", afs_printable_uint32_lu(volume), partition,
        afs_printable_int32_ld(vop.com.programType),
        afs_printable_int32_ld(vop.com.pid),
        afs_printable_int32_ld(vop.com.command),
        afs_printable_int32_ld(vop.com.reason),
        afs_printable_int32_ld(programType),
        afs_printable_int32_ld(pid),
        afs_printable_int32_ld(command),
        afs_printable_int32_ld(reason));

    return SYNC_DENIED;
}