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