1 /* 2 * dir.c - Operations for sysfs directories. 3 */ 4 5 #undef DEBUG 6 7 #include <linux/fs.h> 8 #include <linux/mount.h> 9 #include <linux/module.h> 10 #include <linux/kobject.h> 11 #include <linux/namei.h> 12 #include "sysfs.h" 13 14 DECLARE_RWSEM(sysfs_rename_sem); 15 16 static void sysfs_d_iput(struct dentry * dentry, struct inode * inode) 17 { 18 struct sysfs_dirent * sd = dentry->d_fsdata; 19 20 if (sd) { 21 BUG_ON(sd->s_dentry != dentry); 22 sd->s_dentry = NULL; 23 sysfs_put(sd); 24 } 25 iput(inode); 26 } 27 28 static struct dentry_operations sysfs_dentry_ops = { 29 .d_iput = sysfs_d_iput, 30 }; 31 32 /* 33 * Allocates a new sysfs_dirent and links it to the parent sysfs_dirent 34 */ 35 static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent * parent_sd, 36 void * element) 37 { 38 struct sysfs_dirent * sd; 39 40 sd = kmem_cache_alloc(sysfs_dir_cachep, GFP_KERNEL); 41 if (!sd) 42 return NULL; 43 44 memset(sd, 0, sizeof(*sd)); 45 atomic_set(&sd->s_count, 1); 46 atomic_set(&sd->s_event, 0); 47 INIT_LIST_HEAD(&sd->s_children); 48 list_add(&sd->s_sibling, &parent_sd->s_children); 49 sd->s_element = element; 50 51 return sd; 52 } 53 54 /* 55 * 56 * Return -EEXIST if there is already a sysfs element with the same name for 57 * the same parent. 58 * 59 * called with parent inode's i_mutex held 60 */ 61 int sysfs_dirent_exist(struct sysfs_dirent *parent_sd, 62 const unsigned char *new) 63 { 64 struct sysfs_dirent * sd; 65 66 list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { 67 if (sd->s_element) { 68 const unsigned char *existing = sysfs_get_name(sd); 69 if (strcmp(existing, new)) 70 continue; 71 else 72 return -EEXIST; 73 } 74 } 75 76 return 0; 77 } 78 79 80 int sysfs_make_dirent(struct sysfs_dirent * parent_sd, struct dentry * dentry, 81 void * element, umode_t mode, int type) 82 { 83 struct sysfs_dirent * sd; 84 85 sd = sysfs_new_dirent(parent_sd, element); 86 if (!sd) 87 return -ENOMEM; 88 89 sd->s_mode = mode; 90 sd->s_type = type; 91 sd->s_dentry = dentry; 92 if (dentry) { 93 dentry->d_fsdata = sysfs_get(sd); 94 dentry->d_op = &sysfs_dentry_ops; 95 } 96 97 return 0; 98 } 99 100 static int init_dir(struct inode * inode) 101 { 102 inode->i_op = &sysfs_dir_inode_operations; 103 inode->i_fop = &sysfs_dir_operations; 104 105 /* directory inodes start off with i_nlink == 2 (for "." entry) */ 106 inode->i_nlink++; 107 return 0; 108 } 109 110 static int init_file(struct inode * inode) 111 { 112 inode->i_size = PAGE_SIZE; 113 inode->i_fop = &sysfs_file_operations; 114 return 0; 115 } 116 117 static int init_symlink(struct inode * inode) 118 { 119 inode->i_op = &sysfs_symlink_inode_operations; 120 return 0; 121 } 122 123 static int create_dir(struct kobject * k, struct dentry * p, 124 const char * n, struct dentry ** d) 125 { 126 int error; 127 umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; 128 129 mutex_lock(&p->d_inode->i_mutex); 130 *d = lookup_one_len(n, p, strlen(n)); 131 if (!IS_ERR(*d)) { 132 if (sysfs_dirent_exist(p->d_fsdata, n)) 133 error = -EEXIST; 134 else 135 error = sysfs_make_dirent(p->d_fsdata, *d, k, mode, 136 SYSFS_DIR); 137 if (!error) { 138 error = sysfs_create(*d, mode, init_dir); 139 if (!error) { 140 p->d_inode->i_nlink++; 141 (*d)->d_op = &sysfs_dentry_ops; 142 d_rehash(*d); 143 } 144 } 145 if (error && (error != -EEXIST)) { 146 struct sysfs_dirent *sd = (*d)->d_fsdata; 147 if (sd) { 148 list_del_init(&sd->s_sibling); 149 sysfs_put(sd); 150 } 151 d_drop(*d); 152 } 153 dput(*d); 154 } else 155 error = PTR_ERR(*d); 156 mutex_unlock(&p->d_inode->i_mutex); 157 return error; 158 } 159 160 161 int sysfs_create_subdir(struct kobject * k, const char * n, struct dentry ** d) 162 { 163 return create_dir(k,k->dentry,n,d); 164 } 165 166 /** 167 * sysfs_create_dir - create a directory for an object. 168 * @parent: parent parent object. 169 * @kobj: object we're creating directory for. 170 */ 171 172 int sysfs_create_dir(struct kobject * kobj) 173 { 174 struct dentry * dentry = NULL; 175 struct dentry * parent; 176 int error = 0; 177 178 BUG_ON(!kobj); 179 180 if (kobj->parent) 181 parent = kobj->parent->dentry; 182 else if (sysfs_mount && sysfs_mount->mnt_sb) 183 parent = sysfs_mount->mnt_sb->s_root; 184 else 185 return -EFAULT; 186 187 error = create_dir(kobj,parent,kobject_name(kobj),&dentry); 188 if (!error) 189 kobj->dentry = dentry; 190 return error; 191 } 192 193 /* attaches attribute's sysfs_dirent to the dentry corresponding to the 194 * attribute file 195 */ 196 static int sysfs_attach_attr(struct sysfs_dirent * sd, struct dentry * dentry) 197 { 198 struct attribute * attr = NULL; 199 struct bin_attribute * bin_attr = NULL; 200 int (* init) (struct inode *) = NULL; 201 int error = 0; 202 203 if (sd->s_type & SYSFS_KOBJ_BIN_ATTR) { 204 bin_attr = sd->s_element; 205 attr = &bin_attr->attr; 206 } else { 207 attr = sd->s_element; 208 init = init_file; 209 } 210 211 dentry->d_fsdata = sysfs_get(sd); 212 sd->s_dentry = dentry; 213 error = sysfs_create(dentry, (attr->mode & S_IALLUGO) | S_IFREG, init); 214 if (error) { 215 sysfs_put(sd); 216 return error; 217 } 218 219 if (bin_attr) { 220 dentry->d_inode->i_size = bin_attr->size; 221 dentry->d_inode->i_fop = &bin_fops; 222 } 223 dentry->d_op = &sysfs_dentry_ops; 224 d_rehash(dentry); 225 226 return 0; 227 } 228 229 static int sysfs_attach_link(struct sysfs_dirent * sd, struct dentry * dentry) 230 { 231 int err = 0; 232 233 dentry->d_fsdata = sysfs_get(sd); 234 sd->s_dentry = dentry; 235 err = sysfs_create(dentry, S_IFLNK|S_IRWXUGO, init_symlink); 236 if (!err) { 237 dentry->d_op = &sysfs_dentry_ops; 238 d_rehash(dentry); 239 } else 240 sysfs_put(sd); 241 242 return err; 243 } 244 245 static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, 246 struct nameidata *nd) 247 { 248 struct sysfs_dirent * parent_sd = dentry->d_parent->d_fsdata; 249 struct sysfs_dirent * sd; 250 int err = 0; 251 252 list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { 253 if (sd->s_type & SYSFS_NOT_PINNED) { 254 const unsigned char * name = sysfs_get_name(sd); 255 256 if (strcmp(name, dentry->d_name.name)) 257 continue; 258 259 if (sd->s_type & SYSFS_KOBJ_LINK) 260 err = sysfs_attach_link(sd, dentry); 261 else 262 err = sysfs_attach_attr(sd, dentry); 263 break; 264 } 265 } 266 267 return ERR_PTR(err); 268 } 269 270 struct inode_operations sysfs_dir_inode_operations = { 271 .lookup = sysfs_lookup, 272 .setattr = sysfs_setattr, 273 }; 274 275 static void remove_dir(struct dentry * d) 276 { 277 struct dentry * parent = dget(d->d_parent); 278 struct sysfs_dirent * sd; 279 280 mutex_lock(&parent->d_inode->i_mutex); 281 d_delete(d); 282 sd = d->d_fsdata; 283 list_del_init(&sd->s_sibling); 284 sysfs_put(sd); 285 if (d->d_inode) 286 simple_rmdir(parent->d_inode,d); 287 288 pr_debug(" o %s removing done (%d)\n",d->d_name.name, 289 atomic_read(&d->d_count)); 290 291 mutex_unlock(&parent->d_inode->i_mutex); 292 dput(parent); 293 } 294 295 void sysfs_remove_subdir(struct dentry * d) 296 { 297 remove_dir(d); 298 } 299 300 301 /** 302 * sysfs_remove_dir - remove an object's directory. 303 * @kobj: object. 304 * 305 * The only thing special about this is that we remove any files in 306 * the directory before we remove the directory, and we've inlined 307 * what used to be sysfs_rmdir() below, instead of calling separately. 308 */ 309 310 void sysfs_remove_dir(struct kobject * kobj) 311 { 312 struct dentry * dentry = dget(kobj->dentry); 313 struct sysfs_dirent * parent_sd; 314 struct sysfs_dirent * sd, * tmp; 315 316 if (!dentry) 317 return; 318 319 pr_debug("sysfs %s: removing dir\n",dentry->d_name.name); 320 mutex_lock(&dentry->d_inode->i_mutex); 321 parent_sd = dentry->d_fsdata; 322 list_for_each_entry_safe(sd, tmp, &parent_sd->s_children, s_sibling) { 323 if (!sd->s_element || !(sd->s_type & SYSFS_NOT_PINNED)) 324 continue; 325 list_del_init(&sd->s_sibling); 326 sysfs_drop_dentry(sd, dentry); 327 sysfs_put(sd); 328 } 329 mutex_unlock(&dentry->d_inode->i_mutex); 330 331 remove_dir(dentry); 332 /** 333 * Drop reference from dget() on entrance. 334 */ 335 dput(dentry); 336 kobj->dentry = NULL; 337 } 338 339 int sysfs_rename_dir(struct kobject * kobj, const char *new_name) 340 { 341 int error = 0; 342 struct dentry * new_dentry, * parent; 343 344 if (!strcmp(kobject_name(kobj), new_name)) 345 return -EINVAL; 346 347 if (!kobj->parent) 348 return -EINVAL; 349 350 down_write(&sysfs_rename_sem); 351 parent = kobj->parent->dentry; 352 353 mutex_lock(&parent->d_inode->i_mutex); 354 355 new_dentry = lookup_one_len(new_name, parent, strlen(new_name)); 356 if (!IS_ERR(new_dentry)) { 357 if (!new_dentry->d_inode) { 358 error = kobject_set_name(kobj, "%s", new_name); 359 if (!error) { 360 d_add(new_dentry, NULL); 361 d_move(kobj->dentry, new_dentry); 362 } 363 else 364 d_drop(new_dentry); 365 } else 366 error = -EEXIST; 367 dput(new_dentry); 368 } 369 mutex_unlock(&parent->d_inode->i_mutex); 370 up_write(&sysfs_rename_sem); 371 372 return error; 373 } 374 375 static int sysfs_dir_open(struct inode *inode, struct file *file) 376 { 377 struct dentry * dentry = file->f_dentry; 378 struct sysfs_dirent * parent_sd = dentry->d_fsdata; 379 380 mutex_lock(&dentry->d_inode->i_mutex); 381 file->private_data = sysfs_new_dirent(parent_sd, NULL); 382 mutex_unlock(&dentry->d_inode->i_mutex); 383 384 return file->private_data ? 0 : -ENOMEM; 385 386 } 387 388 static int sysfs_dir_close(struct inode *inode, struct file *file) 389 { 390 struct dentry * dentry = file->f_dentry; 391 struct sysfs_dirent * cursor = file->private_data; 392 393 mutex_lock(&dentry->d_inode->i_mutex); 394 list_del_init(&cursor->s_sibling); 395 mutex_unlock(&dentry->d_inode->i_mutex); 396 397 release_sysfs_dirent(cursor); 398 399 return 0; 400 } 401 402 /* Relationship between s_mode and the DT_xxx types */ 403 static inline unsigned char dt_type(struct sysfs_dirent *sd) 404 { 405 return (sd->s_mode >> 12) & 15; 406 } 407 408 static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) 409 { 410 struct dentry *dentry = filp->f_dentry; 411 struct sysfs_dirent * parent_sd = dentry->d_fsdata; 412 struct sysfs_dirent *cursor = filp->private_data; 413 struct list_head *p, *q = &cursor->s_sibling; 414 ino_t ino; 415 int i = filp->f_pos; 416 417 switch (i) { 418 case 0: 419 ino = dentry->d_inode->i_ino; 420 if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) 421 break; 422 filp->f_pos++; 423 i++; 424 /* fallthrough */ 425 case 1: 426 ino = parent_ino(dentry); 427 if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) 428 break; 429 filp->f_pos++; 430 i++; 431 /* fallthrough */ 432 default: 433 if (filp->f_pos == 2) 434 list_move(q, &parent_sd->s_children); 435 436 for (p=q->next; p!= &parent_sd->s_children; p=p->next) { 437 struct sysfs_dirent *next; 438 const char * name; 439 int len; 440 441 next = list_entry(p, struct sysfs_dirent, 442 s_sibling); 443 if (!next->s_element) 444 continue; 445 446 name = sysfs_get_name(next); 447 len = strlen(name); 448 if (next->s_dentry) 449 ino = next->s_dentry->d_inode->i_ino; 450 else 451 ino = iunique(sysfs_sb, 2); 452 453 if (filldir(dirent, name, len, filp->f_pos, ino, 454 dt_type(next)) < 0) 455 return 0; 456 457 list_move(q, p); 458 p = q; 459 filp->f_pos++; 460 } 461 } 462 return 0; 463 } 464 465 static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin) 466 { 467 struct dentry * dentry = file->f_dentry; 468 469 mutex_lock(&dentry->d_inode->i_mutex); 470 switch (origin) { 471 case 1: 472 offset += file->f_pos; 473 case 0: 474 if (offset >= 0) 475 break; 476 default: 477 mutex_unlock(&file->f_dentry->d_inode->i_mutex); 478 return -EINVAL; 479 } 480 if (offset != file->f_pos) { 481 file->f_pos = offset; 482 if (file->f_pos >= 2) { 483 struct sysfs_dirent *sd = dentry->d_fsdata; 484 struct sysfs_dirent *cursor = file->private_data; 485 struct list_head *p; 486 loff_t n = file->f_pos - 2; 487 488 list_del(&cursor->s_sibling); 489 p = sd->s_children.next; 490 while (n && p != &sd->s_children) { 491 struct sysfs_dirent *next; 492 next = list_entry(p, struct sysfs_dirent, 493 s_sibling); 494 if (next->s_element) 495 n--; 496 p = p->next; 497 } 498 list_add_tail(&cursor->s_sibling, p); 499 } 500 } 501 mutex_unlock(&dentry->d_inode->i_mutex); 502 return offset; 503 } 504 505 const struct file_operations sysfs_dir_operations = { 506 .open = sysfs_dir_open, 507 .release = sysfs_dir_close, 508 .llseek = sysfs_dir_lseek, 509 .read = generic_read_dir, 510 .readdir = sysfs_readdir, 511 }; 512