Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f58df54a authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6: (27 commits)
  Driver core: fix race in dev_driver_string
  Driver Core: Early platform driver buffer
  sysfs: sysfs_setattr remove unnecessary permission check.
  sysfs: Factor out sysfs_rename from sysfs_rename_dir and sysfs_move_dir
  sysfs: Propagate renames to the vfs on demand
  sysfs: Gut sysfs_addrm_start and sysfs_addrm_finish
  sysfs: In sysfs_chmod_file lazily propagate the mode change.
  sysfs: Implement sysfs_getattr & sysfs_permission
  sysfs: Nicely indent sysfs_symlink_inode_operations
  sysfs: Update s_iattr on link and unlink.
  sysfs: Fix locking and factor out sysfs_sd_setattr
  sysfs: Simplify iattr time assignments
  sysfs: Simplify sysfs_chmod_file semantics
  sysfs: Use dentry_ops instead of directly playing with the dcache
  sysfs: Rename sysfs_d_iput to sysfs_dentry_iput
  sysfs: Update sysfs_setxattr so it updates secdata under the sysfs_mutex
  debugfs: fix create mutex racy fops and private data
  Driver core: Don't remove kobjects in device_shutdown.
  firmware_class: make request_firmware_nowait more useful
  Driver-Core: devtmpfs - set root directory mode to 0755
  ...
parents 748e566b 3589972e
Loading
Loading
Loading
Loading
+10 −4
Original line number Diff line number Diff line
@@ -56,7 +56,14 @@ static inline int device_is_not_partition(struct device *dev)
 */
const char *dev_driver_string(const struct device *dev)
{
	return dev->driver ? dev->driver->name :
	struct device_driver *drv;

	/* dev->driver can change to NULL underneath us because of unbinding,
	 * so be careful about accessing it.  dev->bus and dev->class should
	 * never change once they are set, so they don't need special care.
	 */
	drv = ACCESS_ONCE(dev->driver);
	return drv ? drv->name :
			(dev->bus ? dev->bus->name :
			(dev->class ? dev->class->name : ""));
}
@@ -986,6 +993,8 @@ int device_add(struct device *dev)
 AttrsError:
	device_remove_class_symlinks(dev);
 SymlinkError:
	if (MAJOR(dev->devt))
		devtmpfs_delete_node(dev);
	if (MAJOR(dev->devt))
		device_remove_sys_dev_entry(dev);
 devtattrError:
@@ -1728,8 +1737,5 @@ void device_shutdown(void)
			dev->driver->shutdown(dev);
		}
	}
	kobject_put(sysfs_dev_char_kobj);
	kobject_put(sysfs_dev_block_kobj);
	kobject_put(dev_kobj);
	async_synchronize_full();
}
+50 −50
Original line number Diff line number Diff line
@@ -32,6 +32,8 @@ static int dev_mount = 1;
static int dev_mount;
#endif

static rwlock_t dirlock;

static int __init mount_param(char *str)
{
	dev_mount = simple_strtoul(str, NULL, 0);
@@ -74,47 +76,35 @@ static int dev_mkdir(const char *name, mode_t mode)
	dentry = lookup_create(&nd, 1);
	if (!IS_ERR(dentry)) {
		err = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode);
		if (!err)
			/* mark as kernel-created inode */
			dentry->d_inode->i_private = &dev_mnt;
		dput(dentry);
	} else {
		err = PTR_ERR(dentry);
	}
	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);

	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
	path_put(&nd.path);
	return err;
}

static int create_path(const char *nodepath)
{
	int err;

	read_lock(&dirlock);
	err = dev_mkdir(nodepath, 0755);
	if (err == -ENOENT) {
		char *path;
	struct nameidata nd;
	int err = 0;
		char *s;

		/* parent directories do not exist, create them */
		path = kstrdup(nodepath, GFP_KERNEL);
		if (!path)
			return -ENOMEM;

	err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
			      path, LOOKUP_PARENT, &nd);
	if (err == 0) {
		struct dentry *dentry;

		/* create directory right away */
		dentry = lookup_create(&nd, 1);
		if (!IS_ERR(dentry)) {
			err = vfs_mkdir(nd.path.dentry->d_inode,
					dentry, 0755);
			dput(dentry);
		}
		mutex_unlock(&nd.path.dentry->d_inode->i_mutex);

		path_put(&nd.path);
	} else if (err == -ENOENT) {
		char *s;

		/* parent directories do not exist, create them */
		s = path;
		while (1) {
		for (;;) {
			s = strchr(s, '/');
			if (!s)
				break;
@@ -125,9 +115,9 @@ static int create_path(const char *nodepath)
			s[0] = '/';
			s++;
		}
	}

		kfree(path);
	}
	read_unlock(&dirlock);
	return err;
}

@@ -156,34 +146,40 @@ int devtmpfs_create_node(struct device *dev)
		mode |= S_IFCHR;

	curr_cred = override_creds(&init_cred);

	err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
			      nodename, LOOKUP_PARENT, &nd);
	if (err == -ENOENT) {
		/* create missing parent directories */
		create_path(nodename);
		err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
				      nodename, LOOKUP_PARENT, &nd);
	}
	if (err)
		goto out;
	}

	dentry = lookup_create(&nd, 0);
	if (!IS_ERR(dentry)) {
		int umask;

		umask = sys_umask(0000);
		err = vfs_mknod(nd.path.dentry->d_inode,
				dentry, mode, dev->devt);
		sys_umask(umask);
		/* mark as kernel created inode */
		if (!err)
		if (!err) {
			struct iattr newattrs;

			/* fixup possibly umasked mode */
			newattrs.ia_mode = mode;
			newattrs.ia_valid = ATTR_MODE;
			mutex_lock(&dentry->d_inode->i_mutex);
			notify_change(dentry, &newattrs);
			mutex_unlock(&dentry->d_inode->i_mutex);

			/* mark as kernel-created inode */
			dentry->d_inode->i_private = &dev_mnt;
		}
		dput(dentry);
	} else {
		err = PTR_ERR(dentry);
	}
	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);

	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
	path_put(&nd.path);
out:
	kfree(tmp);
@@ -205,16 +201,21 @@ static int dev_rmdir(const char *name)
	mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
	dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
	if (!IS_ERR(dentry)) {
		if (dentry->d_inode)
			err = vfs_rmdir(nd.path.dentry->d_inode, dentry);
		if (dentry->d_inode) {
			if (dentry->d_inode->i_private == &dev_mnt)
				err = vfs_rmdir(nd.path.dentry->d_inode,
						dentry);
			else
				err = -EPERM;
		} else {
			err = -ENOENT;
		}
		dput(dentry);
	} else {
		err = PTR_ERR(dentry);
	}
	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);

	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
	path_put(&nd.path);
	return err;
}
@@ -228,7 +229,8 @@ static int delete_path(const char *nodepath)
	if (!path)
		return -ENOMEM;

	while (1) {
	write_lock(&dirlock);
	for (;;) {
		char *base;

		base = strrchr(path, '/');
@@ -239,6 +241,7 @@ static int delete_path(const char *nodepath)
		if (err)
			break;
	}
	write_unlock(&dirlock);

	kfree(path);
	return err;
@@ -322,9 +325,8 @@ int devtmpfs_delete_node(struct device *dev)
 * If configured, or requested by the commandline, devtmpfs will be
 * auto-mounted after the kernel mounted the root filesystem.
 */
int devtmpfs_mount(const char *mountpoint)
int devtmpfs_mount(const char *mntdir)
{
	struct path path;
	int err;

	if (!dev_mount)
@@ -333,15 +335,11 @@ int devtmpfs_mount(const char *mountpoint)
	if (!dev_mnt)
		return 0;

	err = kern_path(mountpoint, LOOKUP_FOLLOW, &path);
	if (err)
		return err;
	err = do_add_mount(dev_mnt, &path, 0, NULL);
	err = sys_mount("devtmpfs", (char *)mntdir, "devtmpfs", MS_SILENT, NULL);
	if (err)
		printk(KERN_INFO "devtmpfs: error mounting %i\n", err);
	else
		printk(KERN_INFO "devtmpfs: mounted\n");
	path_put(&path);
	return err;
}

@@ -354,6 +352,8 @@ int __init devtmpfs_init(void)
	int err;
	struct vfsmount *mnt;

	rwlock_init(&dirlock);

	err = register_filesystem(&dev_fs_type);
	if (err) {
		printk(KERN_ERR "devtmpfs: unable to register devtmpfs "
@@ -361,7 +361,7 @@ int __init devtmpfs_init(void)
		return err;
	}

	mnt = kern_mount(&dev_fs_type);
	mnt = kern_mount_data(&dev_fs_type, "mode=0755");
	if (IS_ERR(mnt)) {
		err = PTR_ERR(mnt);
		printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i\n", err);
+6 −8
Original line number Diff line number Diff line
@@ -601,12 +601,9 @@ request_firmware_work_func(void *arg)
	}
	ret = _request_firmware(&fw, fw_work->name, fw_work->device,
		fw_work->uevent);
	if (ret < 0)
		fw_work->cont(NULL, fw_work->context);
	else {

	fw_work->cont(fw, fw_work->context);
		release_firmware(fw);
	}

	module_put(fw_work->module);
	kfree(fw_work);
	return ret;
@@ -619,6 +616,7 @@ request_firmware_work_func(void *arg)
 *	is non-zero else the firmware copy must be done manually.
 * @name: name of firmware file
 * @device: device for which firmware is being loaded
 * @gfp: allocation flags
 * @context: will be passed over to @cont, and
 *	@fw may be %NULL if firmware request fails.
 * @cont: function will be called asynchronously when the firmware
@@ -631,12 +629,12 @@ request_firmware_work_func(void *arg)
int
request_firmware_nowait(
	struct module *module, int uevent,
	const char *name, struct device *device, void *context,
	const char *name, struct device *device, gfp_t gfp, void *context,
	void (*cont)(const struct firmware *fw, void *context))
{
	struct task_struct *task;
	struct firmware_work *fw_work = kmalloc(sizeof (struct firmware_work),
						GFP_ATOMIC);
						gfp);

	if (!fw_work)
		return -ENOMEM;
+22 −7
Original line number Diff line number Diff line
@@ -1000,7 +1000,7 @@ static __initdata LIST_HEAD(early_platform_device_list);
int __init early_platform_driver_register(struct early_platform_driver *epdrv,
					  char *buf)
{
	unsigned long index;
	char *tmp;
	int n;

	/* Simply add the driver to the end of the global list.
@@ -1019,13 +1019,28 @@ int __init early_platform_driver_register(struct early_platform_driver *epdrv,
	if (buf && !strncmp(buf, epdrv->pdrv->driver.name, n)) {
		list_move(&epdrv->list, &early_platform_driver_list);

		if (!strcmp(buf, epdrv->pdrv->driver.name))
		/* Allow passing parameters after device name */
		if (buf[n] == '\0' || buf[n] == ',')
			epdrv->requested_id = -1;
		else if (buf[n] == '.' && strict_strtoul(&buf[n + 1], 10,
							 &index) == 0)
			epdrv->requested_id = index;
		else
		else {
			epdrv->requested_id = simple_strtoul(&buf[n + 1],
							     &tmp, 10);

			if (buf[n] != '.' || (tmp == &buf[n + 1])) {
				epdrv->requested_id = EARLY_PLATFORM_ID_ERROR;
				n = 0;
			} else
				n += strcspn(&buf[n + 1], ",") + 1;
		}

		if (buf[n] == ',')
			n++;

		if (epdrv->bufsize) {
			memcpy(epdrv->buffer, &buf[n],
			       min_t(int, epdrv->bufsize, strlen(&buf[n]) + 1));
			epdrv->buffer[epdrv->bufsize - 1] = '\0';
		}
	}

	return 0;
+7 −2
Original line number Diff line number Diff line
@@ -544,9 +544,12 @@ static void callbackfn_rbu(const struct firmware *fw, void *context)
{
	rbu_data.entry_created = 0;

	if (!fw || !fw->size)
	if (!fw)
		return;

	if (!fw->size)
		goto out;

	spin_lock(&rbu_data.lock);
	if (!strcmp(image_type, "mono")) {
		if (!img_update_realloc(fw->size))
@@ -568,6 +571,8 @@ static void callbackfn_rbu(const struct firmware *fw, void *context)
	} else
		pr_debug("invalid image type specified.\n");
	spin_unlock(&rbu_data.lock);
 out:
	release_firmware(fw);
}

static ssize_t read_rbu_image_type(struct kobject *kobj,
@@ -615,7 +620,7 @@ static ssize_t write_rbu_image_type(struct kobject *kobj,
			spin_unlock(&rbu_data.lock);
			req_firm_rc = request_firmware_nowait(THIS_MODULE,
				FW_ACTION_NOHOTPLUG, "dell_rbu",
				&rbu_device->dev, &context,
				&rbu_device->dev, GFP_KERNEL, &context,
				callbackfn_rbu);
			if (req_firm_rc) {
				printk(KERN_ERR
Loading