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 }; 237 238 static void remove_dir(struct dentry * d) 239 { 240 struct dentry * parent = dget(d->d_parent); 241 struct sysfs_dirent * sd; 242 243 down(&parent->d_inode->i_sem); 244 d_delete(d); 245 sd = d->d_fsdata; 246 list_del_init(&sd->s_sibling); 247 sysfs_put(sd); 248 if (d->d_inode) 249 simple_rmdir(parent->d_inode,d); 250 251 pr_debug(" o %s removing done (%d)\n",d->d_name.name, 252 atomic_read(&d->d_count)); 253 254 up(&parent->d_inode->i_sem); 255 dput(parent); 256 } 257 258 void sysfs_remove_subdir(struct dentry * d) 259 { 260 remove_dir(d); 261 } 262 263 264 /** 265 * sysfs_remove_dir - remove an object's directory. 266 * @kobj: object. 267 * 268 * The only thing special about this is that we remove any files in 269 * the directory before we remove the directory, and we've inlined 270 * what used to be sysfs_rmdir() below, instead of calling separately. 271 */ 272 273 void sysfs_remove_dir(struct kobject * kobj) 274 { 275 struct dentry * dentry = dget(kobj->dentry); 276 struct sysfs_dirent * parent_sd; 277 struct sysfs_dirent * sd, * tmp; 278 279 if (!dentry) 280 return; 281 282 pr_debug("sysfs %s: removing dir\n",dentry->d_name.name); 283 down(&dentry->d_inode->i_sem); 284 parent_sd = dentry->d_fsdata; 285 list_for_each_entry_safe(sd, tmp, &parent_sd->s_children, s_sibling) { 286 if (!sd->s_element || !(sd->s_type & SYSFS_NOT_PINNED)) 287 continue; 288 list_del_init(&sd->s_sibling); 289 sysfs_drop_dentry(sd, dentry); 290 sysfs_put(sd); 291 } 292 up(&dentry->d_inode->i_sem); 293 294 remove_dir(dentry); 295 /** 296 * Drop reference from dget() on entrance. 297 */ 298 dput(dentry); 299 } 300 301 int sysfs_rename_dir(struct kobject * kobj, const char *new_name) 302 { 303 int error = 0; 304 struct dentry * new_dentry, * parent; 305 306 if (!strcmp(kobject_name(kobj), new_name)) 307 return -EINVAL; 308 309 if (!kobj->parent) 310 return -EINVAL; 311 312 down_write(&sysfs_rename_sem); 313 parent = kobj->parent->dentry; 314 315 down(&parent->d_inode->i_sem); 316 317 new_dentry = sysfs_get_dentry(parent, new_name); 318 if (!IS_ERR(new_dentry)) { 319 if (!new_dentry->d_inode) { 320 error = kobject_set_name(kobj, "%s", new_name); 321 if (!error) { 322 d_add(new_dentry, NULL); 323 d_move(kobj->dentry, new_dentry); 324 } 325 else 326 d_drop(new_dentry); 327 } else 328 error = -EEXIST; 329 dput(new_dentry); 330 } 331 up(&parent->d_inode->i_sem); 332 up_write(&sysfs_rename_sem); 333 334 return error; 335 } 336 337 static int sysfs_dir_open(struct inode *inode, struct file *file) 338 { 339 struct dentry * dentry = file->f_dentry; 340 struct sysfs_dirent * parent_sd = dentry->d_fsdata; 341 342 down(&dentry->d_inode->i_sem); 343 file->private_data = sysfs_new_dirent(parent_sd, NULL); 344 up(&dentry->d_inode->i_sem); 345 346 return file->private_data ? 0 : -ENOMEM; 347 348 } 349 350 static int sysfs_dir_close(struct inode *inode, struct file *file) 351 { 352 struct dentry * dentry = file->f_dentry; 353 struct sysfs_dirent * cursor = file->private_data; 354 355 down(&dentry->d_inode->i_sem); 356 list_del_init(&cursor->s_sibling); 357 up(&dentry->d_inode->i_sem); 358 359 release_sysfs_dirent(cursor); 360 361 return 0; 362 } 363 364 /* Relationship between s_mode and the DT_xxx types */ 365 static inline unsigned char dt_type(struct sysfs_dirent *sd) 366 { 367 return (sd->s_mode >> 12) & 15; 368 } 369 370 static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) 371 { 372 struct dentry *dentry = filp->f_dentry; 373 struct sysfs_dirent * parent_sd = dentry->d_fsdata; 374 struct sysfs_dirent *cursor = filp->private_data; 375 struct list_head *p, *q = &cursor->s_sibling; 376 ino_t ino; 377 int i = filp->f_pos; 378 379 switch (i) { 380 case 0: 381 ino = dentry->d_inode->i_ino; 382 if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) 383 break; 384 filp->f_pos++; 385 i++; 386 /* fallthrough */ 387 case 1: 388 ino = parent_ino(dentry); 389 if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) 390 break; 391 filp->f_pos++; 392 i++; 393 /* fallthrough */ 394 default: 395 if (filp->f_pos == 2) { 396 list_del(q); 397 list_add(q, &parent_sd->s_children); 398 } 399 for (p=q->next; p!= &parent_sd->s_children; p=p->next) { 400 struct sysfs_dirent *next; 401 const char * name; 402 int len; 403 404 next = list_entry(p, struct sysfs_dirent, 405 s_sibling); 406 if (!next->s_element) 407 continue; 408 409 name = sysfs_get_name(next); 410 len = strlen(name); 411 if (next->s_dentry) 412 ino = next->s_dentry->d_inode->i_ino; 413 else 414 ino = iunique(sysfs_sb, 2); 415 416 if (filldir(dirent, name, len, filp->f_pos, ino, 417 dt_type(next)) < 0) 418 return 0; 419 420 list_del(q); 421 list_add(q, p); 422 p = q; 423 filp->f_pos++; 424 } 425 } 426 return 0; 427 } 428 429 static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin) 430 { 431 struct dentry * dentry = file->f_dentry; 432 433 down(&dentry->d_inode->i_sem); 434 switch (origin) { 435 case 1: 436 offset += file->f_pos; 437 case 0: 438 if (offset >= 0) 439 break; 440 default: 441 up(&file->f_dentry->d_inode->i_sem); 442 return -EINVAL; 443 } 444 if (offset != file->f_pos) { 445 file->f_pos = offset; 446 if (file->f_pos >= 2) { 447 struct sysfs_dirent *sd = dentry->d_fsdata; 448 struct sysfs_dirent *cursor = file->private_data; 449 struct list_head *p; 450 loff_t n = file->f_pos - 2; 451 452 list_del(&cursor->s_sibling); 453 p = sd->s_children.next; 454 while (n && p != &sd->s_children) { 455 struct sysfs_dirent *next; 456 next = list_entry(p, struct sysfs_dirent, 457 s_sibling); 458 if (next->s_element) 459 n--; 460 p = p->next; 461 } 462 list_add_tail(&cursor->s_sibling, p); 463 } 464 } 465 up(&dentry->d_inode->i_sem); 466 return offset; 467 } 468 469 struct file_operations sysfs_dir_operations = { 470 .open = sysfs_dir_open, 471 .release = sysfs_dir_close, 472 .llseek = sysfs_dir_lseek, 473 .read = generic_read_dir, 474 .readdir = sysfs_readdir, 475 }; 476 477 EXPORT_SYMBOL_GPL(sysfs_create_dir); 478 EXPORT_SYMBOL_GPL(sysfs_remove_dir); 479 EXPORT_SYMBOL_GPL(sysfs_rename_dir); 480 481