X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fubox.git;a=blobdiff_plain;f=block.c;h=2289b779a7a485642789cfc303091ee19a0f4b7a;hp=194eb4a17c7ac85353b9e8a19d2ddc2f9fb6b0c1;hb=a9cb25c5c2b9d864f77033533fab9f2f8a6f94ab;hpb=75b17dab43c511d1cecc70c370e9f8283dfbf547 diff --git a/block.c b/block.c index 194eb4a..2289b77 100644 --- a/block.c +++ b/block.c @@ -47,6 +47,7 @@ struct mount { char *target; char *path; char *options; + uint32_t flags; char *uuid; char *label; char *device; @@ -113,6 +114,7 @@ static const struct uci_blob_param_list mount_attr_list = { enum { SWAP_ENABLE, SWAP_UUID, + SWAP_LABEL, SWAP_DEVICE, SWAP_PRIO, __SWAP_MAX @@ -121,6 +123,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 }, }; @@ -130,6 +133,46 @@ static const struct uci_blob_param_list swap_attr_list = { .params = swap_policy, }; +struct mount_flag { + const char *name; + int32_t flag; +}; + +#ifndef MS_DIRSYNC +# define MS_DIRSYNC (1 << 7) +#endif + +#ifndef MS_RELATIME +# define MS_RELATIME (1 << 21) +#endif + +#ifndef MS_STRICTATIME +# define MS_STRICTATIME (1 << 24) +#endif + +static const struct mount_flag mount_flags[] = { + { "sync", MS_SYNCHRONOUS }, + { "async", ~MS_SYNCHRONOUS }, + { "dirsync", MS_DIRSYNC }, + { "mand", MS_MANDLOCK }, + { "nomand", ~MS_MANDLOCK }, + { "atime", ~MS_NOATIME }, + { "noatime", MS_NOATIME }, + { "dev", ~MS_NODEV }, + { "nodev", MS_NODEV }, + { "diratime", ~MS_NODIRATIME }, + { "nodiratime", MS_NODIRATIME }, + { "exec", ~MS_NOEXEC }, + { "noexec", MS_NOEXEC }, + { "suid", ~MS_NOSUID }, + { "nosuid", MS_NOSUID }, + { "rw", ~MS_RDONLY }, + { "ro", MS_RDONLY }, + { "relatime", MS_RELATIME }, + { "norelatime", ~MS_RELATIME }, + { "strictatime", MS_STRICTATIME }, +}; + static char *blobmsg_get_strdup(struct blob_attr *attr) { if (!attr) @@ -146,6 +189,52 @@ static char *blobmsg_get_basename(struct blob_attr *attr) return strdup(basename(blobmsg_get_string(attr))); } +static void parse_mount_options(struct mount *m, char *optstr) +{ + int i; + bool is_flag; + char *p, *opts, *last; + + m->flags = 0; + m->options = NULL; + + if (!optstr || !*optstr) + return; + + m->options = opts = calloc(1, strlen(optstr) + 1); + + if (!m->options) + return; + + p = last = optstr; + + do { + p = strchr(p, ','); + + if (p) + *p++ = 0; + + for (i = 0, is_flag = false; i < ARRAY_SIZE(mount_flags); i++) { + if (!strcmp(last, mount_flags[i].name)) { + if (mount_flags[i].flag < 0) + m->flags &= (uint32_t)mount_flags[i].flag; + else + m->flags |= (uint32_t)mount_flags[i].flag; + is_flag = true; + break; + } + } + + if (!is_flag) + opts += sprintf(opts, "%s%s", (opts > m->options) ? "," : "", last); + + last = p; + + } while (p); + + free(optstr); +} + static int mount_add(struct uci_section *s) { struct blob_attr *tb[__MOUNT_MAX] = { 0 }; @@ -166,8 +255,10 @@ static int mount_add(struct uci_section *s) m->uuid = blobmsg_get_strdup(tb[MOUNT_UUID]); m->label = blobmsg_get_strdup(tb[MOUNT_LABEL]); m->target = blobmsg_get_strdup(tb[MOUNT_TARGET]); - m->options = blobmsg_get_strdup(tb[MOUNT_OPTIONS]); m->device = blobmsg_get_basename(tb[MOUNT_DEVICE]); + + parse_mount_options(m, blobmsg_get_strdup(tb[MOUNT_OPTIONS])); + m->overlay = m->extroot = 0; if (m->target && !strcmp(m->target, "/")) m->extroot = 1; @@ -193,21 +284,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; } @@ -239,7 +341,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; @@ -248,6 +350,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; } @@ -315,6 +419,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; @@ -325,12 +449,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); } @@ -425,8 +545,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; @@ -479,6 +601,36 @@ static void check_filesystem(struct blkid_struct_probe *pr) } } +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); + } +} + static int mount_device(struct blkid_struct_probe *pr, int hotplug) { struct mount *m; @@ -492,7 +644,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)); @@ -525,10 +677,13 @@ static int mount_device(struct blkid_struct_probe *pr, int hotplug) if (check_fs) check_filesystem(pr); - err = mount(pr->dev, target, pr->id->name, 0, (m->options) ? (m->options) : ("")); + 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", pr->dev, pr->id->name, target, err, strerror(err)); + else + handle_swapfiles(true); return err; } @@ -546,6 +701,8 @@ static int mount_device(struct blkid_struct_probe *pr, int hotplug) if (err) fprintf(stderr, "mounting %s (%s) as %s failed (%d) - %s\n", pr->dev, pr->id->name, target, err, strerror(err)); + else + handle_swapfiles(true); return err; } @@ -664,7 +821,7 @@ static int check_extroot(char *path) struct stat s; FILE *fp = NULL; char tag[64]; - char uuid[32] = { 0 }; + char uuid[64] = { 0 }; snprintf(tag, sizeof(tag), "%s/etc/.extroot-uuid", path); if (stat(tag, &s)) { @@ -808,6 +965,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; } @@ -818,6 +977,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);