Patchset related to hibernation resume: one enhancement to make the use of an existing resume file more general and one enhances name_to_dev_t to ignore the trailing newlines coming from userspace.
Both patches are based on the 3.11 tag. This was tested on a Pandaboard with partial hibernation support, and compiled for x86.
Further testing is needed on other platforms. Please let me know if you're able to verify this on any other systems.
[PATCH 1/2] init/do_mounts.c: ignore final \n in name_to_dev_t init/do_mounts.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-)
Changes name_to_dev_t to handle a trailing newline in the input buffer, which will allow name_to_dev_t to be used directly with user buffers without requiring a copy. Also adds a const to the name parameter which reflects how name_to_dev_t is treating the input buffer currently. This also allows direct use of user buffers (from resume_store for example).
[PATCH 2/2] PM / Hibernate: use name_to_dev_t to parse resume kernel/power/hibernate.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-)
Use name_to_dev_t to parse the /sys/power/resume file making the syntax more flexible. It supports the previous use syntax and additionally can support other formats such as /dev/devicenode and UUID= formats.
By changing /sys/debug/resume to accept the same syntax as the resume=device parameter, we can parse the resume=device in the initrd init script and use the resume device directly from the kernel command line.
Changes in v3: -------------- * Dropped documentation patch as it went in through trivial * Added patch for name_to_dev_t to support directly parsing userspace buffer
Changes in v2: -------------- * Added check for null return of kstrndup in hibernate.c
Thanks,
Sebastian
Enhance name_to_dev_t to handle trailing newline characters on device paths. Some inputs to name_to_dev_t may come from userspace where oftentimes a '\n' is appended to the path. Added const to the name buffer in both the function declaration and the prototype to reflect input buffer handling.
By handling trailing newlines in name_to_dev_t, userspace buffers may be directly passed to name_to_dev_t without modification.
Signed-off-by: Sebastian Capella sebastian.capella@linaro.org Cc: Pavel Machek pavel@ucw.cz Cc: "Eric W. Biederman" ebiederm@xmission.com Cc: Serge Hallyn serge.hallyn@canonical.com Cc: Andrew Morton akpm@linux-foundation.org Cc: Stephen Warren swarren@nvidia.com Cc: Jens Axboe axboe@kernel.dk Cc: Greg Kroah-Hartman gregkh@linuxfoundation.org Cc: Al Viro viro@zeniv.linux.org.uk --- include/linux/mount.h | 2 +- init/do_mounts.c | 25 +++++++++++++++++++------ 2 files changed, 20 insertions(+), 7 deletions(-)
diff --git a/include/linux/mount.h b/include/linux/mount.h index 73005f9..b024d5c 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -76,6 +76,6 @@ extern struct vfsmount *vfs_kern_mount(struct file_system_type *type, extern void mnt_set_expiry(struct vfsmount *mnt, struct list_head *expiry_list); extern void mark_mounts_for_expiry(struct list_head *mounts);
-extern dev_t name_to_dev_t(char *name); +extern dev_t name_to_dev_t(const char *name);
#endif /* _LINUX_MOUNT_H */ diff --git a/init/do_mounts.c b/init/do_mounts.c index 816014c..5a031de 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c @@ -143,6 +143,13 @@ static dev_t devt_from_partuuid(const char *uuid_str) clear_root_wait = true; goto done; } + if (uuid_str[cmp.len - 1] == '\n') { + cmp.len--; + if (!cmp.len) { + clear_root_wait = true; + goto done; + } + }
dev = class_find_device(&block_class, NULL, &cmp, &match_dev_by_uuid); @@ -202,12 +209,13 @@ done: * bangs. */
-dev_t name_to_dev_t(char *name) +dev_t name_to_dev_t(const char *name) { char s[32]; char *p; dev_t res = 0; int part; + int n;
#ifdef CONFIG_BLOCK if (strncmp(name, "PARTUUID=", 9) == 0) { @@ -228,7 +236,7 @@ dev_t name_to_dev_t(char *name) goto fail; } else { res = new_decode_dev(simple_strtoul(name, &p, 16)); - if (*p) + if (*p && *p != '\n') goto fail; } goto done; @@ -236,15 +244,20 @@ dev_t name_to_dev_t(char *name)
name += 5; res = Root_NFS; - if (strcmp(name, "nfs") == 0) + if (strncmp(name, "nfs", 3) == 0) goto done; res = Root_RAM0; - if (strcmp(name, "ram") == 0) + if (strncmp(name, "ram", 3) == 0) goto done;
- if (strlen(name) > 31) + n = strlen(name); + if (n != 0 && name[n - 1] == '\n') + n--; + if (n > 31) goto fail; - strcpy(s, name); + strncpy(s, name, n); + s[n] = '\0'; + for (p = s; *p; p++) if (*p == '/') *p = '!';
On Wed 2013-09-18 16:29:01, Sebastian Capella wrote:
Enhance name_to_dev_t to handle trailing newline characters on device paths. Some inputs to name_to_dev_t may come from userspace where oftentimes a '\n' is appended to the path. Added const to the name buffer in both the function declaration and the prototype to reflect input buffer handling.
By handling trailing newlines in name_to_dev_t, userspace buffers may be directly passed to name_to_dev_t without modification.
Signed-off-by: Sebastian Capella sebastian.capella@linaro.org Cc: Pavel Machek pavel@ucw.cz
Reviewed-by: Pavel Machek pavel@ucw.cz
Use the name_to_dev_t call to parse the device name echo'd to to /sys/power/resume. This imitates the method used in hibernate.c in software_resume, and allows the resume partition to be specified using other equivalent device formats as well. By allowing /sys/debug/resume to accept the same syntax as the resume=device parameter, we can parse the resume=device in the init script and use the resume device directly from the kernel command line.
Signed-off-by: Sebastian Capella sebastian.capella@linaro.org Cc: Len Brown len.brown@intel.com Cc: Pavel Machek pavel@ucw.cz Cc: "Rafael J. Wysocki" rjw@sisk.pl --- kernel/power/hibernate.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-)
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index b26f5f1..8b253c2 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -971,16 +971,11 @@ static ssize_t resume_show(struct kobject *kobj, struct kobj_attribute *attr, static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t n) { - unsigned int maj, min; dev_t res; - int ret = -EINVAL;
- if (sscanf(buf, "%u:%u", &maj, &min) != 2) - goto out; - - res = MKDEV(maj,min); - if (maj != MAJOR(res) || min != MINOR(res)) - goto out; + res = name_to_dev_t(buf); + if (res == 0) + return -EINVAL;
lock_system_sleep(); swsusp_resume_device = res; @@ -988,9 +983,7 @@ static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr, printk(KERN_INFO "PM: Starting manual resume from disk\n"); noresume = 0; software_resume(); - ret = n; - out: - return ret; + return n; }
power_attr(resume);
On Wed 2013-09-18 16:29:02, Sebastian Capella wrote:
Use the name_to_dev_t call to parse the device name echo'd to to /sys/power/resume. This imitates the method used in hibernate.c in software_resume, and allows the resume partition to be specified using other equivalent device formats as well. By allowing /sys/debug/resume to accept the same syntax as the resume=device parameter, we can parse the resume=device in the init script and use the resume device directly from the kernel command line.
Signed-off-by: Sebastian Capella sebastian.capella@linaro.org Cc: Len Brown len.brown@intel.com
Acked-by: Pavel Machek pavel@ucw.cz
linaro-kernel@lists.linaro.org