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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * JFFS2 -- Journalling Flash File System, Version 2.
  3.  *
  4.  * Copyright (C) 2001 Red Hat, Inc.
  5.  *
  6.  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  7.  *
  8.  * The original JFFS, from which the design for JFFS2 was derived,
  9.  * was designed and implemented by Axis Communications AB.
  10.  *
  11.  * The contents of this file are subject to the Red Hat eCos Public
  12.  * License Version 1.1 (the "Licence"); you may not use this file
  13.  * except in compliance with the Licence.  You may obtain a copy of
  14.  * the Licence at http://www.redhat.com/
  15.  *
  16.  * Software distributed under the Licence is distributed on an "AS IS"
  17.  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
  18.  * See the Licence for the specific language governing rights and
  19.  * limitations under the Licence.
  20.  *
  21.  * The Original Code is JFFS2 - Journalling Flash File System, version 2
  22.  *
  23.  * Alternatively, the contents of this file may be used under the
  24.  * terms of the GNU General Public License version 2 (the "GPL"), in
  25.  * which case the provisions of the GPL are applicable instead of the
  26.  * above.  If you wish to allow the use of your version of this file
  27.  * only under the terms of the GPL and not to allow others to use your
  28.  * version of this file under the RHEPL, indicate your decision by
  29.  * deleting the provisions above and replace them with the notice and
  30.  * other provisions required by the GPL.  If you do not delete the
  31.  * provisions above, a recipient may use your version of this file
  32.  * under either the RHEPL or the GPL.
  33.  *
  34.  * $Id: dir.c,v 1.45.2.7 2002/08/26 15:30:18 dwmw2 Exp $
  35.  *
  36.  */
  37. #include <linux/kernel.h>
  38. #include <linux/slab.h>
  39. #include <linux/fs.h>
  40. #include <linux/mtd/compatmac.h> /* For completion */
  41. #include <linux/jffs2.h>
  42. #include <linux/jffs2_fs_i.h>
  43. #include <linux/jffs2_fs_sb.h>
  44. #include "nodelist.h"
  45. #include "crc32.h"
  46. static int jffs2_readdir (struct file *, void *, filldir_t);
  47. static int jffs2_create (struct inode *,struct dentry *,int);
  48. static struct dentry *jffs2_lookup (struct inode *,struct dentry *);
  49. static int jffs2_link (struct dentry *,struct inode *,struct dentry *);
  50. static int jffs2_unlink (struct inode *,struct dentry *);
  51. static int jffs2_symlink (struct inode *,struct dentry *,const char *);
  52. static int jffs2_mkdir (struct inode *,struct dentry *,int);
  53. static int jffs2_rmdir (struct inode *,struct dentry *);
  54. static int jffs2_mknod (struct inode *,struct dentry *,int,int);
  55. static int jffs2_rename (struct inode *, struct dentry *,
  56.                         struct inode *, struct dentry *);
  57. struct file_operations jffs2_dir_operations =
  58. {
  59. read: generic_read_dir,
  60. readdir: jffs2_readdir,
  61. ioctl: jffs2_ioctl,
  62. fsync: jffs2_null_fsync
  63. };
  64. struct inode_operations jffs2_dir_inode_operations =
  65. {
  66. create: jffs2_create,
  67. lookup: jffs2_lookup,
  68. link: jffs2_link,
  69. unlink: jffs2_unlink,
  70. symlink: jffs2_symlink,
  71. mkdir: jffs2_mkdir,
  72. rmdir: jffs2_rmdir,
  73. mknod: jffs2_mknod,
  74. rename: jffs2_rename,
  75. setattr: jffs2_setattr,
  76. };
  77. /***********************************************************************/
  78. /* We keep the dirent list sorted in increasing order of name hash,
  79.    and we use the same hash function as the dentries. Makes this 
  80.    nice and simple
  81. */
  82. static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target)
  83. {
  84. struct jffs2_inode_info *dir_f;
  85. struct jffs2_sb_info *c;
  86. struct jffs2_full_dirent *fd = NULL, *fd_list;
  87. __u32 ino = 0;
  88. struct inode *inode = NULL;
  89. D1(printk(KERN_DEBUG "jffs2_lookup()n"));
  90. dir_f = JFFS2_INODE_INFO(dir_i);
  91. c = JFFS2_SB_INFO(dir_i->i_sb);
  92. down(&dir_f->sem);
  93. /* NB: The 2.2 backport will need to explicitly check for '.' and '..' here */
  94. for (fd_list = dir_f->dents; fd_list && fd_list->nhash <= target->d_name.hash; fd_list = fd_list->next) {
  95. if (fd_list->nhash == target->d_name.hash && 
  96.     (!fd || fd_list->version > fd->version) &&
  97.     strlen(fd_list->name) == target->d_name.len &&
  98.     !strncmp(fd_list->name, target->d_name.name, target->d_name.len)) {
  99. fd = fd_list;
  100. }
  101. }
  102. if (fd)
  103. ino = fd->ino;
  104. up(&dir_f->sem);
  105. if (ino) {
  106. inode = iget(dir_i->i_sb, ino);
  107. if (!inode) {
  108. printk(KERN_WARNING "iget() failed for ino #%un", ino);
  109. return (ERR_PTR(-EIO));
  110. }
  111. }
  112. d_add(target, inode);
  113. return NULL;
  114. }
  115. /***********************************************************************/
  116. static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
  117. {
  118. struct jffs2_inode_info *f;
  119. struct jffs2_sb_info *c;
  120. struct inode *inode = filp->f_dentry->d_inode;
  121. struct jffs2_full_dirent *fd;
  122. unsigned long offset, curofs;
  123. D1(printk(KERN_DEBUG "jffs2_readdir() for dir_i #%lun", filp->f_dentry->d_inode->i_ino));
  124. f = JFFS2_INODE_INFO(inode);
  125. c = JFFS2_SB_INFO(inode->i_sb);
  126. offset = filp->f_pos;
  127. if (offset == 0) {
  128. D1(printk(KERN_DEBUG "Dirent 0: ".", ino #%lun", inode->i_ino));
  129. if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0)
  130. goto out;
  131. offset++;
  132. }
  133. if (offset == 1) {
  134. D1(printk(KERN_DEBUG "Dirent 1: "..", ino #%lun", filp->f_dentry->d_parent->d_inode->i_ino));
  135. if (filldir(dirent, "..", 2, 1, filp->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0)
  136. goto out;
  137. offset++;
  138. }
  139. curofs=1;
  140. down(&f->sem);
  141. for (fd = f->dents; fd; fd = fd->next) {
  142. curofs++;
  143. /* First loop: curofs = 2; offset = 2 */
  144. if (curofs < offset) {
  145. D2(printk(KERN_DEBUG "Skipping dirent: "%s", ino #%u, type %d, because curofs %ld < offset %ldn", 
  146.   fd->name, fd->ino, fd->type, curofs, offset));
  147. continue;
  148. }
  149. if (!fd->ino) {
  150. D2(printk(KERN_DEBUG "Skipping deletion dirent "%s"n", fd->name));
  151. offset++;
  152. continue;
  153. }
  154. D2(printk(KERN_DEBUG "Dirent %ld: "%s", ino #%u, type %dn", offset, fd->name, fd->ino, fd->type));
  155. if (filldir(dirent, fd->name, strlen(fd->name), offset, fd->ino, fd->type) < 0)
  156. break;
  157. offset++;
  158. }
  159. up(&f->sem);
  160.  out:
  161. filp->f_pos = offset;
  162. return 0;
  163. }
  164. /***********************************************************************/
  165. static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode)
  166. {
  167. struct jffs2_inode_info *f, *dir_f;
  168. struct jffs2_sb_info *c;
  169. struct inode *inode;
  170. struct jffs2_raw_inode *ri;
  171. struct jffs2_raw_dirent *rd;
  172. struct jffs2_full_dnode *fn;
  173. struct jffs2_full_dirent *fd;
  174. int namelen;
  175. __u32 alloclen, phys_ofs;
  176. __u32 writtenlen;
  177. int ret;
  178. ri = jffs2_alloc_raw_inode();
  179. if (!ri)
  180. return -ENOMEM;
  181. c = JFFS2_SB_INFO(dir_i->i_sb);
  182. D1(printk(KERN_DEBUG "jffs2_create()n"));
  183. /* Try to reserve enough space for both node and dirent. 
  184.  * Just the node will do for now, though 
  185.  */
  186. namelen = dentry->d_name.len;
  187. ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL);
  188. D1(printk(KERN_DEBUG "jffs2_create(): reserved 0x%x bytesn", alloclen));
  189. if (ret) {
  190. jffs2_free_raw_inode(ri);
  191. return ret;
  192. }
  193. inode = jffs2_new_inode(dir_i, mode, ri);
  194. if (IS_ERR(inode)) {
  195. D1(printk(KERN_DEBUG "jffs2_new_inode() failedn"));
  196. jffs2_free_raw_inode(ri);
  197. jffs2_complete_reservation(c);
  198. return PTR_ERR(inode);
  199. }
  200. inode->i_op = &jffs2_file_inode_operations;
  201. inode->i_fop = &jffs2_file_operations;
  202. inode->i_mapping->a_ops = &jffs2_file_address_operations;
  203. inode->i_mapping->nrpages = 0;
  204. f = JFFS2_INODE_INFO(inode);
  205. ri->data_crc = 0;
  206. ri->node_crc = crc32(0, ri, sizeof(*ri)-8);
  207. fn = jffs2_write_dnode(inode, ri, NULL, 0, phys_ofs, &writtenlen);
  208. D1(printk(KERN_DEBUG "jffs2_create created file with mode 0x%xn", ri->mode));
  209. jffs2_free_raw_inode(ri);
  210. if (IS_ERR(fn)) {
  211. D1(printk(KERN_DEBUG "jffs2_write_dnode() failedn"));
  212. /* Eeek. Wave bye bye */
  213. up(&f->sem);
  214. jffs2_complete_reservation(c);
  215. jffs2_clear_inode(inode);
  216. return PTR_ERR(fn);
  217. }
  218. /* No data here. Only a metadata node, which will be 
  219.    obsoleted by the first data write
  220. */
  221. f->metadata = fn;
  222. /* Work out where to put the dirent node now. */
  223. writtenlen = PAD(writtenlen);
  224. phys_ofs += writtenlen;
  225. alloclen -= writtenlen;
  226. up(&f->sem);
  227. if (alloclen < sizeof(*rd)+namelen) {
  228. /* Not enough space left in this chunk. Get some more */
  229. jffs2_complete_reservation(c);
  230. ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL);
  231. if (ret) {
  232. /* Eep. */
  233. D1(printk(KERN_DEBUG "jffs2_reserve_space() for dirent failedn"));
  234. jffs2_clear_inode(inode);
  235. return ret;
  236. }
  237. }
  238. rd = jffs2_alloc_raw_dirent();
  239. if (!rd) {
  240. /* Argh. Now we treat it like a normal delete */
  241. jffs2_complete_reservation(c);
  242. jffs2_clear_inode(inode);
  243. return -ENOMEM;
  244. }
  245. dir_f = JFFS2_INODE_INFO(dir_i);
  246. down(&dir_f->sem);
  247. rd->magic = JFFS2_MAGIC_BITMASK;
  248. rd->nodetype = JFFS2_NODETYPE_DIRENT;
  249. rd->totlen = sizeof(*rd) + namelen;
  250. rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4);
  251. rd->pino = dir_i->i_ino;
  252. rd->version = ++dir_f->highest_version;
  253. rd->ino = inode->i_ino;
  254. rd->mctime = CURRENT_TIME;
  255. rd->nsize = namelen;
  256. rd->type = DT_REG;
  257. rd->node_crc = crc32(0, rd, sizeof(*rd)-8);
  258. rd->name_crc = crc32(0, dentry->d_name.name, namelen);
  259. fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen);
  260. jffs2_complete_reservation(c);
  261. if (IS_ERR(fd)) {
  262. /* dirent failed to write. Delete the inode normally 
  263.    as if it were the final unlink() */
  264. jffs2_free_raw_dirent(rd);
  265. up(&dir_f->sem);
  266. jffs2_clear_inode(inode);
  267. return PTR_ERR(fd);
  268. }
  269. dir_i->i_mtime = dir_i->i_ctime = rd->mctime;
  270. jffs2_free_raw_dirent(rd);
  271. /* Link the fd into the inode's list, obsoleting an old
  272.    one if necessary. */
  273. jffs2_add_fd_to_list(c, fd, &dir_f->dents);
  274. up(&dir_f->sem);
  275. d_instantiate(dentry, inode);
  276. D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d). nrpages %ldn",
  277.   inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink, inode->i_mapping->nrpages));
  278. return 0;
  279. }
  280. /***********************************************************************/
  281. static int jffs2_do_unlink(struct inode *dir_i, struct dentry *dentry, int rename)
  282. {
  283. struct jffs2_inode_info *dir_f, *f;
  284. struct jffs2_sb_info *c;
  285. struct jffs2_raw_dirent *rd;
  286. struct jffs2_full_dirent *fd;
  287. __u32 alloclen, phys_ofs;
  288. int ret;
  289. c = JFFS2_SB_INFO(dir_i->i_sb);
  290. rd = jffs2_alloc_raw_dirent();
  291. if (!rd)
  292. return -ENOMEM;
  293. ret = jffs2_reserve_space(c, sizeof(*rd)+dentry->d_name.len, &phys_ofs, &alloclen, ALLOC_DELETION);
  294. if (ret) {
  295. jffs2_free_raw_dirent(rd);
  296. return ret;
  297. }
  298. dir_f = JFFS2_INODE_INFO(dir_i);
  299. down(&dir_f->sem);
  300. /* Build a deletion node */
  301. rd->magic = JFFS2_MAGIC_BITMASK;
  302. rd->nodetype = JFFS2_NODETYPE_DIRENT;
  303. rd->totlen = sizeof(*rd) + dentry->d_name.len;
  304. rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4);
  305. rd->pino = dir_i->i_ino;
  306. rd->version = ++dir_f->highest_version;
  307. rd->ino = 0;
  308. rd->mctime = CURRENT_TIME;
  309. rd->nsize = dentry->d_name.len;
  310. rd->type = DT_UNKNOWN;
  311. rd->node_crc = crc32(0, rd, sizeof(*rd)-8);
  312. rd->name_crc = crc32(0, dentry->d_name.name, dentry->d_name.len);
  313. fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, dentry->d_name.len, phys_ofs, NULL);
  314. jffs2_complete_reservation(c);
  315. jffs2_free_raw_dirent(rd);
  316. if (IS_ERR(fd)) {
  317. up(&dir_f->sem);
  318. return PTR_ERR(fd);
  319. }
  320. /* File it. This will mark the old one obsolete. */
  321. jffs2_add_fd_to_list(c, fd, &dir_f->dents);
  322. up(&dir_f->sem);
  323. if (!rename) {
  324. f = JFFS2_INODE_INFO(dentry->d_inode);
  325. down(&f->sem);
  326. while (f->dents) {
  327. /* There can be only deleted ones */
  328. fd = f->dents;
  329. f->dents = fd->next;
  330. if (fd->ino) {
  331. printk(KERN_WARNING "Deleting inode #%u with active dentry "%s"->ino #%un",
  332.        f->inocache->ino, fd->name, fd->ino);
  333. } else {
  334. D1(printk(KERN_DEBUG "Removing deletion dirent for "%s" from dir ino #%un", fd->name, f->inocache->ino));
  335. }
  336. jffs2_mark_node_obsolete(c, fd->raw);
  337. jffs2_free_full_dirent(fd);
  338. }
  339. /* Don't oops on unlinking a bad inode */
  340. if (f->inocache)
  341. f->inocache->nlink--;
  342. dentry->d_inode->i_nlink--;
  343. up(&f->sem);
  344. }
  345. return 0;
  346. }
  347. static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry)
  348. {
  349. return jffs2_do_unlink(dir_i, dentry, 0);
  350. }
  351. /***********************************************************************/
  352. static int jffs2_do_link (struct dentry *old_dentry, struct inode *dir_i, struct dentry *dentry, int rename)
  353. {
  354. struct jffs2_inode_info *dir_f, *f;
  355. struct jffs2_sb_info *c;
  356. struct jffs2_raw_dirent *rd;
  357. struct jffs2_full_dirent *fd;
  358. __u32 alloclen, phys_ofs;
  359. int ret;
  360. c = JFFS2_SB_INFO(dir_i->i_sb);
  361. rd = jffs2_alloc_raw_dirent();
  362. if (!rd)
  363. return -ENOMEM;
  364. ret = jffs2_reserve_space(c, sizeof(*rd)+dentry->d_name.len, &phys_ofs, &alloclen, ALLOC_NORMAL);
  365. if (ret) {
  366. jffs2_free_raw_dirent(rd);
  367. return ret;
  368. }
  369. dir_f = JFFS2_INODE_INFO(dir_i);
  370. down(&dir_f->sem);
  371. /* Build a deletion node */
  372. rd->magic = JFFS2_MAGIC_BITMASK;
  373. rd->nodetype = JFFS2_NODETYPE_DIRENT;
  374. rd->totlen = sizeof(*rd) + dentry->d_name.len;
  375. rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4);
  376. rd->pino = dir_i->i_ino;
  377. rd->version = ++dir_f->highest_version;
  378. rd->ino = old_dentry->d_inode->i_ino;
  379. rd->mctime = CURRENT_TIME;
  380. rd->nsize = dentry->d_name.len;
  381. /* XXX: This is ugly. */
  382. rd->type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12;
  383. if (!rd->type) rd->type = DT_REG;
  384. rd->node_crc = crc32(0, rd, sizeof(*rd)-8);
  385. rd->name_crc = crc32(0, dentry->d_name.name, dentry->d_name.len);
  386. fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, dentry->d_name.len, phys_ofs, NULL);
  387. jffs2_complete_reservation(c);
  388. jffs2_free_raw_dirent(rd);
  389. if (IS_ERR(fd)) {
  390. up(&dir_f->sem);
  391. return PTR_ERR(fd);
  392. }
  393. /* File it. This will mark the old one obsolete. */
  394. jffs2_add_fd_to_list(c, fd, &dir_f->dents);
  395. up(&dir_f->sem);
  396. if (!rename) {
  397. f = JFFS2_INODE_INFO(old_dentry->d_inode);
  398. down(&f->sem);
  399. old_dentry->d_inode->i_nlink = ++f->inocache->nlink;
  400. up(&f->sem);
  401. }
  402. return 0;
  403. }
  404. static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct dentry *dentry)
  405. {
  406. int ret;
  407. /* Can't link a bad inode. */
  408. if (!JFFS2_INODE_INFO(old_dentry->d_inode)->inocache)
  409. return -EIO;
  410. if (S_ISDIR(old_dentry->d_inode->i_mode))
  411. return -EPERM;
  412. ret = jffs2_do_link(old_dentry, dir_i, dentry, 0);
  413. if (!ret) {
  414. d_instantiate(dentry, old_dentry->d_inode);
  415. atomic_inc(&old_dentry->d_inode->i_count);
  416. }
  417. return ret;
  418. }
  419. /***********************************************************************/
  420. static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char *target)
  421. {
  422. struct jffs2_inode_info *f, *dir_f;
  423. struct jffs2_sb_info *c;
  424. struct inode *inode;
  425. struct jffs2_raw_inode *ri;
  426. struct jffs2_raw_dirent *rd;
  427. struct jffs2_full_dnode *fn;
  428. struct jffs2_full_dirent *fd;
  429. int namelen;
  430. __u32 alloclen, phys_ofs;
  431. __u32 writtenlen;
  432. int ret;
  433. /* FIXME: If you care. We'd need to use frags for the target
  434.    if it grows much more than this */
  435. if (strlen(target) > 254)
  436. return -EINVAL;
  437. ri = jffs2_alloc_raw_inode();
  438. if (!ri)
  439. return -ENOMEM;
  440. c = JFFS2_SB_INFO(dir_i->i_sb);
  441. /* Try to reserve enough space for both node and dirent. 
  442.  * Just the node will do for now, though 
  443.  */
  444. namelen = dentry->d_name.len;
  445. ret = jffs2_reserve_space(c, sizeof(*ri) + strlen(target), &phys_ofs, &alloclen, ALLOC_NORMAL);
  446. if (ret) {
  447. jffs2_free_raw_inode(ri);
  448. return ret;
  449. }
  450. inode = jffs2_new_inode(dir_i, S_IFLNK | S_IRWXUGO, ri);
  451. if (IS_ERR(inode)) {
  452. jffs2_free_raw_inode(ri);
  453. jffs2_complete_reservation(c);
  454. return PTR_ERR(inode);
  455. }
  456. inode->i_op = &jffs2_symlink_inode_operations;
  457. f = JFFS2_INODE_INFO(inode);
  458. inode->i_size = ri->isize = ri->dsize = ri->csize = strlen(target);
  459. ri->totlen = sizeof(*ri) + ri->dsize;
  460. ri->hdr_crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4);
  461. ri->compr = JFFS2_COMPR_NONE;
  462. ri->data_crc = crc32(0, target, strlen(target));
  463. ri->node_crc = crc32(0, ri, sizeof(*ri)-8);
  464. fn = jffs2_write_dnode(inode, ri, target, strlen(target), phys_ofs, &writtenlen);
  465. jffs2_free_raw_inode(ri);
  466. if (IS_ERR(fn)) {
  467. /* Eeek. Wave bye bye */
  468. up(&f->sem);
  469. jffs2_complete_reservation(c);
  470. jffs2_clear_inode(inode);
  471. return PTR_ERR(fn);
  472. }
  473. /* No data here. Only a metadata node, which will be 
  474.    obsoleted by the first data write
  475. */
  476. f->metadata = fn;
  477. up(&f->sem);
  478. /* Work out where to put the dirent node now. */
  479. writtenlen = (writtenlen+3)&~3;
  480. phys_ofs += writtenlen;
  481. alloclen -= writtenlen;
  482. if (alloclen < sizeof(*rd)+namelen) {
  483. /* Not enough space left in this chunk. Get some more */
  484. jffs2_complete_reservation(c);
  485. ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL);
  486. if (ret) {
  487. /* Eep. */
  488. jffs2_clear_inode(inode);
  489. return ret;
  490. }
  491. }
  492. rd = jffs2_alloc_raw_dirent();
  493. if (!rd) {
  494. /* Argh. Now we treat it like a normal delete */
  495. jffs2_complete_reservation(c);
  496. jffs2_clear_inode(inode);
  497. return -ENOMEM;
  498. }
  499. dir_f = JFFS2_INODE_INFO(dir_i);
  500. down(&dir_f->sem);
  501. rd->magic = JFFS2_MAGIC_BITMASK;
  502. rd->nodetype = JFFS2_NODETYPE_DIRENT;
  503. rd->totlen = sizeof(*rd) + namelen;
  504. rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4);
  505. rd->pino = dir_i->i_ino;
  506. rd->version = ++dir_f->highest_version;
  507. rd->ino = inode->i_ino;
  508. rd->mctime = CURRENT_TIME;
  509. rd->nsize = namelen;
  510. rd->type = DT_LNK;
  511. rd->node_crc = crc32(0, rd, sizeof(*rd)-8);
  512. rd->name_crc = crc32(0, dentry->d_name.name, namelen);
  513. fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen);
  514. jffs2_complete_reservation(c);
  515. if (IS_ERR(fd)) {
  516. /* dirent failed to write. Delete the inode normally 
  517.    as if it were the final unlink() */
  518. jffs2_free_raw_dirent(rd);
  519. up(&dir_f->sem);
  520. jffs2_clear_inode(inode);
  521. return PTR_ERR(fd);
  522. }
  523. dir_i->i_mtime = dir_i->i_ctime = rd->mctime;
  524. jffs2_free_raw_dirent(rd);
  525. /* Link the fd into the inode's list, obsoleting an old
  526.    one if necessary. */
  527. jffs2_add_fd_to_list(c, fd, &dir_f->dents);
  528. up(&dir_f->sem);
  529. d_instantiate(dentry, inode);
  530. return 0;
  531. }
  532. static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
  533. {
  534. struct jffs2_inode_info *f, *dir_f;
  535. struct jffs2_sb_info *c;
  536. struct inode *inode;
  537. struct jffs2_raw_inode *ri;
  538. struct jffs2_raw_dirent *rd;
  539. struct jffs2_full_dnode *fn;
  540. struct jffs2_full_dirent *fd;
  541. int namelen;
  542. __u32 alloclen, phys_ofs;
  543. __u32 writtenlen;
  544. int ret;
  545. mode |= S_IFDIR;
  546. ri = jffs2_alloc_raw_inode();
  547. if (!ri)
  548. return -ENOMEM;
  549. c = JFFS2_SB_INFO(dir_i->i_sb);
  550. /* Try to reserve enough space for both node and dirent. 
  551.  * Just the node will do for now, though 
  552.  */
  553. namelen = dentry->d_name.len;
  554. ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL);
  555. if (ret) {
  556. jffs2_free_raw_inode(ri);
  557. return ret;
  558. }
  559. inode = jffs2_new_inode(dir_i, mode, ri);
  560. if (IS_ERR(inode)) {
  561. jffs2_free_raw_inode(ri);
  562. jffs2_complete_reservation(c);
  563. return PTR_ERR(inode);
  564. }
  565. inode->i_op = &jffs2_dir_inode_operations;
  566. inode->i_fop = &jffs2_dir_operations;
  567. f = JFFS2_INODE_INFO(inode);
  568. ri->data_crc = 0;
  569. ri->node_crc = crc32(0, ri, sizeof(*ri)-8);
  570. fn = jffs2_write_dnode(inode, ri, NULL, 0, phys_ofs, &writtenlen);
  571. jffs2_free_raw_inode(ri);
  572. if (IS_ERR(fn)) {
  573. /* Eeek. Wave bye bye */
  574. up(&f->sem);
  575. jffs2_complete_reservation(c);
  576. jffs2_clear_inode(inode);
  577. return PTR_ERR(fn);
  578. }
  579. /* No data here. Only a metadata node, which will be 
  580.    obsoleted by the first data write
  581. */
  582. f->metadata = fn;
  583. up(&f->sem);
  584. /* Work out where to put the dirent node now. */
  585. writtenlen = PAD(writtenlen);
  586. phys_ofs += writtenlen;
  587. alloclen -= writtenlen;
  588. if (alloclen < sizeof(*rd)+namelen) {
  589. /* Not enough space left in this chunk. Get some more */
  590. jffs2_complete_reservation(c);
  591. ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL);
  592. if (ret) {
  593. /* Eep. */
  594. jffs2_clear_inode(inode);
  595. return ret;
  596. }
  597. }
  598. rd = jffs2_alloc_raw_dirent();
  599. if (!rd) {
  600. /* Argh. Now we treat it like a normal delete */
  601. jffs2_complete_reservation(c);
  602. jffs2_clear_inode(inode);
  603. return -ENOMEM;
  604. }
  605. dir_f = JFFS2_INODE_INFO(dir_i);
  606. down(&dir_f->sem);
  607. rd->magic = JFFS2_MAGIC_BITMASK;
  608. rd->nodetype = JFFS2_NODETYPE_DIRENT;
  609. rd->totlen = sizeof(*rd) + namelen;
  610. rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4);
  611. rd->pino = dir_i->i_ino;
  612. rd->version = ++dir_f->highest_version;
  613. rd->ino = inode->i_ino;
  614. rd->mctime = CURRENT_TIME;
  615. rd->nsize = namelen;
  616. rd->type = DT_DIR;
  617. rd->node_crc = crc32(0, rd, sizeof(*rd)-8);
  618. rd->name_crc = crc32(0, dentry->d_name.name, namelen);
  619. fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen);
  620. jffs2_complete_reservation(c);
  621. if (IS_ERR(fd)) {
  622. /* dirent failed to write. Delete the inode normally 
  623.    as if it were the final unlink() */
  624. jffs2_free_raw_dirent(rd);
  625. up(&dir_f->sem);
  626. jffs2_clear_inode(inode);
  627. return PTR_ERR(fd);
  628. }
  629. dir_i->i_mtime = dir_i->i_ctime = rd->mctime;
  630. jffs2_free_raw_dirent(rd);
  631. /* Link the fd into the inode's list, obsoleting an old
  632.    one if necessary. */
  633. jffs2_add_fd_to_list(c, fd, &dir_f->dents);
  634. up(&dir_f->sem);
  635. d_instantiate(dentry, inode);
  636. return 0;
  637. }
  638. static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry)
  639. {
  640. struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode);
  641. struct jffs2_full_dirent *fd;
  642. for (fd = f->dents ; fd; fd = fd->next) {
  643. if (fd->ino)
  644. return -ENOTEMPTY;
  645. }
  646. return jffs2_unlink(dir_i, dentry);
  647. }
  648. static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, int rdev)
  649. {
  650. struct jffs2_inode_info *f, *dir_f;
  651. struct jffs2_sb_info *c;
  652. struct inode *inode;
  653. struct jffs2_raw_inode *ri;
  654. struct jffs2_raw_dirent *rd;
  655. struct jffs2_full_dnode *fn;
  656. struct jffs2_full_dirent *fd;
  657. int namelen;
  658. unsigned short dev;
  659. int devlen = 0;
  660. __u32 alloclen, phys_ofs;
  661. __u32 writtenlen;
  662. int ret;
  663. ri = jffs2_alloc_raw_inode();
  664. if (!ri)
  665. return -ENOMEM;
  666. c = JFFS2_SB_INFO(dir_i->i_sb);
  667. if (S_ISBLK(mode) || S_ISCHR(mode)) {
  668. dev = (MAJOR(to_kdev_t(rdev)) << 8) | MINOR(to_kdev_t(rdev));
  669. devlen = sizeof(dev);
  670. }
  671. /* Try to reserve enough space for both node and dirent. 
  672.  * Just the node will do for now, though 
  673.  */
  674. namelen = dentry->d_name.len;
  675. ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &phys_ofs, &alloclen, ALLOC_NORMAL);
  676. if (ret) {
  677. jffs2_free_raw_inode(ri);
  678. return ret;
  679. }
  680. inode = jffs2_new_inode(dir_i, mode, ri);
  681. if (IS_ERR(inode)) {
  682. jffs2_free_raw_inode(ri);
  683. jffs2_complete_reservation(c);
  684. return PTR_ERR(inode);
  685. }
  686. inode->i_op = &jffs2_file_inode_operations;
  687. init_special_inode(inode, inode->i_mode, rdev);
  688. f = JFFS2_INODE_INFO(inode);
  689. ri->dsize = ri->csize = devlen;
  690. ri->totlen = sizeof(*ri) + ri->csize;
  691. ri->hdr_crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4);
  692. ri->compr = JFFS2_COMPR_NONE;
  693. ri->data_crc = crc32(0, &dev, devlen);
  694. ri->node_crc = crc32(0, ri, sizeof(*ri)-8);
  695. fn = jffs2_write_dnode(inode, ri, (char *)&dev, devlen, phys_ofs, &writtenlen);
  696. jffs2_free_raw_inode(ri);
  697. if (IS_ERR(fn)) {
  698. /* Eeek. Wave bye bye */
  699. up(&f->sem);
  700. jffs2_complete_reservation(c);
  701. jffs2_clear_inode(inode);
  702. return PTR_ERR(fn);
  703. }
  704. /* No data here. Only a metadata node, which will be 
  705.    obsoleted by the first data write
  706. */
  707. f->metadata = fn;
  708. up(&f->sem);
  709. /* Work out where to put the dirent node now. */
  710. writtenlen = (writtenlen+3)&~3;
  711. phys_ofs += writtenlen;
  712. alloclen -= writtenlen;
  713. if (alloclen < sizeof(*rd)+namelen) {
  714. /* Not enough space left in this chunk. Get some more */
  715. jffs2_complete_reservation(c);
  716. ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL);
  717. if (ret) {
  718. /* Eep. */
  719. jffs2_clear_inode(inode);
  720. return ret;
  721. }
  722. }
  723. rd = jffs2_alloc_raw_dirent();
  724. if (!rd) {
  725. /* Argh. Now we treat it like a normal delete */
  726. jffs2_complete_reservation(c);
  727. jffs2_clear_inode(inode);
  728. return -ENOMEM;
  729. }
  730. dir_f = JFFS2_INODE_INFO(dir_i);
  731. down(&dir_f->sem);
  732. rd->magic = JFFS2_MAGIC_BITMASK;
  733. rd->nodetype = JFFS2_NODETYPE_DIRENT;
  734. rd->totlen = sizeof(*rd) + namelen;
  735. rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4);
  736. rd->pino = dir_i->i_ino;
  737. rd->version = ++dir_f->highest_version;
  738. rd->ino = inode->i_ino;
  739. rd->mctime = CURRENT_TIME;
  740. rd->nsize = namelen;
  741. /* XXX: This is ugly. */
  742. rd->type = (mode & S_IFMT) >> 12;
  743. rd->node_crc = crc32(0, rd, sizeof(*rd)-8);
  744. rd->name_crc = crc32(0, dentry->d_name.name, namelen);
  745. fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen);
  746. jffs2_complete_reservation(c);
  747. if (IS_ERR(fd)) {
  748. /* dirent failed to write. Delete the inode normally 
  749.    as if it were the final unlink() */
  750. jffs2_free_raw_dirent(rd);
  751. up(&dir_f->sem);
  752. jffs2_clear_inode(inode);
  753. return PTR_ERR(fd);
  754. }
  755. dir_i->i_mtime = dir_i->i_ctime = rd->mctime;
  756. jffs2_free_raw_dirent(rd);
  757. /* Link the fd into the inode's list, obsoleting an old
  758.    one if necessary. */
  759. jffs2_add_fd_to_list(c, fd, &dir_f->dents);
  760. up(&dir_f->sem);
  761. d_instantiate(dentry, inode);
  762. return 0;
  763. }
  764. static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
  765.                         struct inode *new_dir_i, struct dentry *new_dentry)
  766. {
  767. int ret;
  768. struct jffs2_inode_info *victim_f = NULL;
  769. /* The VFS will check for us and prevent trying to rename a 
  770.  * file over a directory and vice versa, but if it's a directory,
  771.  * the VFS can't check whether the victim is empty. The filesystem
  772.  * needs to do that for itself.
  773.  */
  774. if (new_dentry->d_inode) {
  775. victim_f = JFFS2_INODE_INFO(new_dentry->d_inode);
  776. if (S_ISDIR(new_dentry->d_inode->i_mode)) {
  777. struct jffs2_full_dirent *fd;
  778. down(&victim_f->sem);
  779. for (fd = victim_f->dents; fd; fd = fd->next) {
  780. if (fd->ino) {
  781. up(&victim_f->sem);
  782. return -ENOTEMPTY;
  783. }
  784. }
  785. up(&victim_f->sem);
  786. }
  787. }
  788. /* XXX: We probably ought to alloc enough space for
  789.    both nodes at the same time. Writing the new link, 
  790.    then getting -ENOSPC, is quite bad :)
  791. */
  792. /* Make a hard link */
  793. ret = jffs2_do_link(old_dentry, new_dir_i, new_dentry, 1);
  794. if (ret)
  795. return ret;
  796. if (victim_f) {
  797. /* There was a victim. Kill it off nicely */
  798. new_dentry->d_inode->i_nlink--;
  799. /* Don't oops if the victim was a dirent pointing to an
  800.    inode which didn't exist. */
  801. if (victim_f->inocache) {
  802. down(&victim_f->sem);
  803. victim_f->inocache->nlink--;
  804. up(&victim_f->sem);
  805. }
  806. }
  807. /* Unlink the original */
  808. ret = jffs2_do_unlink(old_dir_i, old_dentry, 1);
  809. if (ret) {
  810. /* Oh shit. We really ought to make a single node which can do both atomically */
  811. struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode);
  812. down(&f->sem);
  813. if (f->inocache)
  814. old_dentry->d_inode->i_nlink = f->inocache->nlink++;
  815. up(&f->sem);
  816.        
  817. printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard linkn", ret);
  818. /* Might as well let the VFS know */
  819. d_instantiate(new_dentry, old_dentry->d_inode);
  820. atomic_inc(&old_dentry->d_inode->i_count);
  821. }
  822. return ret;
  823. }