Commit f58df54a authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6

* 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
......@@ -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();
}
......@@ -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)
{
char *path;
struct nameidata nd;
int err = 0;
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);
int err;
path_put(&nd.path);
} else if (err == -ENOENT) {
read_lock(&dirlock);
err = dev_mkdir(nodepath, 0755);
if (err == -ENOENT) {
char *path;
char *s;
/* parent directories do not exist, create them */
path = kstrdup(nodepath, GFP_KERNEL);
if (!path)
return -ENOMEM;
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);
}
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;
}
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);
else
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);
......
......@@ -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);
}
fw_work->cont(fw, fw_work->context);
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;
......
......@@ -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
epdrv->requested_id = EARLY_PLATFORM_ID_ERROR;
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;
......
......@@ -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
......
......@@ -44,9 +44,20 @@ struct ilo_hwinfo {
struct pci_dev *ilo_dev;
/*
* open_lock serializes ccb_cnt during open and close
* [ irq disabled ]
* -> alloc_lock used when adding/removing/searching ccb_alloc,
* which represents all ccbs open on the device
* --> fifo_lock controls access to fifo queues shared with hw
*
* Locks must be taken in this order, but open_lock and alloc_lock
* are optional, they do not need to be held in order to take a
* lower level lock.
*/
spinlock_t open_lock;
spinlock_t alloc_lock;
spinlock_t fifo_lock;
spinlock_t open_lock;
struct cdev cdev;
};
......
......@@ -1179,16 +1179,18 @@ static void uart_firmware_cont(const struct firmware *fw, void *context)
if (firmware->header.length != fw->size) {
dev_err(dev, "invalid firmware\n");
return;
goto out;
}
ret = qe_upload_firmware(firmware);
if (ret) {
dev_err(dev, "could not load firmware\n");
return;
goto out;
}
firmware_loaded = 1;
out:
release_firmware(fw);
}
static int ucc_uart_probe(struct of_device *ofdev,
......@@ -1247,7 +1249,7 @@ static int ucc_uart_probe(struct of_device *ofdev,
*/
ret = request_firmware_nowait(THIS_MODULE,
FW_ACTION_HOTPLUG, filename, &ofdev->dev,
&ofdev->dev, uart_firmware_cont);
GFP_KERNEL, &ofdev->dev, uart_firmware_cont);
if (ret) {
dev_err(&ofdev->dev,
"could not load firmware %s\n",
......
......@@ -2327,9 +2327,11 @@ static void usbdux_firmware_request_complete_handler(const struct firmware *fw,
if (ret) {
dev_err(&usbdev->dev,
"Could not upload firmware (err=%d)\n", ret);
return;
goto out;
}
comedi_usb_auto_config(usbdev, BOARDNAME);
out:
release_firmware(fw);
}
/* allocate memory for the urbs and initialise them */
......@@ -2580,6 +2582,7 @@ static int usbduxsub_probe(struct usb_interface *uinterf,
FW_ACTION_HOTPLUG,
"usbdux_firmware.bin",
&udev->dev,
GFP_KERNEL,
usbduxsub + index,
usbdux_firmware_request_complete_handler);
......
......@@ -1451,10 +1451,12 @@ static void usbduxfast_firmware_request_complete_handler(const struct firmware
if (ret) {
dev_err(&usbdev->dev,
"Could not upload firmware (err=%d)\n", ret);
return;
goto out;
}
comedi_usb_auto_config(usbdev, BOARDNAME);
out:
release_firmware(fw);
}
/*
......@@ -1569,6 +1571,7 @@ static int usbduxfastsub_probe(struct usb_interface *uinterf,
FW_ACTION_HOTPLUG,
"usbduxfast_firmware.bin",
&udev->dev,
GFP_KERNEL,
usbduxfastsub + index,
usbduxfast_firmware_request_complete_handler);
......
......@@ -667,12 +667,12 @@ static void uea_upload_pre_firmware(const struct firmware *fw_entry, void *conte
else
uea_info(usb, "firmware uploaded\n");
uea_leaves(usb);
return;
goto err;
err_fw_corrupted:
uea_err(usb, "firmware is corrupted\n");
err:
release_firmware(fw_entry);
uea_leaves(usb);
}
......@@ -705,7 +705,8 @@ static int uea_load_firmware(struct usb_device *usb, unsigned int ver)
break;
}
ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev, usb, uea_upload_pre_firmware);
ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev,
GFP_KERNEL, usb, uea_upload_pre_firmware);
if (ret)
uea_err(usb, "firmware %s is not available\n", fw_name);
else
......
......@@ -32,7 +32,9 @@ static struct vfsmount *debugfs_mount;
static int debugfs_mount_count;
static bool debugfs_registered;
static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t dev)
static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t dev,
void *data, const struct file_operations *fops)
{
struct inode *inode = new_inode(sb);
......@@ -44,14 +46,18 @@ static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t d
init_special_inode(inode, mode, dev);
break;
case S_IFREG:
inode->i_fop = &debugfs_file_operations;
inode->i_fop = fops ? fops : &debugfs_file_operations;
inode->i_private = data;
break;
case S_IFLNK:
inode->i_op = &debugfs_link_operations;
inode->i_fop = fops;
inode->i_private = data;
break;
case S_IFDIR:
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
inode->i_fop = fops ? fops : &simple_dir_operations;
inode->i_private = data;
/* directory inodes start off with i_nlink == 2
* (for "." entry) */
......@@ -64,7 +70,8 @@ static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t d
/* SMP-safe */
static int debugfs_mknod(struct inode *dir, struct dentry *dentry,
int mode, dev_t dev)
int mode, dev_t dev, void *data,
const struct file_operations *fops)
{
struct inode *inode;
int error = -EPERM;
......@@ -72,7 +79,7 @@ static int debugfs_mknod(struct inode *dir, struct dentry *dentry,
if (dentry->d_inode)
return -EEXIST;
inode = debugfs_get_inode(dir->i_sb, mode, dev);
inode = debugfs_get_inode(dir->i_sb, mode, dev, data, fops);
if (inode) {
d_instantiate(dentry, inode);
dget(dentry);
......@@ -81,12 +88,13 @@ static int debugfs_mknod(struct inode *dir, struct dentry *dentry,
return error;
}
static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode,
void *data, const struct file_operations *fops)
{
int res;
mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
res = debugfs_mknod(dir, dentry, mode, 0);
res = debugfs_mknod(dir, dentry, mode, 0, data, fops);
if (!res) {
inc_nlink(dir);
fsnotify_mkdir(dir, dentry);
......@@ -94,18 +102,20 @@ static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
return res;
}
static int debugfs_link(struct inode *dir, struct dentry *dentry, int mode)
static int debugfs_link(struct inode *dir, struct dentry *dentry, int mode,
void *data, const struct file_operations *fops)
{
mode = (mode & S_IALLUGO) | S_IFLNK;
return debugfs_mknod(dir, dentry, mode, 0);
return debugfs_mknod(dir, dentry, mode, 0, data, fops);
}
static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode)
static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode,
void *data, const struct file_operations *fops)
{
int res;
mode = (mode & S_IALLUGO) | S_IFREG;
res = debugfs_mknod(dir, dentry, mode, 0);
res = debugfs_mknod(dir, dentry, mode, 0, data, fops);
if (!res)
fsnotify_create(dir, dentry);
return res;
......@@ -139,7 +149,9 @@ static struct file_system_type debug_fs_type = {
static int debugfs_create_by_name(const char *name, mode_t mode,
struct dentry *parent,
struct dentry **dentry)
struct dentry **dentry,
void *data,
const struct file_operations *fops)
{
int error = 0;
......@@ -164,13 +176,16 @@ static int debugfs_create_by_name(const char *name, mode_t mode,
if (!IS_ERR(*dentry)) {
switch (mode & S_IFMT) {
case S_IFDIR:
error = debugfs_mkdir(parent->d_inode, *dentry, mode);
error = debugfs_mkdir(parent->d_inode, *dentry, mode,
data, fops);
break;
case S_IFLNK:
error = debugfs_link(parent->d_inode, *dentry, mode);
error = debugfs_link(parent->d_inode, *dentry, mode,
data, fops);
break;
default:
error = debugfs_create(parent->d_inode, *dentry, mode);
error = debugfs_create(parent->d_inode, *dentry, mode,
data, fops);
break;
}
dput(*dentry);
......@@ -221,19 +236,13 @@ struct dentry *debugfs_create_file(const char *name, mode_t mode,
if (error)
goto exit;
error = debugfs_create_by_name(name, mode, parent, &dentry);
error = debugfs_create_by_name(name, mode, parent, &dentry,
data, fops);
if (error) {
dentry = NULL;
simple_release_fs(&debugfs_mount, &debugfs_mount_count);
goto exit;
}
if (dentry->d_inode) {
if (data)
dentry->d_inode->i_private = data;
if (fops)
dentry->d_inode->i_fop = fops;
}
exit:
return dentry;
}
......
......@@ -1279,28 +1279,6 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
return __lookup_hash(&this, base, NULL);
}
/**
* lookup_one_noperm - bad hack for sysfs
* @name: pathname component to lookup
* @base: base directory to lookup from
*
* This is a variant of lookup_one_len that doesn't perform any permission
* checks. It's a horrible hack to work around the braindead sysfs
* architecture and should not be used anywhere else.
*
* DON'T USE THIS FUNCTION EVER, thanks.
*/
struct dentry *lookup_one_noperm(const char *name, struct dentry *base)
{
int err;
struct qstr this;
err = __lookup_one_len(name, &this, base, strlen(name));
if (err)
return ERR_PTR(err);
return __lookup_hash(&this, base, NULL);
}
int user_path_at(int dfd, const char __user *name, unsigned flags,
struct path *path)
{
......
This diff is collapsed.
......@@ -579,46 +579,23 @@ EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
*/
int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode)
{
struct sysfs_dirent *victim_sd = NULL;
struct dentry *victim = NULL;
struct inode * inode;
struct sysfs_dirent *sd;
struct iattr newattrs;
int rc;
rc = -ENOENT;
victim_sd = sysfs_get_dirent(kobj->sd, attr->name);
if (!victim_sd)
goto out;
mutex_lock(&sysfs_mutex);
mutex_lock(&sysfs_rename_mutex);
victim = sysfs_get_dentry(victim_sd);
mutex_unlock(&sysfs_rename_mutex);
if (IS_ERR(victim)) {
rc = PTR_ERR(victim);
victim = NULL;
rc = -ENOENT;
sd = sysfs_find_dirent(kobj->sd, attr->name);
if (!sd)
goto out;
}
inode = victim->d_inode;
mutex_lock(&inode->i_mutex);
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
newattrs.ia_ctime = current_fs_time(inode->i_sb);
rc = sysfs_setattr(victim, &newattrs);
newattrs.ia_mode = (mode & S_IALLUGO) | (sd->s_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE;
rc = sysfs_sd_setattr(sd, &newattrs);
if (rc == 0) {
fsnotify_change(victim, newattrs.ia_valid);
mutex_lock(&sysfs_mutex);
victim_sd->s_mode = newattrs.ia_mode;
mutex_unlock(&sysfs_mutex);
}
mutex_unlock(&inode->i_mutex);
out:
dput(victim);
sysfs_put(victim_sd);
mutex_unlock(&sysfs_mutex);
return rc;
}
EXPORT_SYMBOL_GPL(sysfs_chmod_file);
......
......@@ -37,7 +37,9 @@ static struct backing_dev_info sysfs_backing_dev_info = {