diff options
| author | Jeff Garzik <jgarzik@pretzel.yyz.us> | 2005-06-22 21:50:57 -0400 |
|---|---|---|
| committer | Jeff Garzik <jgarzik@pobox.com> | 2005-06-22 21:50:57 -0400 |
| commit | a5324343955997d1439f26518ddac567cd5d134b (patch) | |
| tree | f43558389c41e3a0f076c4ee55d77c4aa1561779 /fs/sysfs/inode.c | |
| parent | 8199d3a79c224bbe5943fa08684e1f93a17881b0 (diff) | |
| parent | a4936044001694f033fe4ea94d6034d51a6b465c (diff) | |
Merge /spare/repo/linux-2.6/
Diffstat (limited to 'fs/sysfs/inode.c')
| -rw-r--r-- | fs/sysfs/inode.c | 102 |
1 files changed, 96 insertions, 6 deletions
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index aff7b2dfa8ee..565cac1d4200 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
| @@ -26,18 +26,107 @@ static struct backing_dev_info sysfs_backing_dev_info = { | |||
| 26 | .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, | 26 | .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, |
| 27 | }; | 27 | }; |
| 28 | 28 | ||
| 29 | struct inode * sysfs_new_inode(mode_t mode) | 29 | static struct inode_operations sysfs_inode_operations ={ |
| 30 | .setattr = sysfs_setattr, | ||
| 31 | }; | ||
| 32 | |||
| 33 | int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) | ||
| 34 | { | ||
| 35 | struct inode * inode = dentry->d_inode; | ||
| 36 | struct sysfs_dirent * sd = dentry->d_fsdata; | ||
| 37 | struct iattr * sd_iattr; | ||
| 38 | unsigned int ia_valid = iattr->ia_valid; | ||
| 39 | int error; | ||
| 40 | |||
| 41 | if (!sd) | ||
| 42 | return -EINVAL; | ||
| 43 | |||
| 44 | sd_iattr = sd->s_iattr; | ||
| 45 | |||
| 46 | error = inode_change_ok(inode, iattr); | ||
| 47 | if (error) | ||
| 48 | return error; | ||
| 49 | |||
| 50 | error = inode_setattr(inode, iattr); | ||
| 51 | if (error) | ||
| 52 | return error; | ||
| 53 | |||
| 54 | if (!sd_iattr) { | ||
| 55 | /* setting attributes for the first time, allocate now */ | ||
| 56 | sd_iattr = kmalloc(sizeof(struct iattr), GFP_KERNEL); | ||
| 57 | if (!sd_iattr) | ||
| 58 | return -ENOMEM; | ||
| 59 | /* assign default attributes */ | ||
| 60 | memset(sd_iattr, 0, sizeof(struct iattr)); | ||
| 61 | sd_iattr->ia_mode = sd->s_mode; | ||
| 62 | sd_iattr->ia_uid = 0; | ||
| 63 | sd_iattr->ia_gid = 0; | ||
| 64 | sd_iattr->ia_atime = sd_iattr->ia_mtime = sd_iattr->ia_ctime = CURRENT_TIME; | ||
| 65 | sd->s_iattr = sd_iattr; | ||
| 66 | } | ||
| 67 | |||
| 68 | /* attributes were changed atleast once in past */ | ||
| 69 | |||
| 70 | if (ia_valid & ATTR_UID) | ||
| 71 | sd_iattr->ia_uid = iattr->ia_uid; | ||
| 72 | if (ia_valid & ATTR_GID) | ||
| 73 | sd_iattr->ia_gid = iattr->ia_gid; | ||
| 74 | if (ia_valid & ATTR_ATIME) | ||
| 75 | sd_iattr->ia_atime = timespec_trunc(iattr->ia_atime, | ||
| 76 | inode->i_sb->s_time_gran); | ||
| 77 | if (ia_valid & ATTR_MTIME) | ||
| 78 | sd_iattr->ia_mtime = timespec_trunc(iattr->ia_mtime, | ||
| 79 | inode->i_sb->s_time_gran); | ||
| 80 | if (ia_valid & ATTR_CTIME) | ||
| 81 | sd_iattr->ia_ctime = timespec_trunc(iattr->ia_ctime, | ||
| 82 | inode->i_sb->s_time_gran); | ||
| 83 | if (ia_valid & ATTR_MODE) { | ||
| 84 | umode_t mode = iattr->ia_mode; | ||
| 85 | |||
| 86 | if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) | ||
| 87 | mode &= ~S_ISGID; | ||
| 88 | sd_iattr->ia_mode = mode; | ||
| 89 | } | ||
| 90 | |||
| 91 | return error; | ||
| 92 | } | ||
| 93 | |||
| 94 | static inline void set_default_inode_attr(struct inode * inode, mode_t mode) | ||
| 95 | { | ||
| 96 | inode->i_mode = mode; | ||
| 97 | inode->i_uid = 0; | ||
| 98 | inode->i_gid = 0; | ||
| 99 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
| 100 | } | ||
| 101 | |||
| 102 | static inline void set_inode_attr(struct inode * inode, struct iattr * iattr) | ||
| 103 | { | ||
| 104 | inode->i_mode = iattr->ia_mode; | ||
| 105 | inode->i_uid = iattr->ia_uid; | ||
| 106 | inode->i_gid = iattr->ia_gid; | ||
| 107 | inode->i_atime = iattr->ia_atime; | ||
| 108 | inode->i_mtime = iattr->ia_mtime; | ||
| 109 | inode->i_ctime = iattr->ia_ctime; | ||
| 110 | } | ||
| 111 | |||
| 112 | struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent * sd) | ||
| 30 | { | 113 | { |
| 31 | struct inode * inode = new_inode(sysfs_sb); | 114 | struct inode * inode = new_inode(sysfs_sb); |
| 32 | if (inode) { | 115 | if (inode) { |
| 33 | inode->i_mode = mode; | ||
| 34 | inode->i_uid = 0; | ||
| 35 | inode->i_gid = 0; | ||
| 36 | inode->i_blksize = PAGE_CACHE_SIZE; | 116 | inode->i_blksize = PAGE_CACHE_SIZE; |
| 37 | inode->i_blocks = 0; | 117 | inode->i_blocks = 0; |
| 38 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
| 39 | inode->i_mapping->a_ops = &sysfs_aops; | 118 | inode->i_mapping->a_ops = &sysfs_aops; |
| 40 | inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; | 119 | inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; |
| 120 | inode->i_op = &sysfs_inode_operations; | ||
| 121 | |||
| 122 | if (sd->s_iattr) { | ||
| 123 | /* sysfs_dirent has non-default attributes | ||
| 124 | * get them for the new inode from persistent copy | ||
| 125 | * in sysfs_dirent | ||
| 126 | */ | ||
| 127 | set_inode_attr(inode, sd->s_iattr); | ||
| 128 | } else | ||
| 129 | set_default_inode_attr(inode, mode); | ||
| 41 | } | 130 | } |
| 42 | return inode; | 131 | return inode; |
| 43 | } | 132 | } |
| @@ -48,7 +137,8 @@ int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *)) | |||
| 48 | struct inode * inode = NULL; | 137 | struct inode * inode = NULL; |
| 49 | if (dentry) { | 138 | if (dentry) { |
| 50 | if (!dentry->d_inode) { | 139 | if (!dentry->d_inode) { |
| 51 | if ((inode = sysfs_new_inode(mode))) { | 140 | struct sysfs_dirent * sd = dentry->d_fsdata; |
| 141 | if ((inode = sysfs_new_inode(mode, sd))) { | ||
| 52 | if (dentry->d_parent && dentry->d_parent->d_inode) { | 142 | if (dentry->d_parent && dentry->d_parent->d_inode) { |
| 53 | struct inode *p_inode = dentry->d_parent->d_inode; | 143 | struct inode *p_inode = dentry->d_parent->d_inode; |
| 54 | p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME; | 144 | p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME; |
