Merge pull request #7237 from keszybz/growfs
Create and grow filesystems
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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)) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user