aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Hilman <khilman@linaro.org>2015-08-04 14:40:50 -0700
committerKevin Hilman <khilman@linaro.org>2015-08-04 14:40:50 -0700
commita06f7d9e6f2702b2726f43ecd1f9808d56e39630 (patch)
treea28465486c2f6015e0a6cf6f1c5387f753fff26c
parent56f9fcf4b64cc418ea7c1524d17a3f1788c5112f (diff)
parentc44a699d96df2e13467fc081bff88b97dcc5afb2 (diff)
Merge branch 'android-3.18' of https://android.googlesource.com/kernel/common into linux-linaro-lsk-v3.18-android
* 'android-3.18' of https://android.googlesource.com/kernel/common: usb: gadget: fix NULL ptr derefer while symlinking PTP func uid_cputime: Iterates over all the threads instead of processes. Fix generic cgroup subsystem permission checks uid_cputime: fix cputime overflow usb:gadget:Add "state" attribute to android_device cpufreq_stats: fix use of cpufreq_for_each_valid_entry() iterator initramfs: Add skip_initramfs command line option cpu_power: Avoids race condition when the task exits. uid_cputime: Avoids double accounting of process stime, utime and cpu_power in task exit. Shrink ashmem directly through shmem_fallocate
-rw-r--r--drivers/cpufreq/cpufreq_stats.c3
-rw-r--r--drivers/misc/uid_cputime.c22
-rw-r--r--drivers/staging/android/ashmem.c2
-rw-r--r--drivers/usb/gadget/configfs.c71
-rw-r--r--drivers/usb/gadget/function/f_mtp.c18
-rw-r--r--drivers/usb/gadget/functions.c2
-rw-r--r--include/linux/initramfs.h32
-rw-r--r--init/Makefile3
-rw-r--r--init/initramfs.c19
-rw-r--r--init/noinitramfs.c9
-rw-r--r--kernel/cgroup.c1
11 files changed, 165 insertions, 17 deletions
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index a460217b513c..a2f1d41820b8 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -140,7 +140,8 @@ void acct_update_power(struct task_struct *task, cputime_t cputime) {
return;
curr = powerstats->curr[stats->last_index];
- task->cpu_power += curr * cputime_to_usecs(cputime);
+ if (task->cpu_power != ULLONG_MAX)
+ task->cpu_power += curr * cputime_to_usecs(cputime);
}
EXPORT_SYMBOL_GPL(acct_update_power);
diff --git a/drivers/misc/uid_cputime.c b/drivers/misc/uid_cputime.c
index 89bfba6c5b6a..43298a43ecc3 100644
--- a/drivers/misc/uid_cputime.c
+++ b/drivers/misc/uid_cputime.c
@@ -75,7 +75,7 @@ static struct uid_entry *find_or_register_uid(uid_t uid)
static int uid_stat_show(struct seq_file *m, void *v)
{
struct uid_entry *uid_entry;
- struct task_struct *task;
+ struct task_struct *task, *temp;
cputime_t utime;
cputime_t stime;
unsigned long bkt;
@@ -89,7 +89,7 @@ static int uid_stat_show(struct seq_file *m, void *v)
}
read_lock(&tasklist_lock);
- for_each_process(task) {
+ do_each_thread(temp, task) {
uid_entry = find_or_register_uid(from_kuid_munged(
current_user_ns(), task_uid(task)));
if (!uid_entry) {
@@ -100,11 +100,16 @@ static int uid_stat_show(struct seq_file *m, void *v)
task_uid(task)));
return -ENOMEM;
}
+ /* if this task is exiting, we have already accounted for the
+ * time and power.
+ */
+ if (task->cpu_power == ULLONG_MAX)
+ continue;
task_cputime_adjusted(task, &utime, &stime);
uid_entry->active_utime += utime;
uid_entry->active_stime += stime;
uid_entry->active_power += task->cpu_power;
- }
+ } while_each_thread(temp, task);
read_unlock(&tasklist_lock);
hash_for_each(hash_table, bkt, uid_entry, hash) {
@@ -114,10 +119,12 @@ static int uid_stat_show(struct seq_file *m, void *v)
uid_entry->active_stime;
unsigned long long total_power = uid_entry->power +
uid_entry->active_power;
- seq_printf(m, "%d: %u %u %llu\n", uid_entry->uid,
- cputime_to_usecs(total_utime),
- cputime_to_usecs(total_stime),
- total_power);
+ seq_printf(m, "%d: %llu %llu %llu\n", uid_entry->uid,
+ (unsigned long long)jiffies_to_msecs(
+ cputime_to_jiffies(total_utime)) * USEC_PER_MSEC,
+ (unsigned long long)jiffies_to_msecs(
+ cputime_to_jiffies(total_stime)) * USEC_PER_MSEC,
+ total_power);
}
mutex_unlock(&uid_lock);
@@ -211,6 +218,7 @@ static int process_notifier(struct notifier_block *self,
uid_entry->utime += utime;
uid_entry->stime += stime;
uid_entry->power += task->cpu_power;
+ task->cpu_power = ULLONG_MAX;
exit:
mutex_unlock(&uid_lock);
diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c
index bd8ee37cadee..afee619b7c1b 100644
--- a/drivers/staging/android/ashmem.c
+++ b/drivers/staging/android/ashmem.c
@@ -440,7 +440,7 @@ ashmem_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
loff_t start = range->pgstart * PAGE_SIZE;
loff_t end = (range->pgend + 1) * PAGE_SIZE;
- do_fallocate(range->asma->file,
+ range->asma->file->f_op->fallocate(range->asma->file,
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
start, end - start);
range->purged = ASHMEM_WAS_PURGED;
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 0ad2aa7338da..1157a532a34d 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -436,6 +436,11 @@ static int config_usb_cfg_link(
}
f = usb_get_function(fi);
+ if (f == NULL) {
+ /* Are we trying to symlink PTP without MTP function? */
+ ret = -EINVAL; /* Invalid Configuration */
+ goto out;
+ }
if (IS_ERR(f)) {
ret = PTR_ERR(f);
goto out;
@@ -1608,11 +1613,49 @@ static const struct usb_gadget_driver configfs_driver_template = {
},
};
+#ifdef CONFIG_USB_CONFIGFS_UEVENT
+static ssize_t state_show(struct device *pdev, struct device_attribute *attr,
+ char *buf)
+{
+ struct gadget_info *dev = dev_get_drvdata(pdev);
+ struct usb_composite_dev *cdev;
+ char *state = "DISCONNECTED";
+ unsigned long flags;
+
+ if (!dev)
+ goto out;
+
+ cdev = &dev->cdev;
+
+ if (!cdev)
+ goto out;
+
+ spin_lock_irqsave(&cdev->lock, flags);
+ if (cdev->config)
+ state = "CONFIGURED";
+ else if (dev->connected)
+ state = "CONNECTED";
+ spin_unlock_irqrestore(&cdev->lock, flags);
+out:
+ return sprintf(buf, "%s\n", state);
+}
+
+static DEVICE_ATTR(state, S_IRUGO, state_show, NULL);
+
+static struct device_attribute *android_usb_attributes[] = {
+ &dev_attr_state,
+ NULL
+};
+#endif
+
static struct config_group *gadgets_make(
struct config_group *group,
const char *name)
{
struct gadget_info *gi;
+ struct device_attribute **attrs;
+ struct device_attribute *attr;
+ int err;
gi = kzalloc(sizeof(*gi), GFP_KERNEL);
if (!gi)
@@ -1658,10 +1701,19 @@ static struct config_group *gadgets_make(
MKDEV(0, 0), NULL, "android0");
if (IS_ERR(android_device))
goto err;
+
+ dev_set_drvdata(android_device, gi);
+
+ attrs = android_usb_attributes;
+ while ((attr = *attrs++)) {
+ err = device_create_file(android_device, attr);
+ if (err)
+ goto err1;
+ }
#endif
if (!gi->composite.gadget_driver.function)
- goto err;
+ goto err1;
#ifdef CONFIG_USB_OTG
gi->otg.bLength = sizeof(struct usb_otg_descriptor);
@@ -1672,6 +1724,16 @@ static struct config_group *gadgets_make(
config_group_init_type_name(&gi->group, name,
&gadget_root_type);
return &gi->group;
+
+err1:
+#ifdef CONFIG_USB_CONFIGFS_UEVENT
+ attrs = android_usb_attributes;
+ while ((attr = *attrs++))
+ device_remove_file(android_device, attr);
+
+ device_destroy(android_device->class,
+ android_device->devt);
+#endif
err:
kfree(gi);
return ERR_PTR(-ENOMEM);
@@ -1679,8 +1741,15 @@ err:
static void gadgets_drop(struct config_group *group, struct config_item *item)
{
+ struct device_attribute **attrs;
+ struct device_attribute *attr;
+
config_item_put(item);
+
#ifdef CONFIG_USB_CONFIGFS_UEVENT
+ attrs = android_usb_attributes;
+ while ((attr = *attrs++))
+ device_remove_file(android_device, attr);
device_destroy(android_device->class, android_device->devt);
#endif
}
diff --git a/drivers/usb/gadget/function/f_mtp.c b/drivers/usb/gadget/function/f_mtp.c
index 82f6b2ebaebb..03a61f8b9d48 100644
--- a/drivers/usb/gadget/function/f_mtp.c
+++ b/drivers/usb/gadget/function/f_mtp.c
@@ -1426,8 +1426,24 @@ struct usb_function *function_alloc_mtp_ptp(struct usb_function_instance *fi,
bool mtp_config)
{
struct mtp_instance *fi_mtp = to_fi_mtp(fi);
- struct mtp_dev *dev = fi_mtp->dev;
+ struct mtp_dev *dev;
+
+ /*
+ * PTP piggybacks on MTP function so make sure we have
+ * created MTP function before we associate this PTP
+ * function with a gadget configuration.
+ */
+ if (fi_mtp->dev == NULL) {
+ pr_err("Error: Create MTP function before linking"
+ " PTP function with a gadget configuration\n");
+ pr_err("\t1: Delete existing PTP function if any\n");
+ pr_err("\t2: Create MTP function\n");
+ pr_err("\t3: Create and symlink PTP function"
+ " with a gadget configuration\n");
+ return NULL;
+ }
+ dev = fi_mtp->dev;
dev->function.name = DRIVER_NAME;
dev->function.strings = mtp_strings;
if (mtp_config) {
diff --git a/drivers/usb/gadget/functions.c b/drivers/usb/gadget/functions.c
index b13f839e7368..389c1f3d0fee 100644
--- a/drivers/usb/gadget/functions.c
+++ b/drivers/usb/gadget/functions.c
@@ -58,7 +58,7 @@ struct usb_function *usb_get_function(struct usb_function_instance *fi)
struct usb_function *f;
f = fi->fd->alloc_func(fi);
- if (IS_ERR(f))
+ if ((f == NULL) || IS_ERR(f))
return f;
f->fi = fi;
return f;
diff --git a/include/linux/initramfs.h b/include/linux/initramfs.h
new file mode 100644
index 000000000000..fc7da63b125b
--- /dev/null
+++ b/include/linux/initramfs.h
@@ -0,0 +1,32 @@
+/*
+ * include/linux/initramfs.h
+ *
+ * Copyright (C) 2015, Google
+ * Rom Lemarchand <romlem@android.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _LINUX_INITRAMFS_H
+#define _LINUX_INITRAMFS_H
+
+#include <linux/kconfig.h>
+
+#if IS_BUILTIN(CONFIG_BLK_DEV_INITRD)
+
+int __init default_rootfs(void);
+
+#endif
+
+#endif /* _LINUX_INITRAMFS_H */
diff --git a/init/Makefile b/init/Makefile
index 7bc47ee31c36..692b91f1c1d4 100644
--- a/init/Makefile
+++ b/init/Makefile
@@ -3,11 +3,8 @@
#
obj-y := main.o version.o mounts.o
-ifneq ($(CONFIG_BLK_DEV_INITRD),y)
obj-y += noinitramfs.o
-else
obj-$(CONFIG_BLK_DEV_INITRD) += initramfs.o
-endif
obj-$(CONFIG_GENERIC_CALIBRATE_DELAY) += calibrate.o
ifneq ($(CONFIG_ARCH_INIT_TASK),y)
diff --git a/init/initramfs.c b/init/initramfs.c
index ad1bd7787bbb..d39079e690fa 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -18,6 +18,7 @@
#include <linux/dirent.h>
#include <linux/syscalls.h>
#include <linux/utime.h>
+#include <linux/initramfs.h>
static ssize_t __init xwrite(int fd, const char *p, size_t count)
{
@@ -605,9 +606,25 @@ static void __init clean_rootfs(void)
}
#endif
+static int __initdata do_skip_initramfs;
+
+static int __init skip_initramfs_param(char *str)
+{
+ if (*str)
+ return 0;
+ do_skip_initramfs = 1;
+ return 1;
+}
+__setup("skip_initramfs", skip_initramfs_param);
+
static int __init populate_rootfs(void)
{
- char *err = unpack_to_rootfs(__initramfs_start, __initramfs_size);
+ char *err;
+
+ if (do_skip_initramfs)
+ return default_rootfs();
+
+ err = unpack_to_rootfs(__initramfs_start, __initramfs_size);
if (err)
panic("%s", err); /* Failed to decompress INTERNAL initramfs */
if (initrd_start) {
diff --git a/init/noinitramfs.c b/init/noinitramfs.c
index 267739d85179..bcc8bcb053ee 100644
--- a/init/noinitramfs.c
+++ b/init/noinitramfs.c
@@ -21,11 +21,16 @@
#include <linux/stat.h>
#include <linux/kdev_t.h>
#include <linux/syscalls.h>
+#include <linux/kconfig.h>
+#include <linux/initramfs.h>
/*
* Create a simple rootfs that is similar to the default initramfs
*/
-static int __init default_rootfs(void)
+#if !IS_BUILTIN(CONFIG_BLK_DEV_INITRD)
+static
+#endif
+int __init default_rootfs(void)
{
int err;
@@ -49,4 +54,6 @@ out:
printk(KERN_WARNING "Failed to create a rootfs\n");
return err;
}
+#if !IS_BUILTIN(CONFIG_BLK_DEV_INITRD)
rootfs_initcall(default_rootfs);
+#endif
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 12b3899ce908..30f180112922 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -2416,6 +2416,7 @@ retry_find_task:
cset = task_css_set(tsk);
list_add(&cset->mg_node, &tset.src_csets);
ret = cgroup_allow_attach(cgrp, &tset);
+ list_del(&tset.src_csets);
if (ret) {
rcu_read_unlock();
goto out_unlock_cgroup;