X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fubox.git;a=blobdiff_plain;f=block.c;h=2d520e10e78a043a0a9302aad9b256108ac719a9;hp=ff35ba793af6624d2d7391d1ae7272073aea2d11;hb=f309065fe99839f8e07ec9a2cc1d53ba62af8236;hpb=e2625200c27c9e3a36d90cd0b38b56486886182f diff --git a/block.c b/block.c index ff35ba7..2d520e1 100644 --- a/block.c +++ b/block.c @@ -13,6 +13,7 @@ */ #define _GNU_SOURCE +#include #include #include #include @@ -35,6 +36,11 @@ #include "libblkid-tiny/libblkid-tiny.h" +#define ERROR(fmt, ...) do { \ + syslog(LOG_ERR, fmt, ## __VA_ARGS__); \ + fprintf(stderr, "block: "fmt, ## __VA_ARGS__); \ + } while (0) + enum { TYPE_MOUNT, TYPE_SWAP, @@ -114,6 +120,7 @@ static const struct uci_blob_param_list mount_attr_list = { enum { SWAP_ENABLE, SWAP_UUID, + SWAP_LABEL, SWAP_DEVICE, SWAP_PRIO, __SWAP_MAX @@ -122,6 +129,7 @@ enum { static const struct blobmsg_policy swap_policy[__SWAP_MAX] = { [SWAP_ENABLE] = { .name = "enabled", .type = BLOBMSG_TYPE_INT32 }, [SWAP_UUID] = { .name = "uuid", .type = BLOBMSG_TYPE_STRING }, + [SWAP_LABEL] = { .name = "label", .type = BLOBMSG_TYPE_STRING }, [SWAP_DEVICE] = { .name = "device", .type = BLOBMSG_TYPE_STRING }, [SWAP_PRIO] = { .name = "priority", .type = BLOBMSG_TYPE_INT32 }, }; @@ -282,21 +290,32 @@ static int swap_add(struct uci_section *s) uci_to_blob(&b, s, &swap_attr_list); blobmsg_parse(swap_policy, __SWAP_MAX, tb, blob_data(b.head), blob_len(b.head)); - if (!tb[SWAP_UUID] && !tb[SWAP_DEVICE]) + if (!tb[SWAP_UUID] && !tb[SWAP_LABEL] && !tb[SWAP_DEVICE]) return -1; m = malloc(sizeof(struct mount)); memset(m, 0, sizeof(struct mount)); m->type = TYPE_SWAP; m->uuid = blobmsg_get_strdup(tb[SWAP_UUID]); + m->label = blobmsg_get_strdup(tb[SWAP_LABEL]); m->device = blobmsg_get_basename(tb[SWAP_DEVICE]); if (tb[SWAP_PRIO]) m->prio = blobmsg_get_u32(tb[SWAP_PRIO]); if (m->prio) m->prio = ((m->prio << SWAP_FLAG_PRIO_SHIFT) & SWAP_FLAG_PRIO_MASK) | SWAP_FLAG_PREFER; - if ((!tb[SWAP_ENABLE]) || blobmsg_get_u32(tb[SWAP_ENABLE])) - vlist_add(&mounts, &m->node, (m->uuid) ? (m->uuid) : (m->device)); + if ((!tb[SWAP_ENABLE]) || blobmsg_get_u32(tb[SWAP_ENABLE])) { + /* store complete swap path */ + if (tb[SWAP_DEVICE]) + m->target = blobmsg_get_strdup(tb[SWAP_DEVICE]); + + if (m->uuid) + vlist_add(&mounts, &m->node, m->uuid); + else if (m->label) + vlist_add(&mounts, &m->node, m->label); + else if (m->device) + vlist_add(&mounts, &m->node, m->device); + } return 0; } @@ -328,7 +347,7 @@ static int global_add(struct uci_section *s) return 0; } -static struct mount* find_swap(const char *uuid, const char *device) +static struct mount* find_swap(const char *uuid, const char *label, const char *device) { struct mount *m; @@ -337,6 +356,8 @@ static struct mount* find_swap(const char *uuid, const char *device) continue; if (uuid && m->uuid && !strcmp(m->uuid, uuid)) return m; + if (label && m->label && !strcmp(m->label, label)) + return m; if (device && m->device && !strcmp(m->device, device)) return m; } @@ -386,7 +407,14 @@ static int config_load(char *cfg) } if (uci_load(ctx, "fstab", &pkg)) + { + char *err; + uci_get_errorstr(ctx, &err, "fstab"); + ERROR("extroot: failed to load %s/etc/config/%s\n", + cfg ? cfg : "", err); + free(err); return -1; + } vlist_update(&mounts); uci_foreach_element(&pkg->sections, e) { @@ -404,6 +432,26 @@ static int config_load(char *cfg) return 0; } +static struct blkid_struct_probe* _probe_path(char *path) +{ + struct blkid_struct_probe *pr; + + pr = malloc(sizeof(*pr)); + + if (!pr) + return NULL; + + memset(pr, 0, sizeof(*pr)); + probe_block(path, pr); + + if (pr->err || !pr->id) { + free(pr); + return NULL; + } + + return pr; +} + static int _cache_load(const char *path) { int gl_flags = GLOB_NOESCAPE | GLOB_MARK; @@ -414,12 +462,8 @@ static int _cache_load(const char *path) return -1; for (j = 0; j < gl.gl_pathc; j++) { - struct blkid_struct_probe *pr = malloc(sizeof(struct blkid_struct_probe)); - memset(pr, 0, sizeof(struct blkid_struct_probe)); - probe_block(gl.gl_pathv[j], pr); - if (pr->err || !pr->id) - free(pr); - else + struct blkid_struct_probe *pr = _probe_path(gl.gl_pathv[j]); + if (pr) list_add_tail(&pr->list, &devices); } @@ -434,7 +478,6 @@ static void cache_load(int mtd) _cache_load("/dev/mtdblock*"); _cache_load("/dev/mmcblk*"); _cache_load("/dev/sd*"); - _cache_load("/dev/sdc*"); _cache_load("/dev/hd*"); _cache_load("/dev/md*"); _cache_load("/dev/mapper/*"); @@ -488,12 +531,12 @@ static struct blkid_struct_probe* find_block_info(char *uuid, char *label, char if (label) list_for_each_entry(pr, &devices, list) - if (strcmp(pr->label, label)) + if (!strcmp(pr->label, label)) return pr; if (path) list_for_each_entry(pr, &devices, list) - if (!strcmp(pr->dev, path)) + if (!strcmp(basename(pr->dev), basename(path))) return pr; return NULL; @@ -514,8 +557,10 @@ static char* find_mount_point(char *block) char *p = &line[len + 1]; char *t = strstr(p, " "); - if (!t) + if (!t) { + fclose(fp); return NULL; + } *t = '\0'; point = p; break; @@ -546,12 +591,12 @@ static void check_filesystem(struct blkid_struct_probe *pr) char *e2fsck = "/usr/sbin/e2fsck"; if (strncmp(pr->id->name, "ext", 3)) { - fprintf(stderr, "check_filesystem: %s is not supported\n", pr->id->name); + ERROR("check_filesystem: %s is not supported\n", pr->id->name); return; } if (stat(e2fsck, &statbuf) < 0) { - fprintf(stderr, "check_filesystem: %s not found\n", e2fsck); + ERROR("check_filesystem: %s not found\n", e2fsck); return; } @@ -564,7 +609,37 @@ static void check_filesystem(struct blkid_struct_probe *pr) waitpid(pid, &status, 0); if (WEXITSTATUS(status)) - fprintf(stderr, "check_filesystem: %s returned %d\n", e2fsck, WEXITSTATUS(status)); + ERROR("check_filesystem: %s returned %d\n", e2fsck, WEXITSTATUS(status)); + } +} + +static void handle_swapfiles(bool on) +{ + struct stat s; + struct mount *m; + struct blkid_struct_probe *pr; + + vlist_for_each_element(&mounts, m, node) + { + if (m->type != TYPE_SWAP || !m->target) + continue; + + if (stat(m->target, &s) || !S_ISREG(s.st_mode)) + continue; + + pr = _probe_path(m->target); + + if (!pr) + continue; + + if (!strcmp(pr->id->name, "swap")) { + if (on) + swapon(pr->dev, m->prio); + else + swapoff(pr->dev); + } + + free(pr); } } @@ -581,7 +656,7 @@ static int mount_device(struct blkid_struct_probe *pr, int hotplug) if (!strcmp(pr->id->name, "swap")) { if (hotplug && !auto_swap) return -1; - m = find_swap(pr->uuid, device); + m = find_swap(pr->uuid, pr->label, device); if (m || anon_swap) swapon(pr->dev, (m) ? (m->prio) : (0)); @@ -592,7 +667,7 @@ static int mount_device(struct blkid_struct_probe *pr, int hotplug) return -1; if (find_mount_point(pr->dev)) { - fprintf(stderr, "%s is already mounted\n", pr->dev); + ERROR("%s is already mounted\n", pr->dev); return -1; } @@ -617,8 +692,10 @@ static int mount_device(struct blkid_struct_probe *pr, int hotplug) err = mount(pr->dev, target, pr->id->name, m->flags, (m->options) ? (m->options) : ("")); if (err) - fprintf(stderr, "mounting %s (%s) as %s failed (%d) - %s\n", + ERROR("mounting %s (%s) as %s failed (%d) - %s\n", pr->dev, pr->id->name, target, err, strerror(err)); + else + handle_swapfiles(true); return err; } @@ -634,8 +711,10 @@ static int mount_device(struct blkid_struct_probe *pr, int hotplug) err = mount(pr->dev, target, pr->id->name, 0, ""); if (err) - fprintf(stderr, "mounting %s (%s) as %s failed (%d) - %s\n", + ERROR("mounting %s (%s) as %s failed (%d) - %s\n", pr->dev, pr->id->name, target, err, strerror(err)); + else + handle_swapfiles(true); return err; } @@ -665,10 +744,10 @@ static int umount_device(struct blkid_struct_probe *pr) err = umount2(mp, MNT_DETACH); if (err) - fprintf(stderr, "unmounting %s (%s) failed (%d) - %s\n", + ERROR("unmounting %s (%s) failed (%d) - %s\n", pr->dev, mp, err, strerror(err)); else - fprintf(stderr, "unmounted %s (%s)\n", + ERROR("unmounted %s (%s)\n", pr->dev, mp); return err; @@ -693,12 +772,12 @@ static int main_hotplug(int argc, char **argv) err = umount2(mount_point, MNT_DETACH); if (err) - fprintf(stderr, "umount of %s failed (%d) - %s\n", + ERROR("umount of %s failed (%d) - %s\n", mount_point, err, strerror(err)); return 0; } else if (strcmp(action, "add")) { - fprintf(stderr, "Unkown action %s\n", action); + ERROR("Unkown action %s\n", action); return -1; } @@ -760,7 +839,7 @@ static int check_extroot(char *path) if (stat(tag, &s)) { fp = fopen(tag, "w+"); if (!fp) { - fprintf(stderr, "extroot: failed to write uuid tag file\n"); + ERROR("extroot: failed to write uuid tag file\n"); /* return 0 to continue boot regardless of error */ return 0; } @@ -771,7 +850,7 @@ static int check_extroot(char *path) fp = fopen(tag, "r"); if (!fp) { - fprintf(stderr, "extroot: failed to open uuid tag file\n"); + ERROR("extroot: failed to open uuid tag file\n"); return -1; } @@ -779,7 +858,7 @@ static int check_extroot(char *path) fclose(fp); if (!strcmp(uuid, pr->uuid)) return 0; - fprintf(stderr, "extroot: uuid tag does not match rom uuid\n"); + ERROR("extroot: uuid tag does not match rom uuid\n"); } } return -1; @@ -802,20 +881,23 @@ static int mount_extroot(char *cfg) m = find_block(NULL, NULL, NULL, "/overlay"); if (!m || !m->extroot) + { + ERROR("extroot: no root or overlay mount defined\n"); return -1; + } - pr = find_block_info(m->uuid, m->label, NULL); + pr = find_block_info(m->uuid, m->label, m->device); if (!pr && delay_root){ - fprintf(stderr, "extroot: is not ready yet, retrying in %u seconds\n", delay_root); + ERROR("extroot: is not ready yet, retrying in %u seconds\n", delay_root); sleep(delay_root); mkblkdev(); cache_load(0); - pr = find_block_info(m->uuid, m->label, NULL); + pr = find_block_info(m->uuid, m->label, m->device); } if (pr) { if (strncmp(pr->id->name, "ext", 3)) { - fprintf(stderr, "extroot: %s is not supported, try ext4\n", pr->id->name); + ERROR("extroot: %s is not supported, try ext4\n", pr->id->name); return -1; } if (m->overlay) @@ -828,13 +910,15 @@ static int mount_extroot(char *cfg) err = mount(pr->dev, path, pr->id->name, 0, (m->options) ? (m->options) : ("")); if (err) { - fprintf(stderr, "mounting %s (%s) as %s failed (%d) - %s\n", + ERROR("mounting %s (%s) as %s failed (%d) - %s\n", pr->dev, pr->id->name, path, err, strerror(err)); } else if (m->overlay) { err = check_extroot(path); if (err) umount(path); } + } else { + ERROR("extroot: cannot find block device\n"); } return err; @@ -859,12 +943,16 @@ static int main_extroot(int argc, char **argv) cache_load(1); find_block_mtd("rootfs", fs, sizeof(fs)); - if (!fs[0]) + if (!fs[0]) { + ERROR("extroot: unable to locate rootfs mtdblock\n"); return -2; + } pr = find_block_info(NULL, NULL, fs); - if (!pr) + if (!pr) { + ERROR("extroot: unable to retrieve rootfs information\n"); return -3; + } find_block_mtd("rootfs_data", fs_data, sizeof(fs_data)); if (fs_data[0]) { @@ -898,6 +986,8 @@ static int main_mount(int argc, char **argv) list_for_each_entry(pr, &devices, list) mount_device(pr, 0); + handle_swapfiles(true); + return 0; } @@ -908,6 +998,8 @@ static int main_umount(int argc, char **argv) if (config_load(NULL)) return -1; + handle_swapfiles(false); + cache_load(0); list_for_each_entry(pr, &devices, list) umount_device(pr); @@ -950,11 +1042,11 @@ static int main_info(int argc, char **argv) struct stat s; if (stat(argv[i], &s)) { - fprintf(stderr, "failed to stat %s\n", argv[i]); + ERROR("failed to stat %s\n", argv[i]); continue; } if (!S_ISBLK(s.st_mode)) { - fprintf(stderr, "%s is not a block device\n", argv[i]); + ERROR("%s is not a block device\n", argv[i]); continue; } pr = find_block_info(NULL, NULL, argv[i]); @@ -965,50 +1057,75 @@ static int main_info(int argc, char **argv) return 0; } +static int swapon_usage(void) +{ + fprintf(stderr, "Usage: swapon [-s] [-a] [[-p pri] DEVICE]\n\n" + "\tStart swapping on [DEVICE]\n" + " -a\tStart swapping on all swap devices\n" + " -p pri\tSet priority of swap device\n" + " -s\tShow summary\n"); + return -1; +} + static int main_swapon(int argc, char **argv) { - if (argc != 2) { - fprintf(stderr, "Usage: swapon <-s> <-a> [DEVICE]\n\n\tStart swapping on [DEVICE]\n -a\tStart swapping on all swap devices\n -s\tShow summary\n"); - return -1; - } + int ch; + FILE *fp; + char *lineptr; + size_t s; + struct blkid_struct_probe *pr; + int flags = 0; + int pri; + struct stat st; + int err; - if (!strcmp(argv[1], "-s")) { - FILE *fp = fopen("/proc/swaps", "r"); - char *lineptr = NULL; - size_t s; + while ((ch = getopt(argc, argv, "ap:s")) != -1) { + switch(ch) { + case 's': + fp = fopen("/proc/swaps", "r"); + lineptr = NULL; - if (!fp) { - fprintf(stderr, "failed to open /proc/swaps\n"); - return -1; + if (!fp) { + ERROR("failed to open /proc/swaps\n"); + return -1; + } + while (getline(&lineptr, &s, fp) > 0) + printf(lineptr); + if (lineptr) + free(lineptr); + fclose(fp); + return 0; + case 'a': + cache_load(0); + list_for_each_entry(pr, &devices, list) { + if (strcmp(pr->id->name, "swap")) + continue; + if (swapon(pr->dev, 0)) + ERROR("failed to swapon %s\n", pr->dev); + } + return 0; + case 'p': + pri = atoi(optarg); + if (pri >= 0) + flags = ((pri << SWAP_FLAG_PRIO_SHIFT) & SWAP_FLAG_PRIO_MASK) | SWAP_FLAG_PREFER; + break; + default: + return swapon_usage(); } - while (getline(&lineptr, &s, fp) > 0) - printf(lineptr); - if (lineptr) - free(lineptr); - fclose(fp); - } else if (!strcmp(argv[1], "-a")) { - struct blkid_struct_probe *pr; - cache_load(0); - list_for_each_entry(pr, &devices, list) { - if (strcmp(pr->id->name, "swap")) - continue; - if (swapon(pr->dev, 0)) - fprintf(stderr, "failed to swapon %s\n", pr->dev); - } - } else { - struct stat s; - int err; + } - if (stat(argv[1], &s) || (!S_ISBLK(s.st_mode) && !S_ISREG(s.st_mode))) { - fprintf(stderr, "%s is not a block device or file\n", argv[1]); - return -1; - } - err = swapon(argv[1], 0); - if (err) { - fprintf(stderr, "failed to swapon %s (%d)\n", argv[1], err); - return err; - } + if (optind != (argc - 1)) + return swapon_usage(); + + if (stat(argv[optind], &st) || (!S_ISBLK(st.st_mode) && !S_ISREG(st.st_mode))) { + ERROR("%s is not a block device or file\n", argv[optind]); + return -1; + } + err = swapon(argv[optind], flags); + if (err) { + ERROR("failed to swapon %s (%d)\n", argv[optind], err); + return err; } return 0; @@ -1017,7 +1134,9 @@ static int main_swapon(int argc, char **argv) static int main_swapoff(int argc, char **argv) { if (argc != 2) { - fprintf(stderr, "Usage: swapoff [-a] [DEVICE]\n\n\tStop swapping on DEVICE\n -a\tStop swapping on all swap devices\n"); + ERROR("Usage: swapoff [-a] [DEVICE]\n\n" + "\tStop swapping on DEVICE\n" + " -a\tStop swapping on all swap devices\n"); return -1; } @@ -1026,7 +1145,7 @@ static int main_swapoff(int argc, char **argv) char line[256]; if (!fp) { - fprintf(stderr, "failed to open /proc/swaps\n"); + ERROR("failed to open /proc/swaps\n"); return -1; } fgets(line, sizeof(line), fp); @@ -1039,7 +1158,7 @@ static int main_swapoff(int argc, char **argv) *end = '\0'; err = swapoff(line); if (err) - fprintf(stderr, "failed to swapoff %s (%d)\n", line, err); + ERROR("failed to swapoff %s (%d)\n", line, err); } fclose(fp); } else { @@ -1047,12 +1166,12 @@ static int main_swapoff(int argc, char **argv) int err; if (stat(argv[1], &s) || (!S_ISBLK(s.st_mode) && !S_ISREG(s.st_mode))) { - fprintf(stderr, "%s is not a block device or file\n", argv[1]); + ERROR("%s is not a block device or file\n", argv[1]); return -1; } err = swapoff(argv[1]); if (err) { - fprintf(stderr, "fsiled to swapoff %s (%d)\n", argv[1], err); + ERROR("fsiled to swapoff %s (%d)\n", argv[1], err); return err; } }