export-tar.c revision b26fa1a2fbcfee7d03b0c8fd15ec3aa64ae70b9f
/***
This file is part of systemd.
Copyright 2015 Lennart Poettering
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "sd-daemon.h"
#include "alloc-util.h"
#include "btrfs-util.h"
#include "export-tar.h"
#include "fd-util.h"
#include "fileio.h"
#include "import-common.h"
#include "process-util.h"
#include "ratelimit.h"
#include "string-util.h"
#include "util.h"
struct TarExport {
void *userdata;
char *path;
char *temp_path;
int output_fd;
int tar_fd;
void *buffer;
unsigned last_percent;
bool eof;
bool tried_splice;
};
if (!e)
return NULL;
if (e->tar_pid > 1) {
}
if (e->temp_path) {
}
import_compress_free(&e->compress);
sd_event_unref(e->event);
safe_close(e->tar_fd);
free(e);
return NULL;
}
int tar_export_new(
void *userdata) {
int r;
if (!e)
return -ENOMEM;
e->on_finished = on_finished;
e->last_percent = (unsigned) -1;
if (event)
else {
r = sd_event_default(&e->event);
if (r < 0)
return r;
}
*ret = e;
e = NULL;
return 0;
}
static void tar_export_report_progress(TarExport *e) {
unsigned percent;
assert(e);
/* Do we have any quota info? If not, we don't know anything about the progress */
return;
if (e->written_uncompressed >= e->quota_referenced)
percent = 100;
else
if (percent == e->last_percent)
return;
if (!ratelimit_test(&e->progress_rate_limit))
return;
e->last_percent = percent;
}
static int tar_export_process(TarExport *e) {
ssize_t l;
int r;
assert(e);
if (l < 0) {
return 0;
e->tried_splice = true;
} else if (l == 0) {
r = 0;
goto finish;
} else {
e->written_uncompressed += l;
e->written_compressed += l;
return 0;
}
}
while (e->buffer_size <= 0) {
if (e->eof) {
r = 0;
goto finish;
}
if (l < 0) {
goto finish;
}
if (l == 0) {
e->eof = true;
} else {
e->written_uncompressed += l;
}
if (r < 0) {
r = log_error_errno(r, "Failed to encode: %m");
goto finish;
}
}
if (l < 0) {
return 0;
goto finish;
}
e->buffer_size -= l;
e->written_compressed += l;
return 0;
if (e->on_finished)
e->on_finished(e, r, e->userdata);
else
sd_event_exit(e->event, r);
return 0;
}
return tar_export_process(i);
}
return tar_export_process(i);
}
int r;
assert(e);
if (e->output_fd >= 0)
return -EBUSY;
if (sfd < 0)
return -errno;
return -errno;
r = fd_nonblock(fd, true);
if (r < 0)
return r;
if (r < 0)
return r;
r = btrfs_subvol_get_subtree_quota_fd(sfd, 0, &q);
if (r >= 0)
e->quota_referenced = q.referenced;
if (r < 0)
return r;
/* Let's try to make a snapshot, if we can, so that the export is atomic */
if (r < 0) {
log_debug_errno(r, "Couldn't create snapshot %s of %s, not exporting atomically: %m", e->temp_path, path);
}
}
if (r < 0)
return r;
if (r == -EPERM) {
if (r < 0)
return r;
}
if (r < 0)
return r;
if (e->tar_fd < 0) {
return e->tar_fd;
}
return r;
}