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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * linux/fs/ext2/namei.c
  3.  *
  4.  * Rewrite to pagecache. Almost all code had been changed, so blame me
  5.  * if the things go wrong. Please, send bug reports to viro@math.psu.edu
  6.  *
  7.  * Stuff here is basically a glue between the VFS and generic UNIXish
  8.  * filesystem that keeps everything in pagecache. All knowledge of the
  9.  * directory layout is in fs/ext2/dir.c - it turned out to be easily separatable
  10.  * and it's easier to debug that way. In principle we might want to
  11.  * generalize that a bit and turn it into a library. Or not.
  12.  *
  13.  * The only non-static object here is ext2_dir_inode_operations.
  14.  *
  15.  * TODO: get rid of kmap() use, add readahead.
  16.  *
  17.  * Copyright (C) 1992, 1993, 1994, 1995
  18.  * Remy Card (card@masi.ibp.fr)
  19.  * Laboratoire MASI - Institut Blaise Pascal
  20.  * Universite Pierre et Marie Curie (Paris VI)
  21.  *
  22.  *  from
  23.  *
  24.  *  linux/fs/minix/namei.c
  25.  *
  26.  *  Copyright (C) 1991, 1992  Linus Torvalds
  27.  *
  28.  *  Big-endian to little-endian byte-swapping/bitmaps by
  29.  *        David S. Miller (davem@caip.rutgers.edu), 1995
  30.  */
  31. #include <linux/fs.h>
  32. #include <linux/ext2_fs.h>
  33. #include <linux/pagemap.h>
  34. /*
  35.  * Couple of helper functions - make the code slightly cleaner.
  36.  */
  37. static inline void ext2_inc_count(struct inode *inode)
  38. {
  39. inode->i_nlink++;
  40. mark_inode_dirty(inode);
  41. }
  42. static inline void ext2_dec_count(struct inode *inode)
  43. {
  44. inode->i_nlink--;
  45. mark_inode_dirty(inode);
  46. }
  47. static inline int ext2_add_nondir(struct dentry *dentry, struct inode *inode)
  48. {
  49. int err = ext2_add_link(dentry, inode);
  50. if (!err) {
  51. d_instantiate(dentry, inode);
  52. return 0;
  53. }
  54. ext2_dec_count(inode);
  55. iput(inode);
  56. return err;
  57. }
  58. /*
  59.  * Methods themselves.
  60.  */
  61. static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry)
  62. {
  63. struct inode * inode;
  64. ino_t ino;
  65. if (dentry->d_name.len > EXT2_NAME_LEN)
  66. return ERR_PTR(-ENAMETOOLONG);
  67. ino = ext2_inode_by_name(dir, dentry);
  68. inode = NULL;
  69. if (ino) {
  70. inode = iget(dir->i_sb, ino);
  71. if (!inode) 
  72. return ERR_PTR(-EACCES);
  73. }
  74. d_add(dentry, inode);
  75. return NULL;
  76. }
  77. /*
  78.  * By the time this is called, we already have created
  79.  * the directory cache entry for the new file, but it
  80.  * is so far negative - it has no inode.
  81.  *
  82.  * If the create succeeds, we fill in the inode information
  83.  * with d_instantiate(). 
  84.  */
  85. static int ext2_create (struct inode * dir, struct dentry * dentry, int mode)
  86. {
  87. struct inode * inode = ext2_new_inode (dir, mode);
  88. int err = PTR_ERR(inode);
  89. if (!IS_ERR(inode)) {
  90. inode->i_op = &ext2_file_inode_operations;
  91. inode->i_fop = &ext2_file_operations;
  92. inode->i_mapping->a_ops = &ext2_aops;
  93. mark_inode_dirty(inode);
  94. err = ext2_add_nondir(dentry, inode);
  95. }
  96. return err;
  97. }
  98. static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
  99. {
  100. struct inode * inode = ext2_new_inode (dir, mode);
  101. int err = PTR_ERR(inode);
  102. if (!IS_ERR(inode)) {
  103. init_special_inode(inode, mode, rdev);
  104. mark_inode_dirty(inode);
  105. err = ext2_add_nondir(dentry, inode);
  106. }
  107. return err;
  108. }
  109. static int ext2_symlink (struct inode * dir, struct dentry * dentry,
  110. const char * symname)
  111. {
  112. struct super_block * sb = dir->i_sb;
  113. int err = -ENAMETOOLONG;
  114. unsigned l = strlen(symname)+1;
  115. struct inode * inode;
  116. if (l > sb->s_blocksize)
  117. goto out;
  118. inode = ext2_new_inode (dir, S_IFLNK | S_IRWXUGO);
  119. err = PTR_ERR(inode);
  120. if (IS_ERR(inode))
  121. goto out;
  122. if (l > sizeof (inode->u.ext2_i.i_data)) {
  123. /* slow symlink */
  124. inode->i_op = &page_symlink_inode_operations;
  125. inode->i_mapping->a_ops = &ext2_aops;
  126. err = block_symlink(inode, symname, l);
  127. if (err)
  128. goto out_fail;
  129. } else {
  130. /* fast symlink */
  131. inode->i_op = &ext2_fast_symlink_inode_operations;
  132. memcpy((char*)&inode->u.ext2_i.i_data,symname,l);
  133. inode->i_size = l-1;
  134. }
  135. mark_inode_dirty(inode);
  136. err = ext2_add_nondir(dentry, inode);
  137. out:
  138. return err;
  139. out_fail:
  140. ext2_dec_count(inode);
  141. iput (inode);
  142. goto out;
  143. }
  144. static int ext2_link (struct dentry * old_dentry, struct inode * dir,
  145. struct dentry *dentry)
  146. {
  147. struct inode *inode = old_dentry->d_inode;
  148. if (S_ISDIR(inode->i_mode))
  149. return -EPERM;
  150. if (inode->i_nlink >= EXT2_LINK_MAX)
  151. return -EMLINK;
  152. inode->i_ctime = CURRENT_TIME;
  153. ext2_inc_count(inode);
  154. atomic_inc(&inode->i_count);
  155. return ext2_add_nondir(dentry, inode);
  156. }
  157. static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
  158. {
  159. struct inode * inode;
  160. int err = -EMLINK;
  161. if (dir->i_nlink >= EXT2_LINK_MAX)
  162. goto out;
  163. ext2_inc_count(dir);
  164. inode = ext2_new_inode (dir, S_IFDIR | mode);
  165. err = PTR_ERR(inode);
  166. if (IS_ERR(inode))
  167. goto out_dir;
  168. inode->i_op = &ext2_dir_inode_operations;
  169. inode->i_fop = &ext2_dir_operations;
  170. inode->i_mapping->a_ops = &ext2_aops;
  171. ext2_inc_count(inode);
  172. err = ext2_make_empty(inode, dir);
  173. if (err)
  174. goto out_fail;
  175. err = ext2_add_link(dentry, inode);
  176. if (err)
  177. goto out_fail;
  178. d_instantiate(dentry, inode);
  179. out:
  180. return err;
  181. out_fail:
  182. ext2_dec_count(inode);
  183. ext2_dec_count(inode);
  184. iput(inode);
  185. out_dir:
  186. ext2_dec_count(dir);
  187. goto out;
  188. }
  189. static int ext2_unlink(struct inode * dir, struct dentry *dentry)
  190. {
  191. struct inode * inode = dentry->d_inode;
  192. struct ext2_dir_entry_2 * de;
  193. struct page * page;
  194. int err = -ENOENT;
  195. de = ext2_find_entry (dir, dentry, &page);
  196. if (!de)
  197. goto out;
  198. err = ext2_delete_entry (de, page);
  199. if (err)
  200. goto out;
  201. inode->i_ctime = dir->i_ctime;
  202. ext2_dec_count(inode);
  203. err = 0;
  204. out:
  205. return err;
  206. }
  207. static int ext2_rmdir (struct inode * dir, struct dentry *dentry)
  208. {
  209. struct inode * inode = dentry->d_inode;
  210. int err = -ENOTEMPTY;
  211. if (ext2_empty_dir(inode)) {
  212. err = ext2_unlink(dir, dentry);
  213. if (!err) {
  214. inode->i_size = 0;
  215. ext2_dec_count(inode);
  216. ext2_dec_count(dir);
  217. }
  218. }
  219. return err;
  220. }
  221. static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry,
  222. struct inode * new_dir, struct dentry * new_dentry )
  223. {
  224. struct inode * old_inode = old_dentry->d_inode;
  225. struct inode * new_inode = new_dentry->d_inode;
  226. struct page * dir_page = NULL;
  227. struct ext2_dir_entry_2 * dir_de = NULL;
  228. struct page * old_page;
  229. struct ext2_dir_entry_2 * old_de;
  230. int err = -ENOENT;
  231. old_de = ext2_find_entry (old_dir, old_dentry, &old_page);
  232. if (!old_de)
  233. goto out;
  234. if (S_ISDIR(old_inode->i_mode)) {
  235. err = -EIO;
  236. dir_de = ext2_dotdot(old_inode, &dir_page);
  237. if (!dir_de)
  238. goto out_old;
  239. }
  240. if (new_inode) {
  241. struct page *new_page;
  242. struct ext2_dir_entry_2 *new_de;
  243. err = -ENOTEMPTY;
  244. if (dir_de && !ext2_empty_dir (new_inode))
  245. goto out_dir;
  246. err = -ENOENT;
  247. new_de = ext2_find_entry (new_dir, new_dentry, &new_page);
  248. if (!new_de)
  249. goto out_dir;
  250. ext2_inc_count(old_inode);
  251. ext2_set_link(new_dir, new_de, new_page, old_inode);
  252. new_inode->i_ctime = CURRENT_TIME;
  253. if (dir_de)
  254. new_inode->i_nlink--;
  255. ext2_dec_count(new_inode);
  256. } else {
  257. if (dir_de) {
  258. err = -EMLINK;
  259. if (new_dir->i_nlink >= EXT2_LINK_MAX)
  260. goto out_dir;
  261. }
  262. ext2_inc_count(old_inode);
  263. err = ext2_add_link(new_dentry, old_inode);
  264. if (err) {
  265. ext2_dec_count(old_inode);
  266. goto out_dir;
  267. }
  268. if (dir_de)
  269. ext2_inc_count(new_dir);
  270. }
  271. ext2_delete_entry (old_de, old_page);
  272. ext2_dec_count(old_inode);
  273. if (dir_de) {
  274. ext2_set_link(old_inode, dir_de, dir_page, new_dir);
  275. ext2_dec_count(old_dir);
  276. }
  277. return 0;
  278. out_dir:
  279. if (dir_de) {
  280. kunmap(dir_page);
  281. page_cache_release(dir_page);
  282. }
  283. out_old:
  284. kunmap(old_page);
  285. page_cache_release(old_page);
  286. out:
  287. return err;
  288. }
  289. struct inode_operations ext2_dir_inode_operations = {
  290. create: ext2_create,
  291. lookup: ext2_lookup,
  292. link: ext2_link,
  293. unlink: ext2_unlink,
  294. symlink: ext2_symlink,
  295. mkdir: ext2_mkdir,
  296. rmdir: ext2_rmdir,
  297. mknod: ext2_mknod,
  298. rename: ext2_rename,
  299. };