Significado de fsync() en la configuración sshfs+LUKS

Significado de fsync() en la configuración sshfs+LUKS

Fondo:Estoy investigando métodos para el almacenamiento cifrado en máquinas que no son de confianza. Mi configuración actual usa sshfs para acceder a una imagen cifrada con LUKS en elremotomáquina, que se descifraen la zonay montado como ext3. (Si usara sshfs únicamente, alguien que obtuviera acceso a la máquina remota podría ver mis datos). Aquí está mi configuración de ejemplo:

# On the local machine:
sshfs remote:/home/crypt /home/crypt
cryptsetup luksOpen /home/crypt/container.img container
mount /dev/mapper/container /home/crypt-open

# Place cleartext files in /home/crypt-open,
# then reverse the above steps to unmount.

Quiero que esto sea resistente a fallas de red. Para hacer esto, me gustaría entender qué sucede con el almacenamiento en caché/búfer con esta configuración. Considere estos dos comandos:

dd if=/dev/random of=/home/crypt-open/test.dat bs=1000000 count=100
dd if=/dev/random of=/home/crypt-open/test.dat bs=1000000 count=100 conv=fsync

El primer comando regresa muy rápidamente y puedo ver por el tráfico de la red que los datos aún se transmiten después de que el comando haya regresado. El segundo comando parece esperar hasta que terminen de transferirse los datos.

Preguntas concretas:¿Qué garantías fsync()ofrece bajo esta configuración? Cuando fsync()regrese, ¿a qué distancia de estas capas se garantiza la sincronización de los datos? ¿Y qué puedo hacer para garantizar que se sincronice completamente con el disco duro de la máquina remota?

--- /home/crypt-open on the local machine
|
| (ext3 fs)
|
--- /dev/mapper/container on the local machine
|
| (LUKS)
|
--- /home/crypt/container.img on the local machine
|
| (sshfs)
|
--- /home/crypt/container.img on the remote machine
|
| (ext3 fs)
|
--- hard drive on the remote machine

Respuesta1

Supongo que el eslabón más débil aquí es el código SSHFS; el resto del material está en el kernel y se usa bastante, por lo que probablemente esté bien. En realidad, nunca antes había mirado ningún código FUSE, por lo que podría haber algo más que me haya perdido, pero de acuerdo con elCódigo fuente SSHFS, la implementación de SSHFS fsync()no hace mucho, solo llama flush()al flujo IO.

static int sshfs_fsync(const char *path, int isdatasync,
                       struct fuse_file_info *fi)
{
    (void) isdatasync;
    return sshfs_flush(path, fi);
}

En sshfs.c:2551, podemos ver que sshfs_flush()la función no envía ningún tipo de comando de sincronización a la máquina remota que aplica fsync. Creo que la sshfs.sync_writebandera significa "esperar a que los comandos vayan al servidor antes de regresar de la escritura", no "fsync en el servidor en cada escritura" porque ese segundo significado sería muy extraño. Por lo tanto, su medición de fsync es más lenta porque está obstaculizada por la velocidad de la red, no por la velocidad del disco remoto.

static int sshfs_flush(const char *path, struct fuse_file_info *fi)
{
    int err;
    struct sshfs_file *sf = get_sshfs_file(fi);
    struct list_head write_reqs;
    struct list_head *curr_list;

    if (!sshfs_file_is_conn(sf))
        return -EIO;

    if (sshfs.sync_write)
        return 0;

    (void) path;
    pthread_mutex_lock(&sshfs.lock);
    if (!list_empty(&sf->write_reqs)) {
        curr_list = sf->write_reqs.prev;
        list_del(&sf->write_reqs);
        list_init(&sf->write_reqs);
        list_add(&write_reqs, curr_list);
        while (!list_empty(&write_reqs))
            pthread_cond_wait(&sf->write_finished, &sshfs.lock);
    }
    err = sf->write_error;
    sf->write_error = 0;
    pthread_mutex_unlock(&sshfs.lock);
    return err;
}

Tenga en cuenta que es posible que la implementación SFTP remota realmente se sincronice en las escrituras, pero creo que eso no es lo que está sucediendo. Según un viejoborrador del estándar SFTP(que es lo mejor que puedo encontrar) hay una manera de especificar este comportamiento:

7.9. attrib-bits and attrib-bits-valid
...
SSH_FILEXFER_ATTR_FLAGS_SYNC
       When the file is modified, the changes are written synchronously
       to the disk.

lo que implicaría que este no es el valor predeterminado (ya que es más rápido no fsync). Según ese documento de estándares, no parece haber una manera de solicitar una sincronización fsync en el archivo remoto, pero parece que OpenSSH admite esto como una extensión de SFTP.

/* SSH2_FXP_EXTENDED submessages */
struct sftp_handler extended_handlers[] = {
    ...
    { "fsync", "[email protected]", 0, process_extended_fsync, 1 },
    ...
};

static void
process_extended_fsync(u_int32_t id)
{
    int handle, fd, ret, status = SSH2_FX_OP_UNSUPPORTED;

    handle = get_handle();
    debug3("request %u: fsync (handle %u)", id, handle);
    verbose("fsync \"%s\"", handle_to_name(handle));
    if ((fd = handle_to_fd(handle)) < 0)
        status = SSH2_FX_NO_SUCH_FILE;
    else if (handle_is_ok(handle, HANDLE_FILE)) {
        ret = fsync(fd);
        status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
    }
    send_status(id, status);
}

Dudo que sea difícil consultar esa extensión y admitir adecuadamente fsync en SSHFS, parece algo bastante razonable. Dicho esto, creo que probablemente sería más fácil usar la compatibilidad con dispositivos de bloqueo de red de Linux, que supongo que admite todas estas cosas correctamente (aunque nunca lo he usado, por lo que podría ser horrible).

información relacionada