Beispiel #1
0
int raw_export_start(RawExport *e, const char *path, int fd, ImportCompressType compress) {
        _cleanup_close_ int sfd = -1, tfd = -1;
        int r;

        assert(e);
        assert(path);
        assert(fd >= 0);
        assert(compress < _IMPORT_COMPRESS_TYPE_MAX);
        assert(compress != IMPORT_COMPRESS_UNKNOWN);

        if (e->output_fd >= 0)
                return -EBUSY;

        r = fd_nonblock(fd, true);
        if (r < 0)
                return r;

        r = free_and_strdup(&e->path, path);
        if (r < 0)
                return r;

        sfd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY);
        if (sfd < 0)
                return -errno;

        if (fstat(sfd, &e->st) < 0)
                return -errno;
        r = stat_verify_regular(&e->st);
        if (r < 0)
                return r;

        /* Try to take a reflink snapshot of the file, if we can t make the export atomic */
        tfd = reflink_snapshot(sfd, path);
        if (tfd >= 0)
                e->input_fd = TAKE_FD(tfd);
        else
                e->input_fd = TAKE_FD(sfd);

        r = import_compress_init(&e->compress, compress);
        if (r < 0)
                return r;

        r = sd_event_add_io(e->event, &e->output_event_source, fd, EPOLLOUT, raw_export_on_output, e);
        if (r == -EPERM) {
                r = sd_event_add_defer(e->event, &e->output_event_source, raw_export_on_defer, e);
                if (r < 0)
                        return r;

                r = sd_event_source_set_enabled(e->output_event_source, SD_EVENT_ON);
        }
        if (r < 0)
                return r;

        e->output_fd = fd;
        return r;
}
Beispiel #2
0
int tar_export_start(TarExport *e, const char *path, int fd, ImportCompressType compress) {
    _cleanup_close_ int sfd = -1;
    int r;

    assert(e);
    assert(path);
    assert(fd >= 0);
    assert(compress < _IMPORT_COMPRESS_TYPE_MAX);
    assert(compress != IMPORT_COMPRESS_UNKNOWN);

    if (e->output_fd >= 0)
        return -EBUSY;

    sfd = open(path, O_DIRECTORY|O_RDONLY|O_NOCTTY|O_CLOEXEC);
    if (sfd < 0)
        return -errno;

    if (fstat(sfd, &e->st) < 0)
        return -errno;

    r = fd_nonblock(fd, true);
    if (r < 0)
        return r;

    r = free_and_strdup(&e->path, path);
    if (r < 0)
        return r;

    e->quota_referenced = (uint64_t) -1;

    if (e->st.st_ino == 256) { /* might be a btrfs subvolume? */
        BtrfsQuotaInfo q;

        r = btrfs_subvol_get_subtree_quota_fd(sfd, 0, &q);
        if (r >= 0)
            e->quota_referenced = q.referenced;

        e->temp_path = mfree(e->temp_path);

        r = tempfn_random(path, NULL, &e->temp_path);
        if (r < 0)
            return r;

        /* Let's try to make a snapshot, if we can, so that the export is atomic */
        r = btrfs_subvol_snapshot_fd(sfd, e->temp_path, BTRFS_SNAPSHOT_READ_ONLY|BTRFS_SNAPSHOT_RECURSIVE);
        if (r < 0) {
            log_debug_errno(r, "Couldn't create snapshot %s of %s, not exporting atomically: %m", e->temp_path, path);
            e->temp_path = mfree(e->temp_path);
        }
    }

    r = import_compress_init(&e->compress, compress);
    if (r < 0)
        return r;

    r = sd_event_add_io(e->event, &e->output_event_source, fd, EPOLLOUT, tar_export_on_output, e);
    if (r == -EPERM) {
        r = sd_event_add_defer(e->event, &e->output_event_source, tar_export_on_defer, e);
        if (r < 0)
            return r;

        r = sd_event_source_set_enabled(e->output_event_source, SD_EVENT_ON);
    }
    if (r < 0)
        return r;

    e->tar_fd = import_fork_tar_c(e->temp_path ?: e->path, &e->tar_pid);
    if (e->tar_fd < 0) {
        e->output_event_source = sd_event_source_unref(e->output_event_source);
        return e->tar_fd;
    }

    e->output_fd = fd;
    return r;
}