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