|
Lines 24-29
Link Here
|
| 24 |
#include <unistd.h> |
24 |
#include <unistd.h> |
| 25 |
#include <fcntl.h> |
25 |
#include <fcntl.h> |
| 26 |
#include <string.h> |
26 |
#include <string.h> |
|
|
27 |
#include <dirent.h> |
| 27 |
#include <sys/types.h> |
28 |
#include <sys/types.h> |
| 28 |
#include <sys/stat.h> |
29 |
#include <sys/stat.h> |
| 29 |
#include <sys/wait.h> |
30 |
#include <sys/wait.h> |
|
Lines 63-74
char *mount_status_str[] = {
Link Here
|
| 63 |
#ifdef TEST |
64 |
#ifdef TEST |
| 64 |
#define DEFAULT_LOGLEVEL LOG_DEBUG |
65 |
#define DEFAULT_LOGLEVEL LOG_DEBUG |
| 65 |
#else |
66 |
#else |
| 66 |
#define DEFAULT_LOGLEVEL LOG_ERR |
67 |
#define DEFAULT_LOGLEVEL LOG_DEBUG |
| 67 |
#endif |
68 |
#endif |
| 68 |
|
69 |
|
| 69 |
/* How log to wait for the background process to terminate */ |
70 |
/* How log to wait for the background process to terminate */ |
| 70 |
#define SIGNAL_TIMEOUT 10 |
71 |
#define SIGNAL_TIMEOUT 10 |
| 71 |
|
72 |
|
|
|
73 |
/* Multipath daemon program */ |
| 74 |
#define MPATHD_PROG "/sbin/multipathd" |
| 75 |
|
| 72 |
/* Fsck program to call */ |
76 |
/* Fsck program to call */ |
| 73 |
#ifdef TEST |
77 |
#ifdef TEST |
| 74 |
#define FSCK_PROG "./fsck_test" |
78 |
#define FSCK_PROG "./fsck_test" |
|
Lines 84-89
char *mount_status_str[] = {
Link Here
|
| 84 |
|
88 |
|
| 85 |
static char *dev; |
89 |
static char *dev; |
| 86 |
static char *mnt; |
90 |
static char *mnt; |
|
|
91 |
static char *action; |
| 87 |
static int major; |
92 |
static int major; |
| 88 |
static int minor; |
93 |
static int minor; |
| 89 |
static unsigned int passno; |
94 |
static unsigned int passno; |
|
Lines 144-150
static void terminate_child(int signo)
Link Here
|
| 144 |
* |
149 |
* |
| 145 |
* Copied from udev. |
150 |
* Copied from udev. |
| 146 |
*/ |
151 |
*/ |
| 147 |
static int run_program(char **argv) |
152 |
static int run_program(char **argv, char *buf, int len) |
| 148 |
{ |
153 |
{ |
| 149 |
int status; |
154 |
int status; |
| 150 |
int outpipe[2] = {-1, -1}; |
155 |
int outpipe[2] = {-1, -1}; |
|
Lines 212-217
static int run_program(char **argv)
Link Here
|
| 212 |
err("fork of '%s' failed: %s\n", argv[0], strerror(errno)); |
217 |
err("fork of '%s' failed: %s\n", argv[0], strerror(errno)); |
| 213 |
return -1; |
218 |
return -1; |
| 214 |
default: |
219 |
default: |
|
|
220 |
if (buf) |
| 221 |
buf[0] = '\0'; |
| 215 |
/* read from child if requested */ |
222 |
/* read from child if requested */ |
| 216 |
if (outpipe[READ_END] > 0 || errpipe[READ_END] > 0) { |
223 |
if (outpipe[READ_END] > 0 || errpipe[READ_END] > 0) { |
| 217 |
ssize_t count; |
224 |
ssize_t count; |
|
Lines 270-275
static int run_program(char **argv)
Link Here
|
| 270 |
inbuf[count] = '\0'; |
277 |
inbuf[count] = '\0'; |
| 271 |
|
278 |
|
| 272 |
pos = inbuf; |
279 |
pos = inbuf; |
|
|
280 |
if (buf) |
| 281 |
strncpy(buf, inbuf, len); |
| 273 |
while ((line = strsep(&pos, "\n"))) |
282 |
while ((line = strsep(&pos, "\n"))) |
| 274 |
if (pos && line[0] != '\0') |
283 |
if (pos && line[0] != '\0') |
| 275 |
warn("%s\n", line); |
284 |
warn("%s\n", line); |
|
Lines 325-330
static int run_program(char **argv)
Link Here
|
| 325 |
} |
334 |
} |
| 326 |
|
335 |
|
| 327 |
/* |
336 |
/* |
|
|
337 |
* check_dev - Check if the device number matches |
| 338 |
* |
| 339 |
* Check if the device number of the event matches with the |
| 340 |
* device number of the device node and if the device does not |
| 341 |
* has any 'holders' in /sys/block/XX. If not than we can |
| 342 |
* discard this event. |
| 343 |
*/ |
| 344 |
int check_dev(void) |
| 345 |
{ |
| 346 |
struct stat stbuf; |
| 347 |
char buf[256]; |
| 348 |
DIR *dirfd; |
| 349 |
struct dirent *dp; |
| 350 |
|
| 351 |
if (stat(dev, &stbuf) < 0) { |
| 352 |
fprintf(stderr,"Cannot stat '%s': %d\n", dev, errno); |
| 353 |
return -ENODEV; |
| 354 |
} |
| 355 |
|
| 356 |
if (!S_ISBLK(stbuf.st_mode)) { |
| 357 |
fprintf(stderr,"Not a block device\n"); |
| 358 |
return -ENOTBLK; |
| 359 |
} |
| 360 |
sprintf(buf,"/sys/dev/block/%d:%d/holders", major, minor); |
| 361 |
dirfd = opendir(buf); |
| 362 |
/* Can happen during remove, not an error */ |
| 363 |
if (!dirfd) |
| 364 |
return 0; |
| 365 |
while ((dp = readdir(dirfd)) != NULL) { |
| 366 |
if (!strcmp(dp->d_name,".") || !strcmp(dp->d_name, "..")) |
| 367 |
continue; |
| 368 |
fprintf(stderr, "Device %d:%d claimed by %s\n", |
| 369 |
major, minor, dp->d_name); |
| 370 |
closedir(dirfd); |
| 371 |
return -EBUSY; |
| 372 |
} |
| 373 |
closedir(dirfd); |
| 374 |
|
| 375 |
return 0; |
| 376 |
} |
| 377 |
|
| 378 |
/* |
| 328 |
* run_fsck - Run fsck and mount |
379 |
* run_fsck - Run fsck and mount |
| 329 |
* |
380 |
* |
| 330 |
* Get an exclusive lock on the lock file and call |
381 |
* Get an exclusive lock on the lock file and call |
|
Lines 335-341
static int run_program(char **argv)
Link Here
|
| 335 |
int run_fsck(char *fstype, char *fsopts) |
386 |
int run_fsck(char *fstype, char *fsopts) |
| 336 |
{ |
387 |
{ |
| 337 |
struct flock lock; |
388 |
struct flock lock; |
| 338 |
char buf[256]; |
389 |
char buf[32]; |
|
|
390 |
char argbuf[32]; |
| 339 |
char *argv[9]; |
391 |
char *argv[9]; |
| 340 |
mount_status status = MOUNT_UNCHECKED; |
392 |
mount_status status = MOUNT_UNCHECKED; |
| 341 |
int rc, i, num; |
393 |
int rc, i, num; |
|
Lines 357-369
int run_fsck(char *fstype, char *fsopts)
Link Here
|
| 357 |
return errno; |
409 |
return errno; |
| 358 |
} |
410 |
} |
| 359 |
|
411 |
|
|
|
412 |
/* Check for multipathing */ |
| 413 |
info("Check for multipath on '%s'\n", dev); |
| 414 |
|
| 415 |
memset(buf,0x0,32); |
| 416 |
strcpy(buf,"waiting"); |
| 417 |
num = write(lock_fd, buf, 32); |
| 418 |
|
| 419 |
sprintf(argbuf,"-kshow daemon"); |
| 420 |
argv[0] = MPATHD_PROG; |
| 421 |
argv[1] = argbuf; |
| 422 |
argv[2] = NULL; |
| 423 |
|
| 424 |
rc = run_program(argv, argbuf, 32); |
| 425 |
if (rc < 0) { |
| 426 |
status = MOUNT_FAILED; |
| 427 |
} else { |
| 428 |
if (strlen(argbuf) > 3 && !strncmp(argbuf,"pid", 3)) { |
| 429 |
/* |
| 430 |
* If multipath is running, it will notify us |
| 431 |
* again via the 'change' event. |
| 432 |
* No action required at this point. |
| 433 |
*/ |
| 434 |
if (!strncmp(action, "add", 3)) { |
| 435 |
status = MOUNT_SKIPPED; |
| 436 |
goto out_unlock; |
| 437 |
} |
| 438 |
} |
| 439 |
} |
| 440 |
|
| 360 |
if (passno == 0) |
441 |
if (passno == 0) |
| 361 |
goto skip_fsck; |
442 |
goto skip_fsck; |
| 362 |
|
443 |
|
| 363 |
info("Starting fsck on '%s'\n", dev); |
444 |
info("Starting fsck on '%s'\n", dev); |
| 364 |
|
445 |
|
|
|
446 |
memset(buf, 0x0, 32); |
| 365 |
strcpy(buf,"checking"); |
447 |
strcpy(buf,"checking"); |
| 366 |
num = write(lock_fd, buf, 20); |
448 |
num = write(lock_fd, buf, 32); |
| 367 |
|
449 |
|
| 368 |
argv[0] = FSCK_PROG; |
450 |
argv[0] = FSCK_PROG; |
| 369 |
argv[1] = "-p"; |
451 |
argv[1] = "-p"; |
|
Lines 379-385
int run_fsck(char *fstype, char *fsopts)
Link Here
|
| 379 |
i++; |
461 |
i++; |
| 380 |
argv[i] = NULL; |
462 |
argv[i] = NULL; |
| 381 |
|
463 |
|
| 382 |
rc = run_program(argv); |
464 |
rc = run_program(argv, NULL, 0); |
| 383 |
if (rc < 0) { |
465 |
if (rc < 0) { |
| 384 |
status = MOUNT_FAILED; |
466 |
status = MOUNT_FAILED; |
| 385 |
} else { |
467 |
} else { |
|
Lines 407-415
int run_fsck(char *fstype, char *fsopts)
Link Here
|
| 407 |
skip_fsck: |
489 |
skip_fsck: |
| 408 |
info("Mounting dev '%s' on '%s'\n", dev, mnt); |
490 |
info("Mounting dev '%s' on '%s'\n", dev, mnt); |
| 409 |
|
491 |
|
|
|
492 |
memset(buf, 0x0, 32); |
| 410 |
strcpy(buf, "mounting"); |
493 |
strcpy(buf, "mounting"); |
| 411 |
lseek(lock_fd, 0, SEEK_SET); |
494 |
lseek(lock_fd, 0, SEEK_SET); |
| 412 |
num = write(lock_fd, buf, 20); |
495 |
num = write(lock_fd, buf, 32); |
| 413 |
|
496 |
|
| 414 |
argv[0] = MOUNT_PROG; |
497 |
argv[0] = MOUNT_PROG; |
| 415 |
i = 1; |
498 |
i = 1; |
|
Lines 431-446
skip_fsck:
Link Here
|
| 431 |
i++; |
514 |
i++; |
| 432 |
argv[i] = NULL; |
515 |
argv[i] = NULL; |
| 433 |
|
516 |
|
| 434 |
rc = run_program(argv); |
517 |
rc = run_program(argv, NULL, 0); |
| 435 |
if (rc == 0) |
518 |
if (rc == 0) |
| 436 |
status = MOUNT_MOUNTED; |
519 |
status = MOUNT_MOUNTED; |
| 437 |
|
520 |
|
| 438 |
info("mount done (%d), status %s\n", rc, mount_status_str[status]); |
521 |
info("mount done (%d), status %s\n", rc, mount_status_str[status]); |
| 439 |
|
522 |
|
| 440 |
out_unlock: |
523 |
out_unlock: |
|
|
524 |
memset(buf, 0x0, 32); |
| 441 |
strcpy(buf,mount_status_str[status]); |
525 |
strcpy(buf,mount_status_str[status]); |
| 442 |
lseek(lock_fd, 0, SEEK_SET); |
526 |
lseek(lock_fd, 0, SEEK_SET); |
| 443 |
num = write(lock_fd, buf, 20); |
527 |
num = write(lock_fd, buf, 32); |
| 444 |
|
528 |
|
| 445 |
lock.l_type = F_UNLCK; |
529 |
lock.l_type = F_UNLCK; |
| 446 |
lock.l_start = 0; |
530 |
lock.l_start = 0; |
|
Lines 504-510
int daemonize_fsck(char *fstype, char *f
Link Here
|
| 504 |
fd = open("/dev/null", O_RDWR); |
588 |
fd = open("/dev/null", O_RDWR); |
| 505 |
fd = dup(0); |
589 |
fd = dup(0); |
| 506 |
fd = dup(0); |
590 |
fd = dup(0); |
| 507 |
openlog("udev.mountd", LOG_CONS, LOG_DAEMON); |
591 |
openlog("udev.mountd", 0, LOG_DAEMON); |
| 508 |
run_fsck(fstype, fsopts); |
592 |
run_fsck(fstype, fsopts); |
| 509 |
closelog(); |
593 |
closelog(); |
| 510 |
exit(0); |
594 |
exit(0); |
|
Lines 590-625
int remove_lock(void)
Link Here
|
| 590 |
} |
674 |
} |
| 591 |
|
675 |
|
| 592 |
/* |
676 |
/* |
| 593 |
* check_dev - Check if the device number matches |
|
|
| 594 |
* |
| 595 |
* Check if the device number of the event matches with the |
| 596 |
* device number of the device node. If not than we can |
| 597 |
* discard this event. |
| 598 |
*/ |
| 599 |
int check_dev(void) |
| 600 |
{ |
| 601 |
struct stat stbuf; |
| 602 |
|
| 603 |
if (stat(dev, &stbuf) < 0) { |
| 604 |
fprintf(stderr,"Cannot stat '%s': %d\n", dev, errno); |
| 605 |
return -ENODEV; |
| 606 |
} |
| 607 |
|
| 608 |
if (!S_ISBLK(stbuf.st_mode)) { |
| 609 |
fprintf(stderr,"Not a block device\n"); |
| 610 |
return -ENOTBLK; |
| 611 |
} |
| 612 |
|
| 613 |
if (stbuf.st_rdev != makedev(major,minor)) { |
| 614 |
fprintf(stdout, "Invalid device (fstab %d:%d, event %d:%d)\n", |
| 615 |
major(stbuf.st_rdev), minor(stbuf.st_rdev), |
| 616 |
major, minor); |
| 617 |
return -EINVAL; |
| 618 |
} |
| 619 |
return 0; |
| 620 |
} |
| 621 |
|
| 622 |
/* |
| 623 |
* check_mnt - Check if the device is mounted |
677 |
* check_mnt - Check if the device is mounted |
| 624 |
* |
678 |
* |
| 625 |
* Compare the device number from the event |
679 |
* Compare the device number from the event |
|
Lines 698-703
int main(int argc, char **argv, char **e
Link Here
|
| 698 |
/* Scan environment */ |
752 |
/* Scan environment */ |
| 699 |
while (envp && *envp) { |
753 |
while (envp && *envp) { |
| 700 |
ep = *envp; |
754 |
ep = *envp; |
|
|
755 |
if (!strncmp(ep, "ACTION", 6) && strlen(ep) > 7) { |
| 756 |
action = malloc(strlen(ep + 7) + 1); |
| 757 |
if (!action) |
| 758 |
return ENOMEM; |
| 759 |
strcpy(action, ep + 7); |
| 760 |
} |
| 701 |
if (!strncmp(ep, "MAJOR", 5) && strlen(ep) > 6) { |
761 |
if (!strncmp(ep, "MAJOR", 5) && strlen(ep) > 6) { |
| 702 |
major = strtoul(ep + 6, &ptr, 10); |
762 |
major = strtoul(ep + 6, &ptr, 10); |
| 703 |
if (ptr == ep + 6) { |
763 |
if (ptr == ep + 6) { |
|
Lines 788-801
int main(int argc, char **argv, char **e
Link Here
|
| 788 |
fprintf(stdout,"FSCK_STATE=unknown\n"); |
848 |
fprintf(stdout,"FSCK_STATE=unknown\n"); |
| 789 |
return 0; |
849 |
return 0; |
| 790 |
} |
850 |
} |
|
|
851 |
if (err == -ENOENT && op == MOUNT_REMOVE) |
| 852 |
goto skip_mount; |
| 853 |
|
| 791 |
return -err; |
854 |
return -err; |
| 792 |
} |
855 |
} |
| 793 |
|
856 |
|
| 794 |
/* Check if the device is mounted */ |
857 |
/* Check if the device is mounted */ |
| 795 |
err = check_mnt(); |
858 |
err = check_mnt(); |
| 796 |
if (err < 0) |
859 |
if (err < 0) { |
|
|
860 |
if (err == -EINVAL && op == MOUNT_FSCK) { |
| 861 |
fprintf(stdout,"FSCK_STATE=skipped\n"); |
| 862 |
return 0; |
| 863 |
} |
| 797 |
return EINVAL; |
864 |
return EINVAL; |
|
|
865 |
} |
| 798 |
|
866 |
|
|
|
867 |
skip_mount: |
| 799 |
/* The real action */ |
868 |
/* The real action */ |
| 800 |
if (op == MOUNT_FSCK) { |
869 |
if (op == MOUNT_FSCK) { |
| 801 |
if (err == 0) { |
870 |
if (err == 0) { |