Skip to content

Commit 0ad9c81

Browse files
committed
btrfs-progs: add error handling for device_get_partition_size_fd_stat()
The function device_get_partition_size_fd_state() has two different error paths: - The target file is not a regular nor block file This should be the common one. - ioctl failed This should be very rare. But it has no way to return error other than returning 0. This is not helpful for end users to know what's going wrong. Change that function to return int, and a u64 pointer to return the size in bytes. And since we're here, also enhance the error handling of the callers to do an explicit error message and return error or exit. Signed-off-by: Qu Wenruo <[email protected]>
1 parent 6d0eabe commit 0ad9c81

File tree

9 files changed

+70
-30
lines changed

9 files changed

+70
-30
lines changed

check/main.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5447,7 +5447,13 @@ static int process_device_item(struct rb_root *dev_cache,
54475447
device->devid);
54485448
goto skip;
54495449
}
5450-
block_dev_size = device_get_partition_size_fd_stat(device->fd, &st);
5450+
ret = device_get_partition_size_fd_stat(device->fd, &st, &block_dev_size);
5451+
if (ret < 0) {
5452+
errno = -ret;
5453+
warning("failed to get device size for %s, skipping size check: %m",
5454+
device->name);
5455+
goto skip;
5456+
}
54515457
if (block_dev_size < rec->total_byte) {
54525458
error(
54535459
"block device size is smaller than total_bytes in device item, has %llu expect >= %llu",

check/mode-lowmem.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4822,7 +4822,14 @@ static int check_dev_item(struct extent_buffer *eb, int slot,
48224822
dev->devid);
48234823
return 0;
48244824
}
4825-
block_dev_size = device_get_partition_size_fd_stat(dev->fd, &st);
4825+
ret = device_get_partition_size_fd_stat(dev->fd, &st, &block_dev_size);
4826+
if (ret < 0) {
4827+
errno = -ret;
4828+
warning(
4829+
"failed to get device size for %s, skipping its block device size check: %m",
4830+
dev->name);
4831+
return 0;
4832+
}
48264833
if (block_dev_size < total_bytes) {
48274834
error(
48284835
"block device size is smaller than total_bytes in device item, has %llu expect >= %llu",

common/device-utils.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -240,9 +240,10 @@ int btrfs_prepare_device(int fd, const char *file, u64 *byte_count_ret,
240240
return 1;
241241
}
242242

243-
byte_count = device_get_partition_size_fd_stat(fd, &st);
244-
if (byte_count == 0) {
245-
error("unable to determine size of %s", file);
243+
ret = device_get_partition_size_fd_stat(fd, &st, &byte_count);
244+
if (ret < 0) {
245+
errno = -ret;
246+
error("unable to determine size of %s: %m", file);
246247
return 1;
247248
}
248249
if (max_byte_count)
@@ -309,17 +310,16 @@ int btrfs_prepare_device(int fd, const char *file, u64 *byte_count_ret,
309310
return 1;
310311
}
311312

312-
u64 device_get_partition_size_fd_stat(int fd, const struct stat *st)
313+
int device_get_partition_size_fd_stat(int fd, const struct stat *st, u64 *size_ret)
313314
{
314-
u64 size;
315-
316-
if (S_ISREG(st->st_mode))
317-
return st->st_size;
318-
if (!S_ISBLK(st->st_mode))
315+
if (S_ISREG(st->st_mode)) {
316+
*size_ret = st->st_size;
319317
return 0;
320-
if (ioctl(fd, BLKGETSIZE64, &size) >= 0)
321-
return size;
322-
318+
}
319+
if (!S_ISBLK(st->st_mode))
320+
return -EINVAL;
321+
if (ioctl(fd, BLKGETSIZE64, size_ret) < 0)
322+
return -errno;
323323
return 0;
324324
}
325325

common/device-utils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ enum {
4343
int device_discard_blocks(int fd, u64 start, u64 len);
4444
int device_zero_blocks(int fd, off_t start, size_t len, const bool direct);
4545
int device_get_partition_size(const char *dev, u64 *size_ret);
46-
u64 device_get_partition_size_fd_stat(int fd, const struct stat *st);
46+
int device_get_partition_size_fd_stat(int fd, const struct stat *st, u64 *size_ret);
4747
int device_get_queue_param(const char *file, const char *param, char *buf, size_t len);
4848
u64 device_get_zone_unusable(int fd, u64 flags);
4949
u64 device_get_zone_size(int fd, const char *name);

image/common.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,12 @@ void write_backup_supers(int fd, u8 *buf)
118118
return;
119119
}
120120

121-
size = device_get_partition_size_fd_stat(fd, &st);
121+
ret = device_get_partition_size_fd_stat(fd, &st, &size);
122+
if (ret < 0) {
123+
errno = -ret;
124+
error("failed to get device size for backup supers: %m");
125+
return;
126+
}
122127

123128
for (i = 1; i < BTRFS_SUPER_MIRROR_MAX; i++) {
124129
bytenr = btrfs_sb_offset(i);

kernel-shared/volumes.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3096,8 +3096,13 @@ static int btrfs_fix_block_device_size(struct btrfs_fs_info *fs_info,
30963096
return -errno;
30973097
}
30983098

3099-
block_dev_size = round_down(device_get_partition_size_fd_stat(device->fd, &st),
3100-
fs_info->sectorsize);
3099+
ret = device_get_partition_size_fd_stat(device->fd, &st, &block_dev_size);
3100+
if (ret < 0) {
3101+
errno = -ret;
3102+
error("failed to get device size for %s: %m", device->name);
3103+
return ret;
3104+
}
3105+
block_dev_size = round_down(block_dev_size, fs_info->sectorsize);
31013106

31023107
/*
31033108
* Total_bytes in device item is no larger than the device block size,

kernel-shared/zoned.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,8 @@ static int emulate_report_zones(const char *file, int fd, u64 pos,
166166
{
167167
const sector_t zone_sectors = emulated_zone_size >> SECTOR_SHIFT;
168168
struct stat st;
169-
sector_t bdev_size;
169+
u64 bdev_size;
170+
sector_t bdev_nr_sectors;
170171
unsigned int i;
171172
int ret;
172173

@@ -176,7 +177,13 @@ static int emulate_report_zones(const char *file, int fd, u64 pos,
176177
return -EIO;
177178
}
178179

179-
bdev_size = device_get_partition_size_fd_stat(fd, &st) >> SECTOR_SHIFT;
180+
ret = device_get_partition_size_fd_stat(fd, &st, &bdev_size);
181+
if (ret < 0) {
182+
errno = -ret;
183+
error("failed to get device size for %s: %m", file);
184+
return ret;
185+
}
186+
bdev_nr_sectors = bdev_size >> SECTOR_SHIFT;
180187

181188
pos >>= SECTOR_SHIFT;
182189
for (i = 0; i < nr_zones; i++) {
@@ -187,7 +194,7 @@ static int emulate_report_zones(const char *file, int fd, u64 pos,
187194
zones[i].type = BLK_ZONE_TYPE_CONVENTIONAL;
188195
zones[i].cond = BLK_ZONE_COND_NOT_WP;
189196

190-
if (zones[i].wp >= bdev_size) {
197+
if (zones[i].wp >= bdev_nr_sectors) {
191198
i++;
192199
break;
193200
}
@@ -325,8 +332,9 @@ static int report_zones(int fd, const char *file,
325332
return -EIO;
326333
}
327334

328-
device_size = device_get_partition_size_fd_stat(fd, &st);
329-
if (device_size == 0) {
335+
ret = device_get_partition_size_fd_stat(fd, &st, &device_size);
336+
if (ret < 0) {
337+
errno = -ret;
330338
error("zoned: failed to read size of %s: %m", file);
331339
exit(1);
332340
}

mkfs/common.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,7 +1170,9 @@ bool test_status_for_mkfs(const char *file, bool force_overwrite)
11701170
int test_minimum_size(const char *file, u64 min_dev_size)
11711171
{
11721172
int fd;
1173+
int ret;
11731174
struct stat statbuf;
1175+
u64 size;
11741176

11751177
fd = open(file, O_RDONLY);
11761178
if (fd < 0)
@@ -1179,11 +1181,12 @@ int test_minimum_size(const char *file, u64 min_dev_size)
11791181
close(fd);
11801182
return -errno;
11811183
}
1182-
if (device_get_partition_size_fd_stat(fd, &statbuf) < min_dev_size) {
1183-
close(fd);
1184-
return 1;
1185-
}
1184+
ret = device_get_partition_size_fd_stat(fd, &statbuf, &size);
11861185
close(fd);
1186+
if (ret < 0)
1187+
return ret;
1188+
if (size < min_dev_size)
1189+
return 1;
11871190
return 0;
11881191
}
11891192

mkfs/main.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1818,9 +1818,15 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
18181818
* Block_count not specified, use file/device size first.
18191819
* Or we will always use source_dir_size calculated for mkfs.
18201820
*/
1821-
if (!byte_count)
1822-
byte_count = round_down(device_get_partition_size_fd_stat(fd, &statbuf),
1823-
sectorsize);
1821+
if (!byte_count) {
1822+
ret = device_get_partition_size_fd_stat(fd, &statbuf, &byte_count);
1823+
if (ret < 0) {
1824+
errno = -ret;
1825+
error("failed to get device size for %s: %m", file);
1826+
goto error;
1827+
}
1828+
byte_count = round_down(byte_count, sectorsize);
1829+
}
18241830
source_dir_size = btrfs_mkfs_size_dir(source_dir, sectorsize,
18251831
min_dev_size, metadata_profile, data_profile);
18261832
UASSERT(IS_ALIGNED(source_dir_size, sectorsize));

0 commit comments

Comments
 (0)