aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteffen Trumtrar <s.trumtrar@pengutronix.de>2020-07-29 10:43:53 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2020-10-01 00:31:11 +0200
commit6561e07460acc5b38af99aa5e80283dc04953eca (patch)
treec73a8a3194c18fa52b712de4e8b3a304470725b4
parentabefc3c276ac2450f756c5232745a145bd14dbdf (diff)
downloadbusybox-w32-6561e07460acc5b38af99aa5e80283dc04953eca.tar.gz
busybox-w32-6561e07460acc5b38af99aa5e80283dc04953eca.tar.bz2
busybox-w32-6561e07460acc5b38af99aa5e80283dc04953eca.zip
mount: support the sizelimit and offset option for loop devices
Starting with linux kernel v5.4 squashfs has a more strict parameter checking implemented. Unlike util-linux mount, busybox never supported the sizelimit option but simply forwards it to the kernel. Since v5.4 mounting will fail with squashfs: Unknown parameter 'sizelimit' Support the sizelimit parameter by setting it in the LOOP_SET_STATUS64 structure before handing it to the kernel. While at it also add support for the offset option, which currently will always be set to 0. function old new delta cut_out_ull_opt - 167 +167 singlemount 1230 1266 +36 set_loop 834 862 +28 losetup_main 479 483 +4 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 3/0 up/down: 235/0) Total: 235 bytes Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--include/libbb.h3
-rw-r--r--libbb/loop.c4
-rw-r--r--util-linux/losetup.c2
-rw-r--r--util-linux/mount.c62
4 files changed, 67 insertions, 4 deletions
diff --git a/include/libbb.h b/include/libbb.h
index 8c7978456..83ecca47f 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1515,7 +1515,8 @@ int del_loop(const char *device) FAST_FUNC;
1515 * malloc and return it in *devname. 1515 * malloc and return it in *devname.
1516 * return value is the opened fd to the loop device, or < on error 1516 * return value is the opened fd to the loop device, or < on error
1517 */ 1517 */
1518int set_loop(char **devname, const char *file, unsigned long long offset, unsigned flags) FAST_FUNC; 1518int set_loop(char **devname, const char *file, unsigned long long offset,
1519 unsigned long long sizelimit, unsigned flags) FAST_FUNC;
1519/* These constants match linux/loop.h (without BB_ prefix): */ 1520/* These constants match linux/loop.h (without BB_ prefix): */
1520#define BB_LO_FLAGS_READ_ONLY 1 1521#define BB_LO_FLAGS_READ_ONLY 1
1521#define BB_LO_FLAGS_AUTOCLEAR 4 1522#define BB_LO_FLAGS_AUTOCLEAR 4
diff --git a/libbb/loop.c b/libbb/loop.c
index ada0c7638..85b2724e5 100644
--- a/libbb/loop.c
+++ b/libbb/loop.c
@@ -102,7 +102,8 @@ int FAST_FUNC get_free_loop(void)
102 * search will re-use an existing loop device already bound to that 102 * search will re-use an existing loop device already bound to that
103 * file/offset if it finds one. 103 * file/offset if it finds one.
104 */ 104 */
105int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offset, unsigned flags) 105int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offset,
106 unsigned long long sizelimit, unsigned flags)
106{ 107{
107 char dev[LOOP_NAMESIZE]; 108 char dev[LOOP_NAMESIZE];
108 char *try; 109 char *try;
@@ -185,6 +186,7 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
185 memset(&loopinfo, 0, sizeof(loopinfo)); 186 memset(&loopinfo, 0, sizeof(loopinfo));
186 safe_strncpy((char *)loopinfo.lo_file_name, file, LO_NAME_SIZE); 187 safe_strncpy((char *)loopinfo.lo_file_name, file, LO_NAME_SIZE);
187 loopinfo.lo_offset = offset; 188 loopinfo.lo_offset = offset;
189 loopinfo.lo_sizelimit = sizelimit;
188 /* 190 /*
189 * Used by mount to set LO_FLAGS_AUTOCLEAR. 191 * Used by mount to set LO_FLAGS_AUTOCLEAR.
190 * LO_FLAGS_READ_ONLY is not set because RO is controlled by open type of the file. 192 * LO_FLAGS_READ_ONLY is not set because RO is controlled by open type of the file.
diff --git a/util-linux/losetup.c b/util-linux/losetup.c
index ac8b79502..24f7a2349 100644
--- a/util-linux/losetup.c
+++ b/util-linux/losetup.c
@@ -150,7 +150,7 @@ int losetup_main(int argc UNUSED_PARAM, char **argv)
150 if (opt & OPT_P) { 150 if (opt & OPT_P) {
151 flags |= BB_LO_FLAGS_PARTSCAN; 151 flags |= BB_LO_FLAGS_PARTSCAN;
152 } 152 }
153 if (set_loop(&d, argv[0], offset, flags) < 0) 153 if (set_loop(&d, argv[0], offset, 0, flags) < 0)
154 bb_simple_perror_msg_and_die(argv[0]); 154 bb_simple_perror_msg_and_die(argv[0]);
155 return EXIT_SUCCESS; 155 return EXIT_SUCCESS;
156 } 156 }
diff --git a/util-linux/mount.c b/util-linux/mount.c
index b92e2c297..19ac13930 100644
--- a/util-linux/mount.c
+++ b/util-linux/mount.c
@@ -1886,6 +1886,58 @@ static int nfsmount(struct mntent *mp, unsigned long vfsflags, char *filteropts)
1886 1886
1887#endif // !ENABLE_FEATURE_MOUNT_NFS 1887#endif // !ENABLE_FEATURE_MOUNT_NFS
1888 1888
1889// Find "...,NAME=NUM,..." in the option string, remove "NAME=NUM" option
1890// and return NUM.
1891// Return 0 if not found.
1892// All instances must be parsed and removed (for example, since kernel 5.4
1893// squashfs: Unknown parameter 'sizelimit'
1894// will result if loopback mount option "sizelimit=NNN" is not removed
1895// and squashfs sees it in option string).
1896static unsigned long long cut_out_ull_opt(char *opts, const char *name_eq)
1897{
1898 unsigned long long ret = 0;
1899
1900 if (!opts) // allow NULL opts (simplifies callers' work)
1901 return ret;
1902
1903 for (;;) {
1904 char *end;
1905 char *opt;
1906
1907 // Find comma-delimited "NAME="
1908 for (;;) {
1909 opt = strstr(opts, name_eq);
1910 if (!opt)
1911 return ret;
1912 if (opt == opts)
1913 break; // found it (it's first opt)
1914 if (opt[-1] == ',') {
1915 opts = opt - 1;
1916 break; // found it (it's not a first opt)
1917 }
1918 // False positive like "VNAME=", we are at "N".
1919 // - skip it, loop back to searching
1920 opts = opt + 1;
1921 }
1922
1923 ret = bb_strtoull(opt + strlen(name_eq), &end, 0);
1924 if (errno && errno != EINVAL) {
1925 err:
1926 bb_error_msg_and_die("bad option '%s'", opt);
1927 }
1928 if (*end == '\0') {
1929 // It is "[,]NAME=NUM\0" - truncate it and return
1930 *opts = '\0';
1931 return ret;
1932 }
1933 if (*end != ',')
1934 goto err;
1935 // We are at trailing comma
1936 // Remove "NAME=NUM," and loop back to check for duplicate opts
1937 overlapping_strcpy(opt, end + 1);
1938 }
1939}
1940
1889// Mount one directory. Handles CIFS, NFS, loopback, autobind, and filesystem 1941// Mount one directory. Handles CIFS, NFS, loopback, autobind, and filesystem
1890// type detection. Returns 0 for success, nonzero for failure. 1942// type detection. Returns 0 for success, nonzero for failure.
1891// NB: mp->xxx fields may be trashed on exit 1943// NB: mp->xxx fields may be trashed on exit
@@ -2029,9 +2081,16 @@ static int singlemount(struct mntent *mp, int ignore_busy)
2029 ) { 2081 ) {
2030 // Do we need to allocate a loopback device for it? 2082 // Do we need to allocate a loopback device for it?
2031 if (ENABLE_FEATURE_MOUNT_LOOP && S_ISREG(st.st_mode)) { 2083 if (ENABLE_FEATURE_MOUNT_LOOP && S_ISREG(st.st_mode)) {
2084 unsigned long long offset;
2085 unsigned long long sizelimit;
2086
2032 loopFile = bb_simplify_path(mp->mnt_fsname); 2087 loopFile = bb_simplify_path(mp->mnt_fsname);
2033 mp->mnt_fsname = NULL; // will receive malloced loop dev name 2088 mp->mnt_fsname = NULL; // will receive malloced loop dev name
2034 2089
2090 // Parse and remove loopback options
2091 offset = cut_out_ull_opt(filteropts, "offset=");
2092 sizelimit = cut_out_ull_opt(filteropts, "sizelimit=");
2093
2035 // mount always creates AUTOCLEARed loopdevs, so that umounting 2094 // mount always creates AUTOCLEARed loopdevs, so that umounting
2036 // drops them without any code in the userspace. 2095 // drops them without any code in the userspace.
2037 // This happens since circa linux-2.6.25: 2096 // This happens since circa linux-2.6.25:
@@ -2040,7 +2099,8 @@ static int singlemount(struct mntent *mp, int ignore_busy)
2040 // Subject: Allow auto-destruction of loop devices 2099 // Subject: Allow auto-destruction of loop devices
2041 loopfd = set_loop(&mp->mnt_fsname, 2100 loopfd = set_loop(&mp->mnt_fsname,
2042 loopFile, 2101 loopFile,
2043 0, 2102 offset,
2103 sizelimit,
2044 ((vfsflags & MS_RDONLY) ? BB_LO_FLAGS_READ_ONLY : 0) 2104 ((vfsflags & MS_RDONLY) ? BB_LO_FLAGS_READ_ONLY : 0)
2045 | BB_LO_FLAGS_AUTOCLEAR 2105 | BB_LO_FLAGS_AUTOCLEAR
2046 ); 2106 );