Merge pull request #7237 from keszybz/growfs

Create and grow filesystems
This commit is contained in:
Lennart Poettering
2017-12-01 17:58:58 +01:00
committed by GitHub
34 changed files with 1339 additions and 341 deletions
+6 -6
View File
@@ -42,6 +42,7 @@
#include "btrfs-util.h"
#include "chattr-util.h"
#include "copy.h"
#include "device-nodes.h"
#include "fd-util.h"
#include "fileio.h"
#include "io-util.h"
@@ -910,7 +911,8 @@ int btrfs_subvol_set_subtree_quota_limit(const char *path, uint64_t subvol_id, u
int btrfs_resize_loopback_fd(int fd, uint64_t new_size, bool grow_only) {
struct btrfs_ioctl_vol_args args = {};
_cleanup_free_ char *p = NULL, *loop = NULL, *backing = NULL;
char p[SYS_BLOCK_PATH_MAX("/loop/backing_file")];
_cleanup_free_ char *backing = NULL;
_cleanup_close_ int loop_fd = -1, backing_fd = -1;
struct stat st;
dev_t dev = 0;
@@ -930,8 +932,7 @@ int btrfs_resize_loopback_fd(int fd, uint64_t new_size, bool grow_only) {
if (r == 0)
return -ENODEV;
if (asprintf(&p, "/sys/dev/block/%u:%u/loop/backing_file", major(dev), minor(dev)) < 0)
return -ENOMEM;
xsprintf_sys_block_path(p, "/loop/backing_file", dev);
r = read_one_line_file(p, &backing);
if (r == -ENOENT)
return -ENODEV;
@@ -955,9 +956,8 @@ int btrfs_resize_loopback_fd(int fd, uint64_t new_size, bool grow_only) {
if (grow_only && new_size < (uint64_t) st.st_size)
return -EINVAL;
if (asprintf(&loop, "/dev/block/%u:%u", major(dev), minor(dev)) < 0)
return -ENOMEM;
loop_fd = open(loop, O_RDWR|O_CLOEXEC|O_NOCTTY);
xsprintf_sys_block_path(p, NULL, dev);
loop_fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY);
if (loop_fd < 0)
return -errno;
+27
View File
@@ -0,0 +1,27 @@
/***
This file is part of systemd.
Copyright 2017 Zbigniew Jędrzejewski-Szmek
systemd is free software; you can redistribute it and/or modify it
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/>.
***/
#if HAVE_LIBCRYPTSETUP
#include "crypt-util.h"
#include "log.h"
void cryptsetup_log_glue(int level, const char *msg, void *usrptr) {
log_debug("%s", msg);
}
#endif
+34
View File
@@ -0,0 +1,34 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
This file is part of systemd.
Copyright 2017 Zbigniew Jędrzejewski-Szmek
systemd is free software; you can redistribute it and/or modify it
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/>.
***/
#if HAVE_LIBCRYPTSETUP
#include <libcryptsetup.h>
#include "macro.h"
/* libcryptsetup define for any LUKS version, compatible with libcryptsetup 1.x */
#ifndef CRYPT_LUKS
#define CRYPT_LUKS NULL
#endif
DEFINE_TRIVIAL_CLEANUP_FUNC(struct crypt_device *, crypt_free);
void cryptsetup_log_glue(int level, const char *msg, void *usrptr);
#endif
+13
View File
@@ -23,5 +23,18 @@
#include <stddef.h>
#include <sys/types.h>
#include "macro.h"
#include "stdio-util.h"
int encode_devnode_name(const char *str, char *str_enc, size_t len);
int whitelisted_char_for_devnode(char c, const char *additional);
#define SYS_BLOCK_PATH_MAX(suffix) \
(strlen("/sys/dev/block/") + DECIMAL_STR_MAX(dev_t) + 1 + DECIMAL_STR_MAX(dev_t) + strlen_ptr(suffix))
#define xsprintf_sys_block_path(buf, suffix, devno) \
xsprintf(buf, "/sys/dev/block/%u:%u%s", major(devno), minor(devno), strempty(suffix))
#define DEV_NUM_PATH_MAX \
(strlen("/dev/block/") + DECIMAL_STR_MAX(dev_t) + 1 + DECIMAL_STR_MAX(dev_t))
#define xsprintf_dev_num_path(buf, type, devno) \
xsprintf(buf, "/dev/%s/%u:%u", type, major(devno), minor(devno))
+12 -3
View File
@@ -661,10 +661,19 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
todo += m;
/* Just a single slash? Then we reached the end. */
if (isempty(first) || path_equal(first, "/"))
/* Empty? Then we reached the end. */
if (isempty(first))
break;
/* Just a single slash? Then we reached the end. */
if (path_equal(first, "/")) {
/* Preserve the trailing slash */
if (!strextend(&done, "/", NULL))
return -ENOMEM;
break;
}
/* Just a dot? Then let's eat this up. */
if (path_equal(first, "/."))
continue;
@@ -726,7 +735,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
if (fstat(child, &st) < 0)
return -errno;
if ((flags & CHASE_NO_AUTOFS) &&
fd_check_fstype(child, AUTOFS_SUPER_MAGIC) > 0)
fd_is_fs_type(child, AUTOFS_SUPER_MAGIC) > 0)
return -EREMOTE;
if (S_ISLNK(st.st_mode)) {
+2
View File
@@ -61,6 +61,8 @@ basic_sources_plain = files('''
copy.h
cpu-set-util.c
cpu-set-util.h
crypt-util.c
crypt-util.h
def.h
device-nodes.c
device-nodes.h
+4
View File
@@ -1271,4 +1271,8 @@ struct fib_rule_uid_range {
#define AF_VSOCK 40
#endif
#ifndef EXT4_IOC_RESIZE_FS
# define EXT4_IOC_RESIZE_FS _IOW('f', 16, __u64)
#endif
#include "missing_syscall.h"
+2 -1
View File
@@ -278,6 +278,7 @@ int path_is_mount_point(const char *t, const char *root, int flags) {
int r;
assert(t);
assert((flags & ~AT_SYMLINK_FOLLOW) == 0);
if (path_equal(t, "/"))
return 1;
@@ -302,7 +303,7 @@ int path_is_mount_point(const char *t, const char *root, int flags) {
if (fd < 0)
return -errno;
return fd_is_mount_point(fd, basename(t), flags);
return fd_is_mount_point(fd, last_path_component(t), flags);
}
int path_get_mnt_id(const char *path, int *ret) {
+31
View File
@@ -703,6 +703,37 @@ char* dirname_malloc(const char *path) {
return dir2;
}
const char *last_path_component(const char *path) {
/* Finds the last component of the path, preserving the
* optional trailing slash that signifies a directory.
* a/b/c → c
* a/b/c/ → c/
* / → /
* // → /
* /foo/a → a
* /foo/a/ → a/
* This is different than basename, which returns "" when
* a trailing slash is present.
*/
unsigned l, k;
l = k = strlen(path);
if (l == 0) /* special case — an empty string */
return path;
while (k > 0 && path[k-1] == '/')
k--;
if (k == 0) /* the root directory */
return path + l - 1;
while (k > 0 && path[k-1] != '/')
k--;
return path + k;
}
bool filename_is_valid(const char *p) {
const char *e;
+1
View File
@@ -130,6 +130,7 @@ char *prefix_root(const char *root, const char *path);
int parse_path_argument_and_warn(const char *path, bool suppress_root, char **arg);
char* dirname_malloc(const char *path);
const char *last_path_component(const char *path);
bool filename_is_valid(const char *p) _pure_;
bool path_is_normalized(const char *p) _pure_;
+3 -3
View File
@@ -193,7 +193,7 @@ bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) {
return F_TYPE_EQUAL(s->f_type, magic_value);
}
int fd_check_fstype(int fd, statfs_f_type_t magic_value) {
int fd_is_fs_type(int fd, statfs_f_type_t magic_value) {
struct statfs s;
if (fstatfs(fd, &s) < 0)
@@ -202,14 +202,14 @@ int fd_check_fstype(int fd, statfs_f_type_t magic_value) {
return is_fs_type(&s, magic_value);
}
int path_check_fstype(const char *path, statfs_f_type_t magic_value) {
int path_is_fs_type(const char *path, statfs_f_type_t magic_value) {
_cleanup_close_ int fd = -1;
fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH);
if (fd < 0)
return -errno;
return fd_check_fstype(fd, magic_value);
return fd_is_fs_type(fd, magic_value);
}
bool is_temporary_fs(const struct statfs *s) {
+2 -2
View File
@@ -57,8 +57,8 @@ int files_same(const char *filea, const char *fileb, int flags);
typedef typeof(((struct statfs*)NULL)->f_type) statfs_f_type_t;
bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) _pure_;
int fd_check_fstype(int fd, statfs_f_type_t magic_value);
int path_check_fstype(const char *path, statfs_f_type_t magic_value);
int fd_is_fs_type(int fd, statfs_f_type_t magic_value);
int path_is_fs_type(const char *path, statfs_f_type_t magic_value);
bool is_temporary_fs(const struct statfs *s) _pure_;
int fd_is_temporary_fs(int fd);
+16 -37
View File
@@ -39,6 +39,7 @@
#include "build.h"
#include "cgroup-util.h"
#include "def.h"
#include "device-nodes.h"
#include "dirent-util.h"
#include "fd-util.h"
#include "fileio.h"
@@ -118,63 +119,42 @@ int socket_from_display(const char *display, char **path) {
}
int block_get_whole_disk(dev_t d, dev_t *ret) {
char *p, *s;
char p[SYS_BLOCK_PATH_MAX("/partition")];
_cleanup_free_ char *s = NULL;
int r;
unsigned n, m;
assert(ret);
/* If it has a queue this is good enough for us */
if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
return -ENOMEM;
r = access(p, F_OK);
free(p);
if (r >= 0) {
xsprintf_sys_block_path(p, "/queue", d);
if (access(p, F_OK) >= 0) {
*ret = d;
return 0;
}
/* If it is a partition find the originating device */
if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
return -ENOMEM;
r = access(p, F_OK);
free(p);
if (r < 0)
xsprintf_sys_block_path(p, "/partition", d);
if (access(p, F_OK) < 0)
return -ENOENT;
/* Get parent dev_t */
if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
return -ENOMEM;
xsprintf_sys_block_path(p, "/../dev", d);
r = read_one_line_file(p, &s);
free(p);
if (r < 0)
return r;
r = sscanf(s, "%u:%u", &m, &n);
free(s);
if (r != 2)
return -EINVAL;
/* Only return this if it is really good enough for us. */
if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
return -ENOMEM;
xsprintf_sys_block_path(p, "/queue", makedev(m, n));
if (access(p, F_OK) < 0)
return -ENOENT;
r = access(p, F_OK);
free(p);
if (r >= 0) {
*ret = makedev(m, n);
return 0;
}
return -ENOENT;
*ret = makedev(m, n);
return 0;
}
bool kexec_loaded(void) {
@@ -749,7 +729,8 @@ int get_block_device(const char *path, dev_t *dev) {
int get_block_device_harder(const char *path, dev_t *dev) {
_cleanup_closedir_ DIR *d = NULL;
_cleanup_free_ char *p = NULL, *t = NULL;
_cleanup_free_ char *t = NULL;
char p[SYS_BLOCK_PATH_MAX("/slaves")];
struct dirent *de, *found = NULL;
const char *q;
unsigned maj, min;
@@ -767,9 +748,7 @@ int get_block_device_harder(const char *path, dev_t *dev) {
if (r <= 0)
return r;
if (asprintf(&p, "/sys/dev/block/%u:%u/slaves", major(dt), minor(dt)) < 0)
return -ENOMEM;
xsprintf_sys_block_path(p, "/slaves", dt);
d = opendir(p);
if (!d) {
if (errno == ENOENT)