Commit e61ab4ae authored by Eric W. Biederman's avatar Eric W. Biederman Committed by Greg Kroah-Hartman

sysfs: Implement sysfs_getattr & sysfs_permission

With the implementation of sysfs_getattr and sysfs_permission
sysfs becomes able to lazily propogate inode attribute changes
from the sysfs_dirents to the vfs inodes.   This paves the way
for deleting significant chunks of now unnecessary code.

While doing this we did not reference sysfs_setattr from
sysfs_symlink_inode_operations so I added along with
sysfs_getattr and sysfs_permission.
Acked-by: default avatarTejun Heo <tj@kernel.org>
Acked-by: default avatarSerge Hallyn <serue@us.ibm.com>
Signed-off-by: default avatarEric W. Biederman <ebiederm@aristanetworks.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent c099aacd
...@@ -800,7 +800,9 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, ...@@ -800,7 +800,9 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
const struct inode_operations sysfs_dir_inode_operations = { const struct inode_operations sysfs_dir_inode_operations = {
.lookup = sysfs_lookup, .lookup = sysfs_lookup,
.permission = sysfs_permission,
.setattr = sysfs_setattr, .setattr = sysfs_setattr,
.getattr = sysfs_getattr,
.setxattr = sysfs_setxattr, .setxattr = sysfs_setxattr,
}; };
......
...@@ -37,7 +37,9 @@ static struct backing_dev_info sysfs_backing_dev_info = { ...@@ -37,7 +37,9 @@ static struct backing_dev_info sysfs_backing_dev_info = {
}; };
static const struct inode_operations sysfs_inode_operations ={ static const struct inode_operations sysfs_inode_operations ={
.permission = sysfs_permission,
.setattr = sysfs_setattr, .setattr = sysfs_setattr,
.getattr = sysfs_getattr,
.setxattr = sysfs_setxattr, .setxattr = sysfs_setxattr,
}; };
...@@ -196,7 +198,6 @@ static inline void set_default_inode_attr(struct inode * inode, mode_t mode) ...@@ -196,7 +198,6 @@ static inline void set_default_inode_attr(struct inode * inode, mode_t mode)
static inline void set_inode_attr(struct inode * inode, struct iattr * iattr) static inline void set_inode_attr(struct inode * inode, struct iattr * iattr)
{ {
inode->i_mode = iattr->ia_mode;
inode->i_uid = iattr->ia_uid; inode->i_uid = iattr->ia_uid;
inode->i_gid = iattr->ia_gid; inode->i_gid = iattr->ia_gid;
inode->i_atime = iattr->ia_atime; inode->i_atime = iattr->ia_atime;
...@@ -227,38 +228,56 @@ static int sysfs_count_nlink(struct sysfs_dirent *sd) ...@@ -227,38 +228,56 @@ static int sysfs_count_nlink(struct sysfs_dirent *sd)
return nr + 2; return nr + 2;
} }
static void sysfs_refresh_inode(struct sysfs_dirent *sd, struct inode *inode)
{
struct sysfs_inode_attrs *iattrs = sd->s_iattr;
inode->i_mode = sd->s_mode;
if (iattrs) {
/* sysfs_dirent has non-default attributes
* get them from persistent copy in sysfs_dirent
*/
set_inode_attr(inode, &iattrs->ia_iattr);
security_inode_notifysecctx(inode,
iattrs->ia_secdata,
iattrs->ia_secdata_len);
}
if (sysfs_type(sd) == SYSFS_DIR)
inode->i_nlink = sysfs_count_nlink(sd);
}
int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
{
struct sysfs_dirent *sd = dentry->d_fsdata;
struct inode *inode = dentry->d_inode;
mutex_lock(&sysfs_mutex);
sysfs_refresh_inode(sd, inode);
mutex_unlock(&sysfs_mutex);
generic_fillattr(inode, stat);
return 0;
}
static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
{ {
struct bin_attribute *bin_attr; struct bin_attribute *bin_attr;
struct sysfs_inode_attrs *iattrs;
inode->i_private = sysfs_get(sd); inode->i_private = sysfs_get(sd);
inode->i_mapping->a_ops = &sysfs_aops; inode->i_mapping->a_ops = &sysfs_aops;
inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
inode->i_op = &sysfs_inode_operations; inode->i_op = &sysfs_inode_operations;
inode->i_ino = sd->s_ino;
lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key); lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key);
iattrs = sd->s_iattr; set_default_inode_attr(inode, sd->s_mode);
if (iattrs) { sysfs_refresh_inode(sd, inode);
/* sysfs_dirent has non-default attributes
* get them for the new inode from persistent copy
* in sysfs_dirent
*/
set_inode_attr(inode, &iattrs->ia_iattr);
if (iattrs->ia_secdata)
security_inode_notifysecctx(inode,
iattrs->ia_secdata,
iattrs->ia_secdata_len);
} else
set_default_inode_attr(inode, sd->s_mode);
/* initialize inode according to type */ /* initialize inode according to type */
switch (sysfs_type(sd)) { switch (sysfs_type(sd)) {
case SYSFS_DIR: case SYSFS_DIR:
inode->i_op = &sysfs_dir_inode_operations; inode->i_op = &sysfs_dir_inode_operations;
inode->i_fop = &sysfs_dir_operations; inode->i_fop = &sysfs_dir_operations;
inode->i_nlink = sysfs_count_nlink(sd);
break; break;
case SYSFS_KOBJ_ATTR: case SYSFS_KOBJ_ATTR:
inode->i_size = PAGE_SIZE; inode->i_size = PAGE_SIZE;
...@@ -341,3 +360,14 @@ int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name) ...@@ -341,3 +360,14 @@ int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name)
else else
return -ENOENT; return -ENOENT;
} }
int sysfs_permission(struct inode *inode, int mask)
{
struct sysfs_dirent *sd = inode->i_private;
mutex_lock(&sysfs_mutex);
sysfs_refresh_inode(sd, inode);
mutex_unlock(&sysfs_mutex);
return generic_permission(inode, mask, NULL);
}
...@@ -214,6 +214,9 @@ const struct inode_operations sysfs_symlink_inode_operations = { ...@@ -214,6 +214,9 @@ const struct inode_operations sysfs_symlink_inode_operations = {
.readlink = generic_readlink, .readlink = generic_readlink,
.follow_link = sysfs_follow_link, .follow_link = sysfs_follow_link,
.put_link = sysfs_put_link, .put_link = sysfs_put_link,
.setattr = sysfs_setattr,
.getattr = sysfs_getattr,
.permission = sysfs_permission,
}; };
......
...@@ -156,7 +156,9 @@ static inline void __sysfs_put(struct sysfs_dirent *sd) ...@@ -156,7 +156,9 @@ static inline void __sysfs_put(struct sysfs_dirent *sd)
struct inode *sysfs_get_inode(struct sysfs_dirent *sd); struct inode *sysfs_get_inode(struct sysfs_dirent *sd);
void sysfs_delete_inode(struct inode *inode); void sysfs_delete_inode(struct inode *inode);
int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr); int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr);
int sysfs_permission(struct inode *inode, int mask);
int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat);
int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
size_t size, int flags); size_t size, int flags);
int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name); int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment