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 <linux/idr.h> 13 #include <asm/semaphore.h> 14 #include "sysfs.h" 15 16 DECLARE_RWSEM(sysfs_rename_sem); 17 spinlock_t sysfs_lock = SPIN_LOCK_UNLOCKED; 18 19 static spinlock_t sysfs_ino_lock = SPIN_LOCK_UNLOCKED; 20 static DEFINE_IDA(sysfs_ino_ida); 21 22 int sysfs_alloc_ino(ino_t *pino) 23 { 24 int ino, rc; 25 26 retry: 27 spin_lock(&sysfs_ino_lock); 28 rc = ida_get_new_above(&sysfs_ino_ida, 2, &ino); 29 spin_unlock(&sysfs_ino_lock); 30 31 if (rc == -EAGAIN) { 32 if (ida_pre_get(&sysfs_ino_ida, GFP_KERNEL)) 33 goto retry; 34 rc = -ENOMEM; 35 } 36 37 *pino = ino; 38 return rc; 39 } 40 41 static void sysfs_free_ino(ino_t ino) 42 { 43 spin_lock(&sysfs_ino_lock); 44 ida_remove(&sysfs_ino_ida, ino); 45 spin_unlock(&sysfs_ino_lock); 46 } 47 48 void release_sysfs_dirent(struct sysfs_dirent * sd) 49 { 50 if (sd->s_type & SYSFS_KOBJ_LINK) { 51 struct sysfs_symlink * sl = sd->s_element; 52 kfree(sl->link_name); 53 kobject_put(sl->target_kobj); 54 kfree(sl); 55 } 56 kfree(sd->s_iattr); 57 sysfs_free_ino(sd->s_ino); 58 kmem_cache_free(sysfs_dir_cachep, sd); 59 } 60 61 static void sysfs_d_iput(struct dentry * dentry, struct inode * inode) 62 { 63 struct sysfs_dirent * sd = dentry->d_fsdata; 64 65 if (sd) { 66 /* sd->s_dentry is protected with sysfs_lock. This 67 * allows sysfs_drop_dentry() to dereference it. 68 */ 69 spin_lock(&sysfs_lock); 70 71 /* The dentry might have been deleted or another 72 * lookup could have happened updating sd->s_dentry to 73 * point the new dentry. Ignore if it isn't pointing 74 * to this dentry. 75 */ 76 if (sd->s_dentry == dentry) 77 sd->s_dentry = NULL; 78 spin_unlock(&sysfs_lock); 79 sysfs_put(sd); 80 } 81 iput(inode); 82 } 83 84 static struct dentry_operations sysfs_dentry_ops = { 85 .d_iput = sysfs_d_iput, 86 }; 87 88 /* 89 * Allocates a new sysfs_dirent and links it to the parent sysfs_dirent 90 */ 91 static struct sysfs_dirent * __sysfs_new_dirent(void * element) 92 { 93 struct sysfs_dirent * sd; 94 95 sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL); 96 if (!sd) 97 return NULL; 98 99 if (sysfs_alloc_ino(&sd->s_ino)) { 100 kmem_cache_free(sysfs_dir_cachep, sd); 101 return NULL; 102 } 103 104 atomic_set(&sd->s_count, 1); 105 atomic_set(&sd->s_event, 1); 106 INIT_LIST_HEAD(&sd->s_children); 107 INIT_LIST_HEAD(&sd->s_sibling); 108 sd->s_element = element; 109 110 return sd; 111 } 112 113 static void __sysfs_list_dirent(struct sysfs_dirent *parent_sd, 114 struct sysfs_dirent *sd) 115 { 116 if (sd) 117 list_add(&sd->s_sibling, &parent_sd->s_children); 118 } 119 120 static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent *parent_sd, 121 void * element) 122 { 123 struct sysfs_dirent *sd; 124 sd = __sysfs_new_dirent(element); 125 __sysfs_list_dirent(parent_sd, sd); 126 return sd; 127 } 128 129 /* 130 * 131 * Return -EEXIST if there is already a sysfs element with the same name for 132 * the same parent. 133 * 134 * called with parent inode's i_mutex held 135 */ 136 int sysfs_dirent_exist(struct sysfs_dirent *parent_sd, 137 const unsigned char *new) 138 { 139 struct sysfs_dirent * sd; 140 141 list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { 142 if (sd->s_element) { 143 const unsigned char *existing = sysfs_get_name(sd); 144 if (strcmp(existing, new)) 145 continue; 146 else 147 return -EEXIST; 148 } 149 } 150 151 return 0; 152 } 153 154 155 static struct sysfs_dirent * 156 __sysfs_make_dirent(struct dentry *dentry, void *element, mode_t mode, int type) 157 { 158 struct sysfs_dirent * sd; 159 160 sd = __sysfs_new_dirent(element); 161 if (!sd) 162 goto out; 163 164 sd->s_mode = mode; 165 sd->s_type = type; 166 sd->s_dentry = dentry; 167 if (dentry) { 168 dentry->d_fsdata = sysfs_get(sd); 169 dentry->d_op = &sysfs_dentry_ops; 170 } 171 172 out: 173 return sd; 174 } 175 176 int sysfs_make_dirent(struct sysfs_dirent * parent_sd, struct dentry * dentry, 177 void * element, umode_t mode, int type) 178 { 179 struct sysfs_dirent *sd; 180 181 sd = __sysfs_make_dirent(dentry, element, mode, type); 182 __sysfs_list_dirent(parent_sd, sd); 183 184 return sd ? 0 : -ENOMEM; 185 } 186 187 static int init_dir(struct inode * inode) 188 { 189 inode->i_op = &sysfs_dir_inode_operations; 190 inode->i_fop = &sysfs_dir_operations; 191 192 /* directory inodes start off with i_nlink == 2 (for "." entry) */ 193 inc_nlink(inode); 194 return 0; 195 } 196 197 static int init_file(struct inode * inode) 198 { 199 inode->i_size = PAGE_SIZE; 200 inode->i_fop = &sysfs_file_operations; 201 return 0; 202 } 203 204 static int init_symlink(struct inode * inode) 205 { 206 inode->i_op = &sysfs_symlink_inode_operations; 207 return 0; 208 } 209 210 static int create_dir(struct kobject *kobj, struct dentry *parent, 211 const char *name, struct dentry **p_dentry) 212 { 213 int error; 214 umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; 215 struct dentry *dentry; 216 struct sysfs_dirent *sd; 217 218 mutex_lock(&parent->d_inode->i_mutex); 219 220 dentry = lookup_one_len(name, parent, strlen(name)); 221 if (IS_ERR(dentry)) { 222 error = PTR_ERR(dentry); 223 goto out_unlock; 224 } 225 226 error = -EEXIST; 227 if (sysfs_dirent_exist(parent->d_fsdata, name)) 228 goto out_dput; 229 230 error = sysfs_make_dirent(parent->d_fsdata, dentry, kobj, mode, 231 SYSFS_DIR); 232 if (error) 233 goto out_drop; 234 235 error = sysfs_create(dentry, mode, init_dir); 236 if (error) 237 goto out_sput; 238 239 inc_nlink(parent->d_inode); 240 dentry->d_op = &sysfs_dentry_ops; 241 d_rehash(dentry); 242 243 *p_dentry = dentry; 244 error = 0; 245 goto out_dput; 246 247 out_sput: 248 sd = dentry->d_fsdata; 249 list_del_init(&sd->s_sibling); 250 sysfs_put(sd); 251 out_drop: 252 d_drop(dentry); 253 out_dput: 254 dput(dentry); 255 out_unlock: 256 mutex_unlock(&parent->d_inode->i_mutex); 257 return error; 258 } 259 260 261 int sysfs_create_subdir(struct kobject * k, const char * n, struct dentry ** d) 262 { 263 return create_dir(k,k->dentry,n,d); 264 } 265 266 /** 267 * sysfs_create_dir - create a directory for an object. 268 * @kobj: object we're creating directory for. 269 * @shadow_parent: parent parent object. 270 */ 271 272 int sysfs_create_dir(struct kobject * kobj, struct dentry *shadow_parent) 273 { 274 struct dentry * dentry = NULL; 275 struct dentry * parent; 276 int error = 0; 277 278 BUG_ON(!kobj); 279 280 if (shadow_parent) 281 parent = shadow_parent; 282 else if (kobj->parent) 283 parent = kobj->parent->dentry; 284 else if (sysfs_mount && sysfs_mount->mnt_sb) 285 parent = sysfs_mount->mnt_sb->s_root; 286 else 287 return -EFAULT; 288 289 error = create_dir(kobj,parent,kobject_name(kobj),&dentry); 290 if (!error) 291 kobj->dentry = dentry; 292 return error; 293 } 294 295 /* attaches attribute's sysfs_dirent to the dentry corresponding to the 296 * attribute file 297 */ 298 static int sysfs_attach_attr(struct sysfs_dirent * sd, struct dentry * dentry) 299 { 300 struct attribute * attr = NULL; 301 struct bin_attribute * bin_attr = NULL; 302 int (* init) (struct inode *) = NULL; 303 int error = 0; 304 305 if (sd->s_type & SYSFS_KOBJ_BIN_ATTR) { 306 bin_attr = sd->s_element; 307 attr = &bin_attr->attr; 308 } else { 309 attr = sd->s_element; 310 init = init_file; 311 } 312 313 dentry->d_fsdata = sysfs_get(sd); 314 /* protect sd->s_dentry against sysfs_d_iput */ 315 spin_lock(&sysfs_lock); 316 sd->s_dentry = dentry; 317 spin_unlock(&sysfs_lock); 318 error = sysfs_create(dentry, (attr->mode & S_IALLUGO) | S_IFREG, init); 319 if (error) { 320 sysfs_put(sd); 321 return error; 322 } 323 324 if (bin_attr) { 325 dentry->d_inode->i_size = bin_attr->size; 326 dentry->d_inode->i_fop = &bin_fops; 327 } 328 dentry->d_op = &sysfs_dentry_ops; 329 d_rehash(dentry); 330 331 return 0; 332 } 333 334 static int sysfs_attach_link(struct sysfs_dirent * sd, struct dentry * dentry) 335 { 336 int err = 0; 337 338 dentry->d_fsdata = sysfs_get(sd); 339 /* protect sd->s_dentry against sysfs_d_iput */ 340 spin_lock(&sysfs_lock); 341 sd->s_dentry = dentry; 342 spin_unlock(&sysfs_lock); 343 err = sysfs_create(dentry, S_IFLNK|S_IRWXUGO, init_symlink); 344 if (!err) { 345 dentry->d_op = &sysfs_dentry_ops; 346 d_rehash(dentry); 347 } else 348 sysfs_put(sd); 349 350 return err; 351 } 352 353 static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, 354 struct nameidata *nd) 355 { 356 struct sysfs_dirent * parent_sd = dentry->d_parent->d_fsdata; 357 struct sysfs_dirent * sd; 358 int err = 0; 359 360 list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { 361 if (sd->s_type & SYSFS_NOT_PINNED) { 362 const unsigned char * name = sysfs_get_name(sd); 363 364 if (strcmp(name, dentry->d_name.name)) 365 continue; 366 367 if (sd->s_type & SYSFS_KOBJ_LINK) 368 err = sysfs_attach_link(sd, dentry); 369 else 370 err = sysfs_attach_attr(sd, dentry); 371 break; 372 } 373 } 374 375 return ERR_PTR(err); 376 } 377 378 const struct inode_operations sysfs_dir_inode_operations = { 379 .lookup = sysfs_lookup, 380 .setattr = sysfs_setattr, 381 }; 382 383 static void remove_dir(struct dentry * d) 384 { 385 struct dentry * parent = dget(d->d_parent); 386 struct sysfs_dirent * sd; 387 388 mutex_lock(&parent->d_inode->i_mutex); 389 d_delete(d); 390 sd = d->d_fsdata; 391 list_del_init(&sd->s_sibling); 392 sysfs_put(sd); 393 if (d->d_inode) 394 simple_rmdir(parent->d_inode,d); 395 396 pr_debug(" o %s removing done (%d)\n",d->d_name.name, 397 atomic_read(&d->d_count)); 398 399 mutex_unlock(&parent->d_inode->i_mutex); 400 dput(parent); 401 } 402 403 void sysfs_remove_subdir(struct dentry * d) 404 { 405 remove_dir(d); 406 } 407 408 409 static void __sysfs_remove_dir(struct dentry *dentry) 410 { 411 struct sysfs_dirent * parent_sd; 412 struct sysfs_dirent * sd, * tmp; 413 414 dget(dentry); 415 if (!dentry) 416 return; 417 418 pr_debug("sysfs %s: removing dir\n",dentry->d_name.name); 419 mutex_lock(&dentry->d_inode->i_mutex); 420 parent_sd = dentry->d_fsdata; 421 list_for_each_entry_safe(sd, tmp, &parent_sd->s_children, s_sibling) { 422 if (!sd->s_element || !(sd->s_type & SYSFS_NOT_PINNED)) 423 continue; 424 list_del_init(&sd->s_sibling); 425 sysfs_drop_dentry(sd, dentry); 426 sysfs_put(sd); 427 } 428 mutex_unlock(&dentry->d_inode->i_mutex); 429 430 remove_dir(dentry); 431 /** 432 * Drop reference from dget() on entrance. 433 */ 434 dput(dentry); 435 } 436 437 /** 438 * sysfs_remove_dir - remove an object's directory. 439 * @kobj: object. 440 * 441 * The only thing special about this is that we remove any files in 442 * the directory before we remove the directory, and we've inlined 443 * what used to be sysfs_rmdir() below, instead of calling separately. 444 */ 445 446 void sysfs_remove_dir(struct kobject * kobj) 447 { 448 __sysfs_remove_dir(kobj->dentry); 449 kobj->dentry = NULL; 450 } 451 452 int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent, 453 const char *new_name) 454 { 455 int error; 456 struct dentry * new_dentry; 457 struct sysfs_dirent *sd, *parent_sd; 458 459 if (!new_parent) 460 return -EFAULT; 461 462 down_write(&sysfs_rename_sem); 463 mutex_lock(&new_parent->d_inode->i_mutex); 464 465 new_dentry = lookup_one_len(new_name, new_parent, strlen(new_name)); 466 if (IS_ERR(new_dentry)) { 467 error = PTR_ERR(new_dentry); 468 goto out_unlock; 469 } 470 471 /* By allowing two different directories with the same 472 * d_parent we allow this routine to move between different 473 * shadows of the same directory 474 */ 475 error = -EINVAL; 476 if (kobj->dentry->d_parent->d_inode != new_parent->d_inode || 477 new_dentry->d_parent->d_inode != new_parent->d_inode || 478 new_dentry == kobj->dentry) 479 goto out_dput; 480 481 error = -EEXIST; 482 if (new_dentry->d_inode) 483 goto out_dput; 484 485 error = kobject_set_name(kobj, "%s", new_name); 486 if (error) 487 goto out_drop; 488 489 d_add(new_dentry, NULL); 490 d_move(kobj->dentry, new_dentry); 491 492 sd = kobj->dentry->d_fsdata; 493 parent_sd = new_parent->d_fsdata; 494 495 list_del_init(&sd->s_sibling); 496 list_add(&sd->s_sibling, &parent_sd->s_children); 497 498 error = 0; 499 goto out_unlock; 500 501 out_drop: 502 d_drop(new_dentry); 503 out_dput: 504 dput(new_dentry); 505 out_unlock: 506 mutex_unlock(&new_parent->d_inode->i_mutex); 507 up_write(&sysfs_rename_sem); 508 return error; 509 } 510 511 int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent) 512 { 513 struct dentry *old_parent_dentry, *new_parent_dentry, *new_dentry; 514 struct sysfs_dirent *new_parent_sd, *sd; 515 int error; 516 517 old_parent_dentry = kobj->parent ? 518 kobj->parent->dentry : sysfs_mount->mnt_sb->s_root; 519 new_parent_dentry = new_parent ? 520 new_parent->dentry : sysfs_mount->mnt_sb->s_root; 521 522 if (old_parent_dentry->d_inode == new_parent_dentry->d_inode) 523 return 0; /* nothing to move */ 524 again: 525 mutex_lock(&old_parent_dentry->d_inode->i_mutex); 526 if (!mutex_trylock(&new_parent_dentry->d_inode->i_mutex)) { 527 mutex_unlock(&old_parent_dentry->d_inode->i_mutex); 528 goto again; 529 } 530 531 new_parent_sd = new_parent_dentry->d_fsdata; 532 sd = kobj->dentry->d_fsdata; 533 534 new_dentry = lookup_one_len(kobj->name, new_parent_dentry, 535 strlen(kobj->name)); 536 if (IS_ERR(new_dentry)) { 537 error = PTR_ERR(new_dentry); 538 goto out; 539 } else 540 error = 0; 541 d_add(new_dentry, NULL); 542 d_move(kobj->dentry, new_dentry); 543 dput(new_dentry); 544 545 /* Remove from old parent's list and insert into new parent's list. */ 546 list_del_init(&sd->s_sibling); 547 list_add(&sd->s_sibling, &new_parent_sd->s_children); 548 549 out: 550 mutex_unlock(&new_parent_dentry->d_inode->i_mutex); 551 mutex_unlock(&old_parent_dentry->d_inode->i_mutex); 552 553 return error; 554 } 555 556 static int sysfs_dir_open(struct inode *inode, struct file *file) 557 { 558 struct dentry * dentry = file->f_path.dentry; 559 struct sysfs_dirent * parent_sd = dentry->d_fsdata; 560 561 mutex_lock(&dentry->d_inode->i_mutex); 562 file->private_data = sysfs_new_dirent(parent_sd, NULL); 563 mutex_unlock(&dentry->d_inode->i_mutex); 564 565 return file->private_data ? 0 : -ENOMEM; 566 567 } 568 569 static int sysfs_dir_close(struct inode *inode, struct file *file) 570 { 571 struct dentry * dentry = file->f_path.dentry; 572 struct sysfs_dirent * cursor = file->private_data; 573 574 mutex_lock(&dentry->d_inode->i_mutex); 575 list_del_init(&cursor->s_sibling); 576 mutex_unlock(&dentry->d_inode->i_mutex); 577 578 release_sysfs_dirent(cursor); 579 580 return 0; 581 } 582 583 /* Relationship between s_mode and the DT_xxx types */ 584 static inline unsigned char dt_type(struct sysfs_dirent *sd) 585 { 586 return (sd->s_mode >> 12) & 15; 587 } 588 589 static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) 590 { 591 struct dentry *dentry = filp->f_path.dentry; 592 struct sysfs_dirent * parent_sd = dentry->d_fsdata; 593 struct sysfs_dirent *cursor = filp->private_data; 594 struct list_head *p, *q = &cursor->s_sibling; 595 ino_t ino; 596 int i = filp->f_pos; 597 598 switch (i) { 599 case 0: 600 ino = parent_sd->s_ino; 601 if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) 602 break; 603 filp->f_pos++; 604 i++; 605 /* fallthrough */ 606 case 1: 607 ino = parent_ino(dentry); 608 if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) 609 break; 610 filp->f_pos++; 611 i++; 612 /* fallthrough */ 613 default: 614 if (filp->f_pos == 2) 615 list_move(q, &parent_sd->s_children); 616 617 for (p=q->next; p!= &parent_sd->s_children; p=p->next) { 618 struct sysfs_dirent *next; 619 const char * name; 620 int len; 621 622 next = list_entry(p, struct sysfs_dirent, 623 s_sibling); 624 if (!next->s_element) 625 continue; 626 627 name = sysfs_get_name(next); 628 len = strlen(name); 629 ino = next->s_ino; 630 631 if (filldir(dirent, name, len, filp->f_pos, ino, 632 dt_type(next)) < 0) 633 return 0; 634 635 list_move(q, p); 636 p = q; 637 filp->f_pos++; 638 } 639 } 640 return 0; 641 } 642 643 static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin) 644 { 645 struct dentry * dentry = file->f_path.dentry; 646 647 mutex_lock(&dentry->d_inode->i_mutex); 648 switch (origin) { 649 case 1: 650 offset += file->f_pos; 651 case 0: 652 if (offset >= 0) 653 break; 654 default: 655 mutex_unlock(&file->f_path.dentry->d_inode->i_mutex); 656 return -EINVAL; 657 } 658 if (offset != file->f_pos) { 659 file->f_pos = offset; 660 if (file->f_pos >= 2) { 661 struct sysfs_dirent *sd = dentry->d_fsdata; 662 struct sysfs_dirent *cursor = file->private_data; 663 struct list_head *p; 664 loff_t n = file->f_pos - 2; 665 666 list_del(&cursor->s_sibling); 667 p = sd->s_children.next; 668 while (n && p != &sd->s_children) { 669 struct sysfs_dirent *next; 670 next = list_entry(p, struct sysfs_dirent, 671 s_sibling); 672 if (next->s_element) 673 n--; 674 p = p->next; 675 } 676 list_add_tail(&cursor->s_sibling, p); 677 } 678 } 679 mutex_unlock(&dentry->d_inode->i_mutex); 680 return offset; 681 } 682 683 684 /** 685 * sysfs_make_shadowed_dir - Setup so a directory can be shadowed 686 * @kobj: object we're creating shadow of. 687 */ 688 689 int sysfs_make_shadowed_dir(struct kobject *kobj, 690 void * (*follow_link)(struct dentry *, struct nameidata *)) 691 { 692 struct inode *inode; 693 struct inode_operations *i_op; 694 695 inode = kobj->dentry->d_inode; 696 if (inode->i_op != &sysfs_dir_inode_operations) 697 return -EINVAL; 698 699 i_op = kmalloc(sizeof(*i_op), GFP_KERNEL); 700 if (!i_op) 701 return -ENOMEM; 702 703 memcpy(i_op, &sysfs_dir_inode_operations, sizeof(*i_op)); 704 i_op->follow_link = follow_link; 705 706 /* Locking of inode->i_op? 707 * Since setting i_op is a single word write and they 708 * are atomic we should be ok here. 709 */ 710 inode->i_op = i_op; 711 return 0; 712 } 713 714 /** 715 * sysfs_create_shadow_dir - create a shadow directory for an object. 716 * @kobj: object we're creating directory for. 717 * 718 * sysfs_make_shadowed_dir must already have been called on this 719 * directory. 720 */ 721 722 struct dentry *sysfs_create_shadow_dir(struct kobject *kobj) 723 { 724 struct sysfs_dirent *sd; 725 struct dentry *parent, *dir, *shadow; 726 struct inode *inode; 727 728 dir = kobj->dentry; 729 inode = dir->d_inode; 730 parent = dir->d_parent; 731 shadow = ERR_PTR(-EINVAL); 732 if (!sysfs_is_shadowed_inode(inode)) 733 goto out; 734 735 shadow = d_alloc(parent, &dir->d_name); 736 if (!shadow) 737 goto nomem; 738 739 sd = __sysfs_make_dirent(shadow, kobj, inode->i_mode, SYSFS_DIR); 740 if (!sd) 741 goto nomem; 742 743 d_instantiate(shadow, igrab(inode)); 744 inc_nlink(inode); 745 inc_nlink(parent->d_inode); 746 shadow->d_op = &sysfs_dentry_ops; 747 748 dget(shadow); /* Extra count - pin the dentry in core */ 749 750 out: 751 return shadow; 752 nomem: 753 dput(shadow); 754 shadow = ERR_PTR(-ENOMEM); 755 goto out; 756 } 757 758 /** 759 * sysfs_remove_shadow_dir - remove an object's directory. 760 * @shadow: dentry of shadow directory 761 * 762 * The only thing special about this is that we remove any files in 763 * the directory before we remove the directory, and we've inlined 764 * what used to be sysfs_rmdir() below, instead of calling separately. 765 */ 766 767 void sysfs_remove_shadow_dir(struct dentry *shadow) 768 { 769 __sysfs_remove_dir(shadow); 770 } 771 772 const struct file_operations sysfs_dir_operations = { 773 .open = sysfs_dir_open, 774 .release = sysfs_dir_close, 775 .llseek = sysfs_dir_lseek, 776 .read = generic_read_dir, 777 .readdir = sysfs_readdir, 778 }; 779