Skip to content

Commit 8414cbf

Browse files
committed
lib/sb.c: fix super block read failure from disk image file
Unlike mkfs.nilfs2, nilfs-tune and dumpseg commands will cause errors if used directly on a disk image files. This is because __nilfs_sb_read(), which reads superblocks, uses the BLKGETSIZE64 ioctl command to get the device size, which fails for disk image files. Fix this issue by using the size information obtained from the fstat system call for regular files. Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
1 parent 4d722cd commit 8414cbf

File tree

1 file changed

+15
-2
lines changed

1 file changed

+15
-2
lines changed

lib/sb.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
#endif /* HAVE_SYS_IOCTL_H */
5858

5959
#include <linux/nilfs2_ondisk.h>
60+
#include <sys/stat.h> /* fstat(), S_ISBLK(), S_ISREG(), etc */
6061
#include <errno.h>
6162
#include <assert.h>
6263
#include "nilfs.h"
@@ -109,15 +110,27 @@ static int __nilfs_sb_read(int devfd, struct nilfs_super_block **sbp,
109110
uint64_t devsize, sb2_offset;
110111
int invalid_fs = 0;
111112
ssize_t ret;
113+
struct stat stat;
112114

113115
sbp[0] = malloc(NILFS_MAX_SB_SIZE);
114116
sbp[1] = malloc(NILFS_MAX_SB_SIZE);
115117
if (unlikely(sbp[0] == NULL || sbp[1] == NULL))
116118
goto failed;
117119

118-
ret = ioctl(devfd, BLKGETSIZE64, &devsize);
119-
if (unlikely(ret != 0))
120+
ret = fstat(devfd, &stat);
121+
if (unlikely(ret < 0))
122+
goto failed;
123+
124+
if (S_ISBLK(stat.st_mode)) {
125+
ret = ioctl(devfd, BLKGETSIZE64, &devsize);
126+
if (unlikely(ret < 0))
127+
goto failed;
128+
} else if (S_ISREG(stat.st_mode)) {
129+
devsize = stat.st_size;
130+
} else {
131+
errno = EBADF;
120132
goto failed;
133+
}
121134

122135
ret = pread(devfd, sbp[0], NILFS_MAX_SB_SIZE, NILFS_SB_OFFSET_BYTES);
123136
if (likely(ret == NILFS_MAX_SB_SIZE)) {

0 commit comments

Comments
 (0)