Blame view
fs/configfs/inode.c
7.7 KB
7063fbf22 [PATCH] configfs:... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
/* -*- mode: c; c-basic-offset: 8; -*- * vim: noexpandtab sw=8 ts=8 sts=0: * * inode.c - basic inode and dentry operations. * * 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; either * version 2 of the License, or (at your option) any later version. * * 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 021110-1307, USA. * * Based on sysfs: * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel * * configfs Copyright (C) 2005 Oracle. All rights reserved. * |
395cf9691 doc: fix broken r... |
26 27 |
* Please see Documentation/filesystems/configfs/configfs.txt for more * information. |
7063fbf22 [PATCH] configfs:... |
28 29 30 31 32 33 34 |
*/ #undef DEBUG #include <linux/pagemap.h> #include <linux/namei.h> #include <linux/backing-dev.h> |
3d0f89bb1 configfs: Add per... |
35 |
#include <linux/capability.h> |
e8edc6e03 Detach sched.h fr... |
36 |
#include <linux/sched.h> |
e74cc06df configfs: Silence... |
37 |
#include <linux/lockdep.h> |
5a0e3ad6a include cleanup: ... |
38 |
#include <linux/slab.h> |
7063fbf22 [PATCH] configfs:... |
39 40 41 |
#include <linux/configfs.h> #include "configfs_internal.h" |
e74cc06df configfs: Silence... |
42 43 44 |
#ifdef CONFIG_LOCKDEP static struct lock_class_key default_group_class[MAX_LOCK_DEPTH]; #endif |
7063fbf22 [PATCH] configfs:... |
45 |
extern struct super_block * configfs_sb; |
f5e54d6e5 [PATCH] mark addr... |
46 |
static const struct address_space_operations configfs_aops = { |
7063fbf22 [PATCH] configfs:... |
47 |
.readpage = simple_readpage, |
800d15a53 implement simple ... |
48 49 |
.write_begin = simple_write_begin, .write_end = simple_write_end, |
7063fbf22 [PATCH] configfs:... |
50 51 52 |
}; static struct backing_dev_info configfs_backing_dev_info = { |
d993831fa writeback: add na... |
53 |
.name = "configfs", |
7063fbf22 [PATCH] configfs:... |
54 |
.ra_pages = 0, /* No readahead */ |
e4ad08fe6 mm: bdi: add sepa... |
55 |
.capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK, |
7063fbf22 [PATCH] configfs:... |
56 |
}; |
754661f14 [PATCH] mark stru... |
57 |
static const struct inode_operations configfs_inode_operations ={ |
3d0f89bb1 configfs: Add per... |
58 59 60 61 62 63 64 65 66 67 68 69 70 |
.setattr = configfs_setattr, }; int configfs_setattr(struct dentry * dentry, struct iattr * iattr) { struct inode * inode = dentry->d_inode; struct configfs_dirent * sd = dentry->d_fsdata; struct iattr * sd_iattr; unsigned int ia_valid = iattr->ia_valid; int error; if (!sd) return -EINVAL; |
3322e79a3 fs: convert simpl... |
71 |
sd_iattr = sd->s_iattr; |
3d0f89bb1 configfs: Add per... |
72 73 |
if (!sd_iattr) { /* setting attributes for the first time, allocate now */ |
f8314dc60 [PATCH] fs: Conve... |
74 |
sd_iattr = kzalloc(sizeof(struct iattr), GFP_KERNEL); |
3d0f89bb1 configfs: Add per... |
75 76 77 |
if (!sd_iattr) return -ENOMEM; /* assign default attributes */ |
3d0f89bb1 configfs: Add per... |
78 79 80 81 82 83 |
sd_iattr->ia_mode = sd->s_mode; sd_iattr->ia_uid = 0; sd_iattr->ia_gid = 0; sd_iattr->ia_atime = sd_iattr->ia_mtime = sd_iattr->ia_ctime = CURRENT_TIME; sd->s_iattr = sd_iattr; } |
3d0f89bb1 configfs: Add per... |
84 |
/* attributes were changed atleast once in past */ |
75de46b98 fix setattr error... |
85 86 87 |
error = simple_setattr(dentry, iattr); if (error) return error; |
3d0f89bb1 configfs: Add per... |
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
if (ia_valid & ATTR_UID) sd_iattr->ia_uid = iattr->ia_uid; if (ia_valid & ATTR_GID) sd_iattr->ia_gid = iattr->ia_gid; if (ia_valid & ATTR_ATIME) sd_iattr->ia_atime = timespec_trunc(iattr->ia_atime, inode->i_sb->s_time_gran); if (ia_valid & ATTR_MTIME) sd_iattr->ia_mtime = timespec_trunc(iattr->ia_mtime, inode->i_sb->s_time_gran); if (ia_valid & ATTR_CTIME) sd_iattr->ia_ctime = timespec_trunc(iattr->ia_ctime, inode->i_sb->s_time_gran); if (ia_valid & ATTR_MODE) { umode_t mode = iattr->ia_mode; if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) mode &= ~S_ISGID; sd_iattr->ia_mode = sd->s_mode = mode; } return error; } |
439475140 configfs: convert... |
111 |
static inline void set_default_inode_attr(struct inode * inode, umode_t mode) |
3d0f89bb1 configfs: Add per... |
112 113 |
{ inode->i_mode = mode; |
3d0f89bb1 configfs: Add per... |
114 115 116 117 118 119 120 121 122 123 124 125 |
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; } 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_gid = iattr->ia_gid; inode->i_atime = iattr->ia_atime; inode->i_mtime = iattr->ia_mtime; inode->i_ctime = iattr->ia_ctime; } |
439475140 configfs: convert... |
126 |
struct inode *configfs_new_inode(umode_t mode, struct configfs_dirent * sd) |
7063fbf22 [PATCH] configfs:... |
127 128 129 |
{ struct inode * inode = new_inode(configfs_sb); if (inode) { |
85fe4025c fs: do not assign... |
130 |
inode->i_ino = get_next_ino(); |
7063fbf22 [PATCH] configfs:... |
131 132 |
inode->i_mapping->a_ops = &configfs_aops; inode->i_mapping->backing_dev_info = &configfs_backing_dev_info; |
3d0f89bb1 configfs: Add per... |
133 134 135 136 137 138 139 140 141 142 |
inode->i_op = &configfs_inode_operations; if (sd->s_iattr) { /* sysfs_dirent has non-default attributes * get them for the new inode from persistent copy * in sysfs_dirent */ set_inode_attr(inode, sd->s_iattr); } else set_default_inode_attr(inode, mode); |
7063fbf22 [PATCH] configfs:... |
143 144 145 |
} return inode; } |
e74cc06df configfs: Silence... |
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
#ifdef CONFIG_LOCKDEP static void configfs_set_inode_lock_class(struct configfs_dirent *sd, struct inode *inode) { int depth = sd->s_depth; if (depth > 0) { if (depth <= ARRAY_SIZE(default_group_class)) { lockdep_set_class(&inode->i_mutex, &default_group_class[depth - 1]); } else { /* * In practice the maximum level of locking depth is * already reached. Just inform about possible reasons. */ printk(KERN_INFO "configfs: Too many levels of inodes" " for the locking correctness validator. "); printk(KERN_INFO "Spurious warnings may appear. "); } } } #else /* CONFIG_LOCKDEP */ static void configfs_set_inode_lock_class(struct configfs_dirent *sd, struct inode *inode) { } #endif /* CONFIG_LOCKDEP */ |
439475140 configfs: convert... |
179 |
int configfs_create(struct dentry * dentry, umode_t mode, int (*init)(struct inode *)) |
7063fbf22 [PATCH] configfs:... |
180 181 182 183 184 |
{ int error = 0; struct inode * inode = NULL; if (dentry) { if (!dentry->d_inode) { |
3d0f89bb1 configfs: Add per... |
185 186 |
struct configfs_dirent *sd = dentry->d_fsdata; if ((inode = configfs_new_inode(mode, sd))) { |
7063fbf22 [PATCH] configfs:... |
187 188 189 190 |
if (dentry->d_parent && dentry->d_parent->d_inode) { struct inode *p_inode = dentry->d_parent->d_inode; p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME; } |
e74cc06df configfs: Silence... |
191 |
configfs_set_inode_lock_class(sd, inode); |
7063fbf22 [PATCH] configfs:... |
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
goto Proceed; } else error = -ENOMEM; } else error = -EEXIST; } else error = -ENOENT; goto Done; Proceed: if (init) error = init(inode); if (!error) { d_instantiate(dentry, inode); if (S_ISDIR(mode) || S_ISLNK(mode)) dget(dentry); /* pin link and directory dentries in core */ } else iput(inode); Done: return error; } /* * Get the name for corresponding element represented by the given configfs_dirent */ const unsigned char * configfs_get_name(struct configfs_dirent *sd) { |
3d0f89bb1 configfs: Add per... |
220 |
struct configfs_attribute *attr; |
7063fbf22 [PATCH] configfs:... |
221 |
|
1a1974fd4 [PATCH] BUG_ON() ... |
222 |
BUG_ON(!sd || !sd->s_element); |
7063fbf22 [PATCH] configfs:... |
223 224 225 226 227 228 229 |
/* These always have a dentry, so use that */ if (sd->s_type & (CONFIGFS_DIR | CONFIGFS_ITEM_LINK)) return sd->s_dentry->d_name.name; if (sd->s_type & CONFIGFS_ITEM_ATTR) { attr = sd->s_element; |
3d0f89bb1 configfs: Add per... |
230 |
return attr->ca_name; |
7063fbf22 [PATCH] configfs:... |
231 232 233 234 235 236 237 |
} return NULL; } /* * Unhashes the dentry corresponding to given configfs_dirent |
1b1dcc1b5 [PATCH] mutex sub... |
238 |
* Called with parent inode's i_mutex held. |
7063fbf22 [PATCH] configfs:... |
239 240 241 242 243 244 |
*/ void configfs_drop_dentry(struct configfs_dirent * sd, struct dentry * parent) { struct dentry * dentry = sd->s_dentry; if (dentry) { |
3d0f89bb1 configfs: Add per... |
245 |
spin_lock(&dentry->d_lock); |
7063fbf22 [PATCH] configfs:... |
246 |
if (!(d_unhashed(dentry) && dentry->d_inode)) { |
dc0474be3 fs: dcache ration... |
247 |
dget_dlock(dentry); |
7063fbf22 [PATCH] configfs:... |
248 |
__d_drop(dentry); |
3d0f89bb1 configfs: Add per... |
249 |
spin_unlock(&dentry->d_lock); |
7063fbf22 [PATCH] configfs:... |
250 |
simple_unlink(parent->d_inode, dentry); |
b5c84bf6f fs: dcache remove... |
251 |
} else |
3d0f89bb1 configfs: Add per... |
252 |
spin_unlock(&dentry->d_lock); |
7063fbf22 [PATCH] configfs:... |
253 254 255 256 257 258 259 |
} } void configfs_hash_and_remove(struct dentry * dir, const char * name) { struct configfs_dirent * sd; struct configfs_dirent * parent_sd = dir->d_fsdata; |
3d0f89bb1 configfs: Add per... |
260 261 262 |
if (dir->d_inode == NULL) /* no inode means this hasn't been made visible yet */ return; |
1b1dcc1b5 [PATCH] mutex sub... |
263 |
mutex_lock(&dir->d_inode->i_mutex); |
7063fbf22 [PATCH] configfs:... |
264 265 266 267 |
list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { if (!sd->s_element) continue; if (!strcmp(configfs_get_name(sd), name)) { |
6f6107640 configfs: Introdu... |
268 |
spin_lock(&configfs_dirent_lock); |
7063fbf22 [PATCH] configfs:... |
269 |
list_del_init(&sd->s_sibling); |
6f6107640 configfs: Introdu... |
270 |
spin_unlock(&configfs_dirent_lock); |
7063fbf22 [PATCH] configfs:... |
271 272 273 274 275 |
configfs_drop_dentry(sd, dir); configfs_put(sd); break; } } |
1b1dcc1b5 [PATCH] mutex sub... |
276 |
mutex_unlock(&dir->d_inode->i_mutex); |
7063fbf22 [PATCH] configfs:... |
277 |
} |
e0bf68dde mm: bdi init hooks |
278 279 280 281 |
int __init configfs_inode_init(void) { return bdi_init(&configfs_backing_dev_info); } |
7063fbf22 [PATCH] configfs:... |
282 |
|
7c6455e36 configfs: registe... |
283 |
void configfs_inode_exit(void) |
e0bf68dde mm: bdi init hooks |
284 285 286 |
{ bdi_destroy(&configfs_backing_dev_info); } |