Skip to content

Commit 37e7547

Browse files
committed
Implement partition mount verification
Do not check a mounted partition and allow the user to allow checking a read-write mounted partition as well. Only check for mounting if we want to write, if we aren't fixing we will not write and so no impact will be on any mounted filesystem to care. Closes #20
1 parent a271f5e commit 37e7547

File tree

5 files changed

+125
-3
lines changed

5 files changed

+125
-3
lines changed

arch/arch-linux.c

+74
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <errno.h>
1919
#include <net/if.h>
2020
#include <netinet/in.h>
21+
#include <mntent.h>
2122

2223
static void strtrim(char *s)
2324
{
@@ -237,6 +238,79 @@ static int sg_ioctl(int fd, unsigned char *cdb, unsigned cdb_len,
237238
return 0;
238239
}
239240

241+
static disk_mount_e mount_point_check(struct mntent *mnt)
242+
{
243+
char *next = mnt->mnt_opts;
244+
char *opt;
245+
246+
/* Device is mounted, check it */
247+
while ((opt = strtok(next, ", \t\r\n")) != NULL) {
248+
next = NULL; // continue scanning for this string
249+
if (strcmp(opt, "rw") == 0)
250+
return DISK_MOUNTED_RW;
251+
}
252+
253+
return DISK_MOUNTED_RO;
254+
}
255+
256+
disk_mount_e disk_dev_mount_state(const char *path)
257+
{
258+
struct stat dev_st_buf;
259+
struct stat st_buf;
260+
FILE *f = NULL;
261+
struct mntent *mnt;
262+
disk_mount_e state = DISK_MOUNTED_RW; // assume the worst
263+
264+
f = setmntent("/proc/mounts", "r");
265+
if (f == NULL) {
266+
ERROR("Failed to open /proc/mounts to know the state, errno=%d", errno);
267+
goto Exit;
268+
}
269+
270+
if (stat(path, &dev_st_buf) != 0) {
271+
ERROR("Failed to stat the path %s, errno=%d", path, errno);
272+
goto Exit;
273+
}
274+
275+
if (!S_ISBLK(dev_st_buf.st_mode)) {
276+
ERROR("Device %s is not a block device", path);
277+
goto Exit; // We only want block devices
278+
}
279+
280+
// From here we assume the disk is not mounted
281+
state = DISK_NOT_MOUNTED;
282+
283+
while ((mnt = getmntent(f)) != NULL) {
284+
disk_mount_e cur_state = DISK_NOT_MOUNTED;
285+
286+
/* Ignore non-full-path entries */
287+
if (mnt->mnt_fsname[0] != '/')
288+
continue;
289+
/* Check for a name prefix match, we may check a full block device and a partition is mounted */
290+
if (strncmp(path, mnt->mnt_fsname, strlen(path)) == 0) {
291+
cur_state = mount_point_check(mnt);
292+
if (cur_state > state)
293+
state = cur_state;
294+
continue;
295+
}
296+
/* Check for an underlying device match (name may have changed in between actions) */
297+
if (stat(mnt->mnt_fsname, &st_buf) == 0) {
298+
if (!S_ISBLK(st_buf.st_mode))
299+
continue;
300+
if (dev_st_buf.st_rdev == st_buf.st_rdev) {
301+
cur_state = mount_point_check(mnt);
302+
if (cur_state > state)
303+
state = cur_state;
304+
}
305+
}
306+
}
307+
308+
Exit:
309+
if (f)
310+
endmntent(f);
311+
return state;
312+
}
313+
240314
bool disk_dev_open(disk_dev_t *dev, const char *path)
241315
{
242316
dev->fd = open(path, O_RDWR|O_DIRECT);

cli/cli.c

+10-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ struct options_t {
4747
unsigned scan_size;
4848
char *data_log_name;
4949
char *data_log_raw_name;
50+
disk_mount_e allowed_mount;
5051
};
5152

5253
static void print_header(void)
@@ -67,6 +68,8 @@ static int usage(void) {
6768
printf(" -e, --size <size> - Scan size (default to 64K, must be multiple of 512)\n");
6869
printf(" -o, --output <file> - Output file (json)\n");
6970
printf(" -r, --raw-log <file> - Raw log of all scan results (json)\n");
71+
printf(" --force-mounted - Allow checking a read-only mounted disk\n");
72+
printf(" --force-mounted-rw - Allow checking a read-write mounted disk\n");
7073
printf("\n");
7174
return 1;
7275
}
@@ -203,6 +206,7 @@ static int parse_args(int argc, char **argv, options_t *opts)
203206
{
204207
int c;
205208
int unknown = 0;
209+
static int allowed_mount = DISK_NOT_MOUNTED;
206210

207211
opts->scan_size = 64*1024;
208212

@@ -215,6 +219,8 @@ static int parse_args(int argc, char **argv, options_t *opts)
215219
{"size", required_argument, 0, 'e'},
216220
{"raw-log", required_argument, 0, 'r'},
217221
{"output", required_argument, 0, 'o'},
222+
{"force-mounted", no_argument, &allowed_mount, DISK_MOUNTED_RO},
223+
{"force-mounted-rw", no_argument, &allowed_mount, DISK_MOUNTED_RW},
218224
{0, 0, 0, 0}
219225
};
220226

@@ -276,6 +282,7 @@ static int parse_args(int argc, char **argv, options_t *opts)
276282
}
277283

278284
opts->disk_path = argv[optind];
285+
opts->allowed_mount = allowed_mount;
279286
return 0;
280287
}
281288

@@ -306,8 +313,10 @@ int diskscan_cli(int argc, char **argv)
306313
{
307314
int ret;
308315
options_t opts;
316+
309317
memset(&opts, 0, sizeof(opts));
310318
opts.mode = SCAN_MODE_SEQ;
319+
opts.allowed_mount = DISK_NOT_MOUNTED;
311320

312321
if (parse_args(argc, argv, &opts))
313322
return 1;
@@ -317,7 +326,7 @@ int diskscan_cli(int argc, char **argv)
317326

318327
setup_signals();
319328

320-
if (disk_open(&disk, opts.disk_path, opts.fix, 70))
329+
if (disk_open(&disk, opts.disk_path, opts.fix, 70, opts.allowed_mount))
321330
return 1;
322331

323332
/*

include/arch.h

+8
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ typedef struct {
2929
unsigned sense_len;
3030
} io_result_t;
3131

32+
typedef enum {
33+
DISK_NOT_MOUNTED = 0,
34+
DISK_MOUNTED_RO = 1,
35+
DISK_MOUNTED_RW = 2,
36+
} disk_mount_e;
37+
38+
disk_mount_e disk_dev_mount_state(const char *path);
39+
3240
bool disk_dev_open(disk_dev_t *dev, const char *path);
3341
void disk_dev_close(disk_dev_t *dev);
3442
void disk_dev_cdb_out(disk_dev_t *dev, unsigned char *cdb, unsigned cdb_len, unsigned char *buf, unsigned buf_size, unsigned *buf_read,

include/diskscan.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ typedef struct disk_t {
8787
data_log_t data_log;
8888
} disk_t;
8989

90-
int disk_open(disk_t *disk, const char *path, int fix, unsigned latency_graph_len);
90+
int disk_open(disk_t *disk, const char *path, int fix, unsigned latency_graph_len, disk_mount_e allowed_mount);
9191
int disk_scan(disk_t *disk, enum scan_mode mode, unsigned data_size);
9292
int disk_close(disk_t *disk);
9393
void disk_scan_stop(disk_t *disk);

lib/diskscan.c

+32-1
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,33 @@ static void disk_scsi_monitor_end(disk_t *disk)
269269
(void)disk;
270270
}
271271

272-
int disk_open(disk_t *disk, const char *path, int fix, unsigned latency_graph_len)
272+
static const char *disk_mount_str(disk_mount_e mount)
273+
{
274+
switch (mount) {
275+
case DISK_NOT_MOUNTED: return "not mounted";
276+
case DISK_MOUNTED_RO: return "mounted read-only";
277+
case DISK_MOUNTED_RW: return "mounted read-write";
278+
default: return "unknown";
279+
}
280+
}
281+
282+
static int disk_mount_allowed(const char *path, disk_mount_e allowed_mount)
283+
{
284+
const disk_mount_e mount_state = disk_dev_mount_state(path);
285+
286+
if (mount_state > allowed_mount) {
287+
ERROR("Disk is currently %s and we only allow %s, use --force-mounted or --force-mounted-rw if the risk of problems is acceptable", disk_mount_str(mount_state), disk_mount_str(allowed_mount));
288+
return 0;
289+
}
290+
291+
if (mount_state != DISK_NOT_MOUNTED) {
292+
INFO("Disk is %s but this is allowed with a force option", disk_mount_str(mount_state));
293+
}
294+
295+
return 1;
296+
}
297+
298+
int disk_open(disk_t *disk, const char *path, int fix, unsigned latency_graph_len, disk_mount_e allowed_mount)
273299
{
274300
memset(disk, 0, sizeof(*disk));
275301
disk->fix = fix;
@@ -286,6 +312,11 @@ int disk_open(disk_t *disk, const char *path, int fix, unsigned latency_graph_le
286312
return 1;
287313
}
288314

315+
if (fix && !disk_mount_allowed(path, allowed_mount)) {
316+
ERROR("Better not fix with the disk mounted, mounted fs may get confused when data is possibly modified under its feet");
317+
return 1;
318+
}
319+
289320
if (!disk_dev_open(&disk->dev, path)) {
290321
ERROR("Failed to open path %s, errno=%d: %s", path, errno, strerror(errno));
291322
return 1;

0 commit comments

Comments
 (0)