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