dir.c 10 KB

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