namei.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:6k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/fs/minix/namei.c
  3.  *
  4.  *  Copyright (C) 1991, 1992  Linus Torvalds
  5.  */
  6. #include <linux/fs.h>
  7. #include <linux/minix_fs.h>
  8. #include <linux/pagemap.h>
  9. static inline void inc_count(struct inode *inode)
  10. {
  11. inode->i_nlink++;
  12. mark_inode_dirty(inode);
  13. }
  14. static inline void dec_count(struct inode *inode)
  15. {
  16. inode->i_nlink--;
  17. mark_inode_dirty(inode);
  18. }
  19. static int add_nondir(struct dentry *dentry, struct inode *inode)
  20. {
  21. int err = minix_add_link(dentry, inode);
  22. if (!err) {
  23. d_instantiate(dentry, inode);
  24. return 0;
  25. }
  26. dec_count(inode);
  27. iput(inode);
  28. return err;
  29. }
  30. static int minix_hash(struct dentry *dentry, struct qstr *qstr)
  31. {
  32. unsigned long hash;
  33. int i;
  34. const unsigned char *name;
  35. i = dentry->d_inode->i_sb->u.minix_sb.s_namelen;
  36. if (i >= qstr->len)
  37. return 0;
  38. /* Truncate the name in place, avoids having to define a compare
  39.    function. */
  40. qstr->len = i;
  41. name = qstr->name;
  42. hash = init_name_hash();
  43. while (i--)
  44. hash = partial_name_hash(*name++, hash);
  45. qstr->hash = end_name_hash(hash);
  46. return 0;
  47. }
  48. struct dentry_operations minix_dentry_operations = {
  49. d_hash: minix_hash,
  50. };
  51. static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry)
  52. {
  53. struct inode * inode = NULL;
  54. ino_t ino;
  55. dentry->d_op = dir->i_sb->s_root->d_op;
  56. if (dentry->d_name.len > dir->i_sb->u.minix_sb.s_namelen)
  57. return ERR_PTR(-ENAMETOOLONG);
  58. ino = minix_inode_by_name(dentry);
  59. if (ino) {
  60. inode = iget(dir->i_sb, ino);
  61.  
  62. if (!inode)
  63. return ERR_PTR(-EACCES);
  64. }
  65. d_add(dentry, inode);
  66. return NULL;
  67. }
  68. static int minix_mknod(struct inode * dir, struct dentry *dentry, int mode, int rdev)
  69. {
  70. int error;
  71. struct inode * inode = minix_new_inode(dir, &error);
  72. if (inode) {
  73. inode->i_mode = mode;
  74. minix_set_inode(inode, rdev);
  75. mark_inode_dirty(inode);
  76. error = add_nondir(dentry, inode);
  77. }
  78. return error;
  79. }
  80. static int minix_create(struct inode * dir, struct dentry *dentry, int mode)
  81. {
  82. return minix_mknod(dir, dentry, mode, 0);
  83. }
  84. static int minix_symlink(struct inode * dir, struct dentry *dentry,
  85.   const char * symname)
  86. {
  87. int err = -ENAMETOOLONG;
  88. int i = strlen(symname)+1;
  89. struct inode * inode;
  90. if (i > dir->i_sb->s_blocksize)
  91. goto out;
  92. inode = minix_new_inode(dir, &err);
  93. if (!inode)
  94. goto out;
  95. inode->i_mode = S_IFLNK | 0777;
  96. minix_set_inode(inode, 0);
  97. err = block_symlink(inode, symname, i);
  98. if (err)
  99. goto out_fail;
  100. err = add_nondir(dentry, inode);
  101. out:
  102. return err;
  103. out_fail:
  104. dec_count(inode);
  105. iput(inode);
  106. goto out;
  107. }
  108. static int minix_link(struct dentry * old_dentry, struct inode * dir,
  109. struct dentry *dentry)
  110. {
  111. struct inode *inode = old_dentry->d_inode;
  112. if (S_ISDIR(inode->i_mode))
  113. return -EPERM;
  114. if (inode->i_nlink >= inode->i_sb->u.minix_sb.s_link_max)
  115. return -EMLINK;
  116. inode->i_ctime = CURRENT_TIME;
  117. inc_count(inode);
  118. atomic_inc(&inode->i_count);
  119. return add_nondir(dentry, inode);
  120. }
  121. static int minix_mkdir(struct inode * dir, struct dentry *dentry, int mode)
  122. {
  123. struct inode * inode;
  124. int err = -EMLINK;
  125. if (dir->i_nlink >= dir->i_sb->u.minix_sb.s_link_max)
  126. goto out;
  127. inc_count(dir);
  128. inode = minix_new_inode(dir, &err);
  129. if (!inode)
  130. goto out_dir;
  131. inode->i_mode = S_IFDIR | mode;
  132. if (dir->i_mode & S_ISGID)
  133. inode->i_mode |= S_ISGID;
  134. minix_set_inode(inode, 0);
  135. inc_count(inode);
  136. err = minix_make_empty(inode, dir);
  137. if (err)
  138. goto out_fail;
  139. err = minix_add_link(dentry, inode);
  140. if (err)
  141. goto out_fail;
  142. d_instantiate(dentry, inode);
  143. out:
  144. return err;
  145. out_fail:
  146. dec_count(inode);
  147. dec_count(inode);
  148. iput(inode);
  149. out_dir:
  150. dec_count(dir);
  151. goto out;
  152. }
  153. static int minix_unlink(struct inode * dir, struct dentry *dentry)
  154. {
  155. int err = -ENOENT;
  156. struct inode * inode = dentry->d_inode;
  157. struct page * page;
  158. struct minix_dir_entry * de;
  159. de = minix_find_entry(dentry, &page);
  160. if (!de)
  161. goto end_unlink;
  162. err = minix_delete_entry(de, page);
  163. if (err)
  164. goto end_unlink;
  165. inode->i_ctime = dir->i_ctime;
  166. dec_count(inode);
  167. end_unlink:
  168. return err;
  169. }
  170. static int minix_rmdir(struct inode * dir, struct dentry *dentry)
  171. {
  172. struct inode * inode = dentry->d_inode;
  173. int err = -ENOTEMPTY;
  174. if (minix_empty_dir(inode)) {
  175. err = minix_unlink(dir, dentry);
  176. if (!err) {
  177. dec_count(dir);
  178. dec_count(inode);
  179. }
  180. }
  181. return err;
  182. }
  183. static int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
  184.    struct inode * new_dir, struct dentry *new_dentry)
  185. {
  186. struct minix_sb_info * info = &old_dir->i_sb->u.minix_sb;
  187. struct inode * old_inode = old_dentry->d_inode;
  188. struct inode * new_inode = new_dentry->d_inode;
  189. struct page * dir_page = NULL;
  190. struct minix_dir_entry * dir_de = NULL;
  191. struct page * old_page;
  192. struct minix_dir_entry * old_de;
  193. int err = -ENOENT;
  194. old_de = minix_find_entry(old_dentry, &old_page);
  195. if (!old_de)
  196. goto out;
  197. if (S_ISDIR(old_inode->i_mode)) {
  198. err = -EIO;
  199. dir_de = minix_dotdot(old_inode, &dir_page);
  200. if (!dir_de)
  201. goto out_old;
  202. }
  203. if (new_inode) {
  204. struct page * new_page;
  205. struct minix_dir_entry * new_de;
  206. err = -ENOTEMPTY;
  207. if (dir_de && !minix_empty_dir(new_inode))
  208. goto out_dir;
  209. err = -ENOENT;
  210. new_de = minix_find_entry(new_dentry, &new_page);
  211. if (!new_de)
  212. goto out_dir;
  213. inc_count(old_inode);
  214. minix_set_link(new_de, new_page, old_inode);
  215. new_inode->i_ctime = CURRENT_TIME;
  216. if (dir_de)
  217. new_inode->i_nlink--;
  218. dec_count(new_inode);
  219. } else {
  220. if (dir_de) {
  221. err = -EMLINK;
  222. if (new_dir->i_nlink >= info->s_link_max)
  223. goto out_dir;
  224. }
  225. inc_count(old_inode);
  226. err = minix_add_link(new_dentry, old_inode);
  227. if (err) {
  228. dec_count(old_inode);
  229. goto out_dir;
  230. }
  231. if (dir_de)
  232. inc_count(new_dir);
  233. }
  234. minix_delete_entry(old_de, old_page);
  235. dec_count(old_inode);
  236. if (dir_de) {
  237. minix_set_link(dir_de, dir_page, new_dir);
  238. dec_count(old_dir);
  239. }
  240. return 0;
  241. out_dir:
  242. if (dir_de) {
  243. kunmap(dir_page);
  244. page_cache_release(dir_page);
  245. }
  246. out_old:
  247. kunmap(old_page);
  248. page_cache_release(old_page);
  249. out:
  250. return err;
  251. }
  252. /*
  253.  * directories can handle most operations...
  254.  */
  255. struct inode_operations minix_dir_inode_operations = {
  256. create: minix_create,
  257. lookup: minix_lookup,
  258. link: minix_link,
  259. unlink: minix_unlink,
  260. symlink: minix_symlink,
  261. mkdir: minix_mkdir,
  262. rmdir: minix_rmdir,
  263. mknod: minix_mknod,
  264. rename: minix_rename,
  265. };