Advertisement
Guest User

linux.add_rfs_1.2.2p1-rc2.patch

a guest
Mar 10th, 2011
2,537
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 399.00 KB | None | 0 0
  1. diff -NurbB linux-2.6.17.14.orig/fs/rfs/cluster.c linux-2.6.17.14.rfs/fs/rfs/cluster.c
  2. --- linux-2.6.17.14.orig/fs/rfs/cluster.c 1970-01-01 01:00:00.000000000 +0100
  3. +++ linux-2.6.17.14.rfs/fs/rfs/cluster.c 2008-12-12 08:04:51.000000000 +0100
  4. @@ -0,0 +1,1915 @@
  5. +/**
  6. + * @file fs/rfs/cluster.c
  7. + * @brief FAT cluster & FAT table handling functions
  8. + *
  9. + *---------------------------------------------------------------------------*
  10. + * *
  11. + * COPYRIGHT 2003-2007 SAMSUNG ELECTRONICS CO., LTD. *
  12. + * ALL RIGHTS RESERVED *
  13. + * *
  14. + * Permission is hereby granted to licensees of Samsung Electronics *
  15. + * Co., Ltd. products to use or abstract this computer program only in *
  16. + * accordance with the terms of the NAND FLASH MEMORY SOFTWARE LICENSE *
  17. + * AGREEMENT for the sole purpose of implementing a product based on *
  18. + * Samsung Electronics Co., Ltd. products. No other rights to reproduce, *
  19. + * use, or disseminate this computer program, whether in part or in *
  20. + * whole, are granted. *
  21. + * *
  22. + * Samsung Electronics Co., Ltd. makes no representation or warranties *
  23. + * with respect to the performance of this computer program, and *
  24. + * specifically disclaims any responsibility for any damages, *
  25. + * special or consequential, connected with the use of this program. *
  26. + * *
  27. + *---------------------------------------------------------------------------*
  28. + *
  29. + */
  30. +
  31. +#include <linux/fs.h>
  32. +#include <linux/rfs_fs.h>
  33. +
  34. +#include "rfs.h"
  35. +#include "log.h"
  36. +
  37. +/*
  38. + * structure for FAT cache (INCORE)
  39. + */
  40. +struct rfs_fcache {
  41. + unsigned int blkoff;
  42. + unsigned int f_dirty;
  43. + struct buffer_head *f_bh;
  44. + struct list_head list;
  45. +};
  46. +
  47. +/*
  48. + * structure of candidate segment (INCORE)
  49. + */
  50. +struct c_segment {
  51. + unsigned int start_cluster;
  52. + unsigned int last_cluster;
  53. + struct list_head list;
  54. +};
  55. +
  56. +/*
  57. + * structure for map destroy (INCORE)
  58. + */
  59. +struct old_map {
  60. + unsigned int block;
  61. + unsigned int nr_blocks;
  62. + struct list_head list;
  63. +};
  64. +
  65. +#define FAT_CACHE_SIZE 128
  66. +
  67. +#define FAT_CACHE_HEAD(sb) (&(RFS_SB(sb)->fcache_lru_list))
  68. +#define FAT_CACHE_ENTRY(p) list_entry(p, struct rfs_fcache, list)
  69. +#define SEGMENT_ENTRY(p) list_entry(p, struct c_segment, list)
  70. +
  71. +#define IS_CONSECUTION(x, y) ((x + 1) == y ? 1 : 0)
  72. +
  73. +#define IS_POOL_EMPTY(n) ((n) == POOL_RESERVED_CLUSTER)
  74. +
  75. +static int rfs_insert_candidate(struct inode *);
  76. +static int rfs_put_pool(struct super_block *, unsigned int, unsigned int, unsigned int);
  77. +
  78. +/*
  79. + * FAT table manipulations
  80. + */
  81. +
  82. +/**
  83. + * initialize internal fat cache entries and add them into fat cache lru list
  84. + * @param sb super block
  85. + * @return return 0 on success, -ENOMEM on failure
  86. + */
  87. +int rfs_fcache_init(struct super_block *sb)
  88. +{
  89. + struct rfs_fcache *array = NULL;
  90. + int i, len;
  91. +
  92. + len = sizeof(struct rfs_fcache) * FAT_CACHE_SIZE;
  93. + array = (struct rfs_fcache *) kmalloc(len, GFP_KERNEL);
  94. + if (!array) /* memory error */
  95. + return -ENOMEM;
  96. +
  97. + INIT_LIST_HEAD(FAT_CACHE_HEAD(sb));
  98. +
  99. + for (i = 0; i < FAT_CACHE_SIZE; i++) {
  100. + array[i].blkoff = NOT_ASSIGNED;
  101. + array[i].f_dirty = FALSE;
  102. + array[i].f_bh = NULL;
  103. + list_add_tail(&(array[i].list), FAT_CACHE_HEAD(sb));
  104. + }
  105. +
  106. + RFS_SB(sb)->fcache_array = array;
  107. +
  108. + return 0;
  109. +}
  110. +
  111. +/**
  112. + * destroy fat cache entries and free memory for them
  113. + * @param sb super block
  114. + */
  115. +void rfs_fcache_release(struct super_block *sb)
  116. +{
  117. + struct list_head *p;
  118. + struct rfs_fcache *fcache_p = NULL;
  119. +
  120. + /* release buffer head */
  121. + list_for_each(p, FAT_CACHE_HEAD(sb)) {
  122. + fcache_p = FAT_CACHE_ENTRY(p);
  123. + brelse(fcache_p->f_bh);
  124. + }
  125. +
  126. + /* release fcache */
  127. + if (RFS_SB(sb)->fcache_array)
  128. + kfree(RFS_SB(sb)->fcache_array);
  129. +}
  130. +
  131. +/**
  132. + * sync all fat cache entries if dirty flag of them are set
  133. + * @param sb super block
  134. + * @param flush whether to flush or not
  135. + *
  136. + * mark dirty flag of buffer head corresponding with all fat cache entries and nullify them
  137. + */
  138. +void rfs_fcache_sync(struct super_block *sb, int flush)
  139. +{
  140. + struct rfs_fcache *fcache_p;
  141. + struct list_head *head, *p;
  142. +
  143. + head = FAT_CACHE_HEAD(sb);
  144. +
  145. + list_for_each(p, head) {
  146. + fcache_p = FAT_CACHE_ENTRY(p);
  147. + if (fcache_p->f_dirty) {
  148. + rfs_mark_buffer_dirty(fcache_p->f_bh, sb);
  149. + fcache_p->f_dirty = FALSE;
  150. +
  151. + if (unlikely(flush)) {
  152. + ll_rw_block(WRITE, 1, &fcache_p->f_bh);
  153. + wait_on_buffer(fcache_p->f_bh);
  154. + }
  155. + }
  156. + }
  157. +}
  158. +
  159. +/**
  160. + * change status of fat cache entry
  161. + * @param sb super block
  162. + * @param blkoff block number to modify
  163. + *
  164. + * if blkoff is equal to block number(blkoff) fat cache entry, set a dirty flag
  165. + */
  166. +static void rfs_fcache_modified(struct super_block *sb, unsigned int blkoff)
  167. +{
  168. + struct rfs_fcache *fcache_p = NULL;
  169. + struct list_head *p;
  170. +
  171. + list_for_each(p, FAT_CACHE_HEAD(sb)) {
  172. + fcache_p = FAT_CACHE_ENTRY(p);
  173. + if (fcache_p->blkoff == blkoff) {
  174. + fcache_p->f_dirty = TRUE;
  175. + return;
  176. + }
  177. + }
  178. +}
  179. +
  180. +/**
  181. + * append fat cache entry to fcache lru list
  182. + * @param sb super block
  183. + * @param blkoff block number of fat cache entry
  184. + * @return return buffer head corrsponding with fat cache entry on success, NULL on failure
  185. + */
  186. +static struct buffer_head *rfs_fcache_add(struct super_block *sb, unsigned int blkoff)
  187. +{
  188. + struct rfs_fcache *fcache_p;
  189. + struct buffer_head *bh;
  190. + struct list_head *head, *p;
  191. +
  192. + head = FAT_CACHE_HEAD(sb);
  193. +
  194. +retry:
  195. + p = head->prev;
  196. + fcache_p = FAT_CACHE_ENTRY(p);
  197. + while (fcache_p->f_bh && fcache_p->f_dirty && p != head) {
  198. + /* We flush the dirty FAT caches only in fat_sync() */
  199. + p = p->prev;
  200. + fcache_p = FAT_CACHE_ENTRY(p);
  201. + }
  202. +
  203. + if (unlikely(p == head)) {
  204. + /* there is no clean fat cache. So, perform fat cache flush */
  205. + rfs_fcache_sync(sb, 1);
  206. + goto retry;
  207. + }
  208. +
  209. + brelse(fcache_p->f_bh);
  210. +
  211. + /*
  212. + * initialize fat cache with some effort
  213. + * because possible error of following sb_bread() makes it false
  214. + */
  215. + fcache_p->f_bh = NULL;
  216. + fcache_p->blkoff = NOT_ASSIGNED;
  217. +
  218. + bh = rfs_bread(sb, blkoff, BH_RFS_FAT);
  219. + if (!bh) { /* I/O error */
  220. + DPRINTK("can't get buffer head related with fat block\n");
  221. + return NULL;
  222. + }
  223. +
  224. + /* fill fcache */
  225. + fcache_p->blkoff = blkoff;
  226. + fcache_p->f_dirty = FALSE; /* just read */
  227. + fcache_p->f_bh = bh;
  228. +
  229. + list_move(p, head);
  230. +
  231. + return bh;
  232. +}
  233. +
  234. +/**
  235. + * lookup fat cache entry by using blkoff
  236. + * @param sb super block
  237. + * @param blkoff block number
  238. + * @return buffer head of fat cache entry
  239. + *
  240. + * if fat cache entry doesn't exist, get free fat entry and fill it
  241. + */
  242. +static struct buffer_head *rfs_fcache_get(struct super_block *sb, unsigned int blkoff)
  243. +{
  244. + struct rfs_fcache *fcache_p = NULL;
  245. + struct list_head *head, *p;
  246. +
  247. + /* find fcache entry included blkoff */
  248. + head = FAT_CACHE_HEAD(sb);
  249. + list_for_each(p, head) {
  250. + fcache_p = FAT_CACHE_ENTRY(p);
  251. + if (fcache_p->blkoff == blkoff) {
  252. + /* Update LRU list */
  253. + if (p != head->next)
  254. + list_move(p, head);
  255. + return fcache_p->f_bh; /* found */
  256. + }
  257. + }
  258. +
  259. + return rfs_fcache_add(sb, blkoff);
  260. +}
  261. +
  262. +/**
  263. + * read a block that contains a fat entry
  264. + * @param sb super block
  265. + * @param[in, out] index index number of fat entry to calculate block number
  266. + * @param[out] blocknr block number corresponding to index
  267. + * @return buffer head of fat cache entry which include a fat entry
  268. + */
  269. +static struct buffer_head *fat_read_block(struct super_block *sb, unsigned int *index, unsigned int *blocknr)
  270. +{
  271. + unsigned int block, offset = *index;
  272. +
  273. + if (IS_FAT16(RFS_SB(sb)))
  274. + offset = (offset << 1) + RFS_SB(sb)->fat_start_addr;
  275. + else if (IS_FAT32(RFS_SB(sb)))
  276. + offset = (offset << 2) + RFS_SB(sb)->fat_start_addr;
  277. +
  278. + block = offset >> sb->s_blocksize_bits;
  279. +
  280. + *index = offset;
  281. + *blocknr = block;
  282. +
  283. + return rfs_fcache_get(sb, block);
  284. +}
  285. +
  286. +/**
  287. + * read a fat entry in fat table
  288. + * @param sb super block
  289. + * @param location location to read a fat entry
  290. + * @param[out] content content cluster number which is saved in fat entry
  291. + * @return return 0 on sucess, EIO on failure
  292. + */
  293. +int fat_read(struct super_block *sb, unsigned int location, unsigned int *content)
  294. +{
  295. + struct buffer_head *bh = NULL;
  296. + unsigned int index = location, dummy;
  297. +
  298. + if (IS_INVAL_CLU(RFS_SB(sb), location)) {
  299. + /* out-of-range input */
  300. + RFS_BUG("invalid cluster number(%u)\n", location);
  301. + return -EINVAL;
  302. + }
  303. +
  304. + if (!(bh = fat_read_block(sb, &index, &dummy))) { /* I/O error */
  305. + RFS_BUG("can't get buffer head related with fat block\n");
  306. + return -EIO;
  307. + }
  308. +
  309. + if (IS_FAT16(RFS_SB(sb))) {
  310. + index &= (sb->s_blocksize - 1);
  311. + *content = GET16(((u16 *)bh->b_data)[index >> 1]);
  312. +
  313. + if (*content >= 0xFFF8)
  314. + *content = CLU_TAIL; /* last cluster of fat chain */
  315. +
  316. + } else if (IS_FAT32(RFS_SB(sb))) {
  317. + index &= (sb->s_blocksize - 1);
  318. + *content = GET32(((u32 *)bh->b_data)[index >> 2]);
  319. +
  320. + if (*content >= 0xFFFFFF8)
  321. + *content = CLU_TAIL; /* last cluster of chain */
  322. + }
  323. +
  324. + /* sanity check */
  325. + if ((*content != CLU_FREE) && (*content != CLU_TAIL)) {
  326. + if (IS_INVAL_CLU(RFS_SB(sb), *content)) {
  327. + RFS_BUG("invalid contents(%u)\n", *content);
  328. + return -EIO;
  329. + }
  330. + }
  331. +
  332. + return 0;
  333. +}
  334. +
  335. +/**
  336. + * write a fat entry in fat table 1 & 2
  337. + * @param sb super block
  338. + * @param location location to write a fat entry
  339. + * @param content next cluster number or end mark of fat chain
  340. + * @return return 0 on sucess, EIO or EINVAL on failure
  341. + * @pre content shouldn't have 0 or 1 which are reserved
  342. + */
  343. +int fat_write(struct super_block *sb, unsigned int location, unsigned int content)
  344. +{
  345. + struct buffer_head *bh;
  346. + unsigned int index = location, block;
  347. +
  348. + if (IS_INVAL_CLU(RFS_SB(sb), location)) {
  349. + /* out-of-range input */
  350. + RFS_BUG("invalid cluster number(%u)\n", location);
  351. + return -EINVAL;
  352. + }
  353. +
  354. + /* sanity check */
  355. + if ((content != CLU_FREE) && (content != CLU_TAIL)) {
  356. + if (IS_INVAL_CLU(RFS_SB(sb), content)) {
  357. + RFS_BUG("invalid contents(%u)\n", content);
  358. + return -EIO;
  359. + }
  360. + }
  361. +
  362. + bh = fat_read_block(sb, &index, &block);
  363. + if (!bh) { /* I/O error */
  364. + RFS_BUG("Can't get buffer head related with fat block\n");
  365. + return -EIO;
  366. + }
  367. +
  368. + if (IS_FAT16(RFS_SB(sb))) {
  369. + index &= sb->s_blocksize - 1;
  370. + content &= 0x0000FFFF;
  371. + SET16(((u16 *)bh->b_data)[index >> 1], content);
  372. +
  373. + } else if (IS_FAT32(RFS_SB(sb))) {
  374. + index &= sb->s_blocksize - 1;
  375. + content &= 0xFFFFFFFF;
  376. + SET32(((u32 *)bh->b_data)[index >> 2], content);
  377. + }
  378. +
  379. + rfs_fcache_modified(sb, block);
  380. +
  381. + return 0;
  382. +}
  383. +
  384. +/*
  385. + * Cluster manipulations
  386. + */
  387. +
  388. +/**
  389. + * find free cluster in fat table
  390. + * @param inode inode
  391. + * @param[out] free_clu free cluster number found
  392. + * @return return 0 on success, errno on failure
  393. + */
  394. +int find_free_cluster(struct inode *inode, unsigned int *free_clu)
  395. +{
  396. + struct rfs_sb_info *sbi = RFS_SB(inode->i_sb);
  397. + unsigned int i;
  398. + int err;
  399. +
  400. + for (i = VALID_CLU; i < sbi->num_clusters; i++) {
  401. + /* search free cluster from hint(search_ptr) */
  402. + if (sbi->search_ptr >= sbi->num_clusters)
  403. + sbi->search_ptr = VALID_CLU;
  404. +
  405. + err = fat_read(inode->i_sb, sbi->search_ptr, free_clu);
  406. + if (!err && *free_clu == 0) {
  407. + *free_clu = sbi->search_ptr++;
  408. + return 0;
  409. + }
  410. + sbi->search_ptr++;
  411. + }
  412. +
  413. + return -ENOSPC;
  414. +}
  415. +
  416. +/**
  417. + * find last cluster and return the number of clusters from specified fat chain of inode
  418. + * @param inode inode
  419. + * @param[out] last_clu last cluster number
  420. + * @return return the number of clusters on success, errno on failure
  421. + */
  422. +int find_last_cluster(struct inode *inode, unsigned int *last_clu)
  423. +{
  424. + struct super_block *sb = inode->i_sb;
  425. + unsigned int prev, next;
  426. + int count = 0;
  427. + int err = 0;
  428. +
  429. + /* set default value */
  430. + if (last_clu)
  431. + *last_clu = CLU_TAIL;
  432. +
  433. + prev = RFS_I(inode)->start_clu;
  434. +
  435. + if (prev == CLU_TAIL) /* cluster dose not be allocated */
  436. + return 0;
  437. +
  438. + fat_lock(sb);
  439. +
  440. + while (1) {
  441. + err = fat_read(sb, prev, &next);
  442. + if (err) {
  443. + fat_unlock(sb);
  444. + return -EIO;
  445. + }
  446. +
  447. + if (next < VALID_CLU) { /* out-of-range input */
  448. + fat_unlock(sb);
  449. + RFS_BUG("fat entry(%u) was corrupted\n", next);
  450. + return -EIO;
  451. + }
  452. +
  453. + count++;
  454. +
  455. + if (next == CLU_TAIL) /* found last clu */
  456. + break;
  457. +
  458. + prev = next;
  459. + }
  460. +
  461. + fat_unlock(sb);
  462. +
  463. + if (last_clu) {
  464. + *last_clu = prev;
  465. + DEBUG(DL2, "last cluster number = %d \n", *last_clu);
  466. + }
  467. +
  468. +
  469. + return count;
  470. +}
  471. +
  472. +/**
  473. + * append new cluster to fat chain of inode
  474. + * @param inode inode
  475. + * @param last_clu current last cluster number of the fat chain
  476. + * @param new_clu new last cluster number to add
  477. + * @return return 0 on success, errno on failure
  478. + */
  479. +int append_new_cluster(struct inode *inode, unsigned int last_clu, unsigned int new_clu)
  480. +{
  481. + int err;
  482. +
  483. + err = fat_write(inode->i_sb, new_clu, CLU_TAIL);
  484. + if (err) {
  485. + DPRINTK("can't write a fat entry(%u)\n", new_clu);
  486. + return err;
  487. + }
  488. +
  489. + err = fat_write(inode->i_sb, last_clu, new_clu);
  490. + if (err) {
  491. + DPRINTK("can't write a fat entry(%u). "
  492. + "cluster(%u) is lost\n", last_clu, new_clu);
  493. + return err;
  494. + }
  495. +
  496. + return err;
  497. +}
  498. +
  499. +/**
  500. + * allocate a new cluster from pool file or fat table
  501. + * @param inode inode
  502. + * @param[out] new_clu new clsuter number to be allocated
  503. + * @param last_clu last clsuter number for logging
  504. + * @return return 0 on success, errno on failure
  505. + */
  506. +static int get_cluster(struct inode *inode, unsigned int *new_clu, unsigned int last_clu)
  507. +{
  508. + struct super_block *sb = inode->i_sb;
  509. + unsigned int pool_prev, pool_next;
  510. + unsigned int clu;
  511. + int where, err;
  512. +
  513. + if (!RFS_SB(sb)->pool_info ||
  514. + IS_POOL_EMPTY(RFS_POOL_I(sb)->num_clusters)) {
  515. + /* alloc-cluster from fat table */
  516. + err = find_free_cluster(inode, &clu);
  517. + if (err)
  518. + return err;
  519. +
  520. + pool_prev = pool_next = CLU_TAIL;
  521. + where = RFS_FAT_TABLE;
  522. + } else {
  523. + /* alloc-cluster from pool file */
  524. + unsigned int dummy;
  525. +
  526. + err = rfs_shrink_pool_chain(sb, &clu,
  527. + 1, &dummy, &pool_next);
  528. + if (err)
  529. + return err;
  530. +
  531. + pool_prev = RFS_POOL_I(sb)->start_cluster;
  532. + where = RFS_POOL;
  533. + }
  534. +
  535. + err = rfs_log_alloc_chain(sb, RFS_I(inode)->p_start_clu,
  536. + RFS_I(inode)->index, pool_prev, pool_next,
  537. + last_clu, CLU_TAIL, 1, &clu);
  538. + if (err)
  539. + return err;
  540. +
  541. + if (where == RFS_POOL) {
  542. + err = rfs_get_pool(sb, pool_next, 1);
  543. + if (err)
  544. + return err;
  545. + }
  546. +
  547. + *new_clu = clu;
  548. + return 0;
  549. +}
  550. +
  551. +/**
  552. + * allocate a new cluster from pool file or fat table
  553. + * @param inode inode
  554. + * @param[out] new_clu new clsuter number to be allocated
  555. + * @return return 0 on success, errno on failure
  556. + *
  557. + * if file write or expand file(truncate), pre-allocation is available
  558. + * if fat table doesn't have a free cluster at normal allocation case, free cluster will be allocated in pool file
  559. + */
  560. +int alloc_cluster(struct inode *inode, unsigned int *new_clu)
  561. +{
  562. + struct super_block *sb = inode->i_sb;
  563. + unsigned int last_clu;
  564. + int is_first = FALSE;
  565. + int err;
  566. +
  567. + if (RFS_I(inode)->start_clu < VALID_CLU) { /* out-of-range input */
  568. + DPRINTK("inode has invalid start cluster(%u)\n",
  569. + RFS_I(inode)->start_clu);
  570. + return -EINVAL;
  571. + }
  572. +
  573. + fat_lock(sb);
  574. +
  575. + if (RFS_I(inode)->start_clu != CLU_TAIL)
  576. + last_clu = RFS_I(inode)->last_clu;
  577. + else
  578. + last_clu = CLU_TAIL;
  579. +
  580. + /* Phase 1 : get one free cluster in source */
  581. + if (tr_pre_alloc(sb)) { /* pre-allocation case */
  582. + err = rfs_log_get_cluster(inode, new_clu);
  583. + if (err)
  584. + goto out;
  585. + } else { /* normal allocation case */
  586. + err = get_cluster(inode, new_clu, last_clu);
  587. + if (err)
  588. + goto out;
  589. + }
  590. +
  591. + /* Phase 2 : append free cluster to end of fat chain related to inode */
  592. + if (RFS_I(inode)->start_clu == CLU_TAIL)
  593. + err = fat_write(sb, *new_clu, CLU_TAIL);
  594. + else
  595. + err = append_new_cluster(inode, last_clu, *new_clu);
  596. + if (err)
  597. + goto out;
  598. +
  599. + /* update start & last cluster */
  600. + if (RFS_I(inode)->start_clu == CLU_TAIL) {
  601. + RFS_I(inode)->start_clu = *new_clu;
  602. + is_first = TRUE;
  603. + }
  604. + RFS_I(inode)->last_clu = *new_clu;
  605. + inode->i_blocks += 1 << (RFS_SB(sb)->cluster_bits - SECTOR_BITS);
  606. +
  607. + RFS_SB(sb)->num_used_clusters++;
  608. +
  609. + /* check rfs-specific inode state */
  610. + if (unlikely(RFS_I(inode)->i_state == RFS_I_FREE)) {
  611. + /* RFS-log : have already logged things about following */
  612. + if (is_first)
  613. + err = rfs_attach_candidate(inode);
  614. + else
  615. + err = rfs_insert_candidate(inode);
  616. + }
  617. +
  618. +out:
  619. + fat_unlock(sb);
  620. +
  621. + return err;
  622. +}
  623. +
  624. +#ifdef CONFIG_RFS_MAPDESTROY
  625. +extern int (*xsr_stl_delete)(dev_t dev, u32 start, u32 nums, u32 b_size);
  626. +#endif
  627. +
  628. +/**
  629. + * destroy stl map corresponding with deallocated clusters
  630. + * @param sb super block
  631. + * @return return 0 on success
  632. + *
  633. + * it is usually invoked after unlink & truncate
  634. + */
  635. +int rfs_map_destroy(struct super_block *sb)
  636. +{
  637. + struct old_map *old_map;
  638. + struct list_head *this, *next;
  639. +
  640. + list_for_each_safe(this, next, &RFS_SB(sb)->free_chunks) {
  641. + old_map = list_entry(this, struct old_map, list);
  642. + if (!old_map) {
  643. + RFS_BUG("Chunk is NULL for fat cleansing\n");
  644. + return -EIO;
  645. + }
  646. + DEBUG(DL2, "block = %d nr_blocks = %d",
  647. + old_map->block, old_map->nr_blocks);
  648. +#ifdef CONFIG_RFS_MAPDESTROY
  649. + xsr_stl_delete(sb->s_dev, old_map->block, old_map->nr_blocks,
  650. + sb->s_blocksize);
  651. +#endif
  652. + /* delete chunk element from list and free them */
  653. + list_del(this);
  654. + kfree(old_map);
  655. + }
  656. +
  657. + /* reinitialize chunk list head */
  658. + list_del_init(&RFS_SB(sb)->free_chunks);
  659. +
  660. + return 0;
  661. +}
  662. +
  663. +/**
  664. + * make a chunk element and add it to chunk list
  665. + * @param sb super block
  666. + * @param start start cluster number to free
  667. + * @param nr_clusters number of clusters to free
  668. + * @return return 0 on success
  669. + */
  670. +static int rfs_add_chunk(struct super_block *sb, unsigned int start, unsigned int nr_clusters)
  671. +{
  672. + struct old_map *old_map;
  673. + unsigned int start_block = START_BLOCK(start, sb);
  674. +
  675. + if (!IS_XSR(sb->s_dev))
  676. + return 0;
  677. +
  678. + if (!nr_clusters)
  679. + return 0;
  680. +
  681. + old_map = (struct old_map *)
  682. + kmalloc(sizeof(struct old_map), GFP_KERNEL);
  683. + if (!old_map) { /* memory error */
  684. + DEBUG(DL1, "memory allocation failed\n");
  685. + return -ENOMEM;
  686. + }
  687. +
  688. + old_map->block = start_block;
  689. + old_map->nr_blocks = nr_clusters << RFS_SB(sb)->blks_per_clu_bits;
  690. + DEBUG(DL2, "start block = %d nr_blocks = %d",
  691. + old_map->block, old_map->nr_blocks);
  692. +
  693. + list_add_tail(&old_map->list, &RFS_SB(sb)->free_chunks);
  694. +
  695. + return 0;
  696. +}
  697. +
  698. +/**
  699. + * count clusters in fat chain & make a chunk list for stl delete
  700. + * @param sb super block
  701. + * @param start_clu start cluster number of fat chain
  702. + * @param[out] last_clu last cluster number of fat chain
  703. + * @param last_val content of last cluster
  704. + * @param[out] clusters number of clusters which may be appended or not
  705. + * @return return 0 on success, errno on failure
  706. + *
  707. + */
  708. +static int rfs_check_size(struct super_block *sb, unsigned int start_clu, unsigned int *last_clu, unsigned int last_val, unsigned int *clusters)
  709. +{
  710. + unsigned int prev = start_clu, next;
  711. + unsigned int total_nr_clus = 0, chunk_nr_clus = 0;
  712. + unsigned int chunk_start = start_clu;
  713. + int err;
  714. +
  715. + while (1) { /* count clusters from start_clu */
  716. + err = fat_read(sb, prev, &next);
  717. + if (err) {
  718. + DPRINTK("can't read a fat entry(%u)\n", prev);
  719. + return err;
  720. + }
  721. +
  722. + if (next < VALID_CLU) { /* out-of-range input */
  723. + RFS_BUG("fat entry(%u) was corrupted\n", next);
  724. + return -EIO;
  725. + }
  726. +
  727. + total_nr_clus++;
  728. +
  729. + /* make a chunk list for map destroy */
  730. + chunk_nr_clus++;
  731. + if (!IS_CONSECUTION(prev, next)) {
  732. + rfs_add_chunk(sb, chunk_start, chunk_nr_clus);
  733. + chunk_start = next;
  734. + chunk_nr_clus = 0;
  735. + }
  736. +
  737. + if (prev == last_val || next == CLU_TAIL) {
  738. + if (IS_CONSECUTION(prev, next))
  739. + rfs_add_chunk(sb, chunk_start, chunk_nr_clus);
  740. + break;
  741. + }
  742. +
  743. + prev = next;
  744. + }
  745. +
  746. + *last_clu = prev;
  747. + *clusters = total_nr_clus;
  748. +
  749. + return 0;
  750. +}
  751. +
  752. +/**
  753. + * free fat chain from start_clu to EOC
  754. + * @param inode inode
  755. + * @param new_last new last cluster number
  756. + * @param start_clu start cluster number to free
  757. + * @param[out] count number of clusters which will be freed
  758. + * @return return 0 on success, errno on failure
  759. + * @pre caller must have a mutex for fat table
  760. + *
  761. + * new_last is only available if reduce a file especially truncate case
  762. + */
  763. +int free_chain(struct inode *inode, unsigned int new_last, unsigned int start_clu, unsigned int *count)
  764. +{
  765. + struct super_block *sb = inode->i_sb;
  766. + unsigned int free_clus[2];
  767. + unsigned int free_count;
  768. + unsigned int next;
  769. + int err = 0;
  770. +
  771. + *count = free_count = 0;
  772. +
  773. + /* check whether clusters are appended to pool file */
  774. + err = rfs_check_size(sb, start_clu, &next, CLU_TAIL, &free_count);
  775. + if (err)
  776. + return err;
  777. +
  778. + free_clus[0] = start_clu;
  779. + free_clus[1] = RFS_I(inode)->last_clu;
  780. + if (rfs_log_move_chain(sb, RFS_I(inode)->p_start_clu,
  781. + RFS_I(inode)->index,
  782. + RFS_POOL_I(sb)->last_cluster,
  783. + RFS_POOL_I(sb)->c_start_cluster,
  784. + new_last, CLU_TAIL, 2, free_clus)) {
  785. + return -EIO;
  786. + }
  787. +
  788. + err = rfs_put_pool(sb, start_clu, next, free_count);
  789. + if (err) {
  790. + DPRINTK("can't append free clusters into pool\n");
  791. + return err;
  792. + }
  793. +
  794. + if (new_last != CLU_TAIL) {
  795. + /* mark new last cluster */
  796. + err = fat_write(sb, new_last, CLU_TAIL);
  797. + if (err) {
  798. + DPRINTK("can't write a fat entry (%u)\n", new_last);
  799. + return err;
  800. + }
  801. +
  802. + RFS_I(inode)->last_clu = new_last;
  803. + } else {
  804. + RFS_I(inode)->start_clu = CLU_TAIL;
  805. + RFS_I(inode)->last_clu = CLU_TAIL;
  806. + }
  807. +
  808. + /* update used clusters */
  809. + RFS_SB(inode->i_sb)->num_used_clusters -= free_count;
  810. + *count = free_count;
  811. +
  812. + return 0;
  813. +}
  814. +
  815. +/**
  816. + * deallocate clusters after skipping some clusters
  817. + * @param inode inode
  818. + * @param skip the number of clusters to skip
  819. + * @return return 0 on success, errno on failure
  820. + */
  821. +int dealloc_clusters(struct inode *inode, unsigned int skip)
  822. +{
  823. + struct super_block *sb = inode->i_sb;
  824. + unsigned int new_last = NOT_ASSIGNED;
  825. + unsigned int prev, next;
  826. + unsigned int off = skip - 1;
  827. + unsigned int count = 0;
  828. + int err = 0;
  829. +
  830. + fat_lock(sb);
  831. +
  832. + if (!skip) { /* free all clusters */
  833. + next = RFS_I(inode)->start_clu;
  834. + goto free;
  835. + }
  836. +
  837. + err = find_cluster(sb, RFS_I(inode)->start_clu, off, &prev, &next);
  838. + if (err)
  839. + goto out;
  840. +
  841. + /* change last cluster number */
  842. + new_last = prev;
  843. +
  844. +free:
  845. + if (next == CLU_TAIL) /* do not need free chain */
  846. + goto out;
  847. +
  848. + err = free_chain(inode, new_last, next, &count);
  849. +
  850. +
  851. +out:
  852. + fat_unlock(sb);
  853. +
  854. + return err;
  855. +}
  856. +
  857. +/**
  858. + * count all used clusters in file system
  859. + * @param sb super block
  860. + * @param[out] used_clusters the number of used clusters in volume
  861. + * @return return 0 on success, errno on failure
  862. + *
  863. + * cluster 0 & 1 are reserved according to the fat spec
  864. + */
  865. +int count_used_clusters(struct super_block *sb, unsigned int *used_clusters)
  866. +{
  867. + unsigned int i, clu;
  868. + unsigned int count = 2; /* clu 0 & 1 are reserved */
  869. + int err;
  870. +
  871. + fat_lock(sb);
  872. +
  873. + for (i = VALID_CLU; i < RFS_SB(sb)->num_clusters; i++) {
  874. + err = fat_read(sb, i, &clu);
  875. + if (err) {
  876. + fat_unlock(sb);
  877. + DPRINTK("can't read a fat entry (%u)\n", i);
  878. + return err;
  879. + }
  880. +
  881. + if (clu)
  882. + count++;
  883. + }
  884. +
  885. + *used_clusters = count;
  886. +
  887. + fat_unlock(sb);
  888. +
  889. + return 0;
  890. +}
  891. +
  892. +/**
  893. + * find a cluster which has an offset into fat chain
  894. + * @param sb super block
  895. + * @param start_clu start cluster number of fat chain
  896. + * @param off offset within fat chain
  897. + * @param[out] clu cluster number found
  898. + * @param[out] value fat entry value of cluster
  899. + * @return return 0 on success, errno on failure
  900. + * @pre caller should get fat lock
  901. + */
  902. +int find_cluster(struct super_block *sb, unsigned int start_clu, unsigned int off, unsigned int *clu, unsigned int *value)
  903. +{
  904. + unsigned int prev, next;
  905. + unsigned int i;
  906. + int err;
  907. +
  908. + prev = start_clu;
  909. + for (i = 0; i <= off; i++) {
  910. + err = fat_read(sb, prev, &next);
  911. + if (err) {
  912. + DPRINTK("can't read a fat entry (%u)\n", prev);
  913. + return err;
  914. + }
  915. +
  916. + if (next < VALID_CLU) { /* out-of-range input */
  917. + /*
  918. + * If reset happened during appending a cluster,
  919. + * the appending cluster had a free status (0).
  920. + * EFAULT notifies it to replay method.
  921. + */
  922. + if (tr_in_replay(sb))
  923. + return -EFAULT;
  924. + else
  925. + return -EIO;
  926. + }
  927. +
  928. + if (i == off) /* do not need to change prev to next */
  929. + break;
  930. +
  931. + if (next == CLU_TAIL)
  932. + return -EFAULT; /* over request */
  933. +
  934. + prev = next;
  935. + }
  936. +
  937. + *clu = prev;
  938. + *value = next;
  939. + return 0;
  940. +}
  941. +
  942. +/*
  943. + * fast unlink
  944. + */
  945. +
  946. +/**
  947. + * initialize first block for meta data of the pool file
  948. + * @param sb super block
  949. + * @param index index of dir entry
  950. + * @param start_clu start cluster number of the pool file
  951. + * @param blocknr block number to save the dir entry of pool file
  952. + * @return return 0 on success, errno on failure
  953. + */
  954. +static int rfs_init_pool_block(struct super_block *sb, unsigned int index, unsigned int start_clu, unsigned long blocknr)
  955. +{
  956. + struct buffer_head *bh = NULL;
  957. + struct rfs_pool_info *pool_info = NULL;
  958. +
  959. + bh = sb_getblk(sb, START_BLOCK(start_clu, sb));
  960. + if (!bh) { /* I/O error */
  961. + DPRINTK("can't get buffer head to get dir entry of pool file\n");
  962. + return -EIO;
  963. + }
  964. + memset(bh->b_data, 0x00, sb->s_blocksize);
  965. +
  966. + pool_info = (struct rfs_pool_info *) bh->b_data;
  967. + SET32(pool_info->index, index);
  968. + SET32(pool_info->start_cluster, start_clu);
  969. + SET32(pool_info->last_cluster, start_clu);
  970. + SET32(pool_info->num_clusters, POOL_RESERVED_CLUSTER);
  971. + SET32(pool_info->c_start_cluster, NOT_ASSIGNED);
  972. + SET32(pool_info->c_last_cluster, NOT_ASSIGNED);
  973. + SET32(pool_info->blocknr, blocknr);
  974. +
  975. +#ifdef RFS_FOR_2_6
  976. + set_buffer_uptodate(bh);
  977. +#else
  978. + mark_buffer_uptodate(bh, 1);
  979. +#endif
  980. + mark_buffer_dirty(bh);
  981. + brelse(bh);
  982. +
  983. + return 0;
  984. +}
  985. +
  986. +/**
  987. + * allocate memory and make the in-core meta data of pool file
  988. + * @param sb super block
  989. + * @param index index of dir entry
  990. + * @param start_clu start cluster number of the pool file
  991. + * @param blocknr block number which saved dir entry
  992. + * @return return 0 on success, errno on failure
  993. + *
  994. + * hint info are written in start block of start cluster allocated the pool file
  995. + */
  996. +static int rfs_alloc_pool(struct super_block *sb, unsigned int index, unsigned int start_clu, unsigned long blocknr)
  997. +{
  998. + struct rfs_pool_info *pool_info = NULL, *disk_pool_info = NULL;
  999. + struct buffer_head *bh = NULL;
  1000. +
  1001. + /* read hint info */
  1002. + bh = rfs_bread(sb, START_BLOCK(start_clu, sb), BH_RFS_POOL_BLOCK);
  1003. + if (!bh) { /* I/O error */
  1004. + DPRINTK("can't get buffer head to get head of pool file\n");
  1005. + return -EIO;
  1006. + }
  1007. +
  1008. + disk_pool_info = (struct rfs_pool_info *) bh->b_data;
  1009. +
  1010. + /* memory allocation */
  1011. + pool_info = (struct rfs_pool_info *)
  1012. + kmalloc(sizeof(struct rfs_pool_info), GFP_KERNEL);
  1013. + if (!pool_info) { /* memory error */
  1014. + DEBUG(DL1, "failed memory allocation for pool info\n");
  1015. + brelse(bh);
  1016. + return -ENOMEM;
  1017. + }
  1018. +
  1019. + /* compare disk info and in-core info */
  1020. + if ((index != GET32(disk_pool_info->index)) ||
  1021. + (start_clu != GET32(disk_pool_info->start_cluster))) {
  1022. + kfree(pool_info);
  1023. + brelse(bh);
  1024. + DPRINTK("disk info and in-core info aren't equal. The file system is corrupted.\n");
  1025. + return -EIO;
  1026. + }
  1027. +
  1028. + /* initialize pool info */
  1029. + pool_info->index = GET32(disk_pool_info->index);
  1030. +// pool_info->blocknr = GET32(disk_pool_info->blocknr);
  1031. + pool_info->start_cluster = GET32(disk_pool_info->start_cluster);
  1032. + pool_info->last_cluster = GET32(disk_pool_info->last_cluster);
  1033. + pool_info->num_clusters = GET32(disk_pool_info->num_clusters);
  1034. + pool_info->c_start_cluster = GET32(disk_pool_info->c_start_cluster);
  1035. + pool_info->c_last_cluster = GET32(disk_pool_info->c_last_cluster);
  1036. +#ifdef RFS_UPDATE_POOLHEADER_AT_MOUNT
  1037. + pool_info->blocknr = GET32(disk_pool_info->blocknr);
  1038. +
  1039. + if (pool_info->blocknr != blocknr) { /* reinit block number */
  1040. + pool_info->blocknr = blocknr;
  1041. + SET32(disk_pool_info->blocknr, blocknr);
  1042. + mark_buffer_dirty(bh);
  1043. + }
  1044. +#else
  1045. + pool_info->blocknr = blocknr;
  1046. +#endif
  1047. +
  1048. + INIT_LIST_HEAD(&pool_info->c_list);
  1049. +
  1050. + brelse(bh);
  1051. +
  1052. + RFS_SB(sb)->pool_info = (void *) pool_info;
  1053. +
  1054. + return 0;
  1055. +}
  1056. +
  1057. +/**
  1058. + * open the pool file
  1059. + * @param sb super block
  1060. + * @return return 0 on success, errno on failure
  1061. + *
  1062. + * the pool file doesn't exist, make the pool file before anything else
  1063. + */
  1064. +static int rfs_open_pool(struct super_block *sb)
  1065. +{
  1066. + struct inode *root_dir = sb->s_root->d_inode;
  1067. + struct buffer_head *bh = NULL;
  1068. + struct rfs_dir_entry *ep = NULL;
  1069. + unsigned int index;
  1070. + int ret;
  1071. +
  1072. + /* find pool file */
  1073. + ret = find_entry(root_dir, RFS_POOL_FILE_NAME, &bh, TYPE_FILE);
  1074. + if (ret < 0) {
  1075. + brelse(bh);
  1076. + return ret;
  1077. + }
  1078. +
  1079. + index = ret;
  1080. + ep = get_entry(root_dir, index, &bh);
  1081. + if (IS_ERR(ep)) {
  1082. + brelse(bh);
  1083. + return PTR_ERR(ep);
  1084. + }
  1085. +
  1086. + /* allocate memory for hint & fill hint info */
  1087. + ret = rfs_alloc_pool(sb, index, START_CLUSTER(ep), bh->b_blocknr);
  1088. + if (ret) {
  1089. + brelse(bh);
  1090. + return ret;
  1091. + }
  1092. +
  1093. + brelse(bh);
  1094. + return 0;
  1095. +}
  1096. +
  1097. +/**
  1098. + * make the pool file
  1099. + * @param sb super block
  1100. + * @return return 0 on success, errno on failure
  1101. + */
  1102. +static int rfs_make_pool(struct super_block *sb)
  1103. +{
  1104. + struct inode *root_dir = sb->s_root->d_inode;
  1105. + struct inode *inode = NULL;
  1106. + struct buffer_head *bh = NULL;
  1107. + struct rfs_dir_entry *ep = NULL;
  1108. + unsigned int start_clu, index;
  1109. + unsigned long blocknr;
  1110. + int err;
  1111. +
  1112. + /* get a new inode */
  1113. + if (!(inode = new_inode(sb)))
  1114. + return -ENOMEM; /* memory error */
  1115. +
  1116. + /* allocate start cluster */
  1117. + RFS_I(inode)->start_clu = CLU_TAIL;
  1118. + err = alloc_cluster(inode, &start_clu);
  1119. + if (err)
  1120. + goto remove_inode;
  1121. +
  1122. + /* make a dir entry */
  1123. + index = build_entry(root_dir, NULL, start_clu, TYPE_FILE,
  1124. + RFS_POOL_FILE_NAME);
  1125. + if ((int) index < 0) {
  1126. + err = index;
  1127. + goto dealloc_cluster;
  1128. + }
  1129. +
  1130. + ep = get_entry(root_dir, index, &bh);
  1131. + if (IS_ERR(ep)) {
  1132. + err = PTR_ERR(ep);
  1133. + goto remove_entry;
  1134. + }
  1135. +
  1136. + blocknr = bh->b_blocknr;
  1137. +
  1138. + ep->attr |= (ATTR_READONLY | ATTR_SYSTEM | ATTR_HIDDEN);
  1139. + SET32(ep->size, RFS_SB(sb)->cluster_size);
  1140. +
  1141. + /* initialize first block of cluster */
  1142. + err = rfs_init_pool_block(sb, index, start_clu, blocknr);
  1143. + if (err) /* I/O error */
  1144. + goto remove_entry;
  1145. +
  1146. + /* allocate memory for hint & fill hint info */
  1147. + err = rfs_alloc_pool(sb, index, start_clu, blocknr);
  1148. + if (err)
  1149. + goto remove_entry;
  1150. +
  1151. + mark_buffer_dirty(bh);
  1152. + brelse(bh);
  1153. +
  1154. + iput(inode);
  1155. +
  1156. + /* flush buffers for internal fcache & dir entry */
  1157. + rfs_sync_vol(sb);
  1158. +
  1159. + return 0;
  1160. +
  1161. +remove_entry:
  1162. + ep->name[0] = (u8) DELETE_MARK;
  1163. + mark_buffer_dirty(bh);
  1164. + brelse(bh);
  1165. +dealloc_cluster:
  1166. + fat_write(sb, start_clu, CLU_FREE);
  1167. +remove_inode:
  1168. + inode->i_nlink--;
  1169. + RFS_BUG_ON(inode->i_nlink);
  1170. + iput(inode);
  1171. + return err;
  1172. +}
  1173. +
  1174. +/**
  1175. + * initialize the pool file at mount time
  1176. + * @param sb super block
  1177. + * @return return 0 on success, errno on failure
  1178. + */
  1179. +int rfs_init_pool(struct super_block *sb)
  1180. +{
  1181. + int err;
  1182. +
  1183. + if (RFS_POOL_I(sb)) /* already initialize it */
  1184. + return 0;
  1185. +
  1186. + /* check whether pool file exist */
  1187. + err = rfs_open_pool(sb);
  1188. + if (err == -ENOENT) {
  1189. + /* make pool file */
  1190. + err = rfs_make_pool(sb);
  1191. + if (err) {
  1192. + DPRINTK("can not create a pool file\n");
  1193. + return err;
  1194. + }
  1195. + } else if (err) {
  1196. + /* unexpected error case */
  1197. + DPRINTK("can not open pool file\n");
  1198. + return err;
  1199. + }
  1200. +
  1201. + return 0;
  1202. +}
  1203. +
  1204. +/**
  1205. + * release the pool file at umount time
  1206. + * @param sb super block
  1207. + */
  1208. +void rfs_release_pool(struct super_block *sb)
  1209. +{
  1210. + if (!RFS_POOL_I(sb))
  1211. + return;
  1212. +
  1213. + kfree(RFS_POOL_I(sb));
  1214. +}
  1215. +
  1216. +#ifdef _RFS_INTERNAL_SANITY_CHECK
  1217. +int sanity_check_pool(struct super_block *sb)
  1218. +{
  1219. + unsigned int prev = RFS_POOL_I(sb)->start_cluster;
  1220. + unsigned int next;
  1221. + unsigned int p_last_clu = RFS_POOL_I(sb)->last_cluster;
  1222. + unsigned int c_start_clu = RFS_POOL_I(sb)->c_start_cluster;
  1223. + unsigned int num_clus = RFS_POOL_I(sb)->num_clusters;
  1224. + unsigned int count = 1;
  1225. + int err;
  1226. +
  1227. + next = prev;
  1228. +
  1229. + while (count < num_clus) {
  1230. + err = fat_read(sb, prev, &next);
  1231. + if (err)
  1232. + return -1;
  1233. +
  1234. + if (next == CLU_TAIL)
  1235. + break;
  1236. +
  1237. + count++;
  1238. + if (next == p_last_clu)
  1239. + break;
  1240. +
  1241. + prev = next;
  1242. + }
  1243. +
  1244. + if (next != p_last_clu || count != RFS_POOL_I(sb)->num_clusters) {
  1245. + RFS_BUG("pool corrupted (%d, %d) (%d, %d)\n", next, p_last_clu,
  1246. + count, RFS_POOL_I(sb)->num_clusters);
  1247. + return -1;
  1248. + }
  1249. +
  1250. + prev = next;
  1251. + fat_read(sb, prev, &next);
  1252. +
  1253. + if (next != c_start_clu) {
  1254. + RFS_BUG("candidate corrupted(%d, %d)\n", next, c_start_clu);
  1255. + return -1;
  1256. + }
  1257. +
  1258. + return 0;
  1259. +}
  1260. +#endif
  1261. +
  1262. +/**
  1263. + * update last cluster number and total clusters for the pool file
  1264. + * @param sb super block
  1265. + * @return return 0 on success, errno on failure
  1266. + */
  1267. +int rfs_update_pool_block(struct super_block *sb)
  1268. +{
  1269. + struct buffer_head *bh = NULL;
  1270. + struct rfs_pool_info *disk_pool = NULL;
  1271. + struct rfs_pool_info *rpi = RFS_POOL_I(sb);
  1272. + struct rfs_sb_info *sbi = RFS_SB(sb);
  1273. + int bug_on = 0;
  1274. +
  1275. + bh = rfs_bread(sb, START_BLOCK(rpi->start_cluster, sb),
  1276. + BH_RFS_POOL_BLOCK);
  1277. + if (!bh) { /* I/O error */
  1278. + DPRINTK("can't get buffer head to get head of pool file\n");
  1279. + return -EIO;
  1280. + }
  1281. +
  1282. + /* sanity check */
  1283. + if (unlikely(rpi->last_cluster != CLU_TAIL &&
  1284. + IS_INVAL_CLU(sbi, rpi->last_cluster)))
  1285. + bug_on = 1;
  1286. + else if (unlikely(rpi->num_clusters > RFS_SB(sb)->num_clusters - 2))
  1287. + bug_on = 1;
  1288. + else if (unlikely(rpi->c_start_cluster != CLU_TAIL &&
  1289. + IS_INVAL_CLU(sbi, rpi->c_start_cluster)))
  1290. + bug_on = 1;
  1291. + else if (unlikely(rpi->c_last_cluster != CLU_TAIL &&
  1292. + IS_INVAL_CLU(sbi, rpi->c_last_cluster)))
  1293. + bug_on = 1;
  1294. +
  1295. + if (unlikely(bug_on)) {
  1296. + DPRINTK("in-memory pool is corrupted(%u, %u, %u, %u)\n",
  1297. + rpi->last_cluster, rpi->num_clusters,
  1298. + rpi->c_start_cluster, rpi->c_last_cluster);
  1299. + BUG();
  1300. + }
  1301. +
  1302. +
  1303. + disk_pool = (struct rfs_pool_info *) bh->b_data;
  1304. + SET32(disk_pool->last_cluster, rpi->last_cluster);
  1305. + SET32(disk_pool->num_clusters, rpi->num_clusters);
  1306. + SET32(disk_pool->c_start_cluster, rpi->c_start_cluster);
  1307. + SET32(disk_pool->c_last_cluster, rpi->c_last_cluster);
  1308. +
  1309. +#ifdef _RFS_INTERNAL_SANITY_CHECK
  1310. + sanity_check_pool(sb);
  1311. +#endif
  1312. + rfs_mark_buffer_dirty(bh, sb);
  1313. + brelse(bh);
  1314. +
  1315. + return 0;
  1316. +}
  1317. +
  1318. +/**
  1319. + * update size of dir entry for the pool file
  1320. + * @param sb super block
  1321. + * @param clusters number of clusters to expand or shrink
  1322. + * @param resize new size of pool file
  1323. + * @return return 0 on success, errno on failure
  1324. + */
  1325. +int rfs_update_pool_entry(struct super_block *sb, unsigned int clusters, int resize)
  1326. +{
  1327. + struct buffer_head *bh = NULL;
  1328. + struct rfs_dir_entry *ep = NULL;
  1329. + struct rfs_pool_info *pool_info = RFS_POOL_I(sb);
  1330. + unsigned int size, total_size;
  1331. + unsigned long offset;
  1332. +
  1333. + bh = rfs_bread(sb, pool_info->blocknr, BH_RFS_ROOT);
  1334. + if (!bh) { /* I/O error */
  1335. + DPRINTK("can't get buffer head related with pool head\n");
  1336. + return -EIO;
  1337. + }
  1338. +
  1339. + offset = pool_info->index << DENTRY_SIZE_BITS;
  1340. + offset += RFS_SB(sb)->root_start_addr;
  1341. + offset &= (sb->s_blocksize - 1);
  1342. + ep = (struct rfs_dir_entry *) (bh->b_data + offset);
  1343. +
  1344. + if (RFS_POOL_I(sb)->start_cluster != START_CLUSTER(ep)) {
  1345. + brelse(bh);
  1346. + RFS_BUG("mismatch start_cluster in-core & disk(%d != %d)\n",
  1347. + pool_info->start_cluster, START_CLUSTER(ep));
  1348. + return -EIO;
  1349. + }
  1350. +
  1351. + /* update size */
  1352. + total_size = GET32(ep->size);
  1353. + size = clusters << RFS_SB(sb)->cluster_bits;
  1354. + if (resize == EXPAND_POOL_SIZE) {
  1355. + /* append case */
  1356. + total_size += size;
  1357. + } else if (resize == SHRINK_POOL_SIZE) {
  1358. + /* shrink case */
  1359. + total_size -= size;
  1360. + } else {
  1361. + /* RFS-log : SET_POOL_SIZE */
  1362. + total_size = size;
  1363. + }
  1364. +
  1365. +
  1366. + SET32(ep->size, total_size);
  1367. + rfs_mark_buffer_dirty(bh, sb);
  1368. + brelse(bh);
  1369. +
  1370. +
  1371. +
  1372. + return 0;
  1373. +}
  1374. +
  1375. +/**
  1376. + * shrink some clusters from the pool chain
  1377. + * @param sb super block
  1378. + * @param[out] clu_list cluster list allocated
  1379. + * @param num_clusters number of clusters will be allocated
  1380. + * @param[out] alloc_clusters number of clusters were allocated
  1381. + * @param[out] next_clu next cluster number to connect with start cluster of pool file
  1382. + * @return return 0 on success, errno on failure
  1383. + *
  1384. + * when it is invoked, fat chain will not be updated
  1385. + */
  1386. +int rfs_shrink_pool_chain(struct super_block *sb, unsigned int *clu_list, unsigned int num_clusters, unsigned int *alloc_clusters, unsigned int *next_clu)
  1387. +{
  1388. + unsigned int prev, next;
  1389. + unsigned int count;
  1390. + unsigned int pool_clusters;
  1391. + int i, err;
  1392. +
  1393. + pool_clusters = RFS_POOL_I(sb)->num_clusters - POOL_RESERVED_CLUSTER;
  1394. + *next_clu = CLU_TAIL;
  1395. +
  1396. + /* first cluster of pool is reserved for pool meta data */
  1397. + if (IS_POOL_EMPTY(RFS_POOL_I(sb)->num_clusters)) {
  1398. + /* run out of free clusters */
  1399. + *alloc_clusters = 0;
  1400. + return 0;
  1401. + }
  1402. +
  1403. + if (num_clusters > pool_clusters)
  1404. + count = pool_clusters;
  1405. + else
  1406. + count = num_clusters;
  1407. +
  1408. + prev = RFS_POOL_I(sb)->start_cluster;
  1409. +
  1410. + for (i = count; i >= 0; i--) {
  1411. + err = fat_read(sb, prev, &next);
  1412. + if (err) {
  1413. + DPRINTK("can't read a fat entry (%u)\n", prev);
  1414. + return -EIO;
  1415. + }
  1416. +
  1417. + if (next < VALID_CLU) { /* out-of-range input */
  1418. + RFS_BUG("fat entry(%u) was corrupted\n", next);
  1419. + return -EIO;
  1420. + }
  1421. +
  1422. + /* do not need to update clu_list */
  1423. + if (i == 0)
  1424. + break;
  1425. +
  1426. + *clu_list++ = next;
  1427. + prev = next;
  1428. + }
  1429. +
  1430. + *next_clu = next;
  1431. + *alloc_clusters = count;
  1432. +
  1433. + return 0;
  1434. +}
  1435. +
  1436. +/**
  1437. + * update the fat chain of pool file
  1438. + * @param sb super block
  1439. + * @param next_clu next cluster number
  1440. + * @param last_clu new last cluster number
  1441. + * @param clusters number of clusters
  1442. + * @param is_expand flag to expand or shrink
  1443. + * @return return 0 on success, errno on failure
  1444. + */
  1445. +static int rfs_move_pool_chain(struct super_block *sb, unsigned int next_clu, unsigned int last_clu, unsigned int clusters, int is_expand)
  1446. +{
  1447. + struct rfs_pool_info *pool_info = RFS_POOL_I(sb);
  1448. + int err;
  1449. +
  1450. + if (is_expand == EXPAND_POOL_SIZE) {
  1451. + err = fat_write(sb, pool_info->last_cluster, next_clu);
  1452. + if (err) {
  1453. + DPRINTK("can't write a fat entry (%u)\n",
  1454. + pool_info->last_cluster);
  1455. + return err;
  1456. + }
  1457. +
  1458. + /* update hint info */
  1459. + pool_info->num_clusters += clusters;
  1460. + pool_info->last_cluster = last_clu;
  1461. +
  1462. + /* check whether candidate segments exist */
  1463. + if (pool_info->c_start_cluster == NOT_ASSIGNED) /* not exist */
  1464. + return 0;
  1465. +
  1466. + /* link start candidate segment with
  1467. + end of free clusters in pool file */
  1468. + err = fat_write(sb, pool_info->last_cluster,
  1469. + pool_info->c_start_cluster);
  1470. + if (err) {
  1471. + DPRINTK("can't write a fat entry (%u)\n",
  1472. + pool_info->last_cluster);
  1473. + return err;
  1474. + }
  1475. + } else if (is_expand == SHRINK_POOL_SIZE) {
  1476. + err = fat_write(sb, pool_info->start_cluster, next_clu);
  1477. + if (err) {
  1478. + DPRINTK("can't write a fat entry (%u)\n",
  1479. + pool_info->start_cluster);
  1480. + return err;
  1481. + }
  1482. +
  1483. + /* update hint info */
  1484. + pool_info->num_clusters -= clusters;
  1485. + if (IS_POOL_EMPTY(pool_info->num_clusters)) {
  1486. + pool_info->last_cluster =
  1487. + pool_info->start_cluster;
  1488. + }
  1489. + } else {
  1490. + /* RFS-log : SET_POOL_SIZE is never passed in this function */
  1491. + }
  1492. +
  1493. + return 0;
  1494. +}
  1495. +
  1496. +/**
  1497. + * put clusters deallocated in the pool file
  1498. + * @param sb super block
  1499. + * @param start_clu start cluster number
  1500. + * @param last_clu new last cluster number
  1501. + * @param clusters number of clusters
  1502. + * @return return 0 on success, errno on failure
  1503. + */
  1504. +static int rfs_put_pool(struct super_block *sb, unsigned int start_clu, unsigned int last_clu, unsigned int clusters)
  1505. +{
  1506. + int err;
  1507. +
  1508. + err = rfs_move_pool_chain(sb, start_clu, last_clu,
  1509. + clusters, EXPAND_POOL_SIZE);
  1510. + if (err)
  1511. + return err;
  1512. +
  1513. + err = rfs_update_pool_entry(sb, clusters, EXPAND_POOL_SIZE);
  1514. + if (err)
  1515. + return err;
  1516. +
  1517. + err = rfs_update_pool_block(sb);
  1518. + if (err) /* I/O error */
  1519. + return err;
  1520. +
  1521. +
  1522. +
  1523. + return 0;
  1524. +}
  1525. +
  1526. +/**
  1527. + * get free clusters in the pool file
  1528. + * @param sb super block
  1529. + * @param next_clu next cluster number
  1530. + * @param clusters number of clusters
  1531. + * @return return 0 on success, errno on failure
  1532. + */
  1533. +int rfs_get_pool(struct super_block *sb, unsigned int next_clu, unsigned int clusters)
  1534. +{
  1535. + int err;
  1536. + unsigned int dummy = 0;
  1537. +
  1538. + err = rfs_move_pool_chain(sb, next_clu, dummy,
  1539. + clusters, SHRINK_POOL_SIZE);
  1540. + if (err)
  1541. + return err;
  1542. +
  1543. + err = rfs_update_pool_entry(sb, clusters, SHRINK_POOL_SIZE);
  1544. + if (err)
  1545. + return err;
  1546. +
  1547. + err = rfs_update_pool_block(sb);
  1548. + if (err) /* I/O error */
  1549. + return err;
  1550. +
  1551. +
  1552. +
  1553. + return 0;
  1554. +}
  1555. +
  1556. +/**
  1557. + * update candidate segment info and fat chain of pool file
  1558. + * @param sb super block
  1559. + * @param segment candidate segment
  1560. + * @param is_attach flag to attach or detach
  1561. + * @return return 0 on success, errno on failure
  1562. + */
  1563. +static int update_candidate_segment(struct super_block *sb, struct c_segment *segment, int is_attach)
  1564. +{
  1565. + struct rfs_pool_info *pool_info = RFS_POOL_I(sb);
  1566. + unsigned int start, last;
  1567. + int err;
  1568. +
  1569. + start = pool_info->c_start_cluster;
  1570. + last = pool_info->c_last_cluster;
  1571. +
  1572. + if (is_attach) { /* attach case */
  1573. + if (start == NOT_ASSIGNED) {
  1574. + err = fat_write(sb, pool_info->last_cluster,
  1575. + segment->start_cluster);
  1576. + if (err) {
  1577. + DPRINTK("can't write a fat entry (%u)\n",
  1578. + pool_info->last_cluster);
  1579. + return err;
  1580. + }
  1581. + pool_info->c_start_cluster = segment->start_cluster;
  1582. + } else {
  1583. + err = fat_write(sb, pool_info->c_last_cluster,
  1584. + segment->start_cluster);
  1585. + if (err) {
  1586. + DPRINTK("can't write a fat entry (%u)\n",
  1587. + pool_info->c_last_cluster);
  1588. + return err;
  1589. + }
  1590. + }
  1591. + pool_info->c_last_cluster = segment->last_cluster;
  1592. + } else { /* detach case */
  1593. + struct c_segment *prev_seg, *next_seg;
  1594. +
  1595. + prev_seg = SEGMENT_ENTRY(segment->list.prev);
  1596. + next_seg = SEGMENT_ENTRY(segment->list.next);
  1597. +
  1598. + if (start == segment->start_cluster &&
  1599. + last == segment->last_cluster) { /* only one */
  1600. + pool_info->c_start_cluster = NOT_ASSIGNED;
  1601. + pool_info->c_last_cluster = NOT_ASSIGNED;
  1602. + } else if (start == segment->start_cluster) { /* first seg */
  1603. + pool_info->c_start_cluster = next_seg->start_cluster;
  1604. + } else if (last == segment->last_cluster) { /* last seg */
  1605. + err = fat_write(sb, pool_info->last_cluster,
  1606. + segment->start_cluster);
  1607. + if (err) {
  1608. + DPRINTK("can't write a fat entry (%u)\n",
  1609. + pool_info->last_cluster);
  1610. + return err;
  1611. + }
  1612. +
  1613. + err = fat_write(sb, segment->last_cluster, start);
  1614. + if (err) {
  1615. + DPRINTK("can't write a fat entry (%u)\n",
  1616. + segment->last_cluster);
  1617. + return err;
  1618. + }
  1619. +
  1620. + err = fat_write(sb, prev_seg->last_cluster, CLU_TAIL);
  1621. + if (err) {
  1622. + DPRINTK("can't write a fat entry (%u)\n",
  1623. + prev_seg->last_cluster);
  1624. + return err;
  1625. + }
  1626. + pool_info->c_last_cluster = prev_seg->last_cluster;
  1627. + } else { /* middle seg */
  1628. + err = fat_write(sb, pool_info->last_cluster,
  1629. + segment->start_cluster);
  1630. + if (err) {
  1631. + DPRINTK("can't write a fat entry (%u)\n",
  1632. + pool_info->last_cluster);
  1633. + return err;
  1634. + }
  1635. +
  1636. + err = fat_write(sb, segment->last_cluster, start);
  1637. + if (err) {
  1638. + DPRINTK("can't write a fat entry (%u)\n",
  1639. + segment->last_cluster);
  1640. + return err;
  1641. + }
  1642. +
  1643. + err = fat_write(sb, prev_seg->last_cluster,
  1644. + next_seg->start_cluster);
  1645. + if (err) {
  1646. + DPRINTK("can't write a fat entry (%u)\n",
  1647. + prev_seg->last_cluster);
  1648. + return err;
  1649. + }
  1650. + }
  1651. + }
  1652. +
  1653. + return 0;
  1654. +}
  1655. +
  1656. +/**
  1657. + * attach segment into candidate segment list on pool file
  1658. + * @param inode inode
  1659. + * @return return 0 on success, errno on failure
  1660. + */
  1661. +int rfs_attach_candidate(struct inode *inode)
  1662. +{
  1663. + struct super_block *sb = inode->i_sb;
  1664. + struct c_segment *segment;
  1665. + unsigned int move_chain[2];
  1666. + unsigned int p_prev_clu;
  1667. + int err;
  1668. +
  1669. + if (RFS_I(inode)->start_clu == CLU_TAIL) /* not assigned to inode */
  1670. + return 0;
  1671. +
  1672. + fat_lock(sb);
  1673. +
  1674. + /* make a candidate segment */
  1675. + segment = (struct c_segment *)
  1676. + kmalloc(sizeof(struct c_segment), GFP_KERNEL);
  1677. + if (!segment) { /* memory error */
  1678. + DEBUG(DL1, "memory allocation failed\n");
  1679. + err = -ENOMEM;
  1680. + goto out;
  1681. + }
  1682. +
  1683. + segment->start_cluster = RFS_I(inode)->start_clu;
  1684. + segment->last_cluster = RFS_I(inode)->last_clu;
  1685. +
  1686. + /* RFS-log : move chain of file to pool's tail */
  1687. + p_prev_clu = (RFS_POOL_I(sb)->c_last_cluster != CLU_TAIL) ?
  1688. + RFS_POOL_I(sb)->c_last_cluster : RFS_POOL_I(sb)->last_cluster;
  1689. +
  1690. + move_chain[0] = segment->start_cluster;
  1691. + move_chain[1] = segment->last_cluster;
  1692. + if ((err = rfs_log_move_chain(sb, RFS_I(inode)->p_start_clu,
  1693. + RFS_I(inode)->index,
  1694. + p_prev_clu, CLU_TAIL,
  1695. + CLU_TAIL, CLU_TAIL, 2, move_chain))) {
  1696. + goto out;
  1697. + }
  1698. +
  1699. + /* update candidate segment list on pool file */
  1700. + err = update_candidate_segment(sb, segment, 1);
  1701. + if (err)
  1702. + goto out;
  1703. +
  1704. + list_add_tail(&segment->list, &RFS_POOL_I(sb)->c_list);
  1705. +
  1706. + /* update hint info of pool file */
  1707. + err = rfs_update_pool_block(sb);
  1708. +
  1709. +out:
  1710. + fat_unlock(sb);
  1711. + return err;
  1712. +}
  1713. +
  1714. +/**
  1715. + * lookup a candidate segment corresponding with start cluster of inode in list
  1716. + * @param inode inode
  1717. + * @return return segment on success, NULL on failure
  1718. + */
  1719. +static struct c_segment *lookup_segment(struct inode *inode)
  1720. +{
  1721. + unsigned int start_clu = RFS_I(inode)->start_clu;
  1722. + struct c_segment *segment;
  1723. + struct list_head *p;
  1724. +
  1725. + list_for_each(p, &RFS_POOL_I(inode->i_sb)->c_list) {
  1726. + segment = SEGMENT_ENTRY(p);
  1727. + if (segment->start_cluster == start_clu)
  1728. + return segment; /* found */
  1729. + }
  1730. +
  1731. + return NULL;
  1732. +}
  1733. +
  1734. +/**
  1735. + * detach segment from candidate segment list
  1736. + * @param inode inode
  1737. + * @return return 0 on success, errno on failure
  1738. + *
  1739. + * And add it into deleted segment on pool file
  1740. + */
  1741. +int rfs_detach_candidate(struct inode *inode)
  1742. +{
  1743. + struct super_block *sb = inode->i_sb;
  1744. + struct c_segment *segment, *s;
  1745. + unsigned int nr_clusters, dummy;
  1746. + unsigned int t_prev_clu, t_next_clu;
  1747. + unsigned int move_chain[2];
  1748. + unsigned int err;
  1749. +
  1750. + if ((RFS_I(inode)->start_clu == CLU_TAIL) ||
  1751. + (RFS_I(inode)->i_state != RFS_I_FREE))
  1752. + return 0;
  1753. +
  1754. + fat_lock(sb);
  1755. +
  1756. + /* lookup candidate segment in list */
  1757. + segment = lookup_segment(inode);
  1758. + if (!segment || segment->last_cluster != RFS_I(inode)->last_clu) {
  1759. + /* NOT found */
  1760. + fat_unlock(sb);
  1761. + RFS_BUG("segment does not exist for %d\n",
  1762. + RFS_I(inode)->start_clu);
  1763. + return -EIO;
  1764. + }
  1765. +
  1766. + /* count clusters in segment and make chunk list for stl delete */
  1767. + err = rfs_check_size(sb, segment->start_cluster, &dummy,
  1768. + segment->last_cluster, &nr_clusters);
  1769. + if (err)
  1770. + goto out;
  1771. +
  1772. + /* RFS-log : get prev and next clu of candidate segment */
  1773. + if (segment->start_cluster !=
  1774. + RFS_POOL_I(inode->i_sb)->c_start_cluster) {
  1775. + s = SEGMENT_ENTRY(segment->list.prev);
  1776. + t_prev_clu = s->last_cluster;
  1777. + } else
  1778. + t_prev_clu = RFS_POOL_I(sb)->last_cluster;
  1779. +
  1780. + if (segment->last_cluster != RFS_POOL_I(inode->i_sb)->c_last_cluster) {
  1781. + s = SEGMENT_ENTRY(segment->list.next);
  1782. + t_next_clu = s->start_cluster;
  1783. + } else
  1784. + t_next_clu = CLU_TAIL;
  1785. +
  1786. + move_chain[0] = segment->start_cluster;
  1787. + move_chain[1] = segment->last_cluster;
  1788. +
  1789. + /* RFS-log : move candidate segment to deleted pool */
  1790. + /* don't care pdir (CLU_TAIL) and entry (-1) */
  1791. + if ((err = rfs_log_move_chain(sb, CLU_TAIL, -1,
  1792. + RFS_POOL_I(sb)->last_cluster,
  1793. + RFS_POOL_I(sb)->c_start_cluster,
  1794. + t_prev_clu, t_next_clu,
  1795. + 2, move_chain))) {
  1796. + goto out;
  1797. + }
  1798. +
  1799. + /* update candidate segment list on pool file */
  1800. + err = update_candidate_segment(sb, segment, 0);
  1801. + if (err)
  1802. + goto out;
  1803. +
  1804. + RFS_POOL_I(sb)->last_cluster = segment->last_cluster;
  1805. + RFS_POOL_I(sb)->num_clusters += nr_clusters;
  1806. +
  1807. + list_del(&segment->list);
  1808. + kfree(segment);
  1809. +
  1810. + /* update hint info & dir entry of pool file */
  1811. + err = rfs_update_pool_entry(sb, nr_clusters, EXPAND_POOL_SIZE);
  1812. + if (err)
  1813. + goto out;
  1814. +
  1815. + err = rfs_update_pool_block(sb);
  1816. + if (err) /* I/O error */
  1817. + goto out;
  1818. +
  1819. + /* update used clusters in volume */
  1820. + RFS_SB(sb)->num_used_clusters -= nr_clusters;
  1821. +
  1822. +
  1823. +out:
  1824. + fat_unlock(sb);
  1825. + return err;
  1826. +}
  1827. +
  1828. +/**
  1829. + * insert cluster into candidate segment
  1830. + * @param inode inode
  1831. + * @return return 0 on success, errno on failure
  1832. + */
  1833. +static int rfs_insert_candidate(struct inode *inode)
  1834. +{
  1835. + struct super_block *sb = inode->i_sb;
  1836. + struct rfs_pool_info *pool_info = RFS_POOL_I(sb);
  1837. + struct c_segment *segment, *next_seg;
  1838. + int err;
  1839. +
  1840. + /* lookup candidate segment in list */
  1841. + segment = lookup_segment(inode);
  1842. + if (!segment) {
  1843. + /* NOT found */
  1844. + RFS_BUG("segment does not exist for %d\n",
  1845. + RFS_I(inode)->start_clu);
  1846. + return -EIO;
  1847. + }
  1848. +
  1849. + /* update fat chain of pool file */
  1850. + if (segment->last_cluster != pool_info->c_last_cluster) {
  1851. + next_seg = SEGMENT_ENTRY(segment->list.next);
  1852. + err = fat_write(sb, RFS_I(inode)->last_clu,
  1853. + next_seg->start_cluster);
  1854. + if (err) {
  1855. + DPRINTK("can't write a fat entry (%u)\n",
  1856. + RFS_I(inode)->last_clu);
  1857. + return err;
  1858. + }
  1859. + }
  1860. +
  1861. + /* update segment info */
  1862. + if (segment->last_cluster == pool_info->c_last_cluster) {
  1863. + pool_info->c_last_cluster = RFS_I(inode)->last_clu;
  1864. + err = rfs_update_pool_block(sb);
  1865. + if (err)
  1866. + return err;
  1867. + }
  1868. +
  1869. + segment->last_cluster = RFS_I(inode)->last_clu;
  1870. +
  1871. + return 0;
  1872. +}
  1873. +
  1874. +/**
  1875. + * remove all candidate segments in pool file
  1876. + * @param sb super block
  1877. + * @return return 0 on success, errno on failure
  1878. + *
  1879. + * It is only invoked at mount time
  1880. + */
  1881. +int rfs_remove_candidates(struct super_block *sb)
  1882. +{
  1883. + struct rfs_pool_info *pool_info = RFS_POOL_I(sb);
  1884. + unsigned int nr_clusters, dummy;
  1885. + int err = 0;
  1886. +
  1887. + if (pool_info->c_start_cluster == NOT_ASSIGNED)
  1888. + return 0;
  1889. +
  1890. + /* count clusters in candidate segments and make chunk for stl delete */
  1891. + err = rfs_check_size(sb, pool_info->c_start_cluster, &dummy,
  1892. + CLU_TAIL, &nr_clusters);
  1893. + if (err)
  1894. + return err;
  1895. +
  1896. + if (rfs_log_start(sb, RFS_LOG_DEL_INODE, NULL))
  1897. + return -EIO;
  1898. +
  1899. + if ((err = rfs_log_update_pool(sb)))
  1900. + goto out;
  1901. +
  1902. + /* update hint info & dir entry of pool file */
  1903. + pool_info->last_cluster = pool_info->c_last_cluster;
  1904. + pool_info->num_clusters += nr_clusters;
  1905. + pool_info->c_start_cluster = NOT_ASSIGNED;
  1906. + pool_info->c_last_cluster = NOT_ASSIGNED;
  1907. +
  1908. + err = rfs_update_pool_entry(sb, nr_clusters, EXPAND_POOL_SIZE);
  1909. + if (err)
  1910. + goto out;
  1911. +
  1912. + err = rfs_update_pool_block(sb);
  1913. +out:
  1914. +
  1915. + if (rfs_log_end(sb, err))
  1916. + return err;
  1917. +
  1918. + return 0;
  1919. +}
  1920. diff -NurbB linux-2.6.17.14.orig/fs/rfs/code_convert.c linux-2.6.17.14.rfs/fs/rfs/code_convert.c
  1921. --- linux-2.6.17.14.orig/fs/rfs/code_convert.c 1970-01-01 01:00:00.000000000 +0100
  1922. +++ linux-2.6.17.14.rfs/fs/rfs/code_convert.c 2008-06-19 04:02:09.000000000 +0200
  1923. @@ -0,0 +1,460 @@
  1924. +/**
  1925. + * @file fs/rfs/code_convert.c
  1926. + *
  1927. + * @brief Dos name and Unicode name handling operations
  1928. + *
  1929. + *---------------------------------------------------------------------------*
  1930. + * *
  1931. + * COPYRIGHT 2003-2007 SAMSUNG ELECTRONICS CO., LTD. *
  1932. + * ALL RIGHTS RESERVED *
  1933. + * *
  1934. + * Permission is hereby granted to licensees of Samsung Electronics *
  1935. + * Co., Ltd. products to use or abstract this computer program only in *
  1936. + * accordance with the terms of the NAND FLASH MEMORY SOFTWARE LICENSE *
  1937. + * AGREEMENT for the sole purpose of implementing a product based on *
  1938. + * Samsung Electronics Co., Ltd. products. No other rights to reproduce, *
  1939. + * use, or disseminate this computer program, whether in part or in *
  1940. + * whole, are granted. *
  1941. + * *
  1942. + * Samsung Electronics Co., Ltd. makes no representation or warranties *
  1943. + * with respect to the performance of this computer program, and *
  1944. + * specifically disclaims any responsibility for any damages, *
  1945. + * special or consequential, connected with the use of this program. *
  1946. + * *
  1947. + *---------------------------------------------------------------------------*
  1948. + */
  1949. +
  1950. +#include <linux/fs.h>
  1951. +#include <linux/types.h>
  1952. +#include <linux/string.h>
  1953. +#include <linux/rfs_fs.h>
  1954. +#include <linux/ctype.h>
  1955. +#include <linux/nls.h>
  1956. +
  1957. +#include "rfs.h"
  1958. +
  1959. +/**
  1960. + * check the invalid character in the short entry
  1961. + * this character will be changed to underscore when configured RFS_VFAT
  1962. + * otherwise, making a entry with this character fails
  1963. + * @param c dosname character to check
  1964. + * @return zero on valid character
  1965. + */
  1966. +static inline int check_invalid_short(u8 c)
  1967. +{
  1968. + if ((c <= 0x20) || (c == '+') || (c == ',') || (c == ';') ||
  1969. + (c == '=') || (c == '[') || (c == ']'))
  1970. + return 1;
  1971. + else
  1972. + return 0;
  1973. +}
  1974. +
  1975. +/**
  1976. + * check the invalid character for FAT file name
  1977. + * @param c unicode character to check
  1978. + * @return zero on valid character
  1979. + */
  1980. +static inline int check_invalid(u16 c)
  1981. +{
  1982. +#ifndef CONFIG_RFS_VFAT
  1983. + if ((c == '\\') || (c == '/') || (c == ':') || (c == '*') || (c == '?')
  1984. + || (c == '\"') || (c == '<') || (c == '>') || (c == '|')
  1985. + || (c <= 0x20) || (c == '+') || (c == ',') || (c == ';')
  1986. + || (c == '=') || (c == '[') || (c == ']'))
  1987. +#else
  1988. + if ((c == '\\') || (c == '/') || (c == ':') || (c == '*') || (c == '?')
  1989. + || (c == '\"') || (c == '<') || (c == '>') || (c == '|'))
  1990. +#endif
  1991. + return 1;
  1992. + else
  1993. + return 0;
  1994. +}
  1995. +
  1996. +/**
  1997. + * Function converting cstring to dosname
  1998. + * @param dosname resulting dosname
  1999. + * @param cstring cstring to be converted
  2000. + * @param status flag indicating the capital combination and whether resulting dosname fits the 8.3 dosname or not
  2001. + * @param check flag indicating whether check invalid characters or not
  2002. + * @return zero on sucess, negative error code on failure.
  2003. + */
  2004. +int convert_cstring_to_dosname(u8 *dosname, const char* cstring, unsigned int *status, unsigned int check)
  2005. +{
  2006. + const char *end_of_name, *last_period;
  2007. + int i, len, lossy = FALSE;
  2008. + char mixed = 0;
  2009. +
  2010. + /* strip all leading spaces and periods */
  2011. + while ((*cstring == SPACE) || (*cstring == PERIOD)) {
  2012. + lossy = TRUE;
  2013. + cstring++;
  2014. + }
  2015. +
  2016. + len = strlen(cstring);
  2017. + if (!len)
  2018. + return -EINVAL;
  2019. +
  2020. + end_of_name = cstring + len - 1;
  2021. +
  2022. + /* check the trailing period & space */
  2023. + if (!check && (*end_of_name == PERIOD || *end_of_name == SPACE))
  2024. + return -EINVAL;
  2025. +
  2026. + /* search for the last embedded period */
  2027. + last_period = strrchr(cstring, PERIOD);
  2028. + if (last_period == NULL)
  2029. + last_period = end_of_name + 1;
  2030. +
  2031. + memset(dosname, SPACE, DOS_NAME_LENGTH);
  2032. +
  2033. + i = 0;
  2034. + for (;(i < DOS_NAME_LENGTH) && (cstring <= end_of_name); cstring++) {
  2035. + if (check && check_invalid((u16)(*cstring & 0x00ff))) {
  2036. + DEBUG(DL3, "Invalid character");
  2037. + return -EINVAL;
  2038. + }
  2039. +
  2040. + if (*cstring == SPACE) {
  2041. + lossy = TRUE;
  2042. + continue;
  2043. + }
  2044. +
  2045. + if (*cstring == PERIOD) {
  2046. + if (cstring < last_period)
  2047. + lossy = TRUE;
  2048. + else
  2049. + i = SHORT_NAME_LENGTH;
  2050. + continue;
  2051. + }
  2052. +
  2053. +#if !defined(CONFIG_RFS_NLS) && defined(CONFIG_RFS_VFAT)
  2054. + /* not support non-ASCII */
  2055. + if (check && (*cstring & 0x80)) {
  2056. + DEBUG(DL3, "NLS not support");
  2057. + return -EINVAL;
  2058. + }
  2059. +#endif
  2060. +
  2061. + /* fill dosname */
  2062. + if (check_invalid_short(*cstring)) {
  2063. + dosname[i++] = UNDERSCORE;
  2064. + lossy = TRUE;
  2065. + } else if (isascii(*cstring) && islower(*cstring)) {
  2066. + if (i < SHORT_NAME_LENGTH)
  2067. + mixed |= PRIMARY_LOWER;
  2068. + else
  2069. + mixed |= EXTENSION_LOWER;
  2070. + dosname[i++] = toupper(*cstring);
  2071. + } else if (isascii(*cstring) && isupper(*cstring)) {
  2072. + if (i < SHORT_NAME_LENGTH)
  2073. + mixed |= PRIMARY_UPPER;
  2074. + else
  2075. + mixed |= EXTENSION_UPPER;
  2076. + dosname[i++] = *cstring;
  2077. + } else {
  2078. + dosname[i++] = *cstring;
  2079. + }
  2080. +
  2081. + if ((i == SHORT_NAME_LENGTH) && ((cstring + 1) < last_period)) {
  2082. + lossy = TRUE;
  2083. +#ifdef CONFIG_RFS_VFAT
  2084. + if (check) {
  2085. + while(++cstring < last_period) {
  2086. + if (check_invalid((u16)(*cstring & 0x0ff)))
  2087. + return -EINVAL;
  2088. + }
  2089. + }
  2090. +#endif
  2091. + cstring = last_period;
  2092. + }
  2093. + } /* end of loop */
  2094. +
  2095. + if (cstring <= end_of_name) {
  2096. + lossy = TRUE;
  2097. +#ifdef CONFIG_RFS_VFAT
  2098. + if (check) {
  2099. + while(cstring <= end_of_name) {
  2100. + if (check_invalid((u16)(*cstring++ & 0x0ff)))
  2101. + return -EINVAL;
  2102. + }
  2103. + }
  2104. +#endif
  2105. + }
  2106. +
  2107. + /* post check */
  2108. + if (dosname[0] == KANJI_LEAD)
  2109. + dosname[0] = REPLACE_KANJI;
  2110. +
  2111. + if (status != NULL) {
  2112. + *status = 0;
  2113. +
  2114. + if ((primary_masked(mixed) == (PRIMARY_UPPER | PRIMARY_LOWER))
  2115. + || (extension_masked(mixed) ==
  2116. + (EXTENSION_UPPER | EXTENSION_LOWER))) {
  2117. + put_mix(*status, UPPER_N_LOWER);
  2118. + } else {
  2119. + if (primary_masked(mixed) == PRIMARY_LOWER)
  2120. + put_mix(*status, PRIMARY_LOWER);
  2121. + if (extension_masked(mixed) == EXTENSION_LOWER)
  2122. + put_mix(*status, EXTENSION_LOWER);
  2123. + }
  2124. +
  2125. + put_lossy(*status, lossy);
  2126. + }
  2127. +
  2128. + return 0;
  2129. +}
  2130. +
  2131. +/**
  2132. + * Function converting dos name to cstring
  2133. + * @param cstring dosname to be converted
  2134. + * @param dosname resulting cstring
  2135. + * @param sysid flag indicating the capital combination
  2136. + * @return none
  2137. + */
  2138. +void convert_dosname_to_cstring(char *cstring, const u8 *dosname, unsigned char sysid)
  2139. +{
  2140. + int i = 0;
  2141. +
  2142. + if (dosname[0] == REPLACE_KANJI) {
  2143. + *cstring++ = (s8) KANJI_LEAD;
  2144. + i = 1;
  2145. + }
  2146. +
  2147. + for ( ; i < SHORT_NAME_LENGTH; i++) {
  2148. + if (dosname[i] == SPACE)
  2149. + break;
  2150. +
  2151. + if (sysid & PRIMARY_LOWER && isascii(dosname[i]))
  2152. + *cstring++ = (s8) tolower(dosname[i]);
  2153. + else
  2154. + *cstring++ = (s8) dosname[i];
  2155. + }
  2156. +
  2157. + /* no extension */
  2158. + if (dosname[SHORT_NAME_LENGTH] == SPACE) {
  2159. + *cstring = '\0';
  2160. + return;
  2161. + }
  2162. +
  2163. + *cstring++ = PERIOD;
  2164. +
  2165. + for (i = SHORT_NAME_LENGTH; i < DOS_NAME_LENGTH; i++) {
  2166. + if (dosname[i] == SPACE)
  2167. + break;
  2168. +
  2169. + if (sysid & EXTENSION_LOWER && isascii(dosname[i]))
  2170. + *cstring++ = (s8) tolower(dosname[i]);
  2171. + else
  2172. + *cstring++ = (s8) dosname[i];
  2173. + }
  2174. +
  2175. + *cstring = '\0';
  2176. + return;
  2177. +}
  2178. +
  2179. +#ifdef CONFIG_RFS_VFAT
  2180. +
  2181. +#ifdef CONFIG_RFS_NLS
  2182. +/**
  2183. + * Function to convert encoded character to unicode by NLS table
  2184. + * @param nls NLS table
  2185. + * @param chars encoded characters
  2186. + * @param chars_len the length of character buffer
  2187. + * @param uni the unicode character converted
  2188. + * @param lower flag indicating the case type of unicode character
  2189. + * @return the length of character converted
  2190. + */
  2191. +static int char2uni(struct nls_table *nls, unsigned char *chars, int chars_len, wchar_t *uni)
  2192. +{
  2193. + int clen = 0;
  2194. + wchar_t uni_tmp;
  2195. +
  2196. + clen = nls->char2uni(chars, chars_len, &uni_tmp);
  2197. + if (clen < 0) {
  2198. + *uni = UNDERSCORE;
  2199. + clen = 1;
  2200. + } else if (clen <= 1) {
  2201. + *uni = uni_tmp;
  2202. + clen = 1;
  2203. + } else {
  2204. + *uni = uni_tmp;
  2205. + }
  2206. +
  2207. + return clen;
  2208. +}
  2209. +#endif /* CONFIG_RFS_NLS */
  2210. +
  2211. +/**
  2212. + * Function converting cstring to unicode name
  2213. + * @param uname unicode name to be converted
  2214. + * @param cstring resulting cstring
  2215. + * @param nls Linux NLS object pointer for future enchancement
  2216. + * @param check flag indicating wether check invalid characters or not
  2217. + * @return the length of uname on success, negative error code on failure
  2218. + */
  2219. +static int convert_cstring_to_uname(u16 *uname, const char *cstring, struct nls_table *nls, unsigned int check)
  2220. +{
  2221. +#ifndef CONFIG_RFS_NLS /* if not support nls */
  2222. + int i = 0;
  2223. +
  2224. + while (cstring[i] != 0x00) {
  2225. + if (cstring[i] & 0x80) {
  2226. + /* cannot convert to unicode without codepage */
  2227. + DEBUG(DL3, "NLS not support");
  2228. + return -EINVAL;
  2229. + }
  2230. +
  2231. + uname[i] = (u16) (cstring[i] & 0x00ff);
  2232. + i++;
  2233. + }
  2234. +
  2235. + /* add the null */
  2236. + uname[i] = 0x0000;
  2237. + return i;
  2238. +#else
  2239. + /* support nls codepage to convert character */
  2240. + int clen = 0, uni_len = 0, len;
  2241. + int i = 0;
  2242. +
  2243. + len = strlen(cstring);
  2244. +
  2245. + for (i = 0; (cstring[i] != '\0') && (uni_len < MAX_NAME_LENGTH); uni_len++) {
  2246. +
  2247. + clen = char2uni(nls, (unsigned char *)&cstring[i],
  2248. + len - i, &uname[uni_len]);
  2249. + i += clen;
  2250. +
  2251. + if (uname[uni_len] == 0x00)
  2252. + break;
  2253. +
  2254. + if (check && check_invalid(uname[uni_len])) {
  2255. + DEBUG(DL3, "Invalid character");
  2256. + return -EINVAL;
  2257. + }
  2258. + }
  2259. +
  2260. + /* the length of unicode name is never over the limitation */
  2261. + {
  2262. + uname[uni_len] = 0x0000;
  2263. +
  2264. + /* return the length of name */
  2265. + return uni_len;
  2266. + }
  2267. +#endif /* CONFIG_RFS_NLS */
  2268. +}
  2269. +
  2270. +/**
  2271. + * Function converting unicode name to cstring
  2272. + * @param cstring resulting converted
  2273. + * @param uname unicode name to be converted
  2274. + * @param nls Linux NLS object pointer for future use
  2275. + * @return zero on success, negative error code on failure
  2276. + */
  2277. +int convert_uname_to_cstring(char *cstring, const u16 *uname, struct nls_table *nls)
  2278. +{
  2279. +#ifndef CONFIG_RFS_NLS /* if not support nls */
  2280. + int i = 0;
  2281. + for (; i < MAX_NAME_LENGTH; i++) {
  2282. + /* cannot convert */
  2283. + if (uname[i] & 0xff80)
  2284. + cstring[i] = UNDERSCORE;
  2285. + else
  2286. + cstring[i] = (s8) uname[i];
  2287. +
  2288. + if (cstring[i] == '\0')
  2289. + break;
  2290. + }
  2291. +
  2292. + /* return the length of unicode name */
  2293. + return i;
  2294. +#else
  2295. + /* need nls codepage to convert character */
  2296. + int clen = 0, stridx = 0, i = 0;
  2297. + const u16 *uname_ptr = uname;
  2298. + char buf[NLS_MAX_CHARSET_SIZE];
  2299. +
  2300. + for (;(i < MAX_NAME_LENGTH) && (stridx <= NAME_MAX); i++, uname_ptr++) {
  2301. + /* end of uname is NULL */
  2302. + if (*uname_ptr == 0x0000)
  2303. + break;
  2304. +
  2305. + clen = nls->uni2char(*uname_ptr, buf, sizeof(buf));
  2306. + if (clen <= 0) {
  2307. + cstring[stridx] = UNDERSCORE;
  2308. + clen = 1;
  2309. + } else if (clen == 1) {
  2310. + cstring[stridx] = buf[0];
  2311. + } else {
  2312. + if (stridx + clen > NAME_MAX)
  2313. + break;
  2314. + memcpy(&cstring[stridx], buf, clen);
  2315. + }
  2316. +
  2317. + stridx += clen;
  2318. + }
  2319. +
  2320. + cstring[stridx] = '\0';
  2321. +
  2322. + /* return the length of unicode name */
  2323. + return i;
  2324. +#endif /* CONFIG_RFS_NLS */
  2325. +
  2326. +}
  2327. +#endif /* CONFIG_RFS_VFAT */
  2328. +
  2329. +/**
  2330. + * translate encoded string from user to 8.3 dosname and unicode
  2331. + *
  2332. + * @param cstring encoded string from user IO
  2333. + * @param dosname resulting dosname of encoded string
  2334. + * @param unicode resulting unicode name
  2335. + * @param status flag indicating the capital combination and whether resulting dosname fits the 8.3 dosname or not
  2336. + * @param nls NLS codepage table
  2337. + * @param check flag whether check invalid characters or not
  2338. + * @return zero or length of uname on success, or errno on failure
  2339. + */
  2340. +int create_fatname(const char *cstring, u8 *dosname, u16 *unicode, unsigned int *status, struct nls_table *nls, unsigned int check)
  2341. +{
  2342. + /*
  2343. + * support NLS or not
  2344. + */
  2345. + int ret = 0;
  2346. +
  2347. +#ifdef CONFIG_RFS_NLS
  2348. + if (unlikely(!nls)) /* out-of-range input */
  2349. + return -EINVAL;
  2350. +#else
  2351. + nls = NULL;
  2352. +#endif /* CONFIG_RFS_NLS */
  2353. +
  2354. + if (dosname) {
  2355. + /* check trailing space, period */
  2356. + ret = convert_cstring_to_dosname(dosname, cstring, status, check);
  2357. + if (ret < 0)
  2358. + return ret;
  2359. + }
  2360. +
  2361. +#ifdef CONFIG_RFS_VFAT
  2362. + if (unicode && status) {
  2363. + /*
  2364. + * don't check the length of unicode name
  2365. + * because it's checked at rfs_lookup
  2366. + */
  2367. +
  2368. + /* make unicode only if condition is satisfied */
  2369. + if (get_lossy(*status) || get_mix(*status) == UPPER_N_LOWER) {
  2370. + /* don't check the length of unicode */
  2371. + ret = convert_cstring_to_uname(unicode, cstring, nls, FALSE);
  2372. + if (ret < 0)
  2373. + return ret;
  2374. + } else {
  2375. + unicode[0] = 0x00;
  2376. + return 0;
  2377. + }
  2378. + }
  2379. +#endif /* CONFIG_RFS_VFAT */
  2380. +
  2381. + return ret;
  2382. +}
  2383. +
  2384. diff -NurbB linux-2.6.17.14.orig/fs/rfs/Config.in linux-2.6.17.14.rfs/fs/rfs/Config.in
  2385. --- linux-2.6.17.14.orig/fs/rfs/Config.in 1970-01-01 01:00:00.000000000 +0100
  2386. +++ linux-2.6.17.14.rfs/fs/rfs/Config.in 2008-06-19 04:02:09.000000000 +0200
  2387. @@ -0,0 +1,37 @@
  2388. +#
  2389. +# RFS FAT configuration
  2390. +#
  2391. +
  2392. +tristate 'RFS filesystem support' CONFIG_RFS_FS
  2393. +
  2394. +if [ "$CONFIG_RFS_FS" = "y" -o "$CONFIG_RFS_FS" = "m" ]; then
  2395. + dep_mbool ' FAT32 & long file name support' CONFIG_RFS_VFAT
  2396. + dep_mbool ' Sync on close support' CONFIG_RFS_SYNC_ON_CLOSE
  2397. + dep_mbool ' Support NLS on RFS filesystem' CONFIG_RFS_NLS $CONFIG_RFS_VFAT
  2398. + if [ "$CONFIG_RFS_NLS" = "y" ]; then
  2399. + string ' Use default NLS Codepage' CONFIG_RFS_DEFAULT_CODEPAGE "cp949"
  2400. + fi
  2401. + dep_mbool ' Debugging' CONFIG_RFS_FAT_DEBUG
  2402. + if [ "$CONFIG_RFS_FAT_DEBUG" = "y" ]; then
  2403. + int ' Debugging verbosity (0 = quiet, 3 = noisy)' CONFIG_RFS_FAT_DEBUG_VERBOSE 0
  2404. + fi
  2405. +fi
  2406. +
  2407. +if [ "$CONFIG_RFS_XSR_STL" = "y" ]; then
  2408. + define_bool CONFIG_RFS_MAPDESTROY y
  2409. +fi
  2410. +
  2411. +if [ "$CONFIG_RFS_FS" = "m" -a "$CONFIG_RFS_XSR_STL" = "m" ]; then
  2412. + define_bool CONFIG_RFS_MAPDESTROY y
  2413. +fi
  2414. +
  2415. +define_bool CONFIG_RFS_IGET4 y
  2416. +define_string CONFIG_RFS_VERSION "1.2.2p1-rc2"
  2417. +
  2418. +# When file is extended, it is the max number of clusters
  2419. +# which one transaction can use.
  2420. +# If the transaction rollbacks, the amount of
  2421. +# (CONFIG_RFS_PRE_ALLOC * cluster size) data would also rollback.
  2422. +define_int CONFIG_RFS_PRE_ALLOC 50
  2423. +
  2424. +define_int CONFIG_RFS_LOG_WAKEUP_DELAY 5
  2425. diff -NurbB linux-2.6.17.14.orig/fs/rfs/dir.c linux-2.6.17.14.rfs/fs/rfs/dir.c
  2426. --- linux-2.6.17.14.orig/fs/rfs/dir.c 1970-01-01 01:00:00.000000000 +0100
  2427. +++ linux-2.6.17.14.rfs/fs/rfs/dir.c 2008-06-19 04:02:09.000000000 +0200
  2428. @@ -0,0 +1,268 @@
  2429. +/**
  2430. + * @file fs/rfs/dir.c
  2431. + * @brief directory handling functions
  2432. + *
  2433. + *---------------------------------------------------------------------------*
  2434. + * *
  2435. + * COPYRIGHT 2003-2007 SAMSUNG ELECTRONICS CO., LTD. *
  2436. + * ALL RIGHTS RESERVED *
  2437. + * *
  2438. + * Permission is hereby granted to licensees of Samsung Electronics *
  2439. + * Co., Ltd. products to use or abstract this computer program only in *
  2440. + * accordance with the terms of the NAND FLASH MEMORY SOFTWARE LICENSE *
  2441. + * AGREEMENT for the sole purpose of implementing a product based on *
  2442. + * Samsung Electronics Co., Ltd. products. No other rights to reproduce, *
  2443. + * use, or disseminate this computer program, whether in part or in *
  2444. + * whole, are granted. *
  2445. + * *
  2446. + * Samsung Electronics Co., Ltd. makes no representation or warranties *
  2447. + * with respect to the performance of this computer program, and *
  2448. + * specifically disclaims any responsibility for any damages, *
  2449. + * special or consequential, connected with the use of this program. *
  2450. + * *
  2451. + *---------------------------------------------------------------------------*
  2452. + *
  2453. + */
  2454. +
  2455. +#include <linux/fs.h>
  2456. +#include <linux/rfs_fs.h>
  2457. +
  2458. +#include "rfs.h"
  2459. +
  2460. +#ifdef CONFIG_GCOV_PROFILE
  2461. +#define loff_t off_t
  2462. +#endif
  2463. +
  2464. +/* internal data structure for readdir */
  2465. +struct rfs_dir_info {
  2466. + unsigned int type;
  2467. + unsigned long ino;
  2468. + char name[NAME_MAX + 1];
  2469. +};
  2470. +
  2471. +/**
  2472. + * initialize the dot(.) and dotdot(..) dir entries for new directory
  2473. + * @param inode inode for itself
  2474. + * @return return 0 on success, EIO on failure
  2475. + *
  2476. + * inode must have start cluster of itself and start cluster of parent dir
  2477. + */
  2478. +int init_new_dir(struct inode *inode)
  2479. +{
  2480. + struct buffer_head *bh = NULL;
  2481. + struct rfs_dir_entry *dot_ep = NULL;
  2482. + struct rfs_dir_entry *dotdot_ep = NULL;
  2483. + unsigned char dummy = 0;
  2484. + int err = 0;
  2485. +
  2486. + /* initialize .(itself) and ..(parent) */
  2487. + dot_ep = get_entry(inode, 0, &bh);
  2488. + if (IS_ERR(dot_ep)) {
  2489. + brelse(bh);
  2490. + return -EIO;
  2491. + }
  2492. +
  2493. + dotdot_ep = (struct rfs_dir_entry *) (bh->b_data + DENTRY_SIZE);
  2494. +
  2495. + init_dir_entry(inode, dot_ep, TYPE_DIR,
  2496. + RFS_I(inode)->start_clu, DOT, &dummy);
  2497. + init_dir_entry(inode, dotdot_ep, TYPE_DIR,
  2498. + RFS_I(inode)->p_start_clu, DOTDOT, &dummy);
  2499. +
  2500. + rfs_mark_buffer_dirty(bh, inode->i_sb);
  2501. + brelse(bh);
  2502. +
  2503. + return err;
  2504. +}
  2505. +
  2506. +/**
  2507. + * check whether directory is emtpy
  2508. + * @param dir inode corresponding to the directory
  2509. + * @return return 0 on success, errno on failure
  2510. + *
  2511. + * is_dir_empty is usually invoked before removing or renaming directry.
  2512. + */
  2513. +int is_dir_empty(struct inode *dir) {
  2514. +
  2515. + struct buffer_head *bh = NULL;
  2516. + struct rfs_dir_entry *ep;
  2517. + unsigned int cpos = 0;
  2518. + int err = 0, count = 0;
  2519. + unsigned int type;
  2520. +
  2521. + if (dir->i_ino == ROOT_INO)
  2522. + return -ENOTEMPTY;
  2523. +
  2524. + while (1) {
  2525. + ep = get_entry(dir, cpos++, &bh);
  2526. + if (IS_ERR(ep)) {
  2527. + err = PTR_ERR(ep);
  2528. + if (err == -EFAULT)
  2529. + err = 0;
  2530. + goto out;
  2531. + }
  2532. +
  2533. + type = entry_type(ep);
  2534. + if ((type == TYPE_FILE) || (type == TYPE_DIR)) {
  2535. + /* check entry index bigger than
  2536. + entry index of parent directory (..) */
  2537. + if (++count > 2) {
  2538. + err = -ENOTEMPTY;
  2539. + goto out;
  2540. + }
  2541. + } else if (type == TYPE_UNUSED) {
  2542. + /* do not need checking anymore */
  2543. + goto out;
  2544. + }
  2545. + }
  2546. +
  2547. +out :
  2548. + brelse(bh);
  2549. + return err;
  2550. +}
  2551. +
  2552. +/**
  2553. + * counts the number of sub-directories in specified directory
  2554. + * @param sb super block
  2555. + * @param clu start cluster number of specified directory to count
  2556. + * @return return the number of sub-directories on sucess, errno on failure
  2557. + */
  2558. +int count_subdir(struct super_block *sb, unsigned int clu)
  2559. +{
  2560. + struct buffer_head *bh = NULL;
  2561. + struct rfs_dir_entry *ep = NULL;
  2562. + unsigned int cpos = 0;
  2563. + unsigned int type;
  2564. + int count = 0, err = 0;
  2565. +
  2566. + while (1) {
  2567. + ep = get_entry_with_cluster(sb, clu, cpos++, &bh);
  2568. + if (IS_ERR(ep)) {
  2569. + err = PTR_ERR(ep);
  2570. + if (err == -EFAULT) /* end of cluster */
  2571. + break;
  2572. + brelse(bh);
  2573. + return err;
  2574. + }
  2575. +
  2576. + /* check type of dir entry */
  2577. + type = entry_type(ep);
  2578. + if (type == TYPE_DIR)
  2579. + count++;
  2580. + else if (type == TYPE_UNUSED)
  2581. + break;
  2582. + }
  2583. +
  2584. + brelse(bh);
  2585. + return count;
  2586. +}
  2587. +
  2588. +/**
  2589. + * read dir entry in specified directory
  2590. + * @param inode specified directory inode
  2591. + * @param bh buffer head to read dir entries
  2592. + * @param ppos entry position to read
  2593. + * @param[out] dir_info to save dir entry info
  2594. + * @return return 0 on success, errno on failure
  2595. + */
  2596. +static int internal_readdir(struct inode *inode, struct buffer_head **bh, loff_t *ppos, struct rfs_dir_info *dir_info)
  2597. +{
  2598. +#ifdef CONFIG_RFS_VFAT
  2599. + unsigned short uname[UNICODE_NAME_LENGTH];
  2600. +#endif
  2601. + struct rfs_dir_entry *ep = NULL;
  2602. + loff_t index = *ppos;
  2603. + unsigned long ino;
  2604. + unsigned int type;
  2605. + int err;
  2606. +
  2607. + while (1) {
  2608. + ep = get_entry(inode, (u32) index, bh);
  2609. + if (IS_ERR(ep))
  2610. + return PTR_ERR(ep);
  2611. +
  2612. + index++;
  2613. +
  2614. + type = entry_type(ep);
  2615. +
  2616. + dir_info->type = type;
  2617. +
  2618. + if (type == TYPE_UNUSED)
  2619. + return -INTERNAL_EOF; /* not error case */
  2620. +
  2621. + if ((type == TYPE_DELETED) || (type == TYPE_EXTEND) ||
  2622. + (type == TYPE_VOLUME))
  2623. + continue;
  2624. +
  2625. +#ifdef CONFIG_RFS_VFAT
  2626. + uname[0] = 0x0;
  2627. + get_uname_from_entry(inode, index - 1, uname);
  2628. + if (uname[0] == 0x0 || !IS_VFAT(RFS_SB(inode->i_sb)))
  2629. + convert_dosname_to_cstring(dir_info->name, ep->name, ep->sysid);
  2630. + else
  2631. + convert_uname_to_cstring(dir_info->name, uname, RFS_SB(inode->i_sb)->nls_disk);
  2632. +#else
  2633. + convert_dosname_to_cstring(dir_info->name, ep->name, ep->sysid);
  2634. +#endif
  2635. +
  2636. + err = rfs_iunique(inode, index - 1, &ino);
  2637. + if (err)
  2638. + return err;
  2639. + dir_info->ino = ino;
  2640. +
  2641. + *ppos = index;
  2642. +
  2643. + return 0;
  2644. +
  2645. + }
  2646. +
  2647. + return 0;
  2648. +}
  2649. +
  2650. +/**
  2651. + * read all dir entries in specified directory
  2652. + * @param filp file pointer of specified directory to read
  2653. + * @param dirent buffer pointer
  2654. + * @param filldir function pointer which fills dir info
  2655. + * @return return 0 on success, errno on failure
  2656. + */
  2657. +static int rfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
  2658. +{
  2659. + struct dentry *dentry = filp->f_dentry;
  2660. + struct inode *inode = dentry->d_inode;
  2661. + struct buffer_head *bh = NULL;
  2662. + struct rfs_dir_info dir_info;
  2663. + unsigned int type;
  2664. + loff_t pos;
  2665. + int ret;
  2666. +
  2667. + CHECK_RFS_INODE(inode, -ENOENT);
  2668. +
  2669. + while (1) {
  2670. + pos = filp->f_pos;
  2671. +
  2672. + ret = internal_readdir(inode, &bh, (loff_t *) &filp->f_pos, &dir_info);
  2673. + if (ret < 0)
  2674. + break;
  2675. +
  2676. + if (dir_info.type == TYPE_DIR)
  2677. + type = DT_DIR;
  2678. + else
  2679. + type = DT_REG;
  2680. +
  2681. + ret = filldir(dirent, dir_info.name, strlen(dir_info.name),
  2682. + pos, dir_info.ino, type);
  2683. + if (ret < 0) {
  2684. + filp->f_pos = pos; /* rollback */
  2685. + break;
  2686. + }
  2687. + }
  2688. +
  2689. + brelse(bh);
  2690. + return 0;
  2691. +}
  2692. +
  2693. +struct file_operations rfs_dir_operations = {
  2694. + .read = generic_read_dir,
  2695. + .readdir = rfs_readdir,
  2696. +};
  2697. diff -NurbB linux-2.6.17.14.orig/fs/rfs/dos.c linux-2.6.17.14.rfs/fs/rfs/dos.c
  2698. --- linux-2.6.17.14.orig/fs/rfs/dos.c 1970-01-01 01:00:00.000000000 +0100
  2699. +++ linux-2.6.17.14.rfs/fs/rfs/dos.c 2008-06-19 04:02:08.000000000 +0200
  2700. @@ -0,0 +1,1148 @@
  2701. +/**
  2702. + * @file fs/rfs/dos.c
  2703. + * @brief FAT directory entry Manipultion and mangement operations
  2704. + *
  2705. + *---------------------------------------------------------------------------*
  2706. + * *
  2707. + * COPYRIGHT 2003-2007 SAMSUNG ELECTRONICS CO., LTD. *
  2708. + * ALL RIGHTS RESERVED *
  2709. + * *
  2710. + * Permission is hereby granted to licensees of Samsung Electronics *
  2711. + * Co., Ltd. products to use or abstract this computer program only in *
  2712. + * accordance with the terms of the NAND FLASH MEMORY SOFTWARE LICENSE *
  2713. + * AGREEMENT for the sole purpose of implementing a product based on *
  2714. + * Samsung Electronics Co., Ltd. products. No other rights to reproduce, *
  2715. + * use, or disseminate this computer program, whether in part or in *
  2716. + * whole, are granted. *
  2717. + * *
  2718. + * Samsung Electronics Co., Ltd. makes no representation or warranties *
  2719. + * with respect to the performance of this computer program, and *
  2720. + * specifically disclaims any responsibility for any damages, *
  2721. + * special or consequential, connected with the use of this program. *
  2722. + * *
  2723. + *---------------------------------------------------------------------------*
  2724. + */
  2725. +
  2726. +#include <linux/fs.h>
  2727. +#include <linux/string.h>
  2728. +#include <linux/sched.h>
  2729. +#include <linux/time.h>
  2730. +#include <linux/rfs_fs.h>
  2731. +
  2732. +#include "rfs.h"
  2733. +#include "log.h"
  2734. +
  2735. +/* for dir entries manipulation */
  2736. +
  2737. +/* local variable definition */
  2738. +static const unsigned int days[] = {
  2739. + 0, 31, 59, 90, 120, 151, 181, 212,
  2740. + 243, 273, 304, 334, 0, 0, 0, 0
  2741. +};
  2742. +extern struct timezone sys_tz;
  2743. +
  2744. +static const u8 *reserved_names[] = {
  2745. + "AUX ", "CON ", "NUL ", "PRN ",
  2746. + "COM1 ", "COM2 ", "COM3 ", "COM4 ",
  2747. + "LPT1 ", "LPT2 ", "LPT3 ", "LPT4 ",
  2748. + NULL };
  2749. +
  2750. +#define MAX_DIGIT 4 /* maximum tail: 1024 */
  2751. +#define MAX_NUMERIC 1024
  2752. +
  2753. +#define SEC_PER_MIN (60) /* 60 secs / min */
  2754. +#define MIN_PER_HR (60) /* 60 mins / hour */
  2755. +#define SEC_PER_HR (3600) /* 3600 secs / hour */
  2756. +#define HR_PER_DAY (24) /* 24 hours / day */
  2757. +#define DAY_PER_YR (365) /* 365 days / year */
  2758. +#define SEC_PER_DAY (60 * 60 * 24) /* 86400 secs / day */
  2759. +#define DAY_PER_10YR (365 * 10 + 2) /* 3650 days / 10years */
  2760. +#define SEC_PER_10YR DAY_PER_10YR * SEC_PER_DAY /* 10 years -> 315532800 secs */
  2761. +#define MIN_DATE SEC_PER_10YR
  2762. +
  2763. +#define leap_days(yr) ((yr + 3) / 4) /* leap-year days during yr years */
  2764. +#define leap_year(yr) ((yr & 3) == 0) /* true if yr is the leap year */
  2765. +
  2766. +/* time: [0-4] 2-second counts [5-10] minutes [11-15] hours */
  2767. +#define FAT_time(sec, min, hour) ((hour << 11) + (min << 5) + (sec / 2))
  2768. +/* date: [0-4] day [5-8] month [9-15] years from 1980*/
  2769. +#define FAT_date(day, month, year) ((year << 9) + (month << 5) + day)
  2770. +
  2771. +/**
  2772. + * Function converting linux time to FAT time
  2773. + * @param linux_date linux time to be converted
  2774. + * @param time return value to contain a time of converted FAT time
  2775. + * @param date return value to contain a date of converted FAT time
  2776. + * @return none
  2777. + *
  2778. + * Linux time starts from 1970.1.1 and FAT time starts from 1980.1.1
  2779. + */
  2780. +static void convert_date_linux2dos(time_t linux_date, unsigned short *time, unsigned short *date)
  2781. +{
  2782. + unsigned int day = 0, year = 0, month = 0;
  2783. +
  2784. + /* set to GMT time */
  2785. + linux_date -= sys_tz.tz_minuteswest * SEC_PER_MIN;
  2786. +
  2787. + /* set the minimum value of date to 1980.1.1 */
  2788. + if (linux_date < MIN_DATE)
  2789. + linux_date = MIN_DATE;
  2790. +
  2791. + /* set the FAT time */
  2792. + *time = FAT_time(linux_date % SEC_PER_MIN,
  2793. + (linux_date / SEC_PER_MIN) % MIN_PER_HR,
  2794. + (linux_date / SEC_PER_HR) % HR_PER_DAY);
  2795. +
  2796. + /* get the days & years */
  2797. + day = (linux_date - MIN_DATE) / SEC_PER_DAY;
  2798. + year = day / DAY_PER_YR;
  2799. +
  2800. + /* re-organize the year & day by the leap-years */
  2801. + if ((leap_days(year) + (year * DAY_PER_YR)) > day)
  2802. + year--;
  2803. + day -= (leap_days(year) + (year * DAY_PER_YR));
  2804. +
  2805. + /* find the month & day */
  2806. + if (day == days[2] && leap_year(year)) {
  2807. + month = 2;
  2808. + } else {
  2809. + if (leap_year(year) && (day > days[2]))
  2810. + day--;
  2811. +
  2812. + for (month = 0; month < 12; month++)
  2813. + if (days[month] > day)
  2814. + break;
  2815. + }
  2816. +
  2817. + /* set the FAT date */
  2818. + *date = FAT_date(day - days[month - 1] + 1, month, year);
  2819. +}
  2820. +
  2821. +#ifdef CONFIG_RFS_VFAT
  2822. +/**
  2823. + * Function setting a given buffer to zero
  2824. + * @param bitmap character buffer to be filled with zero
  2825. + * @param mapsize size of buffer
  2826. + * @return none
  2827. + */
  2828. +static inline void bitmap_clear_all(unsigned char *bitmap, unsigned int mapsize)
  2829. +{
  2830. + memset(bitmap, 0x00, mapsize);
  2831. +}
  2832. +
  2833. +/**
  2834. + * Function check if certain bit of buffer is set to 1
  2835. + * @param bitmap character buffer to be tested
  2836. + * @param i offset of target bit
  2837. + * @return return 1 if a bit is 1, if not, 0
  2838. + */
  2839. +static inline int bitmap_test(unsigned char *bitmap, int i)
  2840. +{
  2841. + unsigned char row;
  2842. +
  2843. + row = bitmap[i >> 3];
  2844. + if ((row >> (i & 0x7)) & 0x1)
  2845. + return 1;
  2846. + else
  2847. + return 0;
  2848. +}
  2849. +
  2850. +/**
  2851. + * Function set certain bit of buffer to 1
  2852. + * @param bitmap character buffer to be modified
  2853. + * @param i offset of target bit
  2854. + * @return none
  2855. + */
  2856. +static inline void bitmap_set(unsigned char *bitmap, int i)
  2857. +{
  2858. + bitmap[i >> 3] |= (0x01 << (i & 0x7));
  2859. +}
  2860. +#endif /* CONFIG_RFS_VFAT */
  2861. +
  2862. +/**
  2863. + * Function checking if given dos file name is one of the reserved names
  2864. + * @param dosname dos name to be tested
  2865. + * @return return zero if dosname is valid, if not, a negative error code
  2866. + *
  2867. + * This function does validity check of give dos file name not to make dosname
  2868. + * same with reserved name
  2869. + */
  2870. +static int check_reserved(u8 *dosname)
  2871. +{
  2872. + const u8 **reserved;
  2873. +
  2874. + for (reserved = reserved_names; *reserved != NULL; reserved++) {
  2875. + if (!strncmp((char *) dosname, (char *)(*reserved), SHORT_NAME_LENGTH))
  2876. + return -EINVAL;
  2877. + }
  2878. +
  2879. + return 0;
  2880. +}
  2881. +
  2882. +/**
  2883. + * Function checking if given name is valid
  2884. + * @param dosname name to be tested
  2885. + * @param lossy indicating wether the original string has lossy or not
  2886. + * @param isvfat indicating VFAT if not zero
  2887. + * @return return zero when name is valid if not a negative error code
  2888. + *
  2889. + * This function does the validity check of given file name. This function is
  2890. + * invoked prior to rfs_lookup
  2891. + */
  2892. +static inline int check_name(u8 *dosname, unsigned int lossy, int isvfat)
  2893. +{
  2894. + if (!isvfat || lossy != TRUE)
  2895. + return check_reserved(dosname);
  2896. + else
  2897. + return 0;
  2898. +}
  2899. +
  2900. +/**
  2901. + * Function replacing the type of directory entry with give type
  2902. + * @param ep directory entry to be modified
  2903. + * @param type entry type
  2904. + * @return return zero on success, a negative value on failure
  2905. + */
  2906. +static int set_entry_type(struct rfs_dir_entry *ep, unsigned char type)
  2907. +{
  2908. + if (type == TYPE_UNUSED) {
  2909. + ep->name[0] = 0x0;
  2910. + } else if (type == TYPE_DELETED) {
  2911. + ep->name[0] = (u8) DELETE_MARK;
  2912. + } else if (type == TYPE_EXTEND) {
  2913. + ep->attr = (u8) ATTR_EXTEND;
  2914. + } else if (type == TYPE_DIR) {
  2915. + ep->attr = (u8) ATTR_SUBDIR;
  2916. + } else if (type == TYPE_FILE) {
  2917. + ep->attr = (u8) ATTR_ARCHIVE;
  2918. + } else if (type == TYPE_SYMLINK) {
  2919. + ep->attr = (u8) ATTR_ARCHIVE;
  2920. + ep->cmsec = SYMLINK_MARK;
  2921. + } else { /* out-of-range input */
  2922. + return -EINVAL;
  2923. + }
  2924. +
  2925. + return 0;
  2926. +}
  2927. +
  2928. +#ifdef CONFIG_RFS_VFAT
  2929. +/**
  2930. + * Function retrieving unicode name from extend directory entry
  2931. + * @param extp extend entry from which unicode is extracted
  2932. + * @param uname pointer to array to store a unicode name
  2933. + * @param is_last condition flag indicating if current extend entry
  2934. + * is the last one.
  2935. + * @return return zero on success, a negative value on failure
  2936. + *
  2937. + * This function is invokded to extract unicode names scatterd in several
  2938. + * directory entries and put them together so that they can be commplete
  2939. + * unicode name.
  2940. + */
  2941. +static int get_uname_from_ext_entry(struct rfs_ext_entry *extp, u16 *uname, unsigned int is_last)
  2942. +{
  2943. + unsigned int i;
  2944. +
  2945. + for (i = 0; i < EXT_UNAME_LENGTH; i++) {
  2946. + if (i < 5) {
  2947. + uname[i] = GET16(extp->uni_0_4[i]);
  2948. + } else if (i < 11) {
  2949. + uname[i] = GET16(extp->uni_5_10[i - 5]);
  2950. + } else {
  2951. + uname[i] = GET16(extp->uni_11_12[i - 11]);
  2952. + }
  2953. + if (uname[i] == 0x0)
  2954. + return 0;
  2955. + }
  2956. +
  2957. + if (is_last)
  2958. + uname[i] = 0x0;
  2959. +
  2960. + return 0;
  2961. +}
  2962. +
  2963. +/**
  2964. + * Function searching numeric tail in an effort to avoid redundancy
  2965. + * of filename.
  2966. + * @param dir inode corresponding to given dos name
  2967. + * @param dos_name dos_name to which numeric tail is to be appended
  2968. + * @return return zero on success, a negative value on failure
  2969. + *
  2970. + * This function check if any file having same dos name with given one exists
  2971. + * in the directory and calcuate a numeric tail.
  2972. + */
  2973. +static int get_numeric_tail(struct inode *dir, u8 *dos_name)
  2974. +{
  2975. + int has_tilde;
  2976. + unsigned char bmap[MAX_NUMERIC >> 3];
  2977. + unsigned int type;
  2978. + unsigned int i, j, cpos = 0;
  2979. + unsigned int count = 0;
  2980. + struct buffer_head *bh = NULL;
  2981. + struct rfs_dir_entry *ep = NULL;
  2982. + int err = 0;
  2983. +
  2984. + bitmap_clear_all(bmap, (MAX_NUMERIC >> 3));
  2985. + bitmap_set(bmap, 0);
  2986. +
  2987. + while (1) {
  2988. + ep = get_entry(dir, cpos++, &bh);
  2989. + if (IS_ERR(ep)) {
  2990. + if (PTR_ERR(ep) == -EFAULT) { /* end-of-directory */
  2991. + break;
  2992. + }
  2993. + err = PTR_ERR(ep);
  2994. + goto out;
  2995. + }
  2996. +
  2997. + type = entry_type(ep);
  2998. + if (type == TYPE_FILE || type == TYPE_DIR) {
  2999. + for (i = 0; i < SHORT_NAME_LENGTH; i++) {
  3000. + if (ep->name[i] == TILDE)
  3001. + break;
  3002. + }
  3003. + if (strncmp(ep->name, dos_name, i))
  3004. + continue;
  3005. +
  3006. + has_tilde = FALSE;
  3007. + for (i = 0, count = 0; i < SHORT_NAME_LENGTH; i++) {
  3008. + if (ep->name[i] == TILDE) {
  3009. + has_tilde = TRUE;
  3010. + } else if (has_tilde) {
  3011. + if (ep->name[i] >= '0' && ep->name[i] <='9') {
  3012. + count = count * 10 + (ep->name[i] - '0');
  3013. + }
  3014. + }
  3015. + }
  3016. + } else if (type == TYPE_UNUSED) {
  3017. + break; /* end of valid entry */
  3018. + }
  3019. +
  3020. + if (count)
  3021. + bitmap_set(bmap, count);
  3022. + }
  3023. +
  3024. + for (count = 0, i = 0; (!count) && (i < (MAX_NUMERIC >> 3)); i++) {
  3025. + if (bmap[i] != (u8) 0xff) {
  3026. + for (j = 0; j < SHORT_NAME_LENGTH; j++) {
  3027. + if (bitmap_test(&bmap[i], j) == 0) {
  3028. + count = (i << 3) + j;
  3029. + break;
  3030. + }
  3031. + }
  3032. + }
  3033. + }
  3034. +
  3035. + if (count == 0 || count >= MAX_NUMERIC) {
  3036. + err = -ENOENT; /* out-of-range input (numeric tail) */
  3037. + goto out;
  3038. + } else {
  3039. + err = count;
  3040. + }
  3041. +
  3042. +out:
  3043. + if (!IS_ERR(bh))
  3044. + brelse(bh);
  3045. +
  3046. + return err;
  3047. +}
  3048. +
  3049. +/**
  3050. + * Function appending a given numerical tail to given dos name
  3051. + * @param dos_name directory entry to be modified
  3052. + * @param count numerical tail to be appended
  3053. + * @return none
  3054. + *
  3055. + * This function does not return error
  3056. + */
  3057. +static void append_tail(u8 *dos_name, unsigned int count)
  3058. +{
  3059. + char str_tail[SHORT_NAME_LENGTH - 1];
  3060. + int length, n_tail = 0;
  3061. +
  3062. + sprintf(str_tail, "%c%d", TILDE, count);
  3063. + length = strlen(str_tail);
  3064. +
  3065. + while (n_tail < (SHORT_NAME_LENGTH - length)) {
  3066. + if (dos_name[n_tail] == SPACE)
  3067. + break;
  3068. + if (dos_name[n_tail] & 0x80) {
  3069. + if (n_tail + 2 < (SHORT_NAME_LENGTH - length))
  3070. + n_tail += 2;
  3071. + else
  3072. + break;
  3073. + } else {
  3074. + n_tail++;
  3075. + }
  3076. + }
  3077. +
  3078. + memcpy(&(dos_name[n_tail]), str_tail, length);
  3079. +
  3080. + memset(&(dos_name[n_tail + length]), SPACE,
  3081. + SHORT_NAME_LENGTH - length - n_tail);
  3082. +}
  3083. +
  3084. +/**
  3085. + * Function appending numeric tail in an effort to avoid redundancy
  3086. + * of filename.
  3087. + * @param dir inode corresponding to given dos name
  3088. + * @param dos_name dos_name to which numeric tail is to be appended
  3089. + * @return return zero on success, a negative value on failure
  3090. + *
  3091. + * This function check if any file having same dos name with given one exists
  3092. + * in the directory and calcuate a numeric tail.
  3093. + */
  3094. +static int add_numeric_tail(struct inode *dir, u8 *dos_name)
  3095. +{
  3096. + int count = 0;
  3097. +
  3098. + count = get_numeric_tail(dir, dos_name);
  3099. + if (count < 0)
  3100. + return count;
  3101. +
  3102. + append_tail(dos_name, count);
  3103. +
  3104. + return 0;
  3105. +}
  3106. +#endif /* CONFIG_RFS_VFAT */
  3107. +
  3108. +/*
  3109. + * Global function
  3110. + */
  3111. +
  3112. +/**
  3113. + * Function assigning a FAT time to directory entry by converting a given
  3114. + * linux time.
  3115. + * @param ep directory entry to be modified
  3116. + * @param cur_time linux time to be converted
  3117. + * @return none
  3118. + */
  3119. +#ifdef RFS_FOR_2_6
  3120. +void set_entry_time(struct rfs_dir_entry *ep, struct timespec cur_time)
  3121. +{
  3122. + unsigned short time = 0x00, date = 0x21;
  3123. + struct timespec tmp_time;
  3124. +
  3125. + /* set current system time by default */
  3126. + tmp_time = (cur_time.tv_sec > 0) ? cur_time : CURRENT_TIME;
  3127. + convert_date_linux2dos(tmp_time.tv_sec, &time, &date);
  3128. +#else
  3129. +void set_entry_time(struct rfs_dir_entry *ep, time_t cur_time)
  3130. +{
  3131. + unsigned short time = 0x00, date = 0x21;
  3132. + time_t tmp_time = 0;
  3133. +
  3134. + /* set current system time by default */
  3135. + tmp_time = (cur_time > 0) ? cur_time : CURRENT_TIME;
  3136. + convert_date_linux2dos(tmp_time, &time, &date);
  3137. +#endif
  3138. +
  3139. + SET16(ep->mtime, time);
  3140. + SET16(ep->mdate, date);
  3141. +}
  3142. +
  3143. +/**
  3144. + * Function retreiving the type of entry and convert it to internal type flag
  3145. + * @param ep directory entry to extract type information
  3146. + * @return internal type flag
  3147. + */
  3148. +unsigned int entry_type(struct rfs_dir_entry *ep)
  3149. +{
  3150. + if (ep->name[0] == (u8) 0x0)
  3151. + return TYPE_UNUSED;
  3152. + else if (ep->name[0] == (u8) DELETE_MARK)
  3153. + return TYPE_DELETED;
  3154. + else if (ep->attr == (u8) ATTR_EXTEND)
  3155. + return TYPE_EXTEND;
  3156. + else if (ep->attr & (u8) ATTR_SUBDIR)
  3157. + return TYPE_DIR;
  3158. + else if (ep->attr & (u8) ATTR_VOLUME)
  3159. + return TYPE_VOLUME;
  3160. +
  3161. + return TYPE_FILE;
  3162. +}
  3163. +
  3164. +#define DOS_time(sec, min, hour) ((sec * 2) + (min * SEC_PER_MIN) + (hour * SEC_PER_HR))
  3165. +#define days_in_years(year) (year / 4) + (year * DAY_PER_YR)
  3166. +#define DOS_date(day, month, year) \
  3167. + ((day - 1) + days[month] + days_in_years(year) + \
  3168. + ((leap_year(year) && (month < 2))? 0: 1))
  3169. +
  3170. +/**
  3171. + * Function converting a FAT time to linux time
  3172. + * @param time a time value of the FAT time
  3173. + * @param date a date value of teh FAT time
  3174. + * @return converted linux time
  3175. + */
  3176. +unsigned int entry_time(unsigned short time, unsigned short date)
  3177. +{
  3178. + int secs, day;
  3179. +
  3180. + /* first subtract and mask after that... Otherwise, if
  3181. + date == 0, bad things happen */
  3182. +
  3183. + secs = DOS_time((time & 0x1F), ((time >> 5) & 0x3F), (time >> 11));
  3184. +
  3185. + /* days since 1.1.70 plus 80's leap day */
  3186. + day = DOS_date((date & 0x1F), (((date >> 5) - 1) & 0xF), (date >> 9)) +
  3187. + DAY_PER_10YR;
  3188. +
  3189. + secs += day * SEC_PER_DAY;
  3190. +
  3191. + /* reflect timezone */
  3192. + secs += sys_tz.tz_minuteswest * 60;
  3193. +
  3194. + return secs;
  3195. +}
  3196. +
  3197. +#ifdef CONFIG_RFS_VFAT
  3198. +/**
  3199. + * Function calculating checksum for given dos name
  3200. + * @param dos_name name to be calcuated
  3201. + * @return checksum value
  3202. + *
  3203. + * This function calcuate the check of dos name, which is the key
  3204. + * to identify the validity of the dos entry.
  3205. + */
  3206. +unsigned char calc_checksum(const u8 *dos_name)
  3207. +{
  3208. + unsigned char checksum = 0;
  3209. + int i;
  3210. +
  3211. + for (i = 0; i < DOS_NAME_LENGTH; i++, dos_name++)
  3212. + checksum = (((checksum & 1) << 7) | ((checksum & 0xFE) >> 1)) + *dos_name;
  3213. +
  3214. + return checksum;
  3215. +}
  3216. +#endif /* CONFIG_RFS_VFAT */
  3217. +
  3218. +/**
  3219. + * Function to create dosname with given cstring
  3220. + * @param dir inode pointer
  3221. + * @param name given cstring
  3222. + * @param dosname empty string buffer
  3223. + * @param mixed return value indicating mixed string
  3224. + * @param uname return unicode name from cstring name
  3225. + * @return the number of the extend slots needed on success, a negative error code on failure
  3226. + */
  3227. +int mk_dosname(struct inode *dir, const char *name, u8 *dosname, unsigned char *mixed, u16 *uname)
  3228. +{
  3229. + struct rfs_sb_info *sbi = RFS_SB(dir->i_sb);
  3230. + unsigned int status = 0;
  3231. + int ret = 0;
  3232. + int uni_len;
  3233. +
  3234. + /* make uname and base dosname (without numeric-tail) */
  3235. + uni_len = create_fatname(name, dosname, uname, &status, sbi->nls_disk, TRUE);
  3236. + if (uni_len < 0)
  3237. + return uni_len;
  3238. +
  3239. + /* check reserved names */
  3240. + /* if not support long name,
  3241. + * must check reserved names regardless of lossy
  3242. + * if support long name, only check reserved names if lossy is true
  3243. + */
  3244. +
  3245. + ret = check_name(dosname, get_lossy(status), IS_VFAT(sbi));
  3246. + if (ret < 0)
  3247. + return ret;
  3248. +
  3249. +#ifdef CONFIG_RFS_VFAT
  3250. + /* when long file name is supported */
  3251. + if (get_lossy(status)) {
  3252. + ret = add_numeric_tail(dir, dosname);
  3253. + if (ret < 0)
  3254. + return ret;
  3255. +
  3256. + ret = ((uni_len + (EXT_UNAME_LENGTH - 1)) / EXT_UNAME_LENGTH);
  3257. + } else if (get_mix(status) == UPPER_N_LOWER) {
  3258. + ret = ((uni_len + (EXT_UNAME_LENGTH - 1)) / EXT_UNAME_LENGTH);
  3259. + } else {
  3260. + ret = 0;
  3261. + }
  3262. +
  3263. + if (mixed) {
  3264. + /*
  3265. + * if SFN has extra slot,
  3266. + * dosname in SFN has mark of lower case in sysid
  3267. + */
  3268. + if (ret)
  3269. + *mixed = (PRIMARY_LOWER | EXTENSION_LOWER);
  3270. + else
  3271. + *mixed = get_mix(status);
  3272. + }
  3273. +
  3274. +#else
  3275. + /* when long file name isn't supported */
  3276. + ret = 0;
  3277. + if (mixed) {
  3278. + /* dosname has mark of lower case in sysid */
  3279. + if (get_mix(status) == UPPER_N_LOWER)
  3280. + *mixed = (PRIMARY_LOWER | EXTENSION_LOWER);
  3281. + else
  3282. + *mixed = get_mix(status);
  3283. + }
  3284. +#endif /* CONFIG_RFS_VFAT */
  3285. +
  3286. + /* there's no unicode name for the extend slots */
  3287. + if ((ret == 0) && uname)
  3288. + uname[0] = 0x0000;
  3289. +
  3290. + /* return the number of extend slots needed */
  3291. + return ret;
  3292. +}
  3293. +
  3294. +/**
  3295. + * Function initializing given entry
  3296. + * @param dir inode of parent directory
  3297. + * @param ep directory entry to be initalized
  3298. + * @param type entry type
  3299. + * @param start_clu start cluster of file
  3300. + * @param dosname dos name of file
  3301. + * @param mixed return value indicating if a file needs extend entry
  3302. + * @return none
  3303. + */
  3304. +void init_dir_entry(struct inode *dir, struct rfs_dir_entry *ep, unsigned int type, unsigned int start_clu, const u8 *dosname, unsigned char *mixed)
  3305. +{
  3306. + ep->cmsec = 0;
  3307. + SET16(ep->ctime, 0);
  3308. + SET16(ep->cdate, 0);
  3309. + SET16(ep->adate, 0);
  3310. + set_entry_time(ep, CURRENT_TIME);
  3311. +
  3312. + SET16(ep->start_clu_lo, start_clu);
  3313. + SET16(ep->start_clu_hi, start_clu >> 16);
  3314. +
  3315. + SET32(ep->size, 0);
  3316. +
  3317. + set_entry_type(ep, type);
  3318. + ep->sysid = *mixed;
  3319. + memcpy(ep->name, dosname, DOS_NAME_LENGTH);
  3320. +}
  3321. +
  3322. +#ifdef CONFIG_RFS_VFAT
  3323. +/**
  3324. + * Function initializing given extend entry
  3325. + * @param extp extend entry to be initalized
  3326. + * @param type entry type
  3327. + * @param entry_offset a sequence number of current extend entry
  3328. + * @param uname unicode name converted from original file name
  3329. + * @param checksum checksum value
  3330. + * @return return zero on success, a negative value on failure
  3331. + */
  3332. +int init_ext_entry(struct rfs_ext_entry *extp, unsigned int type, unsigned int entry_offset, const u16 *uname, unsigned char checksum)
  3333. +{
  3334. + int i, uname_end = FALSE;
  3335. + u16 part;
  3336. +
  3337. + if (unlikely(!uname)) /* out-of-range input */
  3338. + return -EIO;
  3339. +
  3340. + set_entry_type((struct rfs_dir_entry *)extp, type);
  3341. + extp->entry_offset = (u8) entry_offset;
  3342. + extp->sysid = 0;
  3343. + extp->checksum = checksum;
  3344. + SET16(extp->start_clu, 0);
  3345. +
  3346. + for (i =0; i < EXT_UNAME_LENGTH; i++) {
  3347. + if (!uname_end)
  3348. + part = uname[i];
  3349. + else
  3350. + part = 0xFFFF;
  3351. +
  3352. + if (i < 5)
  3353. + SET16(extp->uni_0_4[i], part);
  3354. + else if (i < 11)
  3355. + SET16(extp->uni_5_10[i - 5], part);
  3356. + else
  3357. + SET16(extp->uni_11_12[i - 11], part);
  3358. +
  3359. + if (uname[i] == 0x0)
  3360. + uname_end = TRUE;
  3361. + }
  3362. +
  3363. + return 0;
  3364. +}
  3365. +#endif /* CONFIG_RFS_VFAT */
  3366. +
  3367. +/**
  3368. + * get block number related with offset in FAT16 root directory
  3369. + * @param sb super block pointer
  3370. + * @param[in, out] offset offset of directory entry
  3371. + * @param[out] block block number
  3372. + * @return return 0 on success, errno on failure
  3373. + */
  3374. +static inline int get_root_block(struct super_block *sb, unsigned int *offset, unsigned long *block)
  3375. +{
  3376. + struct rfs_sb_info *sbi = RFS_SB(sb);
  3377. + unsigned int off = *offset;
  3378. +
  3379. + off += sbi->root_start_addr;
  3380. + if (off > sbi->root_end_addr) /* out-of-range input */
  3381. + return -EFAULT;
  3382. +
  3383. + *offset = off;
  3384. + *block = off >> sb->s_blocksize_bits;
  3385. + return 0;
  3386. +}
  3387. +
  3388. +/**
  3389. + * Function retriving directory entry using a given cluster value
  3390. + * @param sb super block pointer
  3391. + * @param clu cluster value
  3392. + * @param entry entry offset
  3393. + * @param bh buffer head pointer
  3394. + * @return a pointer of directory entry on success, a negative value on failure
  3395. + */
  3396. +struct rfs_dir_entry *get_entry_with_cluster(struct super_block *sb, unsigned int clu, unsigned int entry, struct buffer_head **bh)
  3397. +{
  3398. + struct rfs_sb_info *sbi = RFS_SB(sb);
  3399. + struct rfs_dir_entry *ep = NULL;
  3400. + unsigned long block;
  3401. + unsigned int off;
  3402. + int err;
  3403. +
  3404. + off = entry << DENTRY_SIZE_BITS;
  3405. +
  3406. + if ((clu != sbi->root_clu) || IS_FAT32(sbi)) {
  3407. + unsigned int cluster_offset, block_offset;
  3408. + unsigned int prev, next;
  3409. +
  3410. + /* FAT32 or sub directory */
  3411. + cluster_offset = off >> sbi->cluster_bits;
  3412. + block_offset = (off >> sb->s_blocksize_bits)
  3413. + & (sbi->blks_per_clu - 1);
  3414. + fat_lock(sb);
  3415. + err = find_cluster(sb, clu, cluster_offset, &prev, &next);
  3416. + fat_unlock(sb);
  3417. + if (err)
  3418. + return ERR_PTR(err);
  3419. + block = START_BLOCK(prev, sb) + block_offset;
  3420. + } else {
  3421. + /* FAT16 root directory */
  3422. + err = get_root_block(sb, &off, &block);
  3423. + if (err)
  3424. + return ERR_PTR(err);
  3425. + }
  3426. +
  3427. + if (*bh)
  3428. + brelse(*bh);
  3429. +
  3430. + *bh = rfs_bread(sb, block, BH_RFS_DIR);
  3431. + if (!(*bh)) { /* I/O error */
  3432. + DPRINTK("can't get buffer head\n");
  3433. + return ERR_PTR(-EIO);
  3434. + }
  3435. +
  3436. + off &= sb->s_blocksize - 1;
  3437. + ep = (struct rfs_dir_entry *) ((*bh)->b_data + off);
  3438. +
  3439. + return ep;
  3440. +}
  3441. +
  3442. +/**
  3443. + * Function retriving directy entry indicted by given entry num
  3444. + * @param dir inode relating to seeking entry
  3445. + * @param entry entry position to be found
  3446. + * @param res_bh buffer head to contain found directry portion
  3447. + * @return a pointer of directory entry on success, a negative value on failure
  3448. + *
  3449. + * Because of difference in name handling routine, find_entry_long handles only
  3450. + * searching with long file name.
  3451. + */
  3452. +struct rfs_dir_entry *get_entry(struct inode *dir, unsigned int entry, struct buffer_head **res_bh)
  3453. +{
  3454. + struct super_block *sb = dir->i_sb;
  3455. + struct rfs_sb_info *sbi = RFS_SB(sb);
  3456. + struct rfs_dir_entry *ep = NULL;
  3457. + unsigned long block;
  3458. + unsigned int off;
  3459. + int err;
  3460. +
  3461. + /* 1. get the real offset in the buffer head */
  3462. + off = entry << DENTRY_SIZE_BITS;
  3463. +
  3464. + if ((RFS_I(dir)->start_clu != sbi->root_clu) || IS_FAT32(sbi)) {
  3465. + long iblock;
  3466. +
  3467. + /* FAT32 or sub directory */
  3468. + iblock = off >> sb->s_blocksize_bits;
  3469. + err = rfs_bmap(dir, iblock, &block);
  3470. + } else {
  3471. + /* FAT16 root directory */
  3472. + err = get_root_block(sb, &off, &block);
  3473. + }
  3474. +
  3475. + if (err)
  3476. + return ERR_PTR(err);
  3477. +
  3478. + if (*res_bh)
  3479. + brelse(*res_bh);
  3480. +
  3481. + *res_bh = rfs_bread(sb, block, BH_RFS_DIR);
  3482. + if (*res_bh == NULL) { /* I/O error */
  3483. + DPRINTK("can't get buffer head\n");
  3484. + return ERR_PTR(-EIO);
  3485. + }
  3486. +
  3487. + off &= sb->s_blocksize - 1;
  3488. + ep = (struct rfs_dir_entry *) ((*res_bh)->b_data + off);
  3489. +
  3490. + return ep;
  3491. +}
  3492. +
  3493. +#ifdef CONFIG_RFS_VFAT
  3494. +/**
  3495. + * Function retrieving unicode name from directory entry
  3496. + * @param dir inode corresponding to directory entry
  3497. + * @param entry the position of directory entry with short file name
  3498. + * @param uname variable for retrieved unicode name
  3499. + * @return zero on success, a negative error code on failure
  3500. + *
  3501. + * This function retrieves unicode name by seeking extend directory entry
  3502. + * with given a offset of short file name entry.
  3503. + */
  3504. +int get_uname_from_entry (struct inode *dir, unsigned int entry, u16 *uname)
  3505. +{
  3506. + struct rfs_ext_entry *extp = NULL;
  3507. + struct rfs_dir_entry *ep = NULL;
  3508. + struct buffer_head *bh = NULL;
  3509. + int i, err = 0;
  3510. +
  3511. + if ((int) entry <= 0) /* out-of-range input */
  3512. + return err;
  3513. +
  3514. + for (i = 0, entry--; entry >= 0; entry--) {
  3515. + ep = get_entry(dir, entry, &bh);
  3516. + if (IS_ERR(ep)) {
  3517. + if (PTR_ERR(ep) != -EFAULT)
  3518. + err = PTR_ERR(ep);
  3519. + break;
  3520. + }
  3521. + extp = (struct rfs_ext_entry *)ep;
  3522. + /* boundary check for max length of array & error handling*/
  3523. + if (entry_type(ep) == TYPE_EXTEND) {
  3524. + get_uname_from_ext_entry(extp, &(uname[i]), TRUE);
  3525. +
  3526. + if (i > UNICODE_NAME_LENGTH) { /* out-of-range input */
  3527. + err = -EIO;
  3528. + break;
  3529. + }
  3530. +
  3531. + if (extp->entry_offset > EXT_END_MARK)
  3532. + break;
  3533. + } else
  3534. + break;
  3535. +
  3536. + i += 13;
  3537. + }
  3538. +
  3539. + brelse(bh);
  3540. +
  3541. + return err;
  3542. +}
  3543. +
  3544. +/**
  3545. + * Function to extract the unicode name from the extend slots
  3546. + * @param dir inode relating to seeking entry
  3547. + * @param entry entry position of the last extend slot
  3548. + * @param bh buffer head pointer
  3549. + * @param ep the last extend slot as input and the SFN slot as output
  3550. + * @return the number of the extend slots
  3551. + */
  3552. +static int get_long_name(struct inode *dir, unsigned int entry, struct buffer_head **res_bh, struct rfs_dir_entry **ep, u16 *ext_uname)
  3553. +{
  3554. + struct rfs_ext_entry *extp;
  3555. + unsigned char checksum;
  3556. + unsigned int type;
  3557. + unsigned int cpos = entry;
  3558. + int nr_ext, i;
  3559. +
  3560. + /* last index */
  3561. + extp = (struct rfs_ext_entry *) (*ep);
  3562. + nr_ext = (int) (extp->entry_offset - EXT_END_MARK);
  3563. + checksum = extp->checksum;
  3564. +
  3565. + i = nr_ext;
  3566. +
  3567. + while (i > 0) {
  3568. + get_uname_from_ext_entry(extp,
  3569. + ext_uname + (i - 1) * EXT_UNAME_LENGTH,
  3570. + (extp->entry_offset > EXT_END_MARK)? TRUE: FALSE);
  3571. +
  3572. + *ep = get_entry(dir, ++cpos, res_bh);
  3573. + if (IS_ERR(*ep)) {
  3574. + if (PTR_ERR(*ep) == -EFAULT) /* end-of-directory */
  3575. + return -ENOENT;
  3576. + return PTR_ERR(*ep);
  3577. + }
  3578. +
  3579. + /* last is SFN directory entry */
  3580. + if (i == 1)
  3581. + break;
  3582. +
  3583. + /* no extend entries */
  3584. + if (entry_type(*ep) != TYPE_EXTEND) {
  3585. + ext_uname[0] = 0x0000;
  3586. + return 0;
  3587. + }
  3588. +
  3589. + /* orphan LFN entry */
  3590. + extp = (struct rfs_ext_entry *) *ep;
  3591. + if ((extp->entry_offset > EXT_END_MARK) ||
  3592. + (extp->checksum != checksum))
  3593. + return 0;
  3594. +
  3595. + i--;
  3596. + }
  3597. +
  3598. + /* SFN entry with extend slots */
  3599. + type = entry_type(*ep);
  3600. +
  3601. + /* orphan LFN entries upto now */
  3602. + if (!(type == TYPE_DIR || type == TYPE_FILE))
  3603. + return 0;
  3604. +
  3605. + if (checksum != calc_checksum((*ep)->name)) {
  3606. + /* no extend entries */
  3607. + ext_uname[0] = 0x0000;
  3608. + return 0;
  3609. + }
  3610. +
  3611. + return nr_ext;
  3612. +}
  3613. +
  3614. +/**
  3615. + * Function check if given file name is exist
  3616. + * @param dir inode relating to seeking entry
  3617. + * @param name name of file to be sought
  3618. + * @param bh buffer head pointer
  3619. + * @param seek_type entry type to be sought
  3620. + * @return a offset of entry if file name exists, a negative value otherwise.
  3621. + *
  3622. + * Because of difference in name handling routine, find_entry_long handles only
  3623. + * searching with long file name
  3624. + */
  3625. +int find_entry_long (struct inode *dir, const char *name, struct buffer_head **bh, unsigned int seek_type)
  3626. +{
  3627. + struct rfs_dir_entry *ep;
  3628. + struct rfs_ext_entry *extp;
  3629. + u16 ext_uname[MAX_TOTAL_LENGTH];
  3630. + u16 unicode[MAX_TOTAL_LENGTH];
  3631. + char dosname[DOS_NAME_LENGTH + 1];
  3632. + int cpos = 0;
  3633. + int nr_slot = 0;
  3634. + int uni_len = 0, uni_slot = 0;
  3635. + unsigned int status = 0;
  3636. + unsigned int type;
  3637. +
  3638. + if (RFS_I(dir)->start_clu == RFS_SB(dir->i_sb)->root_clu) {
  3639. + if (!strcmp(name, ".") || !strcmp(name, ".."))
  3640. + return -INVALID_ENTRY;
  3641. + }
  3642. +
  3643. + memset(unicode, 0xff, MAX_TOTAL_LENGTH * sizeof(u16));
  3644. +
  3645. + /* uni_len has the length of unicode */
  3646. + uni_len = create_fatname(name, dosname, unicode, &status,
  3647. + RFS_SB(dir->i_sb)->nls_disk, FALSE);
  3648. + if (uni_len < 0)
  3649. + return uni_len;
  3650. +
  3651. + uni_slot = ((uni_len + (EXT_UNAME_LENGTH - 1)) / EXT_UNAME_LENGTH);
  3652. +
  3653. + /* scan the directory */
  3654. + while(1) {
  3655. + ep = get_entry(dir, cpos, bh);
  3656. + if (IS_ERR(ep)) {
  3657. + if (PTR_ERR(ep) == -EFAULT) /* end-of-directory */
  3658. + return -ENOENT;
  3659. + return PTR_ERR(ep);
  3660. + }
  3661. +
  3662. + type = entry_type(ep);
  3663. + if (type == TYPE_UNUSED) /* end-of-directory */
  3664. + return -ENOENT;
  3665. + if (type == TYPE_DELETED || type == TYPE_VOLUME) {
  3666. + cpos++;
  3667. + continue;
  3668. + }
  3669. +
  3670. + if (type == TYPE_EXTEND) {
  3671. + extp = (struct rfs_ext_entry *) ep;
  3672. + if ((extp->entry_offset < EXT_END_MARK) || (uni_len == 0)) {
  3673. + cpos++;
  3674. + continue;
  3675. + }
  3676. +
  3677. + /* get long name from extend slot iff unicode exist */
  3678. + memset(ext_uname, 0xff, MAX_TOTAL_LENGTH * sizeof(u16));
  3679. + nr_slot = get_long_name(dir, cpos, bh, &ep, ext_uname);
  3680. + if (nr_slot > 0) {
  3681. + /* found LFN slot, SFN slot */
  3682. + cpos += nr_slot;
  3683. + } else if (nr_slot == 0) {
  3684. + /* not found LFN slot */
  3685. + cpos++;
  3686. + continue;
  3687. + } else {
  3688. + /* fail */
  3689. + return nr_slot;
  3690. + }
  3691. +
  3692. + /* compare long name if length is same */
  3693. + if (nr_slot == uni_slot) {
  3694. + if (!memcmp(ext_uname, unicode, (nr_slot *
  3695. + EXT_UNAME_LENGTH * sizeof(u16)))) {
  3696. + if ((seek_type == TYPE_ALL) ||
  3697. + (seek_type == type))
  3698. + goto found;
  3699. + }
  3700. + }
  3701. + }
  3702. +
  3703. + if (uni_len == 0) {
  3704. + /* always compare short name */
  3705. + if (!strncmp(dosname, ep->name, DOS_NAME_LENGTH)) {
  3706. + if ((seek_type == TYPE_ALL) || (seek_type == type))
  3707. + goto found;
  3708. + }
  3709. + }
  3710. + cpos++;
  3711. + }
  3712. +
  3713. +found:
  3714. + return cpos;
  3715. +}
  3716. +
  3717. +#else /* !CONFIG_RFS_VFAT */
  3718. +
  3719. +/**
  3720. + * Function check if given file name is exist
  3721. + * @param dir inode relating to seeking entry
  3722. + * @param name file name to be sought
  3723. + * @param bh buffer head to contain found directry portion
  3724. + * @param seek_type entry type to be sought
  3725. + * @return a offset of entry if file name exists, a negative value otherwise.
  3726. + *
  3727. + * Because of difference in name handling routine, find_entry_long handles only
  3728. + * searching with short file name (8.3 dos name)
  3729. + */
  3730. +int find_entry_short(struct inode *dir, const char *name, struct buffer_head **bh, unsigned int seek_type)
  3731. +{
  3732. + struct rfs_dir_entry *ep;
  3733. + char dosname[DOS_NAME_LENGTH];
  3734. + int cpos = 0;
  3735. + unsigned int type;
  3736. +
  3737. + if (RFS_I(dir)->start_clu == RFS_SB(dir->i_sb)->root_clu) {
  3738. + if (!strcmp(name, ".") || !strcmp(name, ".."))
  3739. + return -INVALID_ENTRY;
  3740. + }
  3741. +
  3742. + cpos = create_fatname(name, dosname, NULL, NULL,
  3743. + RFS_SB(dir->i_sb)->nls_disk, FALSE);
  3744. + if (cpos < 0)
  3745. + return cpos;
  3746. +
  3747. + cpos = 0;
  3748. + while (1) {
  3749. + ep = get_entry(dir, cpos, bh);
  3750. + if (IS_ERR(ep)) {
  3751. + if (PTR_ERR(ep) == -EFAULT) /* end-of-directory */
  3752. + return -ENOENT;
  3753. + return PTR_ERR(ep);
  3754. + }
  3755. +
  3756. + type = entry_type(ep);
  3757. + if (type == TYPE_FILE || type == TYPE_DIR) {
  3758. + if (!strncmp(dosname, ep->name, DOS_NAME_LENGTH)) {
  3759. + if (seek_type == TYPE_ALL) {
  3760. + goto found;
  3761. + } else if (seek_type == type) {
  3762. + goto found;
  3763. + }
  3764. + }
  3765. + } else if (type == TYPE_UNUSED) { /* end-of-directory */
  3766. + return -ENOENT;
  3767. + }
  3768. + cpos++;
  3769. + }
  3770. +
  3771. +found:
  3772. + return cpos;
  3773. +}
  3774. +#endif /* CONFIG_RFS_VFAT */
  3775. +
  3776. +/**
  3777. + * Function to remove directy entries
  3778. + * @param dir inode relating to deteted entry
  3779. + * @param entry position of entry deletion will occur
  3780. + * @param bh buffer head containing directory entry
  3781. + * @return zero on success, negative error code on failure
  3782. + */
  3783. +int remove_entry (struct inode *dir, unsigned int entry, struct buffer_head **bh)
  3784. +{
  3785. + struct rfs_dir_entry *ep;
  3786. + unsigned int numof_entries = 0;
  3787. + unsigned int i = 0;
  3788. + /*
  3789. + * RFS-log : 21 comes from
  3790. + * cell(MAX_NAME_LENGTH / EXT_UNAME_LENGTH) + 1.
  3791. + * It means max(extended entries) + original entry
  3792. + */
  3793. + unsigned char undel_buf[21];
  3794. + unsigned char ent_off = 0;
  3795. +
  3796. + while (1) {
  3797. + ep = get_entry(dir, entry - i, bh);
  3798. + if (IS_ERR(ep))
  3799. + goto error;
  3800. +
  3801. + if ((i != 0) && (entry_type(ep) != TYPE_EXTEND))
  3802. + break;
  3803. +
  3804. + if (i == 0) {
  3805. + /* sanity check */
  3806. + if (unlikely((entry_type(ep) != TYPE_FILE) &&
  3807. + (entry_type(ep) != TYPE_DIR))) {
  3808. + RFS_BUG("dir entry (%d, %d) is corrupted\n",
  3809. + RFS_I(dir)->start_clu,
  3810. + entry);
  3811. + return -EIO;
  3812. + }
  3813. + }
  3814. +
  3815. + undel_buf[i] = ep->name[0];
  3816. + numof_entries++;
  3817. + if (entry - i == 0)
  3818. + break;
  3819. + if (entry_type(ep) == TYPE_EXTEND) {
  3820. + ent_off = ((struct rfs_ext_entry *) ep)->entry_offset;
  3821. + if (ent_off > EXT_END_MARK)
  3822. + break;
  3823. + }
  3824. + i++;
  3825. + }
  3826. +
  3827. + /* RFS-log : remove entry */
  3828. + if (rfs_log_remove_entry(dir->i_sb, RFS_I(dir)->start_clu, entry,
  3829. + numof_entries, undel_buf)) {
  3830. + return -EIO;
  3831. + }
  3832. +
  3833. + for (i = 0; i < numof_entries; i++) {
  3834. + ep = get_entry(dir, entry - i, bh);
  3835. + if (IS_ERR(ep))
  3836. + goto error;
  3837. +
  3838. + set_entry_type(ep, TYPE_DELETED);
  3839. +
  3840. + if (buffer_uptodate(*bh))
  3841. + rfs_mark_buffer_dirty(*bh, dir->i_sb);
  3842. + }
  3843. +
  3844. + return 0;
  3845. +
  3846. +error:
  3847. + return PTR_ERR(ep);
  3848. +}
  3849. diff -NurbB linux-2.6.17.14.orig/fs/rfs/file.c linux-2.6.17.14.rfs/fs/rfs/file.c
  3850. --- linux-2.6.17.14.orig/fs/rfs/file.c 1970-01-01 01:00:00.000000000 +0100
  3851. +++ linux-2.6.17.14.rfs/fs/rfs/file.c 2008-06-19 04:02:09.000000000 +0200
  3852. @@ -0,0 +1,731 @@
  3853. +/**
  3854. + *
  3855. + * @file fs/rfs/file.c
  3856. + * @brief file and file inode functions
  3857. + *
  3858. + *---------------------------------------------------------------------------*
  3859. + * *
  3860. + * COPYRIGHT 2003-2007 SAMSUNG ELECTRONICS CO., LTD. *
  3861. + * ALL RIGHTS RESERVED *
  3862. + * *
  3863. + * Permission is hereby granted to licensees of Samsung Electronics *
  3864. + * Co., Ltd. products to use or abstract this computer program only in *
  3865. + * accordance with the terms of the NAND FLASH MEMORY SOFTWARE LICENSE *
  3866. + * AGREEMENT for the sole purpose of implementing a product based on *
  3867. + * Samsung Electronics Co., Ltd. products. No other rights to reproduce, *
  3868. + * use, or disseminate this computer program, whether in part or in *
  3869. + * whole, are granted. *
  3870. + * *
  3871. + * Samsung Electronics Co., Ltd. makes no representation or warranties *
  3872. + * with respect to the performance of this computer program, and *
  3873. + * specifically disclaims any responsibility for any damages, *
  3874. + * special or consequential, connected with the use of this program. *
  3875. + * *
  3876. + *---------------------------------------------------------------------------*
  3877. + *
  3878. + */
  3879. +
  3880. +#include <linux/spinlock.h>
  3881. +#include <linux/smp_lock.h>
  3882. +#include <linux/fs.h>
  3883. +#include <linux/rfs_fs.h>
  3884. +
  3885. +#include "rfs.h"
  3886. +#include "log.h"
  3887. +
  3888. +#ifdef CONFIG_GCOV_PROFILE
  3889. +#define loff_t off_t
  3890. +#endif
  3891. +
  3892. +/**
  3893. + * check the hint info of inode whether it is available
  3894. + * @param inode inode
  3895. + * @param num_clusters number of clusters to skip
  3896. + * @param start_clu start cluster number to read after skipping hint
  3897. + * @return return 0 on success, EINVAL on failure
  3898. + *
  3899. + * If hint info has availability, rest cluster chain can be read after skipping specified clusters
  3900. + */
  3901. +static inline int rfs_lookup_hint(struct inode *inode, unsigned int *num_clusters, unsigned int *start_clu)
  3902. +{
  3903. + if (RFS_I(inode)->start_clu == CLU_TAIL)
  3904. + return -EFAULT;
  3905. +
  3906. + if ((*num_clusters > 0) && (RFS_I(inode)->hint_last_offset > 0)
  3907. + && (RFS_I(inode)->hint_last_clu >= VALID_CLU)
  3908. + && (*num_clusters >= RFS_I(inode)->hint_last_offset)) {
  3909. + *start_clu = RFS_I(inode)->hint_last_clu;
  3910. + *num_clusters -= RFS_I(inode)->hint_last_offset;
  3911. + } else {
  3912. + *start_clu = RFS_I(inode)->start_clu;
  3913. + }
  3914. +
  3915. + return 0;
  3916. +}
  3917. +
  3918. +/**
  3919. + * invalidate the hint info of inode
  3920. + * @param inode inode
  3921. + */
  3922. +void rfs_invalidate_hint(struct inode *inode)
  3923. +{
  3924. + RFS_I(inode)->hint_last_clu = 0;
  3925. + RFS_I(inode)->hint_last_offset = 0;
  3926. +}
  3927. +
  3928. +/**
  3929. + * update the hint info of inode
  3930. + * @param inode inode
  3931. + * @param cluster previous last cluster number accessed
  3932. + * @param offset cluster offset into a fat chain
  3933. + */
  3934. +static inline void rfs_update_hint(struct inode *inode, unsigned int cluster, unsigned int offset)
  3935. +{
  3936. + if (cluster < VALID_CLU || !offset) {
  3937. + rfs_invalidate_hint(inode);
  3938. + } else {
  3939. + RFS_I(inode)->hint_last_clu = cluster;
  3940. + RFS_I(inode)->hint_last_offset = offset;
  3941. + }
  3942. +}
  3943. +
  3944. +/**
  3945. + * fill the page with zero
  3946. + * @param inode inode
  3947. + * @param page page pointer
  3948. + * @param zerofrom start offset within page
  3949. + * @param zeroto last offset within page
  3950. + * @param get_block get_block funciton
  3951. + * @return return 0 on success, errno on failure
  3952. + *
  3953. + * This function is invoked by extend_with_zerofill
  3954. + */
  3955. +static int rfs_page_zerofill(struct inode * inode, struct page * page, unsigned zerofrom, unsigned zeroto, get_block_t *get_block)
  3956. +{
  3957. + struct buffer_head *bh, *head;
  3958. + unsigned long block;
  3959. + unsigned block_start, block_end, blocksize, bbits, blk_aligned_zeroto;
  3960. + int err = 0, partial = 0;
  3961. + char *kaddr;
  3962. +
  3963. + bbits = inode->i_blkbits;
  3964. + blocksize = 1 << bbits;
  3965. +
  3966. +#ifdef RFS_FOR_2_6
  3967. + if (!page_has_buffers(page))
  3968. + create_empty_buffers(page, blocksize, 0);
  3969. + head = page_buffers(page);
  3970. +#else
  3971. + if (!page->buffers)
  3972. + create_empty_buffers(page, inode->i_dev, blocksize);
  3973. + head = page->buffers;
  3974. +#endif
  3975. +
  3976. + block = page->index << (PAGE_CACHE_SHIFT - bbits); /* start block # */
  3977. +
  3978. + /* In the first phase, we allocate buffers and map them to fill zero */
  3979. + for(bh = head, block_start = 0; bh != head || !block_start;
  3980. + block++, block_start = block_end + 1, bh = bh->b_this_page) {
  3981. + if (!bh) { /* I/O error */
  3982. + err = -EIO;
  3983. + RFS_BUG("can't get buffer head\n");
  3984. + goto out;
  3985. + }
  3986. + block_end = block_start + blocksize - 1;
  3987. + if (block_end < zerofrom)
  3988. + continue;
  3989. + else if (block_start > zeroto)
  3990. + break;
  3991. + clear_bit(BH_New, &bh->b_state);
  3992. +
  3993. + /* map new buffer head */
  3994. + err = get_block(inode, block, bh, 1);
  3995. + if (err) {
  3996. + DEBUG(DL1, "no block\n");
  3997. + goto out;
  3998. + }
  3999. + if (!buffer_uptodate(bh) && (block_start < zerofrom)) {
  4000. + ll_rw_block(READ, 1, &bh);
  4001. + wait_on_buffer(bh);
  4002. + if (!buffer_uptodate(bh)) {
  4003. + err = -EIO;
  4004. + goto out;
  4005. + }
  4006. + }
  4007. + }
  4008. +
  4009. + /*
  4010. + * In the second phase, we memset the page with zero,
  4011. + * in the block aligned manner.
  4012. + * If memset is not block-aligned, hole may return garbage data.
  4013. + */
  4014. + blk_aligned_zeroto = zeroto | (blocksize - 1);
  4015. + kaddr = kmap_atomic(page, KM_USER0);
  4016. + memset(kaddr + zerofrom, 0, blk_aligned_zeroto - zerofrom + 1);
  4017. +
  4018. + /* In the third phase, we make the buffers uptodate and dirty */
  4019. + for(bh = head, block_start = 0; bh != head || !block_start;
  4020. + block_start = block_end + 1, bh = bh->b_this_page) {
  4021. + block_end = block_start + blocksize - 1;
  4022. + if (block_end < zerofrom) {
  4023. + /* block exists in the front of zerofrom. */
  4024. + if (!buffer_uptodate(bh))
  4025. + partial = 1;
  4026. + continue;
  4027. + } else if (block_start > zeroto) {
  4028. + /* block exists in the back of zeroto. */
  4029. + partial = 1;
  4030. + break;
  4031. + }
  4032. +
  4033. +#ifdef RFS_FOR_2_6
  4034. + set_buffer_uptodate(bh);
  4035. + mark_buffer_dirty(bh);
  4036. +#else
  4037. + mark_buffer_uptodate(bh, 1);
  4038. + mark_buffer_dirty(bh);
  4039. + down(&RFS_I(inode)->data_mutex);
  4040. + buffer_insert_inode_data_queue(bh, inode);
  4041. + up(&RFS_I(inode)->data_mutex);
  4042. +#endif
  4043. + }
  4044. +
  4045. + /* if all buffers of a page were filled zero */
  4046. + if (!partial)
  4047. + SetPageUptodate(page);
  4048. +
  4049. +out:
  4050. + flush_dcache_page(page);
  4051. + kunmap_atomic(kaddr, KM_USER0);
  4052. + return err;
  4053. +}
  4054. +
  4055. +/**
  4056. + * extend a file with zero-fill
  4057. + * @param inode inode
  4058. + * @param origin_size file size before extend
  4059. + * @param new_size file size to extend
  4060. + * @return return 0 on success, errno on failure
  4061. + *
  4062. + * rfs doesn't allow holes.
  4063. + */
  4064. +int extend_with_zerofill(struct inode *inode, unsigned int origin_size, unsigned int new_size)
  4065. +{
  4066. + struct address_space *mapping = inode->i_mapping;
  4067. + struct super_block *sb = inode->i_sb;
  4068. + struct page *page = NULL;
  4069. + unsigned long index, final_index;
  4070. + unsigned long next_page_start, offset, next_offset;
  4071. + unsigned int origin_clusters, new_clusters, clusters_to_extend;
  4072. + unsigned zerofrom, zeroto; /* offset within page */
  4073. + int err = 0;
  4074. +
  4075. + /* compare the number of required clusters with that of free clusters */
  4076. + origin_clusters = (origin_size + RFS_SB(sb)->cluster_size - 1)
  4077. + >> RFS_SB(sb)->cluster_bits;
  4078. + new_clusters = (new_size + RFS_SB(sb)->cluster_size - 1)
  4079. + >> RFS_SB(sb)->cluster_bits;
  4080. + clusters_to_extend = new_clusters - origin_clusters;
  4081. +
  4082. + if (clusters_to_extend && (clusters_to_extend > GET_FREE_CLUS(RFS_SB(sb)))) {
  4083. + DEBUG(DL2, "No space \n");
  4084. + return -ENOSPC;
  4085. + }
  4086. +
  4087. + offset = origin_size;
  4088. + final_index = (new_size - 1) >> PAGE_CACHE_SHIFT; /* newsize isn't 0 */
  4089. + while ((index = (offset >> PAGE_CACHE_SHIFT)) <= final_index) {
  4090. + page = grab_cache_page(mapping, index);
  4091. + if (!page) { /* memory error */
  4092. + DEBUG(DL0, "out of memory !!");
  4093. + return -ENOMEM;
  4094. + }
  4095. +
  4096. + /* calculate zerofrom and zeroto */
  4097. + next_page_start = (index + 1) << PAGE_CACHE_SHIFT;
  4098. + next_offset = (new_size > next_page_start) ? next_page_start : new_size;
  4099. +
  4100. + zerofrom = offset & (PAGE_CACHE_SIZE - 1);
  4101. + zeroto = (next_offset - 1) & (PAGE_CACHE_SIZE - 1);
  4102. +
  4103. + err = rfs_page_zerofill(inode, page, zerofrom, zeroto, rfs_get_block);
  4104. + if (err) {
  4105. + if (unlikely(err == -ENOSPC)) {
  4106. + DEBUG(DL0, "The # of the real free clusters is different from super block.");
  4107. + err = -EIO;
  4108. + }
  4109. + ClearPageUptodate(page);
  4110. + unlock_page(page);
  4111. + page_cache_release(page);
  4112. + DEBUG(DL1, "zero fill failed (err : %d)\n", err);
  4113. + goto out;
  4114. + }
  4115. +
  4116. + offset = next_page_start;
  4117. + unlock_page(page);
  4118. + page_cache_release(page);
  4119. + }
  4120. +
  4121. +out:
  4122. + return err;
  4123. +}
  4124. +
  4125. +/**
  4126. + * truncate a file to a specified size
  4127. + * @param inode inode
  4128. + *
  4129. + * support to reduce or enlarge a file
  4130. + */
  4131. +void rfs_truncate(struct inode *inode)
  4132. +{
  4133. + struct super_block *sb = inode->i_sb;
  4134. + unsigned int num_clusters = 0;
  4135. + unsigned long origin_size, origin_mmu_private;
  4136. + int is_back = 0;
  4137. + int err;
  4138. +
  4139. + origin_size = RFS_I(inode)->trunc_start;
  4140. + origin_mmu_private = RFS_I(inode)->mmu_private;
  4141. +
  4142. + /* check the validity */
  4143. + if (IS_RDONLY(inode))
  4144. + goto rollback_size;
  4145. +
  4146. + if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
  4147. + S_ISLNK(inode->i_mode)))
  4148. + goto rollback_size;
  4149. +
  4150. + if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  4151. + goto rollback_size;
  4152. +
  4153. + /* RFS-log : start truncate */
  4154. + if ((loff_t) origin_size < (loff_t) inode->i_size) {
  4155. + /* if caller is inode_setattr, tr can be nested */
  4156. + err = rfs_log_start(sb, RFS_LOG_TRUNCATE_F, inode);
  4157. + is_back = 0;
  4158. + } else {
  4159. + err = rfs_log_start(sb, RFS_LOG_TRUNCATE_B, inode);
  4160. + is_back = 1;
  4161. + }
  4162. + if (err)
  4163. + goto rollback_size;
  4164. +
  4165. + /* transactin starts from here */
  4166. + if (RFS_I(inode)->i_state == RFS_I_FREE)
  4167. + /* RFS do not perform truncate of unlinked file */
  4168. + goto end_log;
  4169. +
  4170. + if (is_back) { /* reduce a file */
  4171. + num_clusters = (inode->i_size + RFS_SB(sb)->cluster_size - 1)
  4172. + >> RFS_SB(sb)->cluster_bits;
  4173. +
  4174. + err = dealloc_clusters(inode, num_clusters);
  4175. + if (err) {
  4176. + /*
  4177. + * FIXME: media failure
  4178. + * Even though this failure may result in serious error,
  4179. + * rfs_truncate can propagate it to the upper layer.
  4180. + * This will make it difficult to debug the error
  4181. + * caused by media failure.
  4182. + * Should we revive the dealloced clusters?
  4183. + * Or, should we truncate the file anyway?
  4184. + *
  4185. + * We can mark the inode with media fail.
  4186. + */
  4187. + goto invalidate_hint;
  4188. + }
  4189. + set_mmu_private(inode, inode->i_size);
  4190. + } else if (origin_mmu_private < inode->i_size) {
  4191. + /* extending file with zero */
  4192. + err = extend_with_zerofill(inode,
  4193. + (u32) origin_mmu_private, (u32) inode->i_size);
  4194. + if (err == -ENOSPC) {
  4195. + DEBUG(DL2, "failed to enlarge a file");
  4196. + goto end_log;
  4197. + } else if (err) {
  4198. + DEBUG(DL2, "failed to enlarge a file");
  4199. + truncate_inode_pages(inode->i_mapping, origin_size);
  4200. + num_clusters = (origin_size + RFS_SB(sb)->cluster_size - 1)
  4201. + >> RFS_SB(sb)->cluster_bits;
  4202. +
  4203. + err = dealloc_clusters(inode, num_clusters);
  4204. + if (err)
  4205. + DEBUG(DL2, "failed to reduce a file");
  4206. +
  4207. + goto invalidate_hint;
  4208. + }
  4209. + } else {
  4210. + /* truncate forward but already zero filled, so do nothing */
  4211. + }
  4212. +
  4213. + /* invalidate hint info */
  4214. + rfs_invalidate_hint(inode);
  4215. +
  4216. + inode->i_blocks = (inode->i_size + SECTOR_SIZE - 1) >> SECTOR_BITS;
  4217. + inode->i_mtime = inode->i_atime = CURRENT_TIME;
  4218. + rfs_mark_inode_dirty(inode);
  4219. +
  4220. + /* RFS-log : end truncate */
  4221. + if (rfs_log_end(sb, 0)) {
  4222. + /* should we mark the file with media failure */
  4223. + ;
  4224. + }
  4225. +
  4226. + return;
  4227. +
  4228. +invalidate_hint:
  4229. + rfs_invalidate_hint(inode);
  4230. + RFS_I(inode)->mmu_private = origin_mmu_private;
  4231. + inode->i_size = (loff_t) origin_size;
  4232. + rfs_mark_inode_dirty(inode);
  4233. + rfs_log_end(sb, 1);
  4234. + return;
  4235. +
  4236. +end_log:
  4237. + inode->i_size = (loff_t) origin_size;
  4238. + rfs_mark_inode_dirty(inode);
  4239. + rfs_log_end(sb, 1);
  4240. + return;
  4241. +
  4242. +rollback_size:
  4243. + inode->i_size = (loff_t) origin_size;
  4244. + mark_inode_dirty(inode);
  4245. + return;
  4246. +}
  4247. +
  4248. +/**
  4249. + * change an attribute of inode
  4250. + * @param dentry dentry
  4251. + * @param attr new attribute to set
  4252. + * @return return 0 on success, errno on failure
  4253. + *
  4254. + * it is only used for chmod, especially when read only mode be changed
  4255. + */
  4256. +int rfs_setattr(struct dentry *dentry, struct iattr *attr)
  4257. +{
  4258. + struct inode *inode = dentry->d_inode;
  4259. + struct buffer_head *bh = NULL;
  4260. + struct rfs_dir_entry *ep = NULL;
  4261. + int perm, err = 0;
  4262. + int tr_start = 0;
  4263. +
  4264. + CHECK_RFS_INODE(inode, -EINVAL);
  4265. +
  4266. + if (check_reserved_files(inode, NULL))
  4267. + return -EPERM;
  4268. +
  4269. + if (attr->ia_valid & ATTR_SIZE) {
  4270. + if ((loff_t) inode->i_size < (loff_t) attr->ia_size) {
  4271. + unsigned int end_index = inode->i_size >>
  4272. + PAGE_CACHE_SHIFT;
  4273. + unsigned int mmu_private = RFS_I(inode)->mmu_private;
  4274. + unsigned int next_page_start, to_size;
  4275. +
  4276. + next_page_start = (end_index + 1) << PAGE_CACHE_SHIFT;
  4277. + to_size = ((loff_t) attr->ia_size >
  4278. + (loff_t) next_page_start) ?
  4279. + next_page_start : (unsigned int) attr->ia_size;
  4280. + if (mmu_private < to_size) {
  4281. + /*
  4282. + * RFS-log : fill last page with zero
  4283. + * to avoid race-condition with writepage
  4284. + * (recursive transaction)
  4285. + */
  4286. + if (rfs_log_start(inode->i_sb,
  4287. + RFS_LOG_TRUNCATE_F,
  4288. + inode))
  4289. + return -EIO;
  4290. +
  4291. + tr_start = 1; /* transaction starts */
  4292. +
  4293. + err = extend_with_zerofill(inode,
  4294. + (u32) mmu_private,
  4295. + (u32) to_size);
  4296. +
  4297. + if (err) {
  4298. + rfs_log_end(inode->i_sb, err);
  4299. + return err;
  4300. + }
  4301. +
  4302. + /* update zerofilled inode's size */
  4303. + inode->i_size = to_size;
  4304. + }
  4305. + }
  4306. +
  4307. + /* keep current inode size for truncate operation */
  4308. + RFS_I(inode)->trunc_start = inode->i_size;
  4309. + }
  4310. +
  4311. + if (attr->ia_valid & ATTR_MODE) {
  4312. + perm = attr->ia_mode & 0777;
  4313. + ep = get_entry_with_cluster(inode->i_sb,
  4314. + RFS_I(inode)->p_start_clu,
  4315. + RFS_I(inode)->index, &bh);
  4316. + if (IS_ERR(ep)) {
  4317. + if (PTR_ERR(ep) == -EFAULT)
  4318. + err = -ENOENT;
  4319. + else
  4320. + err = PTR_ERR(ep);
  4321. + goto out;
  4322. + }
  4323. +
  4324. + if (perm & 0222)
  4325. + ep->attr &= ~ATTR_READONLY;
  4326. + else
  4327. + ep->attr |= ATTR_READONLY;
  4328. +
  4329. + mark_buffer_dirty(bh);
  4330. + }
  4331. +
  4332. + err = inode_setattr(inode, attr);
  4333. +
  4334. +out:
  4335. + brelse(bh);
  4336. +
  4337. + if (tr_start)
  4338. + rfs_log_end(inode->i_sb, err);
  4339. +
  4340. + return err;
  4341. +}
  4342. +
  4343. +/**
  4344. + * check a permission of inode
  4345. + * @param inode inode
  4346. + * @param mode mode
  4347. + * @param nd nameidata
  4348. + * @return return 0 on success, EPERM on failure
  4349. + *
  4350. + * System file (log or pool file) can not be accessed
  4351. + */
  4352. +#ifdef RFS_FOR_2_6
  4353. +int rfs_permission(struct inode *inode, int mode, struct nameidata *nd)
  4354. +#else
  4355. +int rfs_permission(struct inode *inode, int mode)
  4356. +#endif
  4357. +{
  4358. + if (mode & (MAY_WRITE | MAY_READ))
  4359. + return check_reserved_files(inode, NULL);
  4360. +
  4361. + return 0; /* all operations are permitted */
  4362. +}
  4363. +
  4364. +#ifdef CONFIG_GCOV_PROFILE
  4365. +#undef loff_t
  4366. +#endif
  4367. +
  4368. +/**
  4369. + * write up to count bytes to file at speicified position
  4370. + * @param file file
  4371. + * @param buf buffer pointer
  4372. + * @param count number of bytes to write
  4373. + * @param ppos offset in file
  4374. + * @return return write bytes on success, errno on failure
  4375. + *
  4376. + * use pre-allocation for reducing working logs
  4377. + */
  4378. +static ssize_t rfs_file_write(struct file *file, const char *buf,
  4379. + size_t count, loff_t *ppos)
  4380. +{
  4381. + struct inode *inode;
  4382. + ssize_t ret;
  4383. + int err;
  4384. +
  4385. + ret = generic_file_write(file, buf, count, ppos);
  4386. + if (ret <= 0)
  4387. + return ret;
  4388. +
  4389. + inode = file->f_dentry->d_inode->i_mapping->host;
  4390. + if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) {
  4391. + err = rfs_log_force_commit(inode->i_sb, inode);
  4392. + if (err)
  4393. + return -EIO;
  4394. + }
  4395. +
  4396. + return ret;
  4397. +}
  4398. +
  4399. +/**
  4400. + * flush all dirty buffers of inode include data and meta data
  4401. + * @param file file pointer
  4402. + * @param dentry dentry pointer
  4403. + * @param datasync flag
  4404. + * @return return 0 on success, EPERM on failure
  4405. + */
  4406. +static int rfs_file_fsync(struct file * file, struct dentry *dentry, int datasync)
  4407. +{
  4408. + struct inode *inode = dentry->d_inode;
  4409. + struct super_block *sb = inode->i_sb;
  4410. + int ret = 0, err = 0;
  4411. +
  4412. + /* data commit */
  4413. + ret = rfs_sync_inode(inode, 1, 1);
  4414. +
  4415. + /* meta-commit deferred tr */
  4416. + if (tr_deferred_commit(sb) && RFS_LOG_I(sb)->inode &&
  4417. + (RFS_LOG_I(sb)->inode == inode)) {
  4418. + err = rfs_log_force_commit(inode->i_sb, inode);
  4419. + if (err && !ret)
  4420. + ret = err;
  4421. + }
  4422. +
  4423. + return ret;
  4424. +}
  4425. +
  4426. +#ifdef CONFIG_RFS_SYNC_ON_CLOSE
  4427. +/**
  4428. + * flush modified data of file object
  4429. + * @inode inode of file object to flush
  4430. + * @file file object to flush
  4431. + *
  4432. + * It is only called when all files are closed, that is inode is released
  4433. + */
  4434. +static int rfs_file_release(struct inode * inode, struct file * file)
  4435. +{
  4436. +#ifdef RFS_FOR_2_6
  4437. + filemap_fdatawrite(inode->i_mapping);
  4438. + filemap_fdatawait(inode->i_mapping);
  4439. +#endif
  4440. + return rfs_file_fsync(file, file->f_dentry, 0);
  4441. +}
  4442. +#endif
  4443. +
  4444. +struct file_operations rfs_file_operations = {
  4445. + .read = generic_file_read,
  4446. + .write = rfs_file_write,
  4447. + .mmap = generic_file_mmap,
  4448. + .fsync = rfs_file_fsync,
  4449. +#ifdef CONFIG_RFS_SYNC_ON_CLOSE
  4450. + .release = rfs_file_release,
  4451. +#endif
  4452. +};
  4453. +
  4454. +struct inode_operations rfs_file_inode_operations = {
  4455. + .truncate = rfs_truncate,
  4456. + .permission = rfs_permission,
  4457. + .setattr = rfs_setattr,
  4458. +};
  4459. +
  4460. +/**
  4461. + * translate index into a logical block
  4462. + * @param inode inode
  4463. + * @param iblock index
  4464. + * @param bh_result buffer head pointer
  4465. + * @param create flag whether new block will be allocated
  4466. + * @return returns 0 on success, errno on failure
  4467. + *
  4468. + * if there aren't logical block, allocate new cluster and map it
  4469. + */
  4470. +#ifdef RFS_FOR_2_6
  4471. +int rfs_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create)
  4472. +#else
  4473. +int rfs_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create)
  4474. +#endif
  4475. +{
  4476. + unsigned long phys = 0;
  4477. + struct super_block *sb = inode->i_sb;
  4478. + unsigned int new_clu;
  4479. + int ret = 0;
  4480. +
  4481. +#ifdef RFS_FOR_2_4
  4482. + lock_kernel();
  4483. +#endif
  4484. +
  4485. + ret = rfs_bmap(inode, iblock, &phys);
  4486. + if (!ret) {
  4487. +#ifdef RFS_FOR_2_6
  4488. + map_bh(bh_result, sb, phys);
  4489. +#else
  4490. + bh_result->b_dev = inode->i_dev;
  4491. + bh_result->b_blocknr = phys;
  4492. + bh_result->b_state |= (1UL << BH_Mapped);
  4493. +#endif
  4494. + goto out;
  4495. + }
  4496. +
  4497. + ret = -EIO;
  4498. + if (!create)
  4499. + goto out;
  4500. +
  4501. + if (iblock != (RFS_I(inode)->mmu_private >> sb->s_blocksize_bits))
  4502. + goto out;
  4503. +
  4504. + if (!(iblock & (RFS_SB(sb)->blks_per_clu - 1))) {
  4505. + ret = alloc_cluster(inode, &new_clu);
  4506. + if (ret)
  4507. + goto out;
  4508. + }
  4509. +
  4510. + RFS_I(inode)->mmu_private += sb->s_blocksize;
  4511. + ret = rfs_bmap(inode, iblock, &phys);
  4512. + if (ret) {
  4513. + RFS_I(inode)->mmu_private -= sb->s_blocksize;
  4514. + RFS_BUG("iblock(%ld) doesn't have a physical mapping",
  4515. + iblock);
  4516. + goto out;
  4517. + }
  4518. +
  4519. +#ifdef RFS_FOR_2_6
  4520. + set_buffer_new(bh_result);
  4521. + map_bh(bh_result, sb, phys);
  4522. +#else
  4523. + bh_result->b_dev = inode->i_dev;
  4524. + bh_result->b_blocknr = phys;
  4525. + bh_result->b_state |= (1UL << BH_Mapped);
  4526. + bh_result->b_state |= (1UL << BH_New);
  4527. +#endif
  4528. +
  4529. +out:
  4530. +#ifdef RFS_FOR_2_4
  4531. + unlock_kernel();
  4532. +#endif
  4533. + return ret;
  4534. +}
  4535. +
  4536. +/**
  4537. + * translation index into logical block number
  4538. + * @param inode inode
  4539. + * @param index index number
  4540. + * @param[out] phys logical block number
  4541. + * @return returns 0 on success, errno on failure
  4542. + * @pre FAT16 root directory's inode does not invoke this function
  4543. + */
  4544. +int rfs_bmap(struct inode *inode, long index, unsigned long *phys)
  4545. +{
  4546. + struct super_block *sb = inode->i_sb;
  4547. + struct rfs_sb_info *sbi = RFS_SB(sb);
  4548. + unsigned int cluster, offset, num_clusters;
  4549. + unsigned int last_block;
  4550. + unsigned int clu, prev, next;
  4551. + int err = 0;
  4552. +
  4553. + fat_lock(sb);
  4554. +
  4555. + cluster = index >> sbi->blks_per_clu_bits;
  4556. + offset = index & (sbi->blks_per_clu - 1);
  4557. +
  4558. + /* check hint info */
  4559. + num_clusters = cluster;
  4560. + err = rfs_lookup_hint(inode, &num_clusters, &clu);
  4561. + if (err)
  4562. + goto out;
  4563. +
  4564. + last_block = (RFS_I(inode)->mmu_private + (sb->s_blocksize - 1))
  4565. + >> sb->s_blocksize_bits;
  4566. + if (index >= last_block) {
  4567. + err = -EFAULT;
  4568. + goto out;
  4569. + }
  4570. +
  4571. + err = find_cluster(sb, clu, num_clusters, &prev, &next);
  4572. + if (err)
  4573. + goto out;
  4574. +
  4575. + /* update hint info */
  4576. + rfs_update_hint(inode, prev, cluster);
  4577. +
  4578. + *phys = START_BLOCK(prev, sb) + offset;
  4579. +out:
  4580. + fat_unlock(sb);
  4581. +
  4582. + return err;
  4583. +}
  4584. diff -NurbB linux-2.6.17.14.orig/fs/rfs/inode.c linux-2.6.17.14.rfs/fs/rfs/inode.c
  4585. --- linux-2.6.17.14.orig/fs/rfs/inode.c 1970-01-01 01:00:00.000000000 +0100
  4586. +++ linux-2.6.17.14.rfs/fs/rfs/inode.c 2008-06-19 04:02:08.000000000 +0200
  4587. @@ -0,0 +1,814 @@
  4588. +/**
  4589. + * @file fs/rfs/inode.c
  4590. + * @brief common inode operations
  4591. + *
  4592. + *---------------------------------------------------------------------------*
  4593. + * *
  4594. + * COPYRIGHT 2003-2007 SAMSUNG ELECTRONICS CO., LTD. *
  4595. + * ALL RIGHTS RESERVED *
  4596. + * *
  4597. + * Permission is hereby granted to licensees of Samsung Electronics *
  4598. + * Co., Ltd. products to use or abstract this computer program only in *
  4599. + * accordance with the terms of the NAND FLASH MEMORY SOFTWARE LICENSE *
  4600. + * AGREEMENT for the sole purpose of implementing a product based on *
  4601. + * Samsung Electronics Co., Ltd. products. No other rights to reproduce, *
  4602. + * use, or disseminate this computer program, whether in part or in *
  4603. + * whole, are granted. *
  4604. + * *
  4605. + * Samsung Electronics Co., Ltd. makes no representation or warranties *
  4606. + * with respect to the performance of this computer program, and *
  4607. + * specifically disclaims any responsibility for any damages, *
  4608. + * special or consequential, connected with the use of this program. *
  4609. + * *
  4610. + *---------------------------------------------------------------------------*
  4611. + *
  4612. + */
  4613. +
  4614. +#include <linux/fs.h>
  4615. +#include <linux/rfs_fs.h>
  4616. +#include <linux/smp_lock.h>
  4617. +
  4618. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
  4619. +#include <linux/mpage.h>
  4620. +#include <linux/backing-dev.h>
  4621. +#endif
  4622. +
  4623. +#include "rfs.h"
  4624. +#include "log.h"
  4625. +
  4626. +#ifdef RFS_FOR_2_6
  4627. +
  4628. +ssize_t rfs_direct_IO(int, struct kiocb *, const struct iovec *,
  4629. + loff_t, unsigned long);
  4630. +
  4631. +#define GET_ENTRY_TIME(ep, inode) \
  4632. +do { \
  4633. + inode->i_ctime.tv_sec = inode->i_atime.tv_sec = \
  4634. + inode->i_mtime.tv_sec = \
  4635. + entry_time(GET16(ep->mtime), GET16(ep->mdate)); \
  4636. + inode->i_ctime.tv_nsec = inode->i_mtime.tv_nsec = \
  4637. + inode->i_atime.tv_nsec = 0; \
  4638. +} while(0);
  4639. +
  4640. +#else /* !RFS_FOR_2_6 */
  4641. +
  4642. +int rfs_direct_IO (int, struct inode *, struct kiobuf *, unsigned long, int);
  4643. +
  4644. +#define GET_ENTRY_TIME(ep, inode) \
  4645. +do { \
  4646. + inode->i_ctime = inode->i_atime= inode->i_mtime = \
  4647. + entry_time(GET16(ep->mtime), GET16(ep->mdate)); \
  4648. +} while(0);
  4649. +#endif /* RFS_FOR_2_6 */
  4650. +
  4651. +/**
  4652. + * read a specified page
  4653. + * @param file file to read
  4654. + * @param page page to read
  4655. + * @return return 0 on success
  4656. + */
  4657. +static int rfs_readpage(struct file *file, struct page *page)
  4658. +{
  4659. +#ifdef RFS_FOR_2_6
  4660. + return mpage_readpage(page, rfs_get_block);
  4661. +#else
  4662. + return block_read_full_page(page, rfs_get_block);
  4663. +#endif
  4664. +}
  4665. +
  4666. +/**
  4667. + * write a specified page
  4668. + * @param page to write page
  4669. + * @param wbc writeback control
  4670. + * @return return 0 on success, errno on failure
  4671. + */
  4672. +#ifdef RFS_FOR_2_6
  4673. +static int rfs_writepage(struct page *page, struct writeback_control *wbc)
  4674. +{
  4675. + return block_write_full_page(page, rfs_get_block, wbc);
  4676. +}
  4677. +#else
  4678. +static int rfs_writepage(struct page *page)
  4679. +{
  4680. + struct inode *inode = page->mapping->host;
  4681. + int ret;
  4682. +
  4683. + down(&RFS_I(inode)->data_mutex);
  4684. + ret = block_write_full_page(page, rfs_get_block);
  4685. + up(&RFS_I(inode)->data_mutex);
  4686. +
  4687. + return ret;
  4688. +}
  4689. +#endif
  4690. +
  4691. +#ifdef RFS_FOR_2_6
  4692. +/**
  4693. + * read multiple pages
  4694. + * @param file file to read
  4695. + * @param mapping address space to read
  4696. + * @param pages page list to read
  4697. + * @param nr_pages number of pages
  4698. + * @return return 0 on success, errno on failure
  4699. + */
  4700. +static int rfs_readpages(struct file *file, struct address_space *mapping,
  4701. + struct list_head *pages, unsigned nr_pages)
  4702. +{
  4703. + return mpage_readpages(mapping, pages, nr_pages, rfs_get_block);
  4704. +}
  4705. +
  4706. +/**
  4707. + * write multiple pages
  4708. + * @param mapping address space to write
  4709. + * @param wbc writeback_control
  4710. + * @return return 0 on success, errno on failure
  4711. + */
  4712. +static int rfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
  4713. +{
  4714. + return mpage_writepages(mapping, wbc, rfs_get_block);
  4715. +}
  4716. +#endif
  4717. +
  4718. +/**
  4719. + * read some paritial page to write rest page
  4720. + * @param file to read file
  4721. + * @param page specified page to read
  4722. + * @param from start position in page
  4723. + * @param to bytes counts to prepare in page
  4724. + * @return return 0 on success, errno on failure
  4725. + *
  4726. + * This function requires addtional code saving inode->i_size because there is
  4727. + * case when inode->i_size is chagned after cont_prepare_write.
  4728. + */
  4729. +#ifdef RFS_FOR_2_4
  4730. +static int rfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
  4731. +{
  4732. + struct inode *inode = page->mapping->host;
  4733. + unsigned page_start_offset = page->index << PAGE_CACHE_SHIFT;
  4734. + unsigned mmu_private = RFS_I(inode)->mmu_private;
  4735. + unsigned mmu_private_in_page = mmu_private & (PAGE_CACHE_SIZE - 1);
  4736. + unsigned newfrom;
  4737. + char *kaddr;
  4738. + int ret = 0;
  4739. +
  4740. + if (rfs_log_start(inode->i_sb, RFS_LOG_WRITE, inode))
  4741. + return -EIO;
  4742. +
  4743. + if ((page_start_offset + from) > mmu_private) {
  4744. + if (page_start_offset > mmu_private)
  4745. + newfrom = 0;
  4746. + else
  4747. + newfrom = mmu_private_in_page;
  4748. + } else
  4749. + newfrom = from;
  4750. +
  4751. + if (page_start_offset > mmu_private) {
  4752. + /* zerofill the previous hole pages */
  4753. + ret = extend_with_zerofill(inode, mmu_private, page_start_offset);
  4754. + if (ret)
  4755. + goto out;
  4756. + }
  4757. +
  4758. + ret = rfs_block_prepare_write(inode, page, newfrom, to-1, rfs_get_block);
  4759. + if (ret)
  4760. + goto out;
  4761. +
  4762. + if (from > newfrom) {
  4763. + /* memset & commit the previous hole in page */
  4764. + kaddr = page_address(page);
  4765. + memset(kaddr+newfrom, 0, from-newfrom);
  4766. + flush_dcache_page(page);
  4767. + rfs_block_commit_write(inode, page, newfrom, from);
  4768. + kunmap(page);
  4769. + }
  4770. +
  4771. + return ret;
  4772. +
  4773. +out:
  4774. + RFS_I(inode)->trunc_start = RFS_I(inode)->mmu_private;
  4775. + rfs_log_end(inode->i_sb, ret);
  4776. +
  4777. + return ret;
  4778. +}
  4779. +
  4780. +#else
  4781. +static int rfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
  4782. +{
  4783. + struct inode *inode = page->mapping->host;
  4784. + int ret = 0;
  4785. +
  4786. + if (rfs_log_start(inode->i_sb, RFS_LOG_WRITE, inode))
  4787. + return -EIO;
  4788. +
  4789. + ret = cont_prepare_write(page, from, to, rfs_get_block,
  4790. + &(RFS_I(inode)->mmu_private));
  4791. +
  4792. + if (ret) {
  4793. + RFS_I(inode)->trunc_start = RFS_I(inode)->mmu_private;
  4794. + rfs_log_end(inode->i_sb, ret);
  4795. + }
  4796. +
  4797. + return ret;
  4798. +}
  4799. +#endif
  4800. +
  4801. +/**
  4802. + * write a specified page
  4803. + * @param file to write file
  4804. + * @param page page descriptor
  4805. + * @param from start position in page
  4806. + * @param to end position in page
  4807. + * @return return 0 on success, errno on failure
  4808. + */
  4809. +static int rfs_commit_write(struct file *file, struct page *page, unsigned from, unsigned to)
  4810. +{
  4811. + struct inode *inode = page->mapping->host;
  4812. + int ret;
  4813. +
  4814. +#ifdef RFS_FOR_2_6
  4815. + ret = generic_commit_write(file, page, from, to);
  4816. +#else
  4817. + down(&RFS_I(inode)->data_mutex);
  4818. + ret = generic_commit_write(file, page, from, to);
  4819. + up(&RFS_I(inode)->data_mutex);
  4820. +#endif
  4821. +
  4822. + if (rfs_log_end(inode->i_sb, ret))
  4823. + return -EIO;
  4824. +
  4825. + return ret;
  4826. +}
  4827. +
  4828. +struct address_space_operations rfs_aops = {
  4829. + .readpage = rfs_readpage,
  4830. + .writepage = rfs_writepage,
  4831. + .sync_page = block_sync_page,
  4832. + .prepare_write = rfs_prepare_write,
  4833. + .commit_write = rfs_commit_write,
  4834. + .direct_IO = rfs_direct_IO,
  4835. +#ifdef RFS_FOR_2_6
  4836. + .readpages = rfs_readpages,
  4837. + .writepages = rfs_writepages,
  4838. +#endif
  4839. +};
  4840. +
  4841. +/*
  4842. + * get an unique inode number
  4843. + * @param dir parent directory
  4844. + * @param index dir entry's offset in parent dir's cluster(s)
  4845. + * @param[out] ino return ino
  4846. + * @return return 0 on success, errno on failure
  4847. + */
  4848. +int rfs_iunique(struct inode *dir, unsigned int index, unsigned long *ino)
  4849. +{
  4850. + struct super_block *sb = dir->i_sb;
  4851. + struct rfs_sb_info *sbi = RFS_SB(sb);
  4852. +
  4853. + /*
  4854. + * NOTE: RFS uses hash value for iunique
  4855. + * which is byte address of index >> bits of dir entry's size.
  4856. + * 0 ~ 15th entries are reserved, because reserved area has one sector
  4857. + * at least. Especially 1 belongs to root inode
  4858. + */
  4859. + if ((RFS_I(dir)->start_clu != sbi->root_clu) || IS_FAT32(sbi)) {
  4860. + unsigned int offset, cluster_offset;
  4861. + unsigned int prev, next;
  4862. + int err;
  4863. +
  4864. + /* in FAT32 root dir or sub-directories */
  4865. + offset = index << DENTRY_SIZE_BITS;
  4866. + cluster_offset = offset >> sbi->cluster_bits;
  4867. + fat_lock(sb);
  4868. + err = find_cluster(sb, RFS_I(dir)->start_clu,
  4869. + cluster_offset, &prev, &next);
  4870. + fat_unlock(sb);
  4871. + if (err)
  4872. + return err;
  4873. +
  4874. + offset &= sbi->cluster_size - 1;
  4875. + offset += (START_BLOCK(prev, sb) << sb->s_blocksize_bits);
  4876. + *ino = offset >> DENTRY_SIZE_BITS;
  4877. + } else {
  4878. + /* in root directory */
  4879. + *ino = (sbi->root_start_addr >> DENTRY_SIZE_BITS) + index;
  4880. + }
  4881. +
  4882. + return 0;
  4883. +}
  4884. +
  4885. +/**
  4886. + * fill up the RFS-specific inode
  4887. + * @param inode inode
  4888. + * @param ep dir entry
  4889. + * @param p_start_clu start cluster number of parent inode
  4890. + * @param dentry dir entry index
  4891. + * @return return 0 on success, errno on failure
  4892. + *
  4893. + * it is only invoked when new inode is allocated
  4894. + */
  4895. +int fill_inode(struct inode *inode, struct rfs_dir_entry *ep, unsigned int p_start_clu, unsigned int dentry)
  4896. +{
  4897. + struct super_block *sb = inode->i_sb;
  4898. + unsigned int type;
  4899. + unsigned int size;
  4900. + int err = 0, link_count = 0;
  4901. + int num_clus = 0;
  4902. +
  4903. + /* fill the RFS-specific inode info */
  4904. + RFS_I(inode)->p_start_clu = p_start_clu;
  4905. + RFS_I(inode)->index = dentry;
  4906. + RFS_I(inode)->hint_last_clu = 0;
  4907. + RFS_I(inode)->hint_last_offset = 0;
  4908. + RFS_I(inode)->i_state = RFS_I_ALLOC;
  4909. +
  4910. + /* sanity code */
  4911. + if (START_CLUSTER(ep) && IS_INVAL_CLU(RFS_SB(sb), START_CLUSTER(ep))) {
  4912. + err = -EIO;
  4913. + RFS_BUG("dir entry(%u, %u) has corrupted start_clu(%u)\n",
  4914. + p_start_clu, dentry, START_CLUSTER(ep));
  4915. + goto bad_inode;
  4916. + }
  4917. +
  4918. + /* set start_clu and last_clu in private */
  4919. + if (RFS_POOL_I(sb) &&
  4920. + (START_CLUSTER(ep) == RFS_POOL_I(sb)->start_cluster)) {
  4921. + RFS_I(inode)->start_clu = RFS_POOL_I(sb)->start_cluster;
  4922. + RFS_I(inode)->last_clu = RFS_POOL_I(sb)->last_cluster;
  4923. + } else if (START_CLUSTER(ep)) {
  4924. + /* pool dose exits or dir entry is not for pool file */
  4925. + unsigned int last_clu;
  4926. +
  4927. + RFS_I(inode)->start_clu = START_CLUSTER(ep);
  4928. + num_clus = find_last_cluster(inode, &last_clu);
  4929. + if (num_clus < 0) {
  4930. + err = num_clus;
  4931. + DEBUG(DL0, "No last cluster (err : %d)\n", err);
  4932. + goto bad_inode;
  4933. + }
  4934. + RFS_I(inode)->last_clu = last_clu;
  4935. + } else {
  4936. + /* cluster was not assigned to inode */
  4937. + RFS_I(inode)->start_clu = CLU_TAIL;
  4938. + RFS_I(inode)->last_clu = CLU_TAIL;
  4939. + }
  4940. +
  4941. + spin_lock_init(&RFS_I(inode)->write_lock);
  4942. +
  4943. + type = entry_type(ep);
  4944. +
  4945. + /* set i_size, i_mode, i_op, i_fop, i_mapping, i_nlink */
  4946. + if (type == TYPE_DIR) {
  4947. + /* directory always has zero-size by fat spec */
  4948. + inode->i_size = num_clus << RFS_SB(sb)->cluster_bits;
  4949. +
  4950. + inode->i_mode = S_IFDIR;
  4951. + inode->i_op = &rfs_dir_inode_operations;
  4952. + inode->i_fop = &rfs_dir_operations;
  4953. + link_count = count_subdir(sb, RFS_I(inode)->start_clu);
  4954. + if (unlikely(link_count < 2)) {
  4955. + err = link_count;
  4956. + goto bad_inode;
  4957. + } else {
  4958. + inode->i_nlink = link_count;
  4959. + }
  4960. + } else if (type == TYPE_FILE) {
  4961. + if ((ep->cmsec & SYMLINK_MARK) == SYMLINK_MARK) {
  4962. + inode->i_mode = S_IFLNK;
  4963. + inode->i_op = &page_symlink_inode_operations;
  4964. + inode->i_mapping->a_ops = &rfs_aops;
  4965. + } else {
  4966. + inode->i_mode = S_IFREG;
  4967. + inode->i_op = &rfs_file_inode_operations;
  4968. + inode->i_fop = &rfs_file_operations;
  4969. + inode->i_mapping->a_ops = &rfs_aops;
  4970. + }
  4971. + inode->i_nlink = 1;
  4972. +
  4973. + /* set inode->i_size */
  4974. + if (RFS_POOL_I(sb) && (START_CLUSTER(ep) ==
  4975. + RFS_POOL_I(sb)->start_cluster)) {
  4976. + /* just temporary */
  4977. + inode->i_size = RFS_SB(sb)->cluster_size;
  4978. + } else {
  4979. + int rcv_clus;
  4980. +
  4981. + size = GET32(ep->size);
  4982. +
  4983. + rcv_clus = (size + RFS_SB(sb)->cluster_size - 1)
  4984. + >> RFS_SB(sb)->cluster_bits;
  4985. +
  4986. + if (rcv_clus < num_clus) {
  4987. + /* RFS-log : data replay */
  4988. + DEBUG(DL0, "data recover(%u, %u, %u):"
  4989. + " %d != %d",
  4990. + RFS_I(inode)->p_start_clu,
  4991. + RFS_I(inode)->index,
  4992. + RFS_I(inode)->start_clu,
  4993. + num_clus, rcv_clus);
  4994. +
  4995. + inode->i_size = size;
  4996. + RFS_I(inode)->trunc_start = num_clus <<
  4997. + RFS_SB(sb)->cluster_bits;
  4998. + rfs_truncate(inode);
  4999. + } else if (rcv_clus > num_clus) {
  5000. + /* just set inode->i_size not modify ep->size */
  5001. + DEBUG(DL0, "size recover (%u, %u, %u):"
  5002. + " %d != %d",
  5003. + RFS_I(inode)->p_start_clu,
  5004. + RFS_I(inode)->index,
  5005. + RFS_I(inode)->start_clu,
  5006. + num_clus, rcv_clus);
  5007. + inode->i_size = num_clus <<
  5008. + RFS_SB(sb)->cluster_bits;
  5009. + } else
  5010. + inode->i_size = size;
  5011. + }
  5012. + } else {
  5013. + DEBUG(DL0, "dos entry type(%x) is invalid\n", type);
  5014. + err = -EINVAL;
  5015. + goto bad_inode;
  5016. + }
  5017. +
  5018. + inode->i_mode |= 0777;
  5019. + if (ep->attr & ATTR_READONLY) /* handle read-only case */
  5020. + inode->i_mode &= ~0222;
  5021. +
  5022. + inode->i_uid = 0;
  5023. + inode->i_gid = 0;
  5024. + inode->i_version = 0;
  5025. + GET_ENTRY_TIME(ep, inode);
  5026. +
  5027. + inode->i_blksize = sb->s_blocksize;
  5028. +
  5029. + inode->i_blocks = (inode->i_size + SECTOR_SIZE - 1) >> SECTOR_BITS;
  5030. +
  5031. + set_mmu_private(inode, inode->i_size);
  5032. +
  5033. +#ifdef RFS_FOR_2_4
  5034. + init_MUTEX(&RFS_I(inode)->data_mutex);
  5035. + init_timer(&RFS_I(inode)->timer);
  5036. + RFS_I(inode)->timer.function = rfs_data_wakeup;
  5037. + RFS_I(inode)->timer.data = (unsigned long) RFS_I(inode);
  5038. +#endif
  5039. +
  5040. + return 0;
  5041. +
  5042. +bad_inode:
  5043. + make_bad_inode(inode);
  5044. + return err;
  5045. +}
  5046. +
  5047. +/**
  5048. + * create a new inode
  5049. + * @param dir inode of parent directory
  5050. + * @param dentry dentry associated with inode will be created
  5051. + * @param type inode type
  5052. + * @return return inode pointer on success, erro on failure
  5053. + */
  5054. +struct inode *rfs_new_inode(struct inode *dir, struct dentry *dentry, unsigned int type)
  5055. +{
  5056. + struct inode *inode = NULL;
  5057. + struct buffer_head *bh = NULL;
  5058. + struct rfs_dir_entry *ep = NULL;
  5059. + unsigned long new_ino;
  5060. + unsigned int index;
  5061. + int ret = 0;
  5062. +
  5063. + /* get a new inode */
  5064. + if (!(inode = new_inode(dir->i_sb)))
  5065. + return ERR_PTR(-ENOMEM); /* memory error */
  5066. +
  5067. + /* initialize dir entry and extend entries */
  5068. + index = build_entry(dir, inode, 0, type, dentry->d_name.name);
  5069. + if ((int) index < 0) {
  5070. + ret = index;
  5071. + goto alloc_failure;
  5072. + }
  5073. +
  5074. + ep = get_entry(dir, index, &bh);
  5075. + if (IS_ERR(ep)) {
  5076. + ret = PTR_ERR(ep);
  5077. + goto alloc_failure;
  5078. + }
  5079. +
  5080. + /* fill inode info */
  5081. + ret = fill_inode(inode, ep, RFS_I(dir)->start_clu, index);
  5082. + if (ret)
  5083. + goto alloc_failure;
  5084. +
  5085. + if (type == TYPE_DIR) {
  5086. + /* increase parent's i_nlink */
  5087. + dir->i_nlink++;
  5088. + } else if (type == TYPE_FILE || type == TYPE_SYMLINK) {
  5089. + /* initialize it when only create time */
  5090. + inode->i_mapping->nrpages = 0;
  5091. + }
  5092. +
  5093. + /* get new inode number */
  5094. + ret = rfs_iunique(dir, index, &new_ino);
  5095. + if (ret) {
  5096. + if (type == TYPE_DIR) {
  5097. + inode->i_nlink--;
  5098. + dir->i_nlink--;
  5099. + }
  5100. + goto alloc_failure;
  5101. + }
  5102. + inode->i_ino = new_ino;
  5103. + insert_inode_hash(inode);
  5104. +
  5105. + /*
  5106. + * we already reigsterd the inode to the transaction
  5107. + * in the above build_entry()
  5108. + */
  5109. + mark_inode_dirty(inode);
  5110. +
  5111. + dir->i_mtime = dir->i_atime = CURRENT_TIME;
  5112. + rfs_mark_inode_dirty(dir);
  5113. +
  5114. + brelse(bh);
  5115. + return inode;
  5116. +
  5117. +alloc_failure:
  5118. + inode->i_nlink--;
  5119. + RFS_BUG_ON(inode->i_nlink);
  5120. + iput(inode);
  5121. +
  5122. + if (!IS_ERR(bh))
  5123. + brelse(bh);
  5124. +
  5125. + return ERR_PTR(ret);
  5126. +}
  5127. +
  5128. +/**
  5129. + * delete blocks of inode and clear inode
  5130. + * @param inode inode will be removed
  5131. + * @return return 0 on success, errno on failure
  5132. + *
  5133. + * It will be invoked at the last iput if i_nlink is zero
  5134. + */
  5135. +void rfs_delete_inode(struct inode *inode)
  5136. +{
  5137. +#ifdef RFS_FOR_2_4
  5138. + lock_kernel();
  5139. +#endif
  5140. +
  5141. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
  5142. + truncate_inode_pages(&inode->i_data, 0);
  5143. +#endif
  5144. +
  5145. + if (!is_bad_inode(inode)) {
  5146. + /* RFS-log : start of transaction */
  5147. + if (rfs_log_start(inode->i_sb, RFS_LOG_DEL_INODE, inode))
  5148. + goto out;
  5149. +
  5150. + /* actual de-allocation of clusters */
  5151. + rfs_detach_candidate(inode);
  5152. +
  5153. + /* RFS-log : end of transaction */
  5154. + rfs_log_end(inode->i_sb, 0);
  5155. + }
  5156. +
  5157. +out:
  5158. + clear_inode(inode);
  5159. +
  5160. +#ifdef RFS_FOR_2_4
  5161. + unlock_kernel();
  5162. +#endif
  5163. +}
  5164. +
  5165. +/**
  5166. + * deallocate clusters and remove entries for inode
  5167. + * @param dir parent directory inode
  5168. + * @param inode inode will be removed
  5169. + * @return return 0 on success, errno on failure
  5170. + */
  5171. +int rfs_delete_entry(struct inode *dir, struct inode *inode)
  5172. +{
  5173. + struct buffer_head *bh = NULL;
  5174. + int ret;
  5175. +
  5176. + /*
  5177. + * free cluster(s) that were allocated to inode
  5178. + * will be reserved such as candidate free clusters
  5179. + */
  5180. + ret = rfs_attach_candidate(inode);
  5181. + if (ret)
  5182. + return ret;
  5183. +
  5184. + /* remove dos & extent entries */
  5185. + ret = remove_entry(dir, RFS_I(inode)->index, &bh);
  5186. + brelse(bh);
  5187. + if (ret)
  5188. + return ret;
  5189. +
  5190. + /* decrease i_nlink */
  5191. + inode->i_nlink--;
  5192. + if (S_ISDIR(inode->i_mode)) {
  5193. + inode->i_nlink--;
  5194. + dir->i_nlink--;
  5195. + }
  5196. + if (unlikely(inode->i_nlink)) {
  5197. + RFS_BUG("nlink of inode is not zero (%u) \n", inode->i_nlink);
  5198. + return -EIO;
  5199. + }
  5200. +
  5201. + inode->i_mtime = inode->i_atime = CURRENT_TIME;
  5202. + dir->i_mtime = dir->i_atime = CURRENT_TIME;
  5203. +
  5204. + /* change ino to avoid sharing */
  5205. + remove_inode_hash(inode);
  5206. +
  5207. + /* do not change the order of statements for sync with write_inode() */
  5208. + spin_lock(&RFS_I(inode)->write_lock);
  5209. + inode->i_ino = RFS_SB(dir->i_sb)->highest_d_ino;
  5210. + RFS_I(inode)->i_state = RFS_I_FREE;
  5211. + spin_unlock(&RFS_I(inode)->write_lock);
  5212. +
  5213. + insert_inode_hash(inode);
  5214. +
  5215. + /*
  5216. + * we already reigsterd the inode to the transaction
  5217. + * in the above remove_entry()
  5218. + */
  5219. + mark_inode_dirty(inode);
  5220. + rfs_mark_inode_dirty(dir);
  5221. +
  5222. + return 0;
  5223. +}
  5224. +
  5225. +#ifdef CONFIG_RFS_IGET4
  5226. +/**
  5227. + * fill up the in-core inode
  5228. + * @param inode created new inode
  5229. + * @param private private argument to fill
  5230. + *
  5231. + * it has a same role with fill_inode
  5232. + */
  5233. +void rfs_read_inode2(struct inode *inode, void *private)
  5234. +{
  5235. + struct rfs_iget4_args *args;
  5236. +
  5237. + args = (struct rfs_iget4_args *) private;
  5238. +
  5239. + fill_inode(inode, args->ep, args->p_start_clu, args->index);
  5240. +}
  5241. +#endif
  5242. +
  5243. +/**
  5244. + * write a inode to dir entry
  5245. + * @param inode inode
  5246. + * @param data_commit flush dirty data and update dir entry's size
  5247. + * @param wait flag whether inode info is flushed
  5248. + * @return return 0 on success, errno on failure
  5249. + */
  5250. +int rfs_sync_inode(struct inode *inode, int data_commit, int wait)
  5251. +{
  5252. + struct super_block *sb = inode->i_sb;
  5253. + struct buffer_head *bh = NULL;
  5254. + struct rfs_dir_entry *ep = NULL;
  5255. + unsigned long backup_ino;
  5256. + int ret = 0;
  5257. + int committed = 0;
  5258. +#ifdef RFS_FOR_2_6
  5259. + int err = 0;
  5260. +#endif
  5261. +
  5262. + if (inode->i_ino == ROOT_INO)
  5263. + return 0;
  5264. +
  5265. + CHECK_RFS_INODE(inode, -EINVAL);
  5266. +
  5267. + /* update size of directory entry except directory */
  5268. + if (!S_ISDIR(inode->i_mode) && data_commit) {
  5269. + DEBUG(DL3, "%u, %u, %u, %llu",
  5270. + RFS_I(inode)->p_start_clu,
  5271. + RFS_I(inode)->index,
  5272. + RFS_I(inode)->start_clu,
  5273. + inode->i_size);
  5274. +
  5275. +#ifdef RFS_FOR_2_6
  5276. + ret = filemap_fdatawrite(inode->i_mapping);
  5277. + err = filemap_fdatawait(inode->i_mapping);
  5278. + if (err && !ret)
  5279. + ret = err;
  5280. +#else
  5281. + rfs_data_down(RFS_I(inode));
  5282. + ret = fsync_inode_data_buffers(inode);
  5283. + rfs_data_up(RFS_I(inode));
  5284. +#endif
  5285. + if (!ret)
  5286. + committed = 1;
  5287. + }
  5288. +
  5289. + backup_ino = inode->i_ino;
  5290. + ep = get_entry_with_cluster(sb, RFS_I(inode)->p_start_clu,
  5291. + RFS_I(inode)->index, &bh);
  5292. + if (IS_ERR(ep))
  5293. + return -EIO;
  5294. +
  5295. + spin_lock(&RFS_I(inode)->write_lock);
  5296. +
  5297. + /*
  5298. + * confirm that inode is not changed by rename/unlink
  5299. + * during getting entry
  5300. + */
  5301. + if (backup_ino != inode->i_ino || RFS_I(inode)->i_state == RFS_I_FREE) {
  5302. + spin_unlock(&RFS_I(inode)->write_lock);
  5303. + brelse(bh);
  5304. + return 0;
  5305. + }
  5306. +
  5307. + /* if data are committed, update entry's size */
  5308. + if (committed)
  5309. + SET32(ep->size, inode->i_size);
  5310. +
  5311. + /* update directory entry's start cluster number */
  5312. + if (RFS_I(inode)->start_clu != CLU_TAIL) {
  5313. + /* sanity check : no case of overwriting non empty file */
  5314. + if ((START_CLUSTER(ep) != 0) &&
  5315. + (START_CLUSTER(ep) != RFS_I(inode)->start_clu)) {
  5316. + spin_unlock(&RFS_I(inode)->write_lock);
  5317. + brelse(bh);
  5318. + RFS_BUG("inode's start cluster is corrupted (%u, %u)\n",
  5319. + START_CLUSTER(ep),
  5320. + RFS_I(inode)->start_clu);
  5321. + return -EIO;
  5322. + }
  5323. +
  5324. + SET16(ep->start_clu_lo, RFS_I(inode)->start_clu);
  5325. + SET16(ep->start_clu_hi, RFS_I(inode)->start_clu >> 16);
  5326. + } else {
  5327. + SET16(ep->start_clu_lo, 0);
  5328. + SET16(ep->start_clu_hi, 0);
  5329. + }
  5330. +
  5331. + /*
  5332. + * Update directory entry's mtime and mdate into inode's mtime
  5333. + * We mistake inode's mtime for current time at RFS-1.2.0 ver
  5334. + * to update directory entry's mtime and mdate
  5335. + */
  5336. + set_entry_time(ep, inode->i_mtime);
  5337. +
  5338. + /*
  5339. + * All changes are done. After unlock, create() on the unlinked entry
  5340. + * can change buffer as it wants
  5341. + */
  5342. + spin_unlock(&RFS_I(inode)->write_lock);
  5343. +
  5344. + if (wait) {
  5345. + mark_buffer_dirty(bh);
  5346. +#ifdef RFS_FOR_2_6
  5347. + err = sync_dirty_buffer(bh);
  5348. + if (err && !ret)
  5349. + ret = err;
  5350. +#else
  5351. + ll_rw_block(WRITE, 1, &bh);
  5352. + wait_on_buffer(bh);
  5353. +#endif
  5354. + } else
  5355. + rfs_mark_buffer_dirty(bh, sb);
  5356. +
  5357. + brelse(bh);
  5358. + return ret;
  5359. +}
  5360. +
  5361. +/**
  5362. + * write inode
  5363. + * @param inode inode
  5364. + * @param wait flag whether inode info is flushed
  5365. + * @return return 0 on success, errno on failure for 2.6
  5366. + */
  5367. +#ifdef RFS_FOR_2_6
  5368. +int rfs_write_inode(struct inode *inode, int wait)
  5369. +#else
  5370. +void rfs_write_inode(struct inode *inode, int wait)
  5371. +#endif
  5372. +{
  5373. + int ret = 0;
  5374. +
  5375. + if (current->flags & PF_MEMALLOC)
  5376. + goto out;
  5377. +
  5378. + /* We return 0 despite teh read-only mode. see ext3_write_inode */
  5379. + if (IS_RDONLY(inode))
  5380. + goto out;
  5381. +
  5382. + if (RFS_I(inode)->i_state == RFS_I_FREE)
  5383. + goto out;
  5384. +
  5385. +#ifdef RFS_FOR_2_4
  5386. + lock_kernel();
  5387. +#endif
  5388. +
  5389. + ret = rfs_sync_inode(inode, 1, wait);
  5390. +
  5391. +#ifdef RFS_FOR_2_4
  5392. + unlock_kernel();
  5393. +#endif
  5394. +
  5395. +out:
  5396. +#ifdef RFS_FOR_2_6
  5397. + return ret;
  5398. +#else
  5399. + return;
  5400. +#endif
  5401. +}
  5402. diff -NurbB linux-2.6.17.14.orig/fs/rfs/Kconfig linux-2.6.17.14.rfs/fs/rfs/Kconfig
  5403. --- linux-2.6.17.14.orig/fs/rfs/Kconfig 1970-01-01 01:00:00.000000000 +0100
  5404. +++ linux-2.6.17.14.rfs/fs/rfs/Kconfig 2008-06-19 04:02:09.000000000 +0200
  5405. @@ -0,0 +1,46 @@
  5406. +menu "RFS Filesystem"
  5407. +
  5408. +config RFS_FS
  5409. + tristate "Robust FAT Filesystem (RFS) support"
  5410. + help
  5411. + Samsung Robust File System support.
  5412. +
  5413. +config RFS_VFAT
  5414. + bool "FAT && long file name support"
  5415. + depends on RFS_FS
  5416. +
  5417. +config RFS_SYNC_ON_CLOSE
  5418. + bool "Sync on close support"
  5419. + depends on RFS_FS
  5420. +
  5421. +config RFS_NLS
  5422. + bool "Support NLS on RFS filesystem"
  5423. + select NLS
  5424. + depends on RFS_VFAT
  5425. +
  5426. +config RFS_DEFAULT_CODEPAGE
  5427. + string "Use default NLS codepage"
  5428. + default "cp949"
  5429. + depends on RFS_NLS
  5430. +
  5431. +config RFS_FAT_DEBUG
  5432. + bool "FAT Debug Message support"
  5433. + depends on RFS_FS
  5434. +
  5435. +config RFS_FAT_DEBUG_VERBOSE
  5436. + int "Debugging versosity (0 = quiet, 3 = noisy)"
  5437. + default 0
  5438. + depends on RFS_FAT_DEBUG
  5439. +
  5440. +config RFS_MAPDESTROY
  5441. + bool
  5442. +
  5443. +config RFS_PRE_ALLOC
  5444. + int
  5445. + default 50
  5446. +
  5447. +config RFS_VERSION
  5448. + string
  5449. + default "1.2.2p1-rc2"
  5450. +
  5451. +endmenu
  5452. diff -NurbB linux-2.6.17.14.orig/fs/rfs/log.c linux-2.6.17.14.rfs/fs/rfs/log.c
  5453. --- linux-2.6.17.14.orig/fs/rfs/log.c 1970-01-01 01:00:00.000000000 +0100
  5454. +++ linux-2.6.17.14.rfs/fs/rfs/log.c 2008-06-19 04:02:08.000000000 +0200
  5455. @@ -0,0 +1,1340 @@
  5456. +/**
  5457. + * @file fs/rfs/log.c
  5458. + * @brief functions for logging
  5459. + *
  5460. + *---------------------------------------------------------------------------*
  5461. + * *
  5462. + * COPYRIGHT 2003-2007 SAMSUNG ELECTRONICS CO., LTD. *
  5463. + * ALL RIGHTS RESERVED *
  5464. + * *
  5465. + * Permission is hereby granted to licensees of Samsung Electronics *
  5466. + * Co., Ltd. products to use or abstract this computer program only in *
  5467. + * accordance with the terms of the NAND FLASH MEMORY SOFTWARE LICENSE *
  5468. + * AGREEMENT for the sole purpose of implementing a product based on *
  5469. + * Samsung Electronics Co., Ltd. products. No other rights to reproduce, *
  5470. + * use, or disseminate this computer program, whether in part or in *
  5471. + * whole, are granted. *
  5472. + * *
  5473. + * Samsung Electronics Co., Ltd. makes no representation or warranties *
  5474. + * with respect to the performance of this computer program, and *
  5475. + * specifically disclaims any responsibility for any damages, *
  5476. + * special or consequential, connected with the use of this program. *
  5477. + * *
  5478. + *---------------------------------------------------------------------------*
  5479. + *
  5480. + */
  5481. +
  5482. +#include <linux/bitops.h>
  5483. +#include <linux/rfs_fs.h>
  5484. +#include "rfs.h"
  5485. +#include "log.h"
  5486. +
  5487. +#ifdef CONFIG_RFS_FAT_DEBUG
  5488. +#define CHECK_MUTEX(X, Y) \
  5489. +do { \
  5490. + if ((X) != (Y)) { \
  5491. + RFS_BUG("RFS-log : lock is broken %d " \
  5492. + "(should be %d)\n", \
  5493. + (int)(X), (int)(Y)); \
  5494. + } \
  5495. +} while (0)
  5496. +#else
  5497. +#define CHECK_MUTEX(...) do { } while (0)
  5498. +#endif
  5499. +
  5500. +static int rfs_log_open(struct super_block *sb);
  5501. +static int rfs_make_logfile(struct super_block *sb);
  5502. +static int rfs_log_start_nolock(struct super_block *sb, unsigned int type,
  5503. + struct inode *inode);
  5504. +static int pre_alloc_clusters(struct inode *inode);
  5505. +static int commit_deferred_tr(struct super_block *sb, unsigned long ino);
  5506. +
  5507. +/**
  5508. + * mark buffer dirty & register buffer to the transaction if we are inside transaction
  5509. + * @param bh buffer
  5510. + * @param sb super block
  5511. + */
  5512. +void mark_buffer_tr_dirty(struct buffer_head *bh, struct super_block *sb)
  5513. +{
  5514. +#ifdef RFS_FOR_2_4
  5515. + struct inode *tr_inode = &(RFS_LOG_I(sb)->tr_buf_inode);
  5516. +
  5517. + mark_buffer_dirty(bh);
  5518. +
  5519. + if (RFS_LOG_I(sb) && get_log_lock_owner(sb) == current->pid) {
  5520. + /* inside transaction */
  5521. + buffer_insert_inode_queue(bh, tr_inode);
  5522. + }
  5523. +#endif
  5524. +#ifdef RFS_FOR_2_6
  5525. + mark_buffer_dirty(bh);
  5526. +#endif
  5527. +}
  5528. +
  5529. +/**
  5530. + * mark inode dirty & write inode if we are inside transaction
  5531. + * @param inode inode
  5532. + */
  5533. +void mark_inode_tr_dirty(struct inode *inode)
  5534. +{
  5535. + struct super_block *sb = inode->i_sb;
  5536. +
  5537. + mark_inode_dirty(inode);
  5538. + if (RFS_LOG_I(sb) && get_log_lock_owner(sb) == current->pid) {
  5539. + /* inside transaction */
  5540. + rfs_sync_inode(inode, 0, 0);
  5541. + }
  5542. +}
  5543. +
  5544. +/**
  5545. + * commit rfs meta-data
  5546. + * @param sb super block
  5547. + */
  5548. +int rfs_meta_commit(struct super_block *sb)
  5549. +{
  5550. +#ifdef RFS_FOR_2_4
  5551. + struct inode *tr_inode = &(RFS_LOG_I(sb)->tr_buf_inode);
  5552. +#endif
  5553. + struct inode *inode = RFS_LOG_I(sb)->inode;
  5554. + int err = 0, ret = 0;
  5555. +
  5556. + /* fat cache sync */
  5557. + fat_lock(sb);
  5558. + rfs_fcache_sync(sb, 0);
  5559. + fat_unlock(sb);
  5560. +
  5561. + /* other transactions except write register dir entry */
  5562. + if (tr_pre_alloc(sb) && inode)
  5563. + ret = rfs_sync_inode(inode, 0, 0);
  5564. +
  5565. + /* rfs meta-data include link path */
  5566. + if (RFS_LOG_I(sb)->type == RFS_LOG_SYMLINK &&
  5567. + (inode = RFS_LOG_I(sb)->symlink_inode)) {
  5568. + err = rfs_sync_inode(inode, 1, 0);
  5569. + if (err && !ret)
  5570. + ret = err;
  5571. + }
  5572. +
  5573. +
  5574. +#ifdef RFS_FOR_2_6
  5575. + err = sync_blockdev(sb->s_bdev);
  5576. +#else
  5577. + err = fsync_inode_buffers(tr_inode);
  5578. +#endif
  5579. + if (err && !ret)
  5580. + ret = err;
  5581. +
  5582. + return ret;
  5583. +}
  5584. +
  5585. +#ifdef _RFS_INTERNAL_UNUSED_LOG
  5586. +/**
  5587. + * commit rfs data
  5588. + * @param sb super block
  5589. + * @param wait write and wait for inode?
  5590. + */
  5591. +int rfs_data_commit(struct inode *inode, int wait)
  5592. +{
  5593. + int ret;
  5594. + ret = rfs_sync_inode(inode, 1, wait);
  5595. +
  5596. + return ret;
  5597. +}
  5598. +#endif
  5599. +
  5600. +/**
  5601. + * Does transaction deferredly commit?
  5602. + * @param sb super block
  5603. + * @return if transaction is feasible for deferred commit, then return TRUE,
  5604. + * otherwise return FALSE.
  5605. + */
  5606. +int tr_deferred_commit(struct super_block *sb)
  5607. +{
  5608. + if (RFS_LOG_I(sb)->type == RFS_LOG_WRITE)
  5609. + return TRUE;
  5610. +
  5611. + return FALSE;
  5612. +}
  5613. +
  5614. +/**
  5615. + * Does transaction need pre allocation?
  5616. + * @param sb super block
  5617. + * @return if transaction is feasible for pre-allocation, then return TRUE,
  5618. + * otherwise return FALSE.
  5619. + */
  5620. +int tr_pre_alloc(struct super_block *sb)
  5621. +{
  5622. + if (!RFS_LOG_I(sb)) {
  5623. + /* special case : creation of pool file */
  5624. + return FALSE;
  5625. + }
  5626. +
  5627. + /* must include all tr_deferred_commit() */
  5628. + if (RFS_LOG_I(sb)->type == RFS_LOG_WRITE ||
  5629. + RFS_LOG_I(sb)->type == RFS_LOG_TRUNCATE_F)
  5630. + return TRUE;
  5631. +
  5632. + return FALSE;
  5633. +}
  5634. +
  5635. +/*****************************************************************************/
  5636. +/* log init/exit functions */
  5637. +/*****************************************************************************/
  5638. +/**
  5639. + * init logfile
  5640. + * @param sb super block
  5641. + * @return 0 on success, errno on failure
  5642. + */
  5643. +static int init_logfile(struct super_block *sb)
  5644. +{
  5645. + unsigned int i;
  5646. +
  5647. + for (i = 0; i < RFS_LOG_MAX_COUNT; i++) {
  5648. + if (rfs_log_read(sb, i))
  5649. + return -EIO;
  5650. +
  5651. + memset(RFS_LOG(sb), (unsigned char) RFS_LOG_NONE, SECTOR_SIZE);
  5652. + mark_buffer_dirty(RFS_LOG_I(sb)->bh);
  5653. + }
  5654. +
  5655. + brelse(RFS_LOG_I(sb)->bh);
  5656. + RFS_LOG_I(sb)->bh = NULL;
  5657. + RFS_LOG_I(sb)->log = NULL;
  5658. +
  5659. + rfs_sync_vol(sb);
  5660. +
  5661. + return 0;
  5662. +}
  5663. +
  5664. +/**
  5665. + * initialize log
  5666. + * @param sb super block
  5667. + * @return 0 on success, errno on failure
  5668. + */
  5669. +int rfs_log_init(struct super_block *sb)
  5670. +{
  5671. + int ret;
  5672. +
  5673. + if (sizeof(struct rfs_trans_log) > SECTOR_SIZE) {
  5674. + DPRINTK("RFS-log : Current log record is %u bytes."
  5675. + "Log record must be 512 bytes at most\n",
  5676. + sizeof(struct rfs_trans_log));
  5677. + return -EINVAL;
  5678. + }
  5679. +
  5680. + if ((ret = rfs_log_open(sb)) == -ENOENT) { /* there is no logfile */
  5681. + if ((ret = rfs_make_logfile(sb))) {
  5682. + DPRINTK("RFS-log(%d) : Couldn't make log file."
  5683. + " RFS cannot mount without logfile\n", ret);
  5684. + if (ret == -ENOSPC) {
  5685. + printk(KERN_WARNING "Please check there is"
  5686. + " enough space to create logfile"
  5687. + " (MIN : %u bytes)\n",
  5688. + RFS_LOG_MAX_COUNT * SECTOR_SIZE);
  5689. + }
  5690. + return ret;
  5691. + }
  5692. +
  5693. + /* open again */
  5694. + if ((ret = rfs_log_open(sb))) {
  5695. + /* I/O error */
  5696. + DPRINTK("RFS-log(%d) : Although it was made"
  5697. + " can't open log file\n", ret);
  5698. + return -EIO;
  5699. + }
  5700. +
  5701. + /* initialize log file to prevent confusing garbage value */
  5702. + if ((ret = init_logfile(sb))) {
  5703. + /* I/O error */
  5704. + DPRINTK("RFS-log(%d) : Cannot init logfile\n", ret);
  5705. + return -EIO;
  5706. + }
  5707. + } else if (ret) {
  5708. + /* I/O error */
  5709. + DPRINTK("RFS-log(%d) : Can't open log file\n", ret);
  5710. + return -EIO;
  5711. + } else { /* success in openning log */
  5712. + ret = rfs_log_replay(sb);
  5713. + if (ret) {
  5714. + /* I/O error */
  5715. + DPRINTK("RFS-log(%d) : Fail to replay log\n", ret);
  5716. + return -EIO;
  5717. + }
  5718. + }
  5719. +
  5720. + return 0;
  5721. +}
  5722. +
  5723. +/**
  5724. + * clean up log
  5725. + * @param sb super block
  5726. + * cleanup log info at normal umount
  5727. + */
  5728. +void rfs_log_cleanup(struct super_block *sb)
  5729. +{
  5730. + if (!RFS_LOG_I(sb))
  5731. + return;
  5732. +
  5733. + commit_deferred_tr(sb, 0);
  5734. + brelse(RFS_LOG_I(sb)->bh);
  5735. + kfree(RFS_LOG_I(sb)->log_mutex);
  5736. + kfree(RFS_LOG_I(sb));
  5737. + RFS_SB(sb)->log_info = NULL;
  5738. +}
  5739. +
  5740. +/*****************************************************************************/
  5741. +/* log open function */
  5742. +/*****************************************************************************/
  5743. +/**
  5744. + * open logfile
  5745. + * @param sb super block
  5746. + * @return 0 on success, errno on failure
  5747. + */
  5748. +static int rfs_log_open(struct super_block *sb)
  5749. +{
  5750. + struct inode *root_dir;
  5751. + struct inode *inode;
  5752. + struct dentry *root_dentry;
  5753. + struct rfs_dir_entry *ep;
  5754. + struct buffer_head *bh = NULL;
  5755. + struct rfs_log_info *log_info;
  5756. + unsigned int i;
  5757. + unsigned int iblock;
  5758. + int index;
  5759. + int ret = 0;
  5760. +
  5761. + root_dentry = sb->s_root;
  5762. + root_dir = root_dentry->d_inode;
  5763. +
  5764. + index = find_entry(root_dir, RFS_LOG_FILE_NAME, &bh, TYPE_FILE);
  5765. + if (index < 0) {
  5766. + DEBUG(DL0, "can't find log (%d)", index);
  5767. + ret = -ENOENT;
  5768. + goto rel_bh;
  5769. + }
  5770. +
  5771. + ep = get_entry(root_dir, index, &bh);
  5772. + if (IS_ERR(ep)) {
  5773. + /* I/O error */
  5774. + DEBUG(DL0, "can't get entry in root_dir");
  5775. + ret = PTR_ERR(ep);
  5776. + goto rel_bh;
  5777. + }
  5778. +
  5779. + /* get a new inode */
  5780. + if (!(inode = new_inode(root_dir->i_sb))) {
  5781. + /* memory error */
  5782. + DEBUG(DL0, "Can not alloc inode for logfile");
  5783. + ret = -ENOMEM;
  5784. + goto rel_bh;
  5785. + }
  5786. +
  5787. + /* fill inode info */
  5788. + ret = fill_inode(inode, ep, RFS_SB(sb)->root_clu, index);
  5789. + if (ret)
  5790. + goto rel_bh;
  5791. +
  5792. + log_info = kmalloc(sizeof(struct rfs_log_info), GFP_KERNEL);
  5793. + if (!log_info) {
  5794. + /* memory error */
  5795. + DEBUG(DL0, "memory allocation error");
  5796. + ret = -ENOMEM;
  5797. + goto out;
  5798. + }
  5799. +
  5800. + /* log size is 9th power of 2 (512B) */
  5801. + log_info->secs_per_blk = sb->s_blocksize >> 9;
  5802. + log_info->secs_per_blk_bits =
  5803. + (unsigned int) ffs(log_info->secs_per_blk) - 1;
  5804. +
  5805. + DEBUG(DL3, "sectors per block : %u its bit : %u\n",
  5806. + log_info->secs_per_blk, log_info->secs_per_blk_bits);
  5807. +
  5808. + for (i = 0; i < RFS_LOG_MAX_COUNT; i++) {
  5809. + iblock = i >> log_info->secs_per_blk_bits;
  5810. + ret = rfs_bmap(inode, iblock, &(log_info->blocks[i]));
  5811. + if (ret) {
  5812. + kfree(log_info);
  5813. + goto out;
  5814. + }
  5815. + }
  5816. + log_info->type = RFS_LOG_NONE;
  5817. + log_info->sequence = 1;
  5818. + log_info->bh = NULL;
  5819. + log_info->inode = NULL;
  5820. + log_info->isec = 0;
  5821. +
  5822. + /* init fields for deferred commit */
  5823. + log_info->alloc_index = 0;
  5824. + log_info->numof_pre_alloc = 0;
  5825. +
  5826. + log_info->start_cluster = RFS_I(inode)->start_clu;
  5827. +
  5828. + log_info->log_mutex = kmalloc(sizeof(struct rfs_semaphore), GFP_KERNEL);
  5829. + if (!(log_info->log_mutex)) {
  5830. + /* memory error */
  5831. + DEBUG(DL0, "memory allocation failed");
  5832. + kfree(log_info);
  5833. + ret = -ENOMEM;
  5834. + goto out;
  5835. + }
  5836. +
  5837. +#ifdef RFS_FOR_2_4
  5838. + INIT_LIST_HEAD(&(log_info->tr_buf_inode.i_dirty_buffers));
  5839. +#endif
  5840. + RFS_SB(sb)->log_info = (void *) log_info;
  5841. +
  5842. + init_log_lock(sb);
  5843. +out:
  5844. + iput(inode);
  5845. +rel_bh:
  5846. + brelse(bh);
  5847. + return ret;
  5848. +}
  5849. +
  5850. +/*****************************************************************************/
  5851. +/* logging functions */
  5852. +/*****************************************************************************/
  5853. +/**
  5854. + * force to commit write transaction
  5855. + * @param sb super block
  5856. + * @param inode inode for target file or NULL for volume sync
  5857. + * @return 0 on success, errno on failure
  5858. + * @pre It can be called in middle of transaction, so
  5859. + * it should get a lock for committing transaction
  5860. + *
  5861. + * Never sleep holding super lock. Log lock can protects RFS key data
  5862. + */
  5863. +int rfs_log_force_commit(struct super_block *sb, struct inode *inode)
  5864. +{
  5865. + int ret;
  5866. +
  5867. + if (inode && inode != RFS_LOG_I(sb)->inode)
  5868. + return 0;
  5869. +
  5870. + lock_log(sb);
  5871. +
  5872. + if (!inode) {
  5873. + unlock_super(sb);
  5874. + ret = commit_deferred_tr(sb, 0);
  5875. + unlock_log(sb);
  5876. + lock_super(sb);
  5877. + } else {
  5878. + ret = commit_deferred_tr(sb, inode->i_ino);
  5879. + unlock_log(sb);
  5880. + }
  5881. +
  5882. + return ret;
  5883. +}
  5884. +
  5885. +/**
  5886. + * release remaining pre-allocations
  5887. + * @param sb super block
  5888. + * @return 0 on success, errno on failure
  5889. + */
  5890. +static int release_pre_alloc(struct super_block *sb)
  5891. +{
  5892. + unsigned int i;
  5893. + int ret = 0;
  5894. +
  5895. + if (RFS_LOG_I(sb)->alloc_index >= RFS_LOG_I(sb)->numof_pre_alloc)
  5896. + goto out;
  5897. +
  5898. + fat_lock(sb);
  5899. + if (RFS_LOG_I(sb)->where == RFS_POOL) {
  5900. +#ifdef _RFS_INTERNAL_SANITY_CHECK
  5901. + struct rfs_log_info *rli = RFS_LOG_I(sb);
  5902. + unsigned int value;
  5903. +
  5904. + for (i = rli->alloc_index;
  5905. + i < rli->numof_pre_alloc - 1; i++) {
  5906. + ret = fat_read(sb, rli->pre_alloc_clus[i],
  5907. + &value);
  5908. + if (ret) {
  5909. + printk("can not read fat table\n");
  5910. + BUG();
  5911. + }
  5912. +
  5913. + if (value != rli->pre_alloc_clus[i + 1]) {
  5914. + printk("free cluster from fat is not zero\n");
  5915. + BUG();
  5916. + }
  5917. + }
  5918. +#endif
  5919. +
  5920. + for (i = RFS_LOG_I(sb)->alloc_index;
  5921. + i < RFS_LOG_I(sb)->numof_pre_alloc; i++) {
  5922. + ret = fat_write(sb, RFS_LOG_I(sb)->pre_alloc_clus[i],
  5923. + CLU_FREE);
  5924. + if (ret)
  5925. + break;
  5926. +
  5927. + DEBUG(DL3, "chained cluster %u freed",
  5928. + RFS_LOG_I(sb)->pre_alloc_clus[i]);
  5929. + }
  5930. + } else { /* RFS_LOG_I(sb)->where == RFS_FAT_TABLE */
  5931. + /* pre-allocated clusters had CLU_FREE */
  5932. +#ifdef _RFS_INTERNAL_SANITY_CHECK
  5933. + struct rfs_log_info *rli = RFS_LOG_I(sb);
  5934. + unsigned int value;
  5935. +
  5936. + for (i = rli->alloc_index;
  5937. + i < rli->numof_pre_alloc; i++) {
  5938. + ret = fat_read(sb, rli->pre_alloc_clus[i],
  5939. + &value);
  5940. + if (ret) {
  5941. + printk("can not read fat table\n");
  5942. + BUG();
  5943. + }
  5944. + if (value != CLU_FREE) {
  5945. + printk("free cluster from fat is not zero\n");
  5946. + BUG();
  5947. + }
  5948. + }
  5949. +#endif
  5950. + i = RFS_LOG_I(sb)->numof_pre_alloc;
  5951. + RFS_SB(sb)->search_ptr = RFS_LOG_I(sb)->pre_alloc_clus[
  5952. + RFS_LOG_I(sb)->alloc_index];
  5953. + }
  5954. +
  5955. + if (i != RFS_LOG_I(sb)->numof_pre_alloc)
  5956. + DPRINTK("RFS-log : critical error!! FAT chain is crashed\n");
  5957. +
  5958. + fat_unlock(sb);
  5959. +out:
  5960. + RFS_LOG_I(sb)->alloc_index = RFS_LOG_I(sb)->numof_pre_alloc = 0;
  5961. + return ret;
  5962. +}
  5963. +
  5964. +/**
  5965. + * commit deferred transaction for pre-allocation
  5966. + * @param sb super block
  5967. + * @param ino inode number
  5968. + * @return 0 on success, errno on failure
  5969. + */
  5970. +static int commit_deferred_tr(struct super_block *sb, unsigned long ino)
  5971. +{
  5972. + int ret = 0;
  5973. +
  5974. + if (tr_deferred_commit(sb) &&
  5975. + (!ino || (RFS_LOG_I(sb)->inode && (RFS_LOG_I(sb)->inode->i_ino == ino)))) {
  5976. + ret = release_pre_alloc(sb);
  5977. + if (ret) /* I/O error */
  5978. + return ret;
  5979. +
  5980. + ret = rfs_meta_commit(sb);
  5981. + if (ret)
  5982. + return ret;
  5983. +
  5984. + DEBUG(DL3, "where pre clusters are : %d", RFS_LOG_I(sb)->where);
  5985. + if (rfs_log_mark_end(sb, RFS_SUBLOG_COMMIT)) {
  5986. + /* I/O error */
  5987. + DPRINTK("RFS-log : Couldn't commit write"
  5988. + " transaction\n");
  5989. + return -EIO;
  5990. + }
  5991. + sb->s_dirt = 0;
  5992. + }
  5993. +
  5994. + return ret;
  5995. +}
  5996. +
  5997. +/**
  5998. + * get a lock and mark start of transaction
  5999. + * @param sb super block
  6000. + * @param log_type log type
  6001. + * @param inode relative inode
  6002. + * @return 0 on success, errno on failure
  6003. + * @post locking log has been remained until trasaction ends
  6004. + *
  6005. + * pre-allocation is commited if there is no further write to the same file
  6006. + * as that of previous transaction
  6007. + */
  6008. +int rfs_log_start(struct super_block *sb, unsigned int log_type,
  6009. + struct inode *inode)
  6010. +{
  6011. + int ret;
  6012. +
  6013. + /*
  6014. + * Exception handling : Inode for root can be clear
  6015. + * if mounting rfs is failed during initialization of log,
  6016. + * and then rfs_delete_inode is called.
  6017. + * So, logging for delete_inode must handle this exceptional case.
  6018. + */
  6019. + if (!RFS_LOG_I(sb)) {
  6020. + if (log_type == RFS_LOG_DEL_INODE) {
  6021. + return 0;
  6022. + } else {
  6023. + RFS_BUG("RFS-log : System crashed\n");
  6024. + return -EIO;
  6025. + }
  6026. + }
  6027. +
  6028. + /* check nested transaction */
  6029. + /* Any process cannot set owner to own pid without a mutex */
  6030. + if (lock_log(sb) >= 2) {
  6031. + /* recursive acquisition */
  6032. + return 0;
  6033. + }
  6034. +
  6035. + if (tr_deferred_commit(sb)) {
  6036. + if ((log_type == RFS_LOG_I(sb)->type) &&
  6037. + (RFS_LOG_I(sb)->inode == inode)) {
  6038. + /* write data in the same file */
  6039. + return 0;
  6040. + }
  6041. + /* different transaction; flush prev write-transaction */
  6042. + DEBUG(DL2, "prev : write, cur : %d, ino : %lu", log_type, inode->i_ino);
  6043. + ret = commit_deferred_tr(sb, RFS_LOG_I(sb)->inode->i_ino);
  6044. + if (ret) /* I/O error */
  6045. + goto err;
  6046. + }
  6047. +
  6048. +
  6049. + if (rfs_log_start_nolock(sb, log_type, inode)) {
  6050. + DPRINTK("RFS-log : Couldn't start log\n");
  6051. + ret = -EIO;
  6052. + goto err;
  6053. + }
  6054. +
  6055. + return 0;
  6056. +err:
  6057. + unlock_log(sb);
  6058. +
  6059. + return ret;
  6060. +}
  6061. +
  6062. +/**
  6063. + * mark end of transaction and release lock
  6064. + * @param sb super block
  6065. + * @param result result of transaction (0 : success, others : failure)
  6066. + * @return 0 on success, errno on failure
  6067. + * @pre trasaction must have started
  6068. + *
  6069. + * mark EOT and flush it unless transaction is for pre-allocation.
  6070. + */
  6071. +int rfs_log_end(struct super_block *sb, int result)
  6072. +{
  6073. + unsigned int sub_type = RFS_SUBLOG_COMMIT;
  6074. + int ret = 0;
  6075. +
  6076. + /*
  6077. + * Exception handling : Filtered all faulty transactions which
  6078. + * start without log info except for delete_inode, which
  6079. + * must be handled.
  6080. + * Please reference a comment in rfs_log_start().
  6081. + */
  6082. + if (!RFS_LOG_I(sb))
  6083. + return 0;
  6084. +
  6085. + /* recursive lock */
  6086. + /* Any process cannot increase ref_count without a mutex */
  6087. + if (get_log_lock_depth(sb) > 1) {
  6088. + unlock_log(sb);
  6089. + DEBUG(DL2, "release self recursive lock (ref: %d)",
  6090. + get_log_lock_depth(sb));
  6091. + return 0;
  6092. + }
  6093. +
  6094. + /* transaction did not change any meta data */
  6095. + if (is_empty_tr(sb)) {
  6096. + DEBUG(DL3, "empty transaction");
  6097. +
  6098. + brelse(RFS_LOG_I(sb)->bh);
  6099. + RFS_LOG_I(sb)->bh = NULL;
  6100. + RFS_LOG_I(sb)->log = NULL;
  6101. + RFS_LOG_I(sb)->type = RFS_LOG_NONE;
  6102. +
  6103. + goto rel_lock;
  6104. + }
  6105. +
  6106. + DEBUG(DL2, "result : %d, type : %d", result, RFS_LOG_I(sb)->type);
  6107. + if (result)
  6108. + sub_type = RFS_SUBLOG_ABORT;
  6109. +
  6110. + if (tr_deferred_commit(sb) && (sub_type == RFS_SUBLOG_COMMIT)) {
  6111. + DEBUG(DL2, "deferred commit");
  6112. + ret = 0;
  6113. + sb->s_dirt = 1;
  6114. + goto rel_lock;
  6115. + }
  6116. +
  6117. + if (tr_pre_alloc(sb)) {
  6118. + ret = release_pre_alloc(sb);
  6119. + if (ret) /* I/O error */
  6120. + goto rel_lock;
  6121. + }
  6122. +
  6123. + ret = rfs_meta_commit(sb);
  6124. + if (ret)
  6125. + goto rel_lock;
  6126. +
  6127. + ret = rfs_log_mark_end(sb, sub_type);
  6128. +
  6129. +rel_lock:
  6130. + CHECK_MUTEX(get_log_lock_depth(sb), 1);
  6131. +
  6132. + unlock_log(sb);
  6133. +
  6134. + return ret;
  6135. +}
  6136. +
  6137. +/**
  6138. + * logging for entry to be built
  6139. + * @param sb super block
  6140. + * @param pdir the start cluster of parent
  6141. + * @param entry entry index
  6142. + * @param numof_entries the number of entries
  6143. + * @return 0 on success, errno on failure
  6144. + * @pre trasaction must have been started
  6145. + */
  6146. +int rfs_log_build_entry(struct super_block *sb, unsigned int pdir,
  6147. + unsigned int entry, unsigned int numof_entries)
  6148. +{
  6149. + if (!RFS_LOG_I(sb)) {
  6150. + /* special case : pool file is created at format */
  6151. + return 0;
  6152. + }
  6153. +
  6154. + if (rfs_log_read(sb, RFS_LOG_I(sb)->isec))
  6155. + return -EIO;
  6156. +
  6157. + SET32(RFS_LOG(sb)->type, MK_LOG_TYPE(RFS_LOG_I(sb)->type,
  6158. + RFS_SUBLOG_BUILD_ENTRY));
  6159. + SET32(RFS_LOG(sb)->log_entry.pdir, pdir);
  6160. + SET32(RFS_LOG(sb)->log_entry.entry, entry);
  6161. + SET32(RFS_LOG(sb)->log_entry.numof_entries, numof_entries);
  6162. +
  6163. + DEBUG(DL2, "pdir : %u, entry : %u, numof_entries : %u",
  6164. + pdir, entry, numof_entries);
  6165. +
  6166. + if (rfs_log_write(RFS_LOG_I(sb)))
  6167. + return -EIO;
  6168. +
  6169. + return 0;
  6170. +}
  6171. +
  6172. +/**
  6173. + * logging for entry to be removed
  6174. + * @param sb super block
  6175. + * @param pdir the start cluster of parent
  6176. + * @param entry entry index
  6177. + * @param numof_entries the number of entries
  6178. + * @param undel_buf the original value at position of deletion mark
  6179. + * @return 0 on success, errno on failure
  6180. + * @pre trasaction must have been started
  6181. + */
  6182. +int rfs_log_remove_entry(struct super_block *sb, unsigned int pdir,
  6183. + unsigned int entry, unsigned int numof_entries,
  6184. + unsigned char *undel_buf)
  6185. +{
  6186. + unsigned int i;
  6187. +
  6188. + if (rfs_log_read(sb, RFS_LOG_I(sb)->isec))
  6189. + return -EIO;
  6190. +
  6191. + SET32(RFS_LOG(sb)->type, MK_LOG_TYPE(RFS_LOG_I(sb)->type,
  6192. + RFS_SUBLOG_REMOVE_ENTRY));
  6193. + SET32(RFS_LOG(sb)->log_entry.pdir, pdir);
  6194. + SET32(RFS_LOG(sb)->log_entry.entry, entry);
  6195. + SET32(RFS_LOG(sb)->log_entry.numof_entries, numof_entries);
  6196. + for (i = 0; i < numof_entries; i++)
  6197. + RFS_LOG(sb)->log_entry.undel_buf[i] = undel_buf[i];
  6198. +
  6199. + DEBUG(DL2, "pdir : %u, entry : %u, numof_entries : %u",
  6200. + pdir, entry, numof_entries);
  6201. +
  6202. + if (rfs_log_write(RFS_LOG_I(sb)))
  6203. + return -EIO;
  6204. +
  6205. + return 0;
  6206. +}
  6207. +
  6208. +#ifdef _RFS_INTERNAL_UNUSED_LOG
  6209. +/**
  6210. + * logging for entry to be updated
  6211. + * @param sb super block
  6212. + * @param pdir the start cluster of parent
  6213. + * @param entry entry index
  6214. + * @param from_size the original size used to undo
  6215. + * @param to_size the changed size used to redo
  6216. + * @return 0 on success, errno on failure
  6217. + * @pre trasaction must have been started
  6218. + */
  6219. +int rfs_log_update_entry(struct super_block *sb, unsigned int pdir,
  6220. + unsigned int entry, unsigned int from_size,
  6221. + unsigned int to_size)
  6222. +{
  6223. + if (rfs_log_read(sb, RFS_LOG_I(sb)->isec))
  6224. + return -EIO;
  6225. +
  6226. + SET32(RFS_LOG(sb)->type, MK_LOG_TYPE(RFS_LOG_I(sb)->type,
  6227. + RFS_SUBLOG_UPDATE_ENTRY));
  6228. + SET32(RFS_LOG(sb)->log_entry.pdir, pdir);
  6229. + SET32(RFS_LOG(sb)->log_entry.entry, entry);
  6230. + SET32(RFS_LOG(sb)->log_entry.from_size, from_size);
  6231. + SET32(RFS_LOG(sb)->log_entry.to_size, to_size);
  6232. +
  6233. + DEBUG(DL2, "pdir : %u, entry : %u, from : %u, to : %u",
  6234. + pdir, entry, from_size, to_size);
  6235. +
  6236. + if (rfs_log_write(RFS_LOG_I(sb)))
  6237. + return -EIO;
  6238. +
  6239. + return 0;
  6240. +}
  6241. +#endif
  6242. +
  6243. +/**
  6244. + * logging for updation of chain
  6245. + * @param sb super block
  6246. + * @param subtype sub transaction
  6247. + * @param pdir the start cluster of parent
  6248. + * @param entry entry index
  6249. + * @param pool_next next cluster in pool related to chain
  6250. + * @param pool_prev previous cluster in pool related to chain
  6251. + * @param pool_next next cluster in pool related to chain
  6252. + * @param target_prev previous cluster in file or pool related to chain
  6253. + * @param target_next next cluster in file or pool related to chain
  6254. + * @param numof_clus the number of clusters in chain
  6255. + * @param clus the clusters in chain
  6256. + */
  6257. +static void rfs_log_update_chain(struct super_block *sb, unsigned int subtype,
  6258. + unsigned int pdir, unsigned int entry,
  6259. + unsigned int pool_prev, unsigned int pool_next,
  6260. + unsigned int target_prev, unsigned int target_next,
  6261. + unsigned int numof_clus, unsigned int *clus)
  6262. +{
  6263. + unsigned int i;
  6264. +
  6265. + SET32(RFS_LOG(sb)->type, MK_LOG_TYPE(RFS_LOG_I(sb)->type, subtype));
  6266. + DEBUG(DL2, "SUBTYPE : %u", subtype);
  6267. +
  6268. + SET32(RFS_LOG(sb)->log_fat.pdir, pdir);
  6269. + SET32(RFS_LOG(sb)->log_fat.entry, entry);
  6270. +
  6271. + SET32(RFS_LOG(sb)->log_fat.p_last_clu, RFS_POOL_I(sb)->last_cluster);
  6272. + SET32(RFS_LOG(sb)->log_fat.p_num_clus, RFS_POOL_I(sb)->num_clusters);
  6273. + SET32(RFS_LOG(sb)->log_fat.p_c_start_clu,
  6274. + RFS_POOL_I(sb)->c_start_cluster);
  6275. + SET32(RFS_LOG(sb)->log_fat.p_c_last_clu,
  6276. + RFS_POOL_I(sb)->c_last_cluster);
  6277. + DEBUG(DL2, "POOL_INFO : <%u, %u>, <%u, %u>",
  6278. + RFS_POOL_I(sb)->last_cluster,
  6279. + RFS_POOL_I(sb)->num_clusters,
  6280. + RFS_POOL_I(sb)->c_start_cluster,
  6281. + RFS_POOL_I(sb)->c_last_cluster);
  6282. +
  6283. + SET32(RFS_LOG(sb)->log_fat.p_prev_clu, pool_prev);
  6284. + SET32(RFS_LOG(sb)->log_fat.p_next_clu, pool_next);
  6285. + DEBUG(DL2, "POOL_CHAIN : <%u, %u>", pool_prev, pool_next);
  6286. +
  6287. + SET32(RFS_LOG(sb)->log_fat.t_prev_clu, target_prev);
  6288. + SET32(RFS_LOG(sb)->log_fat.t_next_clu, target_next);
  6289. + DEBUG(DL2, "TARGET_CHAIN : <%u, %u>", target_prev, target_next);
  6290. +
  6291. + SET32(RFS_LOG(sb)->log_fat.numof_clus, numof_clus);
  6292. + for (i = 0; i < numof_clus; i++) {
  6293. + DEBUG(DL3, "%u, ", clus[i]);
  6294. + SET32(RFS_LOG(sb)->log_fat.clus[i], clus[i]);
  6295. + }
  6296. +
  6297. + DEBUG(DL2, "NUMOF_LOG_CLU : <%u>", numof_clus);
  6298. +}
  6299. +
  6300. +/**
  6301. + * logging alloc chain from fat table or pool
  6302. + * @param sb super block
  6303. + * @param pdir the start cluster of parent
  6304. + * @param entry entry index
  6305. + * @param pool_prev previous cluster of detached chain in pool
  6306. + * @param pool_next next cluster of detached chain in pool
  6307. + * @param target_prev previous cluster of extented chain in file
  6308. + * @param target_next next cluster of extented chain in file
  6309. + * @param numof_clus the number of clusters in chain
  6310. + * @param clus the clusters in chain
  6311. + * @return 0 on success, errno on failure
  6312. + */
  6313. +int rfs_log_alloc_chain(struct super_block *sb,
  6314. + unsigned int pdir, unsigned int entry,
  6315. + unsigned int pool_prev, unsigned int pool_next,
  6316. + unsigned int target_prev, unsigned int target_next,
  6317. + unsigned int numof_clus, unsigned int *clus)
  6318. +{
  6319. + unsigned int subtype;
  6320. + int ret;
  6321. +
  6322. + if (!RFS_LOG_I(sb)) {
  6323. + /* special case : poolfile is created
  6324. + before logfile at format */
  6325. + return 0;
  6326. + }
  6327. +
  6328. + if ((!is_empty_tr(sb)) && tr_pre_alloc(sb)) {
  6329. + struct inode *inode = RFS_LOG_I(sb)->inode;
  6330. + unsigned int type = RFS_LOG_I(sb)->type;
  6331. +
  6332. + /* commit pre-allocation windows */
  6333. + ret = rfs_meta_commit(sb);
  6334. + if (ret)
  6335. + return ret;
  6336. +
  6337. + if (rfs_log_mark_end(sb, RFS_SUBLOG_COMMIT))
  6338. + return -EIO;
  6339. +
  6340. + if (rfs_log_start_nolock(sb, type, inode))
  6341. + return -EIO;
  6342. + }
  6343. +
  6344. + if (rfs_log_read(sb, RFS_LOG_I(sb)->isec))
  6345. + return -EIO;
  6346. +
  6347. + subtype = (pool_prev == CLU_TAIL) ? RFS_SUBLOG_ALLOC_CHAIN :
  6348. + RFS_SUBLOG_GET_CHAIN;
  6349. +
  6350. + rfs_log_update_chain(sb, subtype, pdir, entry, pool_prev, pool_next,
  6351. + target_prev, target_next, numof_clus, clus);
  6352. +
  6353. + if (rfs_log_write(RFS_LOG_I(sb)))
  6354. + return -EIO;
  6355. +
  6356. + return 0;
  6357. +}
  6358. +
  6359. +#ifdef _RFS_INTERNAL_UNUSED_LOG
  6360. +/**
  6361. + * logging dealloc chain to fat table or pool
  6362. + * @param sb super block
  6363. + * @param pdir the start cluster of parent
  6364. + * @param entry entry index
  6365. + * @param pool_prev previous cluster of chain to be attached in pool
  6366. + * @param pool_next next cluster of chain to be attached in pool
  6367. + * @param target_prev previous cluster of free-chain in file
  6368. + * @param target_next next cluster of free-chain in file
  6369. + * @param numof_clus the number of clusters in chain
  6370. + * @param clus the clusters in chain
  6371. + * @return 0 on success, errno on failure
  6372. + */
  6373. +int rfs_log_free_chain(struct super_block *sb,
  6374. + unsigned int pdir, unsigned int entry,
  6375. + unsigned int pool_prev, unsigned int pool_next,
  6376. + unsigned int target_prev, unsigned int target_next,
  6377. + unsigned int numof_clus, unsigned int *clus)
  6378. +{
  6379. + unsigned int subtype;
  6380. +
  6381. + if (rfs_log_read(sb, RFS_LOG_I(sb)->isec))
  6382. + return -EIO;
  6383. +
  6384. + subtype = (pool_prev == CLU_TAIL) ? RFS_SUBLOG_FREE_CHAIN :
  6385. + RFS_SUBLOG_PUT_CHAIN;
  6386. +
  6387. + rfs_log_update_chain(sb, subtype, pdir, entry, pool_prev, pool_next,
  6388. + target_prev, target_next, numof_clus, clus);
  6389. +
  6390. + if (rfs_log_write(RFS_LOG_I(sb)))
  6391. + return -EIO;
  6392. +
  6393. + return 0;
  6394. +}
  6395. +#endif
  6396. +
  6397. +/**
  6398. + * logging move candidate segment to deleted partition in pool
  6399. + * @param sb super block
  6400. + * @param pdir the start cluster of parent
  6401. + * @param entry entry index
  6402. + * @param pool_prev previous cluster of chain to be moved in pool
  6403. + * @param pool_next next cluster of chain to be moved in pool
  6404. + * @param target_prev previous cluster of segment(chain)
  6405. + * @param target_next next cluster of segment(chain)
  6406. + * @param numof_clus the number of clusters in chain
  6407. + * @param clus the clusters in chain
  6408. + * @return 0 on success, errno on failure
  6409. + */
  6410. +int rfs_log_move_chain(struct super_block *sb,
  6411. + unsigned int pdir, unsigned int entry,
  6412. + unsigned int pool_prev, unsigned int pool_next,
  6413. + unsigned int target_prev, unsigned int target_next,
  6414. + unsigned int numof_clus, unsigned int *clus)
  6415. +{
  6416. + if (rfs_log_read(sb, RFS_LOG_I(sb)->isec))
  6417. + return -EIO;
  6418. +
  6419. + rfs_log_update_chain(sb, RFS_SUBLOG_MOVE_CHAIN, pdir, entry,
  6420. + pool_prev, pool_next, target_prev, target_next,
  6421. + numof_clus, clus);
  6422. +
  6423. + if (rfs_log_write(RFS_LOG_I(sb)))
  6424. + return -EIO;
  6425. +
  6426. + return 0;
  6427. +}
  6428. +
  6429. +/**
  6430. + * logging updation of pool file
  6431. + * @param sb super block
  6432. + * @return 0 on success, errno on failure
  6433. + */
  6434. +int rfs_log_update_pool(struct super_block *sb)
  6435. +{
  6436. + if (rfs_log_read(sb, RFS_LOG_I(sb)->isec))
  6437. + return -EIO;
  6438. +
  6439. + rfs_log_update_chain(sb, RFS_SUBLOG_UPDATE_POOL, CLU_TAIL, -1,
  6440. + CLU_TAIL, CLU_TAIL, CLU_TAIL, CLU_TAIL, 0, NULL);
  6441. +
  6442. + if (rfs_log_write(RFS_LOG_I(sb)))
  6443. + return -EIO;
  6444. +
  6445. + return 0;
  6446. +}
  6447. +
  6448. +/**
  6449. + * logging start of transaction without a lock
  6450. + * @param sb super block
  6451. + * @param type log type
  6452. + * @param inode modified inode
  6453. + * @return 0 on success, errno on failure
  6454. + */
  6455. +static int rfs_log_start_nolock(struct super_block *sb, unsigned int type,
  6456. + struct inode *inode)
  6457. +{
  6458. + extern int sanity_check_pool(struct super_block *);
  6459. +
  6460. +#ifdef _RFS_INTERNAL_SANITY_CHECK
  6461. + extern int sanity_check_pool(struct super_block *sb);
  6462. +
  6463. + sanity_check_pool(sb);
  6464. +#endif
  6465. +
  6466. +#ifdef _RFS_INTERNAL_SANITY_CHECK
  6467. + sanity_check_pool(sb);
  6468. +#endif
  6469. +
  6470. + RFS_LOG_I(sb)->type = type;
  6471. + RFS_LOG_I(sb)->inode = inode;
  6472. + RFS_LOG_I(sb)->dirty = FALSE;
  6473. +
  6474. + return 0;
  6475. +}
  6476. +
  6477. +/**
  6478. + * mark an end of transaction
  6479. + * @param sb super block
  6480. + * @param sub_type commit or abort
  6481. + * @return 0 on success, errno on failure
  6482. + */
  6483. +int rfs_log_mark_end(struct super_block *sb, unsigned int sub_type)
  6484. +{
  6485. + if (rfs_log_read(sb, RFS_LOG_I(sb)->isec))
  6486. + return -EIO;
  6487. +
  6488. + set_bit(BH_RFS_LOG_COMMIT, &(RFS_LOG_I(sb)->bh->b_state));
  6489. +
  6490. + SET32(RFS_LOG(sb)->type, MK_LOG_TYPE(RFS_LOG_I(sb)->type, sub_type));
  6491. + if (rfs_log_write(RFS_LOG_I(sb)))
  6492. + return -EIO;
  6493. +
  6494. + RFS_LOG_I(sb)->inode = NULL;
  6495. + RFS_LOG_I(sb)->type = RFS_LOG_NONE;
  6496. +
  6497. + /* destroy stl mapping */
  6498. + if (IS_XSR(sb->s_dev))
  6499. + rfs_map_destroy(sb);
  6500. +
  6501. + return 0;
  6502. +}
  6503. +
  6504. +/*****************************************************************************/
  6505. +/* log read / write functions */
  6506. +/*****************************************************************************/
  6507. +/**
  6508. + * read log
  6509. + * @param sb super block
  6510. + * @param isec logical sector to read
  6511. + * @return 0 on success, errno on failure
  6512. + */
  6513. +int rfs_log_read(struct super_block *sb, unsigned int isec)
  6514. +{
  6515. + struct buffer_head *bh;
  6516. + int state = BH_RFS_LOG;
  6517. + int sec_off;
  6518. +
  6519. + if (RFS_LOG_I(sb)->bh)
  6520. + brelse(RFS_LOG_I(sb)->bh);
  6521. +
  6522. + /* rotational logfile */
  6523. + if (isec >= RFS_LOG_MAX_COUNT) {
  6524. + RFS_BUG("RFS-log : can't read log record\n");
  6525. + return -EIO;
  6526. + }
  6527. +
  6528. + DEBUG(DL3, "read log [%dth : 0x%x]\n", isec, (unsigned int) RFS_LOG_I(sb)->sequence);
  6529. +
  6530. + if (is_empty_tr(sb))
  6531. + state = BH_RFS_LOG_START;
  6532. +
  6533. + bh = rfs_bread(sb, RFS_LOG_I(sb)->blocks[isec], state);
  6534. + if (!bh) {
  6535. + RFS_BUG("RFS-log : Couldn't read log\n");
  6536. + return -EIO;
  6537. + }
  6538. +
  6539. + RFS_LOG_I(sb)->bh = bh;
  6540. +
  6541. + /* point next log record */
  6542. + if (isec == RFS_LOG_MAX_COUNT - 1)
  6543. + RFS_LOG_I(sb)->isec = 0;
  6544. + else
  6545. + RFS_LOG_I(sb)->isec = isec + 1;
  6546. +
  6547. + sec_off = isec & (RFS_LOG_I(sb)->secs_per_blk - 1);
  6548. + RFS_LOG_I(sb)->log = (struct rfs_trans_log *) ((bh->b_data) +
  6549. + (sec_off << SECTOR_BITS));
  6550. +
  6551. + return 0;
  6552. +}
  6553. +
  6554. +/**
  6555. + * write log to logfile and release it
  6556. + * @param log_info rfs's log structure
  6557. + * @return 0 on success, errno on failure
  6558. + */
  6559. +int rfs_log_write(struct rfs_log_info *log_info)
  6560. +{
  6561. + int ret = 0;
  6562. +
  6563. + if (!log_info->bh) {
  6564. + RFS_BUG("RFS-log : No buffer head for log\n");
  6565. + return -EIO;
  6566. + }
  6567. +
  6568. + SET64(log_info->log->sequence, (log_info->sequence)++);
  6569. + mark_buffer_dirty(log_info->bh);
  6570. +#ifdef RFS_FOR_2_6
  6571. + ret = sync_dirty_buffer(log_info->bh);
  6572. +#else
  6573. + ll_rw_block(WRITE, 1, &(log_info->bh));
  6574. + wait_on_buffer(log_info->bh);
  6575. +#endif
  6576. +
  6577. + brelse(log_info->bh);
  6578. + log_info->bh = NULL;
  6579. + log_info->log = NULL;
  6580. + log_info->dirty = TRUE;
  6581. +
  6582. + return ret;
  6583. +}
  6584. +
  6585. +/*****************************************************************************/
  6586. +/* misc. */
  6587. +/*****************************************************************************/
  6588. +/**
  6589. + * make logfile
  6590. + * @param sb super block
  6591. + * @return 0 on success, errno on failure
  6592. + */
  6593. +static int rfs_make_logfile(struct super_block *sb)
  6594. +{
  6595. + struct inode tmp_inode;
  6596. + struct inode *root_dir;
  6597. + struct dentry *root_dentry;
  6598. + struct rfs_dir_entry *ep;
  6599. + struct buffer_head *bh = NULL;
  6600. + unsigned int file_size;
  6601. + unsigned int numof_clus;
  6602. + unsigned int *clus;
  6603. + unsigned int clu = 0;
  6604. + unsigned int i;
  6605. + unsigned int index;
  6606. + int ret;
  6607. +
  6608. + root_dentry = sb->s_root;
  6609. + root_dir = root_dentry->d_inode;
  6610. +
  6611. + /* scan enough space to create log file */
  6612. + file_size = RFS_LOG_MAX_COUNT * SECTOR_SIZE;
  6613. + numof_clus = file_size >> RFS_SB(sb)->cluster_bits;
  6614. + if (file_size & (RFS_SB(sb)->cluster_size - 1))
  6615. + numof_clus++;
  6616. +
  6617. + DEBUG(DL3, "file_size : %u, numof_clus : %u\n", file_size, numof_clus);
  6618. + DEBUG(DL3, "sector_size : %lu, cluster_size : %u", sb->s_blocksize,
  6619. + RFS_SB(sb)->cluster_size);
  6620. +
  6621. + clus = kmalloc(numof_clus * sizeof(unsigned int), GFP_KERNEL);
  6622. + if (!clus)
  6623. + return -ENOMEM;
  6624. +
  6625. + for (i = 0; i < numof_clus; i++) {
  6626. + ret = find_free_cluster(root_dir, &clu);
  6627. + if (ret) {
  6628. + kfree(clus);
  6629. + return -EACCES;
  6630. + }
  6631. + clus[i] = clu;
  6632. + }
  6633. +
  6634. + if (i < numof_clus) { /* insufficient space */
  6635. + kfree(clus);
  6636. + return -ENOSPC;
  6637. + }
  6638. +
  6639. + ret = fat_write(sb, clus[0], CLU_TAIL);
  6640. + if (ret) {
  6641. + kfree(clus);
  6642. + return ret;
  6643. + }
  6644. +
  6645. + index = build_entry(root_dir, NULL, clus[0], TYPE_FILE,
  6646. + RFS_LOG_FILE_NAME);
  6647. + if ((int) index < 0) {
  6648. + kfree(clus);
  6649. + return index;
  6650. + }
  6651. +
  6652. + ep = get_entry(root_dir, index, &bh);
  6653. + if (IS_ERR(ep)) {
  6654. + kfree(clus);
  6655. + brelse(bh);
  6656. + return PTR_ERR(ep);
  6657. + }
  6658. +
  6659. + /* set tmp_inode for log file */
  6660. + tmp_inode.i_sb = sb;
  6661. + RFS_I(&tmp_inode)->start_clu = clus[0];
  6662. +
  6663. + /* allocate enough clusters */
  6664. + for (i = 1; i < numof_clus; i++) {
  6665. + ret = append_new_cluster(&tmp_inode, clus[i - 1], clus[i]);
  6666. + if (ret) {
  6667. + kfree(clus);
  6668. + brelse(bh);
  6669. + return ret;
  6670. + }
  6671. + }
  6672. +
  6673. + ep->attr |= (ATTR_READONLY | ATTR_SYSTEM | ATTR_HIDDEN);
  6674. + SET32(ep->size, file_size);
  6675. + mark_buffer_dirty(bh);
  6676. + brelse(bh);
  6677. +
  6678. + kfree(clus);
  6679. + return 0;
  6680. +}
  6681. +
  6682. +/**
  6683. + * return a pre-allocated cluster
  6684. + * @param inode inode of file to be extended
  6685. + * @param new_clu out-var to save free cluster number
  6686. + * @return 0 on success, errno on failure
  6687. + */
  6688. +int rfs_log_get_cluster(struct inode *inode, unsigned int *new_clu)
  6689. +{
  6690. + struct super_block *sb = inode->i_sb;
  6691. + int ret;
  6692. +
  6693. + /* set default invalid value */
  6694. + *new_clu = CLU_TAIL;
  6695. +
  6696. + if (RFS_LOG_I(sb)->alloc_index >= RFS_LOG_I(sb)->numof_pre_alloc) {
  6697. + ret = pre_alloc_clusters(inode);
  6698. + if (ret)
  6699. + return ret;
  6700. + }
  6701. +
  6702. + if (likely(RFS_LOG_I(sb)->alloc_index <
  6703. + RFS_LOG_I(sb)->numof_pre_alloc)) {
  6704. + *new_clu = RFS_LOG_I(sb)->pre_alloc_clus[
  6705. + (RFS_LOG_I(sb)->alloc_index)++];
  6706. + } else {
  6707. + RFS_BUG("RFS-log : pre-allocation corruption\n");
  6708. + return -EIO;
  6709. + }
  6710. +
  6711. + DEBUG(DL3, "alloc_cluster : %u", *new_clu);
  6712. + return 0;
  6713. +}
  6714. +
  6715. +/**
  6716. + * do pre-allocation
  6717. + * @param inode inode of file to be written
  6718. + * @return 0 on success, errno on failure
  6719. + *
  6720. + * pre-allocate clusters and save them in log buffer
  6721. + */
  6722. +static int pre_alloc_clusters(struct inode *inode)
  6723. +{
  6724. + struct super_block *sb = inode->i_sb;
  6725. + struct rfs_sb_info *sbi = RFS_SB(sb);
  6726. + unsigned int count = 0;
  6727. + unsigned int p_prev_clu, p_next_clu;
  6728. + unsigned int t_next_clu = NOT_ASSIGNED;
  6729. + unsigned int content = NOT_ASSIGNED;
  6730. + unsigned int i;
  6731. + int err;
  6732. +
  6733. + /* first, find free clusters in free chain pool */
  6734. + err = rfs_shrink_pool_chain(sb, RFS_LOG_I(sb)->pre_alloc_clus,
  6735. + RFS_LOG_PRE_ALLOC, &count, &p_next_clu);
  6736. + if (err)
  6737. + return err;
  6738. +
  6739. + p_prev_clu = RFS_POOL_I(sb)->start_cluster;
  6740. + RFS_LOG_I(sb)->where = RFS_POOL;
  6741. +
  6742. + /* if there are no free clusters in pool file,
  6743. + find free clusters in fat table */
  6744. + if (!count) {
  6745. + for (i = VALID_CLU; i < sbi->num_clusters; i++,
  6746. + sbi->search_ptr++) {
  6747. + /* search free cluster from hint(search_ptr) */
  6748. + if (sbi->search_ptr >= sbi->num_clusters)
  6749. + sbi->search_ptr = VALID_CLU;
  6750. +
  6751. + err = fat_read(sb, sbi->search_ptr, &content);
  6752. + if (err)
  6753. + return err;
  6754. +
  6755. + if (content == CLU_FREE) {
  6756. + RFS_LOG_I(sb)->pre_alloc_clus[count++] =
  6757. + sbi->search_ptr;
  6758. +
  6759. + if (count >= RFS_LOG_PRE_ALLOC)
  6760. + break;
  6761. + }
  6762. + }
  6763. + if (!count)
  6764. + return -ENOSPC;
  6765. +
  6766. + p_prev_clu = p_next_clu = CLU_TAIL;
  6767. + RFS_LOG_I(sb)->where = RFS_FAT_TABLE;
  6768. + }
  6769. + RFS_LOG_I(sb)->alloc_index = 0;
  6770. + RFS_LOG_I(sb)->numof_pre_alloc = count;
  6771. +
  6772. + /* in case of unlinked inode, t_next_clu is the head of other chain */
  6773. + if (RFS_I(inode)->last_clu != CLU_TAIL) {
  6774. + err = fat_read(sb, RFS_I(inode)->last_clu, &t_next_clu);
  6775. + if (err)
  6776. + return err;
  6777. + } else
  6778. + t_next_clu = CLU_TAIL;
  6779. +
  6780. + if ((err = rfs_log_alloc_chain(sb, RFS_I(inode)->p_start_clu,
  6781. + RFS_I(inode)->index,
  6782. + p_prev_clu, p_next_clu,
  6783. + RFS_I(inode)->last_clu, t_next_clu,
  6784. + RFS_LOG_I(sb)->numof_pre_alloc,
  6785. + RFS_LOG_I(sb)->pre_alloc_clus))) {
  6786. + return err;
  6787. + }
  6788. +
  6789. + if (RFS_LOG_I(sb)->where == RFS_POOL) {
  6790. + if ((err = rfs_get_pool(sb, p_next_clu, count)))
  6791. + return err;
  6792. + }
  6793. +
  6794. + return 0;
  6795. +}
  6796. diff -NurbB linux-2.6.17.14.orig/fs/rfs/log.h linux-2.6.17.14.rfs/fs/rfs/log.h
  6797. --- linux-2.6.17.14.orig/fs/rfs/log.h 1970-01-01 01:00:00.000000000 +0100
  6798. +++ linux-2.6.17.14.rfs/fs/rfs/log.h 2008-06-19 04:02:09.000000000 +0200
  6799. @@ -0,0 +1,254 @@
  6800. +/**
  6801. + * @file fs/rfs/log.h
  6802. + * @brief header file for log
  6803. + *
  6804. + *---------------------------------------------------------------------------*
  6805. + * *
  6806. + * COPYRIGHT 2003-2007 SAMSUNG ELECTRONICS CO., LTD. *
  6807. + * ALL RIGHTS RESERVED *
  6808. + * *
  6809. + * Permission is hereby granted to licensees of Samsung Electronics *
  6810. + * Co., Ltd. products to use or abstract this computer program only in *
  6811. + * accordance with the terms of the NAND FLASH MEMORY SOFTWARE LICENSE *
  6812. + * AGREEMENT for the sole purpose of implementing a product based on *
  6813. + * Samsung Electronics Co., Ltd. products. No other rights to reproduce, *
  6814. + * use, or disseminate this computer program, whether in part or in *
  6815. + * whole, are granted. *
  6816. + * *
  6817. + * Samsung Electronics Co., Ltd. makes no representation or warranties *
  6818. + * with respect to the performance of this computer program, and *
  6819. + * specifically disclaims any responsibility for any damages, *
  6820. + * special or consequential, connected with the use of this program. *
  6821. + * *
  6822. + *---------------------------------------------------------------------------*
  6823. + *
  6824. + */
  6825. +
  6826. +#ifndef _LINUX_RFS_LOG_H
  6827. +#define _LINUX_RFS_LOG_H
  6828. +
  6829. +#ifdef __KERNEL__
  6830. +#include <linux/sched.h>
  6831. +#include <linux/rfs_fs.h>
  6832. +#else
  6833. +#define u8 unsigned char
  6834. +#define u16 unsigned short
  6835. +#define u32 unsigned int
  6836. +#define u64 unsigned long long
  6837. +#endif
  6838. +
  6839. +/***************************************************************************/
  6840. +/* RFS Common definitions */
  6841. +/***************************************************************************/
  6842. +/* max value is set with extra space */
  6843. +#define RFS_LOG_MAX_ENTRIES 464
  6844. +#define RFS_LOG_MAX_CLUSTERS 112
  6845. +
  6846. +
  6847. +#if defined(CONFIG_RFS_PRE_ALLOC) && (CONFIG_RFS_PRE_ALLOC < RFS_LOG_MAX_CLUSTERS)
  6848. +#define RFS_LOG_PRE_ALLOC CONFIG_RFS_PRE_ALLOC
  6849. +#else
  6850. +#define RFS_LOG_PRE_ALLOC RFS_LOG_MAX_CLUSTERS
  6851. +#endif
  6852. +
  6853. +/* logfile used for unlink */
  6854. +#define RFS_LOG_FILE_NAME "$RFS_LOG.LO$"
  6855. +
  6856. +#define RFS_LOG_FILE_LEN 12
  6857. +
  6858. +/***************************************************************************/
  6859. +/* RFS dependant definitions */
  6860. +/***************************************************************************/
  6861. +#define RFS_LOG_MAX_COUNT 256
  6862. +
  6863. +/* transaction type */
  6864. +#define RFS_LOG_NONE 0x0000
  6865. +#define RFS_LOG_CREATE 0x0001
  6866. +#define RFS_LOG_RENAME 0x0002
  6867. +#define RFS_LOG_WRITE 0x0003
  6868. +#define RFS_LOG_TRUNCATE_F 0x0004
  6869. +#define RFS_LOG_TRUNCATE_B 0x0005
  6870. +#define RFS_LOG_UNLINK 0x0006
  6871. +#define RFS_LOG_DEL_INODE 0x0007
  6872. +#define RFS_LOG_SYMLINK 0x0008
  6873. +#define RFS_LOG_REPLAY 0x0010
  6874. +#define RFS_LOG_INVALID 0xffff
  6875. +
  6876. +/* sub transaction type */
  6877. +#define RFS_SUBLOG_COMMIT 0x0000
  6878. +#define RFS_SUBLOG_ABORT 0x0001
  6879. +#define RFS_SUBLOG_START 0x0002
  6880. +#define RFS_SUBLOG_ALLOC_CHAIN 0x0003
  6881. +#define RFS_SUBLOG_BUILD_ENTRY 0x0005
  6882. +#define RFS_SUBLOG_REMOVE_ENTRY 0x0006
  6883. +#define RFS_SUBLOG_UPDATE_ENTRY 0x0007
  6884. +#define RFS_SUBLOG_GET_CHAIN 0x0009
  6885. +#define RFS_SUBLOG_MOVE_CHAIN 0x000B
  6886. +#define RFS_SUBLOG_UPDATE_POOL 0x000C
  6887. +
  6888. +
  6889. +/* logtype specific MACRO */
  6890. +#define MK_LOG_TYPE(X, Y) (((X) << 16) | (Y))
  6891. +#define GET_LOG(X) ((X) >> 16)
  6892. +#define GET_SUBLOG(X) ((X) & 0x0000ffff)
  6893. +
  6894. +/* where pre-alloction happens */
  6895. +#define RFS_POOL 1
  6896. +#define RFS_FAT_TABLE 2
  6897. +
  6898. +#ifdef CONFIG_GCOV_PROFILE
  6899. +typedef u32 rfs_log_seq_t;
  6900. +#else
  6901. +typedef u64 rfs_log_seq_t;
  6902. +#endif
  6903. +
  6904. +struct rfs_log_entry {
  6905. + u32 pdir;
  6906. + u32 entry;
  6907. + u32 numof_entries;
  6908. + u32 from_size;
  6909. + u32 to_size;
  6910. + u8 undel_buf[RFS_LOG_MAX_ENTRIES];
  6911. +};
  6912. +
  6913. +struct rfs_log_fat {
  6914. + /* two fields for minimal fat entry infos */
  6915. + u32 pdir;
  6916. + u32 entry;
  6917. +
  6918. + /* four fields for pool contents */
  6919. + u32 p_last_clu;
  6920. + u32 p_num_clus;
  6921. + u32 p_c_start_clu;
  6922. + u32 p_c_last_clu;
  6923. +
  6924. + /* two fields for pool chain */
  6925. + u32 p_prev_clu;
  6926. + u32 p_next_clu;
  6927. +
  6928. + /* two fields for target chain */
  6929. + u32 t_prev_clu;
  6930. + u32 t_next_clu;
  6931. +
  6932. + u32 numof_clus;
  6933. + u32 clus[RFS_LOG_MAX_CLUSTERS];
  6934. +};
  6935. +
  6936. +struct rfs_trans_log {
  6937. + u32 type;
  6938. + union {
  6939. + rfs_log_seq_t sequence;
  6940. + u64 dummy; /* place holder for compatibility */
  6941. + };
  6942. + union {
  6943. + struct rfs_log_fat log_fat;
  6944. + struct rfs_log_entry log_entry;
  6945. + };
  6946. +} __attribute__ ((packed));
  6947. +
  6948. +#ifdef __KERNEL__
  6949. +struct rfs_log_info {
  6950. + unsigned long blocks[RFS_LOG_MAX_COUNT];
  6951. + unsigned int secs_per_blk;
  6952. + unsigned int secs_per_blk_bits;
  6953. + unsigned int isec;
  6954. + unsigned int type;
  6955. + rfs_log_seq_t sequence;
  6956. + int dirty;
  6957. +
  6958. + void *log_mutex;
  6959. +
  6960. + unsigned int numof_pre_alloc;
  6961. + unsigned int alloc_index;
  6962. + unsigned int pre_alloc_clus[RFS_LOG_MAX_CLUSTERS];
  6963. + int where;
  6964. +
  6965. + struct inode *inode; /* target file */
  6966. + struct buffer_head *bh;
  6967. + struct rfs_trans_log *log;
  6968. +
  6969. + unsigned int start_cluster; /* for logfile itself */
  6970. +#ifdef RFS_FOR_2_4
  6971. + struct inode tr_buf_inode; /* in order to link transaction dirty buffers */
  6972. +#endif
  6973. + struct inode *symlink_inode; /* in order to point the symlink inode */
  6974. +};
  6975. +
  6976. +/* get rfs log info */
  6977. +static inline struct rfs_log_info *RFS_LOG_I(struct super_block *sb)
  6978. +{
  6979. + return (struct rfs_log_info *)(RFS_SB(sb)->log_info);
  6980. +}
  6981. +
  6982. +/* get rfs log */
  6983. +static inline struct rfs_trans_log *RFS_LOG(struct super_block *sb)
  6984. +{
  6985. + return ((struct rfs_log_info *)(RFS_SB(sb)->log_info))->log;
  6986. +}
  6987. +
  6988. +static inline void rfs_sync_bh(struct buffer_head *bh)
  6989. +{
  6990. + if (!bh)
  6991. + return;
  6992. +
  6993. + if (buffer_dirty(bh)) {
  6994. + ll_rw_block(WRITE, 1, &bh);
  6995. + wait_on_buffer(bh);
  6996. + } else if (buffer_locked(bh))
  6997. + wait_on_buffer(bh);
  6998. +}
  6999. +
  7000. +static inline int is_empty_tr(struct super_block *sb)
  7001. +{
  7002. + if (!(RFS_LOG_I(sb)->dirty))
  7003. + return 1;
  7004. +
  7005. + return 0;
  7006. +}
  7007. +
  7008. +static inline int tr_in_replay(struct super_block *sb)
  7009. +{
  7010. + if (RFS_LOG_I(sb)->type == RFS_LOG_REPLAY)
  7011. + return 1;
  7012. + return 0;
  7013. +}
  7014. +
  7015. +/* called by FAT */
  7016. +int rfs_log_init(struct super_block *sb);
  7017. +int rfs_log_start(struct super_block *sb, unsigned int log_type,
  7018. + struct inode *inode);
  7019. +int rfs_log_end(struct super_block *sb, int result);
  7020. +int rfs_log_build_entry(struct super_block *sb, unsigned int pdir,
  7021. + unsigned int entry, unsigned int numof_entries);
  7022. +int rfs_log_remove_entry(struct super_block *sb, unsigned int pdir,
  7023. + unsigned int entry, unsigned int numof_entries,
  7024. + unsigned char *undel_buf);
  7025. +int rfs_log_update_entry(struct super_block *sb, unsigned int pdir,
  7026. + unsigned int entry, unsigned int from_size,
  7027. + unsigned int to_size);
  7028. +int rfs_log_alloc_chain(struct super_block *sb,
  7029. + unsigned int pdir, unsigned int entry,
  7030. + unsigned int pool_prev, unsigned int pool_next,
  7031. + unsigned int target_prev, unsigned int target_next,
  7032. + unsigned int numof_clus, unsigned int *clus);
  7033. +int rfs_log_move_chain(struct super_block *sb,
  7034. + unsigned int pdir, unsigned int entry,
  7035. + unsigned int pool_prev, unsigned int pool_next,
  7036. + unsigned int target_prev, unsigned int target_next,
  7037. + unsigned int numof_clus, unsigned int *clus);
  7038. +int rfs_log_update_pool(struct super_block *sb);
  7039. +int tr_pre_alloc(struct super_block *sb);
  7040. +int rfs_log_get_cluster(struct inode *inode, unsigned int *new_clu);
  7041. +void rfs_log_cleanup(struct super_block *sb);
  7042. +int rfs_log_force_commit(struct super_block *sb, struct inode *inode);
  7043. +int rfs_log_read(struct super_block *sb, unsigned int isec);
  7044. +int rfs_log_write(struct rfs_log_info *log_info);
  7045. +int rfs_log_mark_end(struct super_block *sb, unsigned int sub_type);
  7046. +int rfs_meta_commit(struct super_block *);
  7047. +int tr_deferred_commit(struct super_block *sb);
  7048. +
  7049. +int rfs_log_replay(struct super_block *sb);
  7050. +#endif /* __KERNEL__ */
  7051. +
  7052. +#endif /* _LINUX_RFS_FS_H */
  7053. +
  7054. diff -NurbB linux-2.6.17.14.orig/fs/rfs/log_replay.c linux-2.6.17.14.rfs/fs/rfs/log_replay.c
  7055. --- linux-2.6.17.14.orig/fs/rfs/log_replay.c 1970-01-01 01:00:00.000000000 +0100
  7056. +++ linux-2.6.17.14.rfs/fs/rfs/log_replay.c 2008-06-19 04:02:08.000000000 +0200
  7057. @@ -0,0 +1,691 @@
  7058. +/**
  7059. + * @file fs/rfs/log_replay.c
  7060. + * @brief functions for replaying log
  7061. + *
  7062. + *---------------------------------------------------------------------------*
  7063. + * *
  7064. + * COPYRIGHT 2003-2007 SAMSUNG ELECTRONICS CO., LTD. *
  7065. + * ALL RIGHTS RESERVED *
  7066. + * *
  7067. + * Permission is hereby granted to licensees of Samsung Electronics *
  7068. + * Co., Ltd. products to use or abstract this computer program only in *
  7069. + * accordance with the terms of the NAND FLASH MEMORY SOFTWARE LICENSE *
  7070. + * AGREEMENT for the sole purpose of implementing a product based on *
  7071. + * Samsung Electronics Co., Ltd. products. No other rights to reproduce, *
  7072. + * use, or disseminate this computer program, whether in part or in *
  7073. + * whole, are granted. *
  7074. + * *
  7075. + * Samsung Electronics Co., Ltd. makes no representation or warranties *
  7076. + * with respect to the performance of this computer program, and *
  7077. + * specifically disclaims any responsibility for any damages, *
  7078. + * special or consequential, connected with the use of this program. *
  7079. + * *
  7080. + *---------------------------------------------------------------------------*
  7081. + *
  7082. + */
  7083. +
  7084. +#include <linux/rfs_fs.h>
  7085. +#include "rfs.h"
  7086. +#include "log.h"
  7087. +
  7088. +#ifdef LOG_BINARY_SCAN
  7089. +#define SEARCH_MAX(sb, from, to, outvar) \
  7090. + binary_search_max(sb, from, to, outvar)
  7091. +#else
  7092. +#define SEARCH_MAX(sb, from, to, outvar) \
  7093. + sequential_search_max(sb, from, to, outvar)
  7094. +#endif
  7095. +
  7096. +/**
  7097. + * undo alloc chain from pool or fat table
  7098. + * @param sb super block
  7099. + * @return 0 on success, errno on failure
  7100. + *
  7101. + * make target's chain complete and then return allocated chain to pool or
  7102. + * fat table
  7103. + */
  7104. +static int rfs_log_undo_alloc_chain(struct super_block *sb)
  7105. +{
  7106. + struct rfs_log_fat *log_fat;
  7107. + unsigned int numof_clus;
  7108. + unsigned int sub_type;
  7109. + unsigned int i;
  7110. + int ret = 0;
  7111. +
  7112. + sub_type = GET_SUBLOG(GET32(RFS_LOG(sb)->type));
  7113. + log_fat = &(RFS_LOG(sb)->log_fat);
  7114. +
  7115. + if (GET32(log_fat->t_prev_clu) != CLU_TAIL) {
  7116. + /* make target chain complete */
  7117. + if (fat_write(sb, GET32(log_fat->t_prev_clu),
  7118. + GET32(log_fat->t_next_clu)))
  7119. + return -EIO;
  7120. + DEBUG(DL1, "make target %u -> %u", GET32(log_fat->t_prev_clu),
  7121. + GET32(log_fat->t_next_clu));
  7122. + } else if (GET32(log_fat->pdir) != CLU_TAIL) {
  7123. + /*
  7124. + * In case of mkdir, allocating cluster precedes
  7125. + * building entry, which is remarked
  7126. + * by setting CLU_TAIL to pdir
  7127. + */
  7128. + struct buffer_head *bh = NULL;
  7129. + struct rfs_dir_entry *ep;
  7130. +
  7131. + ep = get_entry_with_cluster(sb, GET32(log_fat->pdir),
  7132. + GET32(log_fat->entry), &bh);
  7133. + if (IS_ERR(ep)) {
  7134. + /*
  7135. + * EFAULT means extension of parent is not flushed and
  7136. + * there is no dir entry for new file.
  7137. + */
  7138. + if (PTR_ERR(ep) != -EFAULT) {
  7139. + brelse(bh);
  7140. + return -EIO;
  7141. + }
  7142. + } else {
  7143. + DEBUG(DL1, "ep's start_clu [%u -> 0]",
  7144. + START_CLUSTER(ep));
  7145. +
  7146. + SET16(ep->start_clu_lo, 0);
  7147. + SET16(ep->start_clu_hi, 0);
  7148. +
  7149. + if (buffer_uptodate(bh))
  7150. + mark_buffer_dirty(bh);
  7151. + }
  7152. +
  7153. + brelse(bh);
  7154. + }
  7155. +
  7156. + numof_clus = GET32(log_fat->numof_clus);
  7157. +
  7158. + if (sub_type == RFS_SUBLOG_GET_CHAIN) {
  7159. + /* link pool prev with head of chain */
  7160. + if (fat_write(sb, GET32(log_fat->p_prev_clu),
  7161. + GET32(log_fat->clus[0])))
  7162. + return -EIO;
  7163. +
  7164. + /* make chain from pool complete */
  7165. + for (i = 0; i < numof_clus - 1; i++) {
  7166. + if (fat_write(sb, GET32(log_fat->clus[i]),
  7167. + GET32(log_fat->clus[i + 1]))) {
  7168. + return -EIO;
  7169. + }
  7170. + }
  7171. +
  7172. + /* link chain with pool next */
  7173. + if (fat_write(sb, GET32(log_fat->clus[i]),
  7174. + GET32(log_fat->p_next_clu)))
  7175. + return -EIO;
  7176. +
  7177. + DEBUG(DL1, "make pool %u -> %u, %u -> %u",
  7178. + GET32(log_fat->p_prev_clu), GET32(log_fat->clus[0]),
  7179. + GET32(log_fat->clus[i]), GET32(log_fat->p_next_clu));
  7180. +
  7181. + DEBUG(DL1, "make target %u -> %u",
  7182. + GET32(log_fat->t_prev_clu), GET32(log_fat->t_next_clu));
  7183. + } else { /* RFS_SUBLOG_ALLOC_CHAIN */
  7184. + /* set free allocated chain */
  7185. + for (i = 0; i < numof_clus; i++) {
  7186. + if (fat_write(sb, GET32(log_fat->clus[i]), CLU_FREE))
  7187. + return -EIO;
  7188. + DEBUG(DL2, "free %u", GET32(log_fat->clus[i]));
  7189. + }
  7190. + }
  7191. +
  7192. + /* update pool file */
  7193. + RFS_POOL_I(sb)->last_cluster = GET32(log_fat->p_last_clu);
  7194. + RFS_POOL_I(sb)->num_clusters = GET32(log_fat->p_num_clus);
  7195. + RFS_POOL_I(sb)->c_start_cluster = GET32(log_fat->p_c_start_clu);
  7196. + RFS_POOL_I(sb)->c_last_cluster = GET32(log_fat->p_c_last_clu);
  7197. +
  7198. + /* rewrite pool file */
  7199. + ret = rfs_update_pool_block(sb);
  7200. + if (ret)
  7201. + return ret;
  7202. +
  7203. + /* resize entry of pool file */
  7204. + ret = rfs_update_pool_entry(sb, GET32(log_fat->p_num_clus),
  7205. + SET_POOL_SIZE);
  7206. +
  7207. + return ret;
  7208. +}
  7209. +
  7210. +#ifdef _RFS_INTERNAL_UNUSED_LOG
  7211. +/**
  7212. + * undo dealloc chain to fat table
  7213. + * @param sb super block
  7214. + * @return 0 on success, -EIO on failure
  7215. + *
  7216. + * make sure the logged chain and link the chain with old prev and next
  7217. + */
  7218. +static int rfs_log_undo_free_chain(struct super_block *sb)
  7219. +{
  7220. + struct rfs_log_fat *log_fat;
  7221. + unsigned int numof_clus;
  7222. + unsigned int i;
  7223. +
  7224. + log_fat = &(RFS_LOG(sb)->log_fat);
  7225. + numof_clus = GET32(log_fat->numof_clus);
  7226. +
  7227. + /* link target prev with head of free_chain */
  7228. + if (GET32(log_fat->t_prev_clu) != CLU_TAIL) { /* if not unlink file */
  7229. + if (fat_write(sb, GET32(log_fat->t_prev_clu),
  7230. + GET32(log_fat->clus[0])))
  7231. + return -EIO;
  7232. + } else {
  7233. + struct buffer_head *bh = NULL;
  7234. + struct rfs_dir_entry *ep;
  7235. +
  7236. + if (numof_clus == 0) {
  7237. + RFS_BUG("RFS-log : no deleted chain\n");
  7238. + return -EIO;
  7239. + }
  7240. +
  7241. + ep = get_entry_with_cluster(sb, GET32(log_fat->pdir),
  7242. + GET32(log_fat->entry), &bh);
  7243. + if (IS_ERR(ep)) {
  7244. + brelse(bh);
  7245. + return -EIO;
  7246. + }
  7247. + DEBUG(DL1, "ep's start_clu [%u -> %u]",
  7248. + START_CLUSTER(ep), GET32(log_fat->clus[0]));
  7249. +
  7250. + SET16(ep->start_clu_lo, GET32(log_fat->clus[0]));
  7251. + SET16(ep->start_clu_hi, GET32(log_fat->clus[0]) >> 16);
  7252. +
  7253. + if (buffer_uptodate(bh))
  7254. + mark_buffer_dirty(bh);
  7255. +
  7256. + brelse(bh);
  7257. + }
  7258. +
  7259. + /* make chain from free clusters */
  7260. + for (i = 0; i < numof_clus - 1; i++) {
  7261. + if (fat_write(sb, GET32(log_fat->clus[i]),
  7262. + GET32(log_fat->clus[i + 1]))) {
  7263. + return -EIO;
  7264. + }
  7265. + }
  7266. +
  7267. + /* link free_chain with target next */
  7268. + if (fat_write(sb, GET32(log_fat->clus[i]), GET32(log_fat->t_next_clu)))
  7269. + return -EIO;
  7270. +
  7271. + DEBUG(DL1, "make target %u -> %u, %u -> %u",
  7272. + GET32(log_fat->t_prev_clu), GET32(log_fat->clus[0]),
  7273. + GET32(log_fat->clus[i]), GET32(log_fat->t_next_clu));
  7274. + return 0;
  7275. +}
  7276. +#endif
  7277. +
  7278. +/**
  7279. + * undo built entries
  7280. + * @param sb super block
  7281. + * @return 0 on success, errno on failure
  7282. + *
  7283. + * for each entry in built entries {
  7284. + * if (entry is built)
  7285. + * entry->name[0] = DELETION_MARK;
  7286. + * }
  7287. + */
  7288. +static int rfs_log_undo_built_entry(struct super_block *sb)
  7289. +{
  7290. + struct rfs_log_entry *log_entry;
  7291. + struct buffer_head *bh = NULL;
  7292. + struct rfs_dir_entry *ep;
  7293. + unsigned int numof_entries;
  7294. + unsigned int i;
  7295. + int ret = 0;
  7296. +
  7297. + log_entry = &(RFS_LOG(sb)->log_entry);
  7298. + numof_entries = GET32(log_entry->numof_entries);
  7299. +
  7300. + for (i = 0; i < numof_entries; i++) {
  7301. + ep = get_entry_with_cluster(sb, GET32(log_entry->pdir),
  7302. + GET32(log_entry->entry) - i, &bh);
  7303. + if (IS_ERR(ep)) {
  7304. + ret = PTR_ERR(ep);
  7305. + if (ret == -EFAULT) {
  7306. + /* beyond file limit */
  7307. + /* the extended cluster was
  7308. + not flushed, so do nothing
  7309. + for build-entry on it */
  7310. + ret = 0;
  7311. + }
  7312. + goto rel_bh;
  7313. + }
  7314. +
  7315. + if (!IS_FREE(ep->name))
  7316. + ep->name[0] = (unsigned char) DELETE_MARK;
  7317. +
  7318. + if (buffer_uptodate(bh))
  7319. + mark_buffer_dirty(bh);
  7320. + }
  7321. +
  7322. +rel_bh:
  7323. + brelse(bh);
  7324. +
  7325. + return ret;
  7326. +}
  7327. +
  7328. +/**
  7329. + * undo removed entries
  7330. + * @param sb super block
  7331. + * @return 0 on success, errno on failure
  7332. + * @pre the way to delete entries is marking deletion at ep->name[0]
  7333. + *
  7334. + * for each entry in built entries {
  7335. + * entry->name[0] = log_entry->undel_buf[index];
  7336. + * }
  7337. + */
  7338. +static int rfs_log_undo_removed_entry(struct super_block *sb)
  7339. +{
  7340. + struct rfs_log_entry *log_entry;
  7341. + struct buffer_head *bh = NULL;
  7342. + struct rfs_dir_entry *ep;
  7343. + unsigned int numof_entries;
  7344. + unsigned int i;
  7345. + int ret = 0;
  7346. +
  7347. + log_entry = &(RFS_LOG(sb)->log_entry);
  7348. + numof_entries = GET32(log_entry->numof_entries);
  7349. +
  7350. + for (i = 0; i < numof_entries; i++) {
  7351. + ep = get_entry_with_cluster(sb, GET32(log_entry->pdir),
  7352. + GET32(log_entry->entry) - i, &bh);
  7353. + if (IS_ERR(ep)) {
  7354. + /*
  7355. + * In rfs_symlink(), removing entry could happen
  7356. + * for recovery of ENOSPC. In this case,
  7357. + * entries can not be found, so returns EFAULT.
  7358. + */
  7359. + if ((ret = PTR_ERR(ep)) == -EFAULT)
  7360. + ret = 0;
  7361. +
  7362. + goto rel_bh;
  7363. + }
  7364. +
  7365. + ep->name[0] = log_entry->undel_buf[i];
  7366. +
  7367. + if (buffer_uptodate(bh))
  7368. + mark_buffer_dirty(bh);
  7369. + }
  7370. +
  7371. +rel_bh:
  7372. + brelse(bh);
  7373. +
  7374. + return ret;
  7375. +}
  7376. +
  7377. +#ifdef _RFS_INTERNAL_UNUSED_LOG
  7378. +/**
  7379. + * undo updated entry
  7380. + * @param sb super block
  7381. + * @return 0 on success, errno on failure
  7382. + *
  7383. + * restore old size
  7384. + */
  7385. +static int rfs_log_undo_updated_entry(struct super_block *sb)
  7386. +{
  7387. + struct rfs_log_entry *log_entry;
  7388. + struct buffer_head *bh = NULL;
  7389. + struct rfs_dir_entry *ep;
  7390. + int ret = 0;
  7391. +
  7392. + log_entry = &(RFS_LOG(sb)->log_entry);
  7393. +
  7394. + ep = get_entry_with_cluster(sb, GET32(log_entry->pdir),
  7395. + GET32(log_entry->entry), &bh);
  7396. + if (IS_ERR(ep)) {
  7397. + ret = PTR_ERR(ep);
  7398. + goto rel_bh;
  7399. + }
  7400. + SET32(ep->size, GET32(log_entry->from_size));
  7401. + mark_buffer_dirty(bh);
  7402. +
  7403. +rel_bh:
  7404. + brelse(bh);
  7405. +
  7406. + return ret;
  7407. +}
  7408. +#endif
  7409. +
  7410. +/**
  7411. + * undo moving chain (delete chain or delete inode)
  7412. + * @param sb super block
  7413. + * @return 0 on success, errno on failure
  7414. + * @pre logging only head and tail for moved chain
  7415. + *
  7416. + * link logged chain with old prev and old, and rollback pool chain
  7417. + * update pool file
  7418. + */
  7419. +static int rfs_log_undo_move_chain(struct super_block *sb)
  7420. +{
  7421. + struct rfs_log_fat *log_fat;
  7422. + int ret;
  7423. +
  7424. + log_fat = &(RFS_LOG(sb)->log_fat);
  7425. +
  7426. + /* link target prev with head of chain */
  7427. + if (GET32(log_fat->t_prev_clu) != CLU_TAIL) {
  7428. + /* Shrink file to positive size or delete inode */
  7429. + if (fat_write(sb, GET32(log_fat->t_prev_clu),
  7430. + GET32(log_fat->clus[0])))
  7431. + return -EIO;
  7432. + } else if (GET32(log_fat->pdir) != CLU_TAIL) {
  7433. + /*
  7434. + * Shrink file to 0 or unlink file.
  7435. + * In case of run-time rollback of mkdir by -ENOSPC,
  7436. + * when dir entry have not been built yet
  7437. + * log_fat->pdir has CLU_TAIL.
  7438. + */
  7439. + struct buffer_head *bh = NULL;
  7440. + struct rfs_dir_entry *ep;
  7441. +
  7442. + if (GET32(log_fat->numof_clus) == 0) {
  7443. + RFS_BUG("RFS-log : no deleted chain\n");
  7444. + return -EIO;
  7445. + }
  7446. +
  7447. + ep = get_entry_with_cluster(sb, GET32(log_fat->pdir),
  7448. + GET32(log_fat->entry), &bh);
  7449. + if (IS_ERR(ep)) {
  7450. + brelse(bh);
  7451. + return -EIO;
  7452. + }
  7453. + DEBUG(DL1, "ep's start_clu [%u -> %u]",
  7454. + START_CLUSTER(ep), GET32(log_fat->clus[0]));
  7455. +
  7456. + SET16(ep->start_clu_lo, GET32(log_fat->clus[0]));
  7457. + SET16(ep->start_clu_hi, GET32(log_fat->clus[0]) >> 16);
  7458. +
  7459. + if (buffer_uptodate(bh))
  7460. + mark_buffer_dirty(bh);
  7461. +
  7462. + brelse(bh);
  7463. + }
  7464. +
  7465. + /* link tail of chain with tail of chain */
  7466. + if (fat_write(sb, GET32(log_fat->clus[1]), GET32(log_fat->t_next_clu)))
  7467. + return -EIO;
  7468. +
  7469. + DEBUG(DL1, "make target %u -> %u, %u -> %u",
  7470. + GET32(log_fat->t_prev_clu), GET32(log_fat->clus[0]),
  7471. + GET32(log_fat->clus[1]), GET32(log_fat->t_next_clu));
  7472. +
  7473. + /* make pool chain complete */
  7474. + if (fat_write(sb, GET32(log_fat->p_prev_clu),
  7475. + GET32(log_fat->p_next_clu)))
  7476. + return -EIO;
  7477. +
  7478. + DEBUG(DL1, "make pool %u -> %u",
  7479. + GET32(log_fat->p_prev_clu), GET32(log_fat->p_next_clu));
  7480. +
  7481. + /* update pool file */
  7482. + RFS_POOL_I(sb)->last_cluster = GET32(log_fat->p_last_clu);
  7483. + RFS_POOL_I(sb)->num_clusters = GET32(log_fat->p_num_clus);
  7484. + RFS_POOL_I(sb)->c_start_cluster = GET32(log_fat->p_c_start_clu);
  7485. + RFS_POOL_I(sb)->c_last_cluster = GET32(log_fat->p_c_last_clu);
  7486. +
  7487. + /* rewrite pool file */
  7488. + ret = rfs_update_pool_block(sb);
  7489. + if (ret)
  7490. + return ret;
  7491. +
  7492. + /* resize entry of pool file */
  7493. + ret = rfs_update_pool_entry(sb, GET32(log_fat->p_num_clus),
  7494. + SET_POOL_SIZE);
  7495. + if (ret)
  7496. + return ret;
  7497. +
  7498. + return 0;
  7499. +}
  7500. +
  7501. +/**
  7502. + * undo change of pool file
  7503. + * @param sb super block
  7504. + * @return 0 on success, errno on failure
  7505. + * @pre logging only head and tail for moved chain
  7506. + */
  7507. +static int rfs_log_undo_updated_pool(struct super_block *sb)
  7508. +{
  7509. + struct rfs_log_fat *log_fat;
  7510. + int ret;
  7511. +
  7512. + log_fat = &(RFS_LOG(sb)->log_fat);
  7513. +
  7514. + /* update pool file */
  7515. + RFS_POOL_I(sb)->last_cluster = GET32(log_fat->p_last_clu);
  7516. + RFS_POOL_I(sb)->num_clusters = GET32(log_fat->p_num_clus);
  7517. + RFS_POOL_I(sb)->c_start_cluster = GET32(log_fat->p_c_start_clu);
  7518. + RFS_POOL_I(sb)->c_last_cluster = GET32(log_fat->p_c_last_clu);
  7519. +
  7520. + DEBUG(DL1, "POOL_INFO : <%u, %u>, <%u, %u>",
  7521. + RFS_POOL_I(sb)->last_cluster,
  7522. + RFS_POOL_I(sb)->num_clusters,
  7523. + RFS_POOL_I(sb)->c_start_cluster,
  7524. + RFS_POOL_I(sb)->c_last_cluster);
  7525. +
  7526. + /* rewrite pool file */
  7527. + ret = rfs_update_pool_block(sb);
  7528. + if (ret)
  7529. + return ret;
  7530. +
  7531. + /* resize entry of pool file */
  7532. + ret = rfs_update_pool_entry(sb, GET32(log_fat->p_num_clus),
  7533. + SET_POOL_SIZE);
  7534. + if (ret)
  7535. + return ret;
  7536. +
  7537. + return 0;
  7538. +}
  7539. +
  7540. +/**
  7541. + * sequential search for the index of a log with max sequence
  7542. + * @param sb super block
  7543. + * @param from from index
  7544. + * @param to to index
  7545. + * @param[out] last_index the index of log with max sequence
  7546. + * @return 0 on success, error no on failure.
  7547. + */
  7548. +static int sequential_search_max(struct super_block *sb, unsigned int from,
  7549. + unsigned int to, unsigned int *last_index)
  7550. +{
  7551. + rfs_log_seq_t max_seq, seq;
  7552. + unsigned int i;
  7553. +
  7554. + max_seq = seq = 0;
  7555. + *last_index = -1;
  7556. +
  7557. + DEBUG(DL3, "from : %d, to : %d\n", from, to);
  7558. + for (i = from; i <= to; i++) {
  7559. + if (rfs_log_read(sb, i))
  7560. + return -EIO;
  7561. +
  7562. + seq = GET64(RFS_LOG(sb)->sequence);
  7563. +
  7564. + DEBUG(DL3, "%d, max : 0x%0x, cur : 0x%0x\n",
  7565. + i, (unsigned int) max_seq, (unsigned int) seq);
  7566. + if (max_seq < seq) {
  7567. + max_seq = seq;
  7568. + *last_index = i;
  7569. + }
  7570. + }
  7571. +
  7572. + DEBUG(DL2, "last tr is : %d, max_seq : 0x%0x\n",
  7573. + *last_index, (unsigned int) max_seq);
  7574. +
  7575. + /* notice that it is possible to overflow sequence number */
  7576. + if (max_seq == (rfs_log_seq_t) (~0))
  7577. + return -EILSEQ;
  7578. +
  7579. + return 0;
  7580. +}
  7581. +
  7582. +/**
  7583. + * get the index of a log with max sequence in log file
  7584. + * @param sb super block
  7585. + * @param[out] last_index the index of log with max sequence
  7586. + * @return 0 or -ENOENT on success, other errnos on failure
  7587. + */
  7588. +static int rfs_log_get_trans(struct super_block *sb, int *last_index)
  7589. +{
  7590. + int ret;
  7591. +
  7592. + /* set default value */
  7593. + *last_index = -1;
  7594. +
  7595. + /* check empty log file */
  7596. + if (rfs_log_read(sb, 0))
  7597. + return -EIO;
  7598. +
  7599. + if (GET32(RFS_LOG(sb)->type) == RFS_LOG_NONE)
  7600. + return -ENOENT;
  7601. +
  7602. +
  7603. + ret = sequential_search_max(sb, 0, RFS_LOG_MAX_COUNT - 1, last_index);
  7604. +
  7605. + /*
  7606. + * TODO
  7607. + * Is it necessary to handle overflowing sequence number? (EILSEQ)
  7608. + */
  7609. + if (ret < 0)
  7610. + return ret;
  7611. +
  7612. + return 0;
  7613. +}
  7614. +
  7615. +/**
  7616. + * replay logs from latest uncommited log
  7617. + * @param sb rfs private super block
  7618. + * @return 0 on success, errno on failure
  7619. + * @pre super block should be initialized
  7620. + */
  7621. +int rfs_log_replay(struct super_block *sb)
  7622. +{
  7623. + rfs_log_seq_t prev_seq = 0;
  7624. + /* sub_type should be used as 'int' type */
  7625. + int sub_type = RFS_LOG_NONE;
  7626. + int last_index = 0, index;
  7627. + int ret = 0;
  7628. +
  7629. + if ((ret = rfs_log_get_trans(sb, &last_index))) {
  7630. + if (ret == -ENOENT) {
  7631. + RFS_LOG_I(sb)->isec = 0;
  7632. + ret = 0;
  7633. + }
  7634. + goto out;
  7635. + }
  7636. +
  7637. + ret = rfs_log_read(sb, last_index);
  7638. + if (ret)
  7639. + goto out;
  7640. +
  7641. + index = last_index;
  7642. + RFS_LOG_I(sb)->sequence = GET64(RFS_LOG(sb)->sequence) + 1;
  7643. + RFS_LOG_I(sb)->type = RFS_LOG_REPLAY;
  7644. + sub_type = GET_SUBLOG(GET32(RFS_LOG(sb)->type));
  7645. +
  7646. + /* In order to check continuity of sequence number */
  7647. + prev_seq = GET64(RFS_LOG(sb)->sequence) + 1;
  7648. + while (1) {
  7649. + /*
  7650. + * Note: It's important use 'int' type in swtich condition.
  7651. + * 'unsigned int' condition can't handle it correctly
  7652. + * in gcov mode
  7653. + */
  7654. +
  7655. + /* Are the sequence numbers continuous? */
  7656. + if (prev_seq - 1 != GET64(RFS_LOG(sb)->sequence)) {
  7657. + DPRINTK("Log records are not continuous."
  7658. + "Log file is broken\n");
  7659. + return -EIO;
  7660. + }
  7661. +
  7662. + switch (sub_type) {
  7663. + case RFS_SUBLOG_ALLOC_CHAIN:
  7664. + case RFS_SUBLOG_GET_CHAIN:
  7665. + DEBUG(DL0, "RFS_SUBLOG_ALLOC_CHAIN");
  7666. + ret = rfs_log_undo_alloc_chain(sb);
  7667. + break;
  7668. +#ifdef _RFS_INTERNAL_UNUSED_LOG
  7669. + case RFS_SUBLOG_FREE_CHAIN:
  7670. + DEBUG(DL0, "RFS_SUBLOG_FREE_CHAIN");
  7671. + ret = rfs_log_undo_free_chain(sb);
  7672. + break;
  7673. + case RFS_SUBLOG_UPDATE_ENTRY:
  7674. + DEBUG(DL0, "RFS_SUBLOG_UPDATE_ENTRY");
  7675. + ret = rfs_log_undo_updated_entry(sb);
  7676. + break;
  7677. + case RFS_SUBLOG_PUT_CHAIN:
  7678. +#endif
  7679. + case RFS_SUBLOG_MOVE_CHAIN:
  7680. + DEBUG(DL0, "RFS_SUBLOG_MOVE_CHAIN");
  7681. + ret = rfs_log_undo_move_chain(sb);
  7682. + break;
  7683. + case RFS_SUBLOG_BUILD_ENTRY:
  7684. + DEBUG(DL0, "RFS_SUBLOG_BUILD_ENTRY");
  7685. + ret = rfs_log_undo_built_entry(sb);
  7686. + break;
  7687. + case RFS_SUBLOG_REMOVE_ENTRY:
  7688. + DEBUG(DL0, "RFS_SUBLOG_REMOVE_ENTRY");
  7689. + ret = rfs_log_undo_removed_entry(sb);
  7690. + break;
  7691. + case RFS_SUBLOG_UPDATE_POOL:
  7692. + DEBUG(DL0, "RFS_SUBLOG_UPDATE_POOL");
  7693. + ret = rfs_log_undo_updated_pool(sb);
  7694. + break;
  7695. + case RFS_SUBLOG_ABORT: /* transaction is aborted */
  7696. + DEBUG(DL0, "Latest transaction is aborted."
  7697. + " Strongly recommend to check filesystem\n");
  7698. + case RFS_SUBLOG_COMMIT: /* transaction completes */
  7699. + case RFS_SUBLOG_START: /* transaction dose nothing */
  7700. + /* do nothing. do not need to commit */
  7701. + DEBUG(DL0, "RFS_SUBLOG_COMMIT");
  7702. + if (last_index == index) {
  7703. + brelse(RFS_LOG_I(sb)->bh);
  7704. + RFS_LOG_I(sb)->bh = NULL;
  7705. + RFS_LOG_I(sb)->log = NULL;
  7706. + goto out;
  7707. + }
  7708. +
  7709. + goto commit;
  7710. + default:
  7711. + RFS_BUG("RFS-log : Unsupporting log record\n");
  7712. + ret = -EIO;
  7713. + }
  7714. +
  7715. + if (ret)
  7716. + goto out;
  7717. +
  7718. + if (index == 0)
  7719. + index = RFS_LOG_MAX_COUNT;
  7720. +
  7721. + /* the prev seq is greater than current by 1 */
  7722. + prev_seq--;
  7723. +
  7724. + /* get next log */
  7725. + ret = rfs_log_read(sb, --index);
  7726. + if (ret)
  7727. + goto out;
  7728. +
  7729. + sub_type = GET_SUBLOG(GET32(RFS_LOG(sb)->type));
  7730. + }
  7731. +commit:
  7732. + rfs_sync_vol(sb);
  7733. +
  7734. + /* commit mark */
  7735. + if (last_index == RFS_LOG_MAX_COUNT - 1)
  7736. + RFS_LOG_I(sb)->isec = 0;
  7737. + else
  7738. + RFS_LOG_I(sb)->isec = last_index + 1;
  7739. +
  7740. + ret = rfs_log_mark_end(sb, RFS_SUBLOG_COMMIT);
  7741. +
  7742. + DEBUG(DL0, "end mark commit");
  7743. + return ret;
  7744. +out:
  7745. + RFS_LOG_I(sb)->type = RFS_LOG_NONE;
  7746. +
  7747. + return ret;
  7748. +}
  7749. diff -NurbB linux-2.6.17.14.orig/fs/rfs/Makefile linux-2.6.17.14.rfs/fs/rfs/Makefile
  7750. --- linux-2.6.17.14.orig/fs/rfs/Makefile 1970-01-01 01:00:00.000000000 +0100
  7751. +++ linux-2.6.17.14.rfs/fs/rfs/Makefile 2008-06-19 04:02:10.000000000 +0200
  7752. @@ -0,0 +1,32 @@
  7753. +#
  7754. +# Makefile for the linux rfs-filesystem
  7755. +#
  7756. +
  7757. +ifeq ($(CONFIG_GCOV_PROFILE),y)
  7758. +ifeq ($(PATCHLEVEL),4)
  7759. +include Makefile.gcov
  7760. +else
  7761. +include $(srctree)/fs/rfs/Makefile.gcov
  7762. +endif
  7763. +# In profile mode, we always turn on log replay test without power-off
  7764. +EXTRA_CFLAGS += -D_RFS_INTERNAL_RECOVERY_TEST
  7765. +endif
  7766. +
  7767. +#
  7768. +# RFS internal configurations
  7769. +#
  7770. +
  7771. +# trace writing block
  7772. +#EXTRA_CFLAGS += -D_RFS_INTERNAL_STAT_BH
  7773. +
  7774. +# Flush user cache
  7775. +#EXTRA_CFLAGS += -D_RFS_INTERNAL_FLUSH_CACHE
  7776. +
  7777. +# Sanity check
  7778. +#EXTRA_CFLAGS += -D_RFS_INTERNAL_SANITY_CHECK
  7779. +
  7780. +ifeq ($(PATCHLEVEL),4)
  7781. +include Makefile.24
  7782. +else
  7783. +include $(srctree)/fs/rfs/Makefile.26
  7784. +endif
  7785. diff -NurbB linux-2.6.17.14.orig/fs/rfs/Makefile.24 linux-2.6.17.14.rfs/fs/rfs/Makefile.24
  7786. --- linux-2.6.17.14.orig/fs/rfs/Makefile.24 1970-01-01 01:00:00.000000000 +0100
  7787. +++ linux-2.6.17.14.rfs/fs/rfs/Makefile.24 2008-06-19 04:02:09.000000000 +0200
  7788. @@ -0,0 +1,14 @@
  7789. +#
  7790. +# Makefile for the linux rfs-filesystem (kernel 2.4)
  7791. +#
  7792. +
  7793. +O_TARGET := rfs.o
  7794. +
  7795. +obj-y += cluster.o code_convert.o dos.o
  7796. +obj-y += dir.o file.o inode.o namei.o super.o
  7797. +obj-y += log.o log_replay.o
  7798. +obj-y += rfs_24.o
  7799. +
  7800. +obj-m += $(O_TARGET)
  7801. +
  7802. +include $(TOPDIR)/Rules.make
  7803. diff -NurbB linux-2.6.17.14.orig/fs/rfs/Makefile.26 linux-2.6.17.14.rfs/fs/rfs/Makefile.26
  7804. --- linux-2.6.17.14.orig/fs/rfs/Makefile.26 1970-01-01 01:00:00.000000000 +0100
  7805. +++ linux-2.6.17.14.rfs/fs/rfs/Makefile.26 2008-06-19 04:02:09.000000000 +0200
  7806. @@ -0,0 +1,10 @@
  7807. +#
  7808. +# Makefile for the linux rfs-filesystem (kernel 2.6)
  7809. +#
  7810. +
  7811. +obj-$(CONFIG_RFS_FS) += rfs.o
  7812. +
  7813. +rfs-y += cluster.o code_convert.o dos.o
  7814. +rfs-y += dir.o file.o inode.o namei.o super.o
  7815. +rfs-y += log.o log_replay.o
  7816. +rfs-y += rfs_26.o
  7817. diff -NurbB linux-2.6.17.14.orig/fs/rfs/Makefile.gcov linux-2.6.17.14.rfs/fs/rfs/Makefile.gcov
  7818. --- linux-2.6.17.14.orig/fs/rfs/Makefile.gcov 1970-01-01 01:00:00.000000000 +0100
  7819. +++ linux-2.6.17.14.rfs/fs/rfs/Makefile.gcov 2008-06-19 04:02:09.000000000 +0200
  7820. @@ -0,0 +1,17 @@
  7821. +#
  7822. +# Makefile for the linux rfs-filesystem for gcov
  7823. +#
  7824. +
  7825. +CFLAGS_cluster.o += $(GCOV_FLAGS)
  7826. +CFLAGS_code_convert.o += $(GCOV_FLAGS)
  7827. +CFLAGS_dir.o += $(GCOV_FLAGS)
  7828. +CFLAGS_dos.o += $(GCOV_FLAGS)
  7829. +CFLAGS_file.o += $(GCOV_FLAGS)
  7830. +CFLAGS_inode.o += $(GCOV_FLAGS)
  7831. +CFLAGS_log.o += $(GCOV_FLAGS)
  7832. +CFLAGS_log_replay.o += $(GCOV_FLAGS)
  7833. +CFLAGS_namei.o += $(GCOV_FLAGS)
  7834. +CFLAGS_rfs_24.o += $(GCOV_FLAGS)
  7835. +CFLAGS_rfs_26.o += $(GCOV_FLAGS)
  7836. +CFLAGS_super.o += $(GCOV_FLAGS)
  7837. +CC = $(CROSS_COMPILE)gcc
  7838. diff -NurbB linux-2.6.17.14.orig/fs/rfs/namei.c linux-2.6.17.14.rfs/fs/rfs/namei.c
  7839. --- linux-2.6.17.14.orig/fs/rfs/namei.c 1970-01-01 01:00:00.000000000 +0100
  7840. +++ linux-2.6.17.14.rfs/fs/rfs/namei.c 2008-06-19 04:02:09.000000000 +0200
  7841. @@ -0,0 +1,1093 @@
  7842. +/**
  7843. + * @file fs/rfs/namei.c
  7844. + * @brief Here is adaptation layer between the VFS and RFS filesystem for inode ops
  7845. + *
  7846. + *---------------------------------------------------------------------------*
  7847. + * *
  7848. + * COPYRIGHT 2003-2007 SAMSUNG ELECTRONICS CO., LTD. *
  7849. + * ALL RIGHTS RESERVED *
  7850. + * *
  7851. + * Permission is hereby granted to licensees of Samsung Electronics *
  7852. + * Co., Ltd. products to use or abstract this computer program only in *
  7853. + * accordance with the terms of the NAND FLASH MEMORY SOFTWARE LICENSE *
  7854. + * AGREEMENT for the sole purpose of implementing a product based on *
  7855. + * Samsung Electronics Co., Ltd. products. No other rights to reproduce, *
  7856. + * use, or disseminate this computer program, whether in part or in *
  7857. + * whole, are granted. *
  7858. + * *
  7859. + * Samsung Electronics Co., Ltd. makes no representation or warranties *
  7860. + * with respect to the performance of this computer program, and *
  7861. + * specifically disclaims any responsibility for any damages, *
  7862. + * special or consequential, connected with the use of this program. *
  7863. + * *
  7864. + *---------------------------------------------------------------------------*
  7865. + *
  7866. + */
  7867. +
  7868. +#include <linux/fs.h>
  7869. +#include <linux/rfs_fs.h>
  7870. +#include <linux/sched.h>
  7871. +
  7872. +#include "rfs.h"
  7873. +#include "log.h"
  7874. +
  7875. +#define SLASH '/'
  7876. +
  7877. +#define ROOT_MTIME(sb) (sb->s_root->d_inode->i_mtime)
  7878. +
  7879. +/* structure for rename */
  7880. +struct rename_info {
  7881. + struct inode *old_dir;
  7882. + struct inode *old_inode;
  7883. + struct inode *new_dir;
  7884. + unsigned int *new_index;
  7885. + const char *new_name;
  7886. +};
  7887. +
  7888. +/**
  7889. + * Function extending a directory on request of saving larger entries that left entries.
  7890. + * @param dir inode corresponding to extending directory
  7891. + * @param start_clu return value to contain a start cluster value when this function is used to create new directory
  7892. + * @return zero on success, if not, negative error code.
  7893. + *
  7894. + * extend_dir invokes alloc_cluster in it, and assumes that alloc_cluster
  7895. + * takes care of not only allocating new cluster but also updating FAT table.
  7896. + * In addition, this function is used to create new directory.
  7897. + */
  7898. +static struct buffer_head *extend_dir(struct inode * dir, unsigned int *start_clu) {
  7899. +
  7900. + struct super_block *sb = dir->i_sb;
  7901. + struct buffer_head *bh, *ret = NULL;
  7902. + unsigned int start_block, last_block, cur_block;
  7903. + unsigned int new_clu;
  7904. + int err;
  7905. +
  7906. + if ((RFS_I(dir)->start_clu == RFS_SB(sb)->root_clu)
  7907. + && !IS_FAT32(RFS_SB(sb)))
  7908. + return ERR_PTR(-ENOSPC);
  7909. +
  7910. + if ((dir->i_size + RFS_SB(sb)->cluster_size) >
  7911. + (MAX_DIR_DENTRY << DENTRY_SIZE_BITS))
  7912. + return ERR_PTR(-ENOSPC);
  7913. +
  7914. + /* alloc new cluster */
  7915. + err = alloc_cluster(dir, &new_clu);
  7916. + if (err)
  7917. + return ERR_PTR(err);
  7918. +
  7919. + if (start_clu)
  7920. + *start_clu = new_clu;
  7921. +
  7922. + /* reset new cluster with zero to initalize directory entry */
  7923. + start_block = START_BLOCK(new_clu, sb);
  7924. + last_block = start_block + RFS_SB(sb)->blks_per_clu;
  7925. + cur_block = start_block;
  7926. + do {
  7927. + if ((bh = sb_getblk(sb, cur_block))) {
  7928. + memset(bh->b_data, 0x00 , sb->s_blocksize);
  7929. +
  7930. +#ifdef RFS_FOR_2_6
  7931. + set_buffer_uptodate(bh);
  7932. +#else
  7933. + mark_buffer_uptodate(bh, 1);
  7934. +#endif
  7935. + rfs_mark_buffer_dirty(bh, sb);
  7936. + if (!ret)
  7937. + ret = bh;
  7938. + else
  7939. + brelse(bh);
  7940. + }
  7941. + } while (++cur_block < last_block);
  7942. +
  7943. + if (!ret) /* I/O error */
  7944. + return ERR_PTR(-EIO);
  7945. +
  7946. + /* new inode is also initialized by 0 */
  7947. + dir->i_size += RFS_SB(sb)->cluster_size;
  7948. + RFS_I(dir)->mmu_private += RFS_SB(sb)->cluster_size;
  7949. +
  7950. + return ret;
  7951. +}
  7952. +
  7953. +/**
  7954. + * allocate a cluster for new directory
  7955. + * @param inode new inode
  7956. + * @param start_clu allocated cluster to inode
  7957. + * @return zero on success, or errno
  7958. + */
  7959. +static inline int init_dir_clu(struct inode *inode, unsigned int *start_clu)
  7960. +{
  7961. + struct buffer_head *bh = NULL;
  7962. + int ret;
  7963. +
  7964. + /* CLU_TAIL is temporary value for cluster allocation */
  7965. + RFS_I(inode)->start_clu = CLU_TAIL;
  7966. + RFS_I(inode)->mmu_private = 0; /* set 0 for extend_dir() */
  7967. +
  7968. + /*
  7969. + * RFS-log : setting CLU_TAIL to inode's p_start_clu informs
  7970. + * that inode does not have a entry yet
  7971. + */
  7972. + RFS_I(inode)->p_start_clu = CLU_TAIL;
  7973. + bh = extend_dir(inode, start_clu);
  7974. + if (IS_ERR(bh))
  7975. + return PTR_ERR(bh);
  7976. +
  7977. + ret = init_new_dir(inode);
  7978. +
  7979. + brelse(bh);
  7980. + return ret;
  7981. +}
  7982. +
  7983. +/**
  7984. + * Function to find proper postion where new entry is stored
  7985. + * @param dir inode relating to parent directory
  7986. + * @param slots the number of entries to be saved
  7987. + * @param bh buffer head containing directory entry
  7988. + * @return a offset of empty slot of a current directory on sucess, negative value on falure.
  7989. + *
  7990. + * This function is invoked by upper functions, upper functions are different
  7991. + * according the FAT type of current system.
  7992. + */
  7993. +static int find_empty_entry (struct inode *dir, int slots, struct buffer_head **bh) {
  7994. +
  7995. + struct super_block *sb = dir->i_sb;
  7996. + struct buffer_head *new_bh;
  7997. + struct rfs_dir_entry *ep;
  7998. + unsigned int cpos = 0, free = 0;
  7999. + int nr_clus = 0;
  8000. +
  8001. + while (1) {
  8002. + ep = get_entry(dir, cpos, bh);
  8003. + if (IS_ERR(ep)) {
  8004. + if (PTR_ERR(ep) == -EFAULT)
  8005. + break;
  8006. + else
  8007. + return PTR_ERR(ep);
  8008. + }
  8009. +
  8010. + if (IS_FREE(ep->name)) {
  8011. + if (++free == slots)
  8012. + return cpos;
  8013. + } else {
  8014. + free = 0;
  8015. + }
  8016. +
  8017. + cpos++;
  8018. + }
  8019. +
  8020. + /* If fail to find requested slots, decide whether to extend directory */
  8021. + if ((RFS_I(dir)->start_clu == RFS_SB(sb)->root_clu) &&
  8022. + (!IS_FAT32(RFS_SB(sb)))) {
  8023. + return -ENOSPC;
  8024. + }
  8025. +
  8026. + /* calculate the number of cluster */
  8027. + nr_clus = (slots - free +
  8028. + (RFS_SB(sb)->cluster_size >> DENTRY_SIZE_BITS) - 1) /
  8029. + (RFS_SB(sb)->cluster_size >> DENTRY_SIZE_BITS);
  8030. + if (nr_clus > GET_FREE_CLUS(RFS_SB(sb)))
  8031. + return -ENOSPC;
  8032. +
  8033. + /* extend entry */
  8034. + while (nr_clus-- > 0) {
  8035. + new_bh = extend_dir(dir, NULL);
  8036. + if (IS_ERR(new_bh))
  8037. + return PTR_ERR(new_bh);
  8038. + }
  8039. +
  8040. + while (1) {
  8041. + ep = get_entry(dir, cpos, &new_bh);
  8042. + if (IS_ERR(ep)) {
  8043. + if (PTR_ERR(ep) == -EFAULT)
  8044. + return -ENOSPC;
  8045. + else
  8046. + return PTR_ERR(ep);
  8047. + }
  8048. + if (++free == slots)
  8049. + break;
  8050. + cpos++;
  8051. + }
  8052. +
  8053. + *bh = new_bh;
  8054. + /* return accumulated offset regardless of cluster */
  8055. + return cpos;
  8056. +}
  8057. +
  8058. +#ifndef CONFIG_RFS_VFAT
  8059. +/**
  8060. + * compare two dos names
  8061. + * @param dentry dentry to be computed
  8062. + * @param a file name cached in dentry cache
  8063. + * @param b file name to be compared for corresponding dentry
  8064. + * @return return 0 on success, errno on failure
  8065. + *
  8066. + * If either of the names are invalid, do the standard name comparison
  8067. + */
  8068. +
  8069. +static int rfs_dentry_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b)
  8070. +{
  8071. + u8 a_dosname[DOS_NAME_LENGTH], b_dosname[DOS_NAME_LENGTH];
  8072. + char valid_name[NAME_MAX + 1];
  8073. + int err = 0;
  8074. +
  8075. + if (a->len > NAME_MAX || b->len > NAME_MAX) /* out-of-range input */
  8076. + return -EINVAL;
  8077. +
  8078. + memcpy(valid_name, a->name, a->len);
  8079. + valid_name[a->len] = '\0';
  8080. + err = convert_cstring_to_dosname(a_dosname, valid_name, NULL, FALSE);
  8081. + if (err < 0)
  8082. + goto out;
  8083. +
  8084. + memcpy(valid_name, b->name, b->len);
  8085. + valid_name[b->len] = '\0';
  8086. + err = convert_cstring_to_dosname(b_dosname, valid_name, NULL, FALSE);
  8087. + if (err < 0)
  8088. + goto out;
  8089. + err = memcmp(a_dosname, b_dosname, DOS_NAME_LENGTH);
  8090. +
  8091. +out:
  8092. + return err;
  8093. +}
  8094. +
  8095. +/**
  8096. + * compute the hash for the dos name corresponding to the dentry
  8097. + * @param dentry dentry to be computed
  8098. + * @param qstr parameter to contain resulting hash value
  8099. + * @return return 0
  8100. + */
  8101. +static int rfs_dentry_hash(struct dentry *dentry, struct qstr *qstr)
  8102. +{
  8103. + unsigned char hash_name[DOS_NAME_LENGTH];
  8104. + char valid_name[NAME_MAX + 1];
  8105. + int err;
  8106. +
  8107. + if (qstr->len > NAME_MAX) /* out-of-range input */
  8108. + return 0;
  8109. +
  8110. + memcpy(valid_name, qstr->name, qstr->len);
  8111. + valid_name[qstr->len] = '\0';
  8112. + err = convert_cstring_to_dosname(hash_name, valid_name, NULL, FALSE);
  8113. + if (!err)
  8114. + qstr->hash = full_name_hash(hash_name, DOS_NAME_LENGTH);
  8115. +
  8116. + return 0;
  8117. +}
  8118. +
  8119. +struct dentry_operations rfs_dentry_operations = {
  8120. + .d_hash = rfs_dentry_hash,
  8121. + .d_compare = rfs_dentry_cmp,
  8122. +};
  8123. +
  8124. +/**
  8125. + * create a dir entry and fill it
  8126. + * @param dir parent dir inode
  8127. + * @param inode inode of new dir entry
  8128. + * @param start_clu start cluster number for itself
  8129. + * @param type entry type
  8130. + * @param name object name
  8131. + * @return return index(pointer to save dir entry index) on success, errno on failure
  8132. + */
  8133. +int build_entry_short(struct inode *dir, struct inode *inode, unsigned int start_clu, unsigned int type, const char *name)
  8134. +{
  8135. + struct buffer_head *bh = NULL;
  8136. + struct rfs_dir_entry *ep = NULL;
  8137. + unsigned char dosname[DOS_NAME_LENGTH];
  8138. + unsigned char is_mixed = 0;
  8139. + unsigned int index;
  8140. + int ret = 0;
  8141. +
  8142. + /* convert a cstring into dosname */
  8143. + ret = mk_dosname(dir, name, dosname, &is_mixed, NULL);
  8144. + if (ret < 0)
  8145. + goto out;
  8146. +
  8147. + /* find empty dir entry */
  8148. + index = find_empty_entry(dir, 1, &bh);
  8149. + if ((int) index < 0) {
  8150. + ret = index;
  8151. + goto out;
  8152. + }
  8153. +
  8154. + /* allocate a new cluster for directory */
  8155. + if (type == TYPE_DIR && inode)
  8156. + if ((ret = init_dir_clu(inode, &start_clu)) < 0)
  8157. + goto out;
  8158. +
  8159. + ret = index;
  8160. + /* get dir entry pointer */
  8161. + ep = get_entry(dir, index, &bh);
  8162. + if (IS_ERR(ep)) {
  8163. + ret = PTR_ERR(ep);
  8164. + goto out;
  8165. + }
  8166. +
  8167. + /* RFS-log sub trans */
  8168. + if (rfs_log_build_entry(dir->i_sb, RFS_I(dir)->start_clu, index, 1)) {
  8169. + ret = -EIO;
  8170. + goto out;
  8171. + }
  8172. +
  8173. + /* init dir entry */
  8174. + init_dir_entry(dir, ep, type, start_clu, dosname, &is_mixed);
  8175. +
  8176. + rfs_mark_buffer_dirty(bh, dir->i_sb);
  8177. +
  8178. +out:
  8179. + brelse(bh);
  8180. + return ret;
  8181. +}
  8182. +
  8183. +#else /* CONFIG_RFS_VFAT */
  8184. +
  8185. +/**
  8186. + * create a dir entry and extend entries
  8187. + * @param dir parent dir inode
  8188. + * @param inode inode of new dir entry
  8189. + * @param start_clu start cluster number for itself
  8190. + * @param type entry type
  8191. + * @param name object name
  8192. + * @return return index(pointer to save dir entry index) on success, errno on failure
  8193. + */
  8194. +int build_entry_long(struct inode *dir, struct inode *inode, unsigned int start_clu, unsigned int type, const char *name)
  8195. +{
  8196. + struct buffer_head *bh = NULL;
  8197. + struct rfs_dir_entry *ep = NULL, *tmp_ep = NULL;
  8198. + struct rfs_ext_entry *extp = NULL;
  8199. + unsigned char checksum;
  8200. + unsigned short uname[UNICODE_NAME_LENGTH];
  8201. + unsigned char dosname[DOS_NAME_LENGTH];
  8202. + unsigned int num_entries, i;
  8203. + unsigned char is_mixed = 0;
  8204. + unsigned int index;
  8205. + int ret = 0;
  8206. +
  8207. + /*
  8208. + * convert a cstring into dosname &
  8209. + * return the count of needed extend slots
  8210. + */
  8211. + if ((ret = mk_dosname(dir, name, dosname, &is_mixed, uname)) < 0)
  8212. + return ret;
  8213. +
  8214. + /* ret has the number of the extend slot */
  8215. + num_entries = ret + 1;
  8216. +
  8217. + /* find empty dir entry */
  8218. + index = find_empty_entry(dir, num_entries, &bh);
  8219. + if ((int) index < 0) {
  8220. + ret = index;
  8221. + goto out;
  8222. + }
  8223. +
  8224. + /* allocate a new cluster for directory */
  8225. + if (type == TYPE_DIR && inode)
  8226. + if ((ret = init_dir_clu(inode, &start_clu)) < 0)
  8227. + goto out;
  8228. +
  8229. + ret = index;
  8230. + /* get dir entry pointer */
  8231. + ep = get_entry(dir, index, &bh);
  8232. + if (IS_ERR(ep)) {
  8233. + ret = PTR_ERR(ep);
  8234. + goto out;
  8235. + }
  8236. +
  8237. + /* RFS-log sub trans */
  8238. + if (rfs_log_build_entry(dir->i_sb, RFS_I(dir)->start_clu, index,
  8239. + num_entries)) {
  8240. + ret = -EIO;
  8241. + goto out;
  8242. + }
  8243. +
  8244. + /* init dir entry */
  8245. + init_dir_entry(dir, ep, type, start_clu, dosname, &is_mixed);
  8246. +
  8247. + rfs_mark_buffer_dirty(bh, dir->i_sb);
  8248. +
  8249. + /* only have dos entry */
  8250. + if (num_entries == 1)
  8251. + goto out;
  8252. +
  8253. + checksum = calc_checksum(dosname);
  8254. +
  8255. + /* init extend entries */
  8256. + for (i = 1; i < num_entries; i++) {
  8257. + tmp_ep = get_entry(dir, index - i, &bh);
  8258. + if (IS_ERR(tmp_ep)) {
  8259. + ret = PTR_ERR(ep);
  8260. + goto out;
  8261. + }
  8262. + extp = (struct rfs_ext_entry *)tmp_ep;
  8263. + if (init_ext_entry(extp, TYPE_EXTEND,
  8264. + ((i == (num_entries - 1))? i + EXT_END_MARK: i),
  8265. + &(uname[EXT_UNAME_LENGTH * (i - 1)]),
  8266. + checksum) < 0) { /* out-of-range input */
  8267. + ret = -EIO;
  8268. + goto out;
  8269. + }
  8270. +
  8271. + rfs_mark_buffer_dirty(bh, dir->i_sb);
  8272. + }
  8273. +
  8274. +out:
  8275. + brelse(bh);
  8276. +
  8277. + return ret;
  8278. +}
  8279. +
  8280. +#endif /* !CONFIG_RFS_VFAT */
  8281. +
  8282. +/**
  8283. + * find inode for dir entry and return
  8284. + * @param sb super block
  8285. + * @param ino inode number of dir entry
  8286. + * @param p_start_clu parent's start cluster
  8287. + * @param index dir entry's offset in parent dir
  8288. + * @param ep dir entry
  8289. + * @return inode of dir entry on success or errno on failure
  8290. + */
  8291. +static inline struct inode *rfs_iget(struct super_block *sb, unsigned long ino, unsigned int p_start_clu, unsigned int index, struct rfs_dir_entry *ep)
  8292. +{
  8293. +#ifndef CONFIG_RFS_IGET4
  8294. + struct inode *inode = iget_locked(sb, ino);
  8295. +
  8296. + if (inode && (inode->i_state & I_NEW)) {
  8297. + fill_inode(inode, ep, p_start_clu, index);
  8298. + unlock_new_inode(inode);
  8299. + }
  8300. +#else
  8301. + struct inode *inode;
  8302. + struct rfs_iget4_args args;
  8303. +
  8304. + args.ep = ep;
  8305. + args.p_start_clu = p_start_clu;
  8306. + args.index = index;
  8307. +
  8308. + /*
  8309. + * Some kernel version(under Linux kernel version 2.4.25) does not
  8310. + * support iget_locked.
  8311. + */
  8312. + inode = iget4(sb, ino, NULL, (void *) (&args));
  8313. +#endif
  8314. +
  8315. + return inode;
  8316. +}
  8317. +
  8318. +/**
  8319. + * find dir entry for inode in parent dir and return a dir entry & entry index
  8320. + * @param dir parent dir inode
  8321. + * @param inode inode for itself
  8322. + * @param bh buffer head included dir entry for inode
  8323. + * @param name object name to search
  8324. + * @param type dir entry type
  8325. + * @return return dir entry on success, errno on failure
  8326. + */
  8327. +static struct rfs_dir_entry *search_entry(struct inode *dir, struct inode *inode, struct buffer_head **bh, const char *name, unsigned char type)
  8328. +{
  8329. + if (!inode) /* out-of-range input */
  8330. + return ERR_PTR(-EINVAL);
  8331. +
  8332. + CHECK_RFS_INODE(inode, ERR_PTR(-EINVAL));
  8333. +
  8334. + return get_entry(dir, RFS_I(inode)->index, bh);
  8335. +}
  8336. +
  8337. +/**
  8338. + * lookup inode associated with dentry
  8339. + * @param dir inode of parent directory
  8340. + * @param dentry dentry for itself
  8341. + * @param nd namei data structure
  8342. + * @return return dentry object on success, errno on failure
  8343. + *
  8344. + * if inode doesn't exist, allocate new inode, fill it, and associated with dentry
  8345. + */
  8346. +#ifdef RFS_FOR_2_6
  8347. +static struct dentry *rfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
  8348. +#else
  8349. +static struct dentry *rfs_lookup(struct inode *dir, struct dentry *dentry)
  8350. +#endif
  8351. +{
  8352. + struct inode *inode = NULL;
  8353. + struct buffer_head *bh = NULL;
  8354. + struct rfs_dir_entry *ep = NULL;
  8355. + unsigned int index;
  8356. + unsigned long ino;
  8357. + int ret = 0;
  8358. +
  8359. + /* check the name length */
  8360. + if (dentry->d_name.len > NAME_MAX)
  8361. + return ERR_PTR(-ENAMETOOLONG);
  8362. +
  8363. +#ifndef CONFIG_RFS_VFAT
  8364. + dentry->d_op = &rfs_dentry_operations;
  8365. +#endif
  8366. +
  8367. + /* find dir entry */
  8368. + ret = find_entry(dir, dentry->d_name.name, &bh, TYPE_ALL);
  8369. + if (ret < 0) {
  8370. + if (ret == -ENOENT)
  8371. + goto add;
  8372. + if ((ret != -EINVAL) && (ret != -ENAMETOOLONG))
  8373. + ret = -EIO;
  8374. + goto out;
  8375. + }
  8376. + index = ret;
  8377. +
  8378. + ep = get_entry(dir, index, &bh);
  8379. + if (IS_ERR(ep)) {
  8380. + ret = -EIO;
  8381. + goto out;
  8382. + }
  8383. +
  8384. + /* get unique inode number */
  8385. + ret = rfs_iunique(dir, index, &ino);
  8386. + if (ret)
  8387. + goto out;
  8388. +
  8389. + inode = rfs_iget(dir->i_sb, ino, RFS_I(dir)->start_clu, index, ep);
  8390. + if (!inode) {
  8391. + ret = -EACCES;
  8392. + goto out;
  8393. + }
  8394. +
  8395. +#ifdef CONFIG_RFS_VFAT
  8396. + do {
  8397. + struct dentry *alias = NULL;
  8398. +
  8399. + alias = d_find_alias(inode);
  8400. + if (alias) {
  8401. + if (d_invalidate(alias) == 0) {
  8402. + dput(alias);
  8403. + } else {
  8404. + iput(inode);
  8405. + brelse(bh);
  8406. + return alias;
  8407. + }
  8408. + }
  8409. + } while (0);
  8410. +#endif
  8411. +add:
  8412. + brelse(bh);
  8413. +#ifdef RFS_FOR_2_6
  8414. + return d_splice_alias(inode, dentry);
  8415. +#else
  8416. + d_add(dentry, inode);
  8417. + return NULL;
  8418. +#endif
  8419. +out:
  8420. + brelse(bh);
  8421. + return ERR_PTR(ret);
  8422. +}
  8423. +
  8424. +/**
  8425. + * create a new file
  8426. + * @param dir inode of parent directory
  8427. + * @param dentry dentry corresponding with a file will be created
  8428. + * @param mode mode
  8429. + * @param nd namei data structure
  8430. + * @return return 0 on success, errno on failure
  8431. + */
  8432. +#ifdef RFS_FOR_2_6
  8433. +static int rfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
  8434. +#else
  8435. +static int rfs_create(struct inode *dir, struct dentry *dentry, int mode)
  8436. +#endif
  8437. +{
  8438. + struct inode *inode = NULL;
  8439. + int ret;
  8440. +
  8441. + /* check the validity */
  8442. + if (IS_RDONLY(dir))
  8443. + return -EROFS;
  8444. +
  8445. + if (rfs_log_start(dir->i_sb, RFS_LOG_CREATE, dir))
  8446. + return -EIO;
  8447. +
  8448. + /* create a new inode */
  8449. + inode = rfs_new_inode(dir, dentry, TYPE_FILE);
  8450. + if (IS_ERR(inode))
  8451. + ret = PTR_ERR(inode);
  8452. + else
  8453. + ret = 0;
  8454. +
  8455. + /* If failed, RFS-log can't rollback due to media error */
  8456. + if (rfs_log_end(dir->i_sb, ret))
  8457. + return -EIO;
  8458. +
  8459. + if (!ret) /* attach inode to dentry */
  8460. + d_instantiate(dentry, inode);
  8461. + return ret;
  8462. +}
  8463. +
  8464. +/**
  8465. + * check whether a file of inode has start cluster number of RFS reserved files
  8466. + * @param inode inode of checked file
  8467. + * @param name name of checked file
  8468. + * @return return 0 if inode has different start cluster number, else return errno
  8469. + *
  8470. + * special files for fast unlink & logging are reserved files
  8471. + */
  8472. +int check_reserved_files(struct inode *inode, const char *name)
  8473. +{
  8474. + if (inode) {
  8475. + struct super_block *sb = inode->i_sb;
  8476. + unsigned int cluster = RFS_I(inode)->start_clu;
  8477. +
  8478. + if (cluster == RFS_POOL_I(sb)->start_cluster)
  8479. + return -EPERM;
  8480. + if (cluster == RFS_LOG_I(sb)->start_cluster)
  8481. + return -EPERM;
  8482. + } else if (name) {
  8483. + int len = strlen(name);
  8484. +
  8485. + if ((len != RFS_LOG_FILE_LEN) || (len != RFS_POOL_FILE_LEN))
  8486. + return 0;
  8487. +
  8488. + if (!strncmp(name, RFS_LOG_FILE_NAME, RFS_LOG_FILE_LEN))
  8489. + return -EPERM;
  8490. +
  8491. + if (!strncmp(name, RFS_POOL_FILE_NAME, RFS_POOL_FILE_LEN))
  8492. + return -EPERM;
  8493. + }
  8494. +
  8495. + return 0;
  8496. +}
  8497. +
  8498. +/**
  8499. + * remove a file
  8500. + * @param dir parent directory inode
  8501. + * @param dentry dentry corresponding with a file will be removed
  8502. + * @return return 0 on success, errno on failure
  8503. + */
  8504. +static int rfs_unlink(struct inode *dir, struct dentry *dentry)
  8505. +{
  8506. + struct inode *inode = dentry->d_inode;
  8507. + struct buffer_head *bh = NULL;
  8508. + struct rfs_dir_entry *ep = NULL;
  8509. + int ret;
  8510. +
  8511. + /* check the validity */
  8512. + if (IS_RDONLY(dir))
  8513. + return -EROFS;
  8514. +
  8515. + /* check the name length */
  8516. + if (dentry->d_name.len > NAME_MAX)
  8517. + return -ENAMETOOLONG;
  8518. +
  8519. + /* check the system files */
  8520. + if (check_reserved_files(inode, NULL))
  8521. + return -EPERM;
  8522. +
  8523. + /* find dir entry */
  8524. + ep = search_entry(dir, inode, &bh, dentry->d_name.name, TYPE_FILE);
  8525. + if (IS_ERR(ep)) {
  8526. + brelse(bh);
  8527. + return PTR_ERR(ep);
  8528. + }
  8529. +
  8530. + if ((ep->attr & ATTR_READONLY) && (!capable(CAP_SYS_ADMIN))) {
  8531. + brelse(bh);
  8532. + return -EPERM;
  8533. + }
  8534. + brelse(bh);
  8535. +
  8536. + /* RFS-log : start unlink */
  8537. + if (rfs_log_start(dir->i_sb, RFS_LOG_UNLINK, dir))
  8538. + return -EIO;
  8539. +
  8540. + /* remove dir entry and dealloc all clusters for inode allocated */
  8541. + ret = rfs_delete_entry(dir, inode);
  8542. +
  8543. + /* If failed, RFS-log can't rollback due to media error */
  8544. + if (rfs_log_end(dir->i_sb, ret))
  8545. + return -EIO;
  8546. +
  8547. + return ret;
  8548. +}
  8549. +
  8550. +/**
  8551. + * create a new directory
  8552. + * @param dir parent directory inode
  8553. + * @param dentry dentry corresponding with a directory will be created
  8554. + * @param mode mode
  8555. + * @return return 0 on success, errno on failure
  8556. + */
  8557. +static int rfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
  8558. +{
  8559. + struct inode *inode = NULL;
  8560. + int ret;
  8561. +
  8562. + /* check the validity */
  8563. + if (IS_RDONLY(dir))
  8564. + return -EROFS;
  8565. +
  8566. + /* RFS-log : start mkdir */
  8567. + if (rfs_log_start(dir->i_sb, RFS_LOG_CREATE, dir))
  8568. + return -EIO;
  8569. +
  8570. + /* create a new inode */
  8571. + inode = rfs_new_inode(dir, dentry, TYPE_DIR);
  8572. + if (IS_ERR(inode))
  8573. + ret = PTR_ERR(inode);
  8574. + else
  8575. + ret = 0;
  8576. +
  8577. + /* If failed, RFS-log can't rollback due to media error */
  8578. + if (rfs_log_end(dir->i_sb, ret))
  8579. + return -EIO;
  8580. +
  8581. + if (!ret) /* attach inode to dentry */
  8582. + d_instantiate(dentry, inode);
  8583. +
  8584. + return ret;
  8585. +}
  8586. +
  8587. +/**
  8588. + * remove a directory
  8589. + * @param dir parent directory inode
  8590. + * @param dentry dentry corresponding with a directory will be removed
  8591. + * @return return 0 on success, errno on failure
  8592. + */
  8593. +static int rfs_rmdir(struct inode *dir, struct dentry *dentry)
  8594. +{
  8595. + struct inode *inode = dentry->d_inode;
  8596. + struct buffer_head *bh = NULL;
  8597. + struct rfs_dir_entry *ep = NULL;
  8598. + int ret;
  8599. +
  8600. + /* check the validity */
  8601. + if (IS_RDONLY(dir))
  8602. + return -EROFS;
  8603. +
  8604. + /* check the name length */
  8605. + if (dentry->d_name.len > NAME_MAX)
  8606. + return -ENAMETOOLONG;
  8607. +
  8608. + /* find dir entry */
  8609. + ep = search_entry(dir, inode, &bh, dentry->d_name.name, TYPE_DIR);
  8610. + if (IS_ERR(ep)) {
  8611. + ret = PTR_ERR(ep);
  8612. + brelse(bh);
  8613. + return ret;
  8614. + }
  8615. + brelse(bh);
  8616. +
  8617. + if (((dir->i_ino == ROOT_INO) && (RFS_I(inode)->index < 0)) ||
  8618. + ((dir->i_ino != ROOT_INO) && (RFS_I(inode)->index < 2)))
  8619. + return -ENOENT;
  8620. +
  8621. + /* check whether directory is empty */
  8622. + ret = is_dir_empty(inode);
  8623. + if (ret)
  8624. + return ret;
  8625. +
  8626. + /* RFS-log : start rmdir */
  8627. + if (rfs_log_start(dir->i_sb, RFS_LOG_UNLINK, dir))
  8628. + return -EIO;
  8629. +
  8630. + /* remove directory */
  8631. + ret = rfs_delete_entry(dir, inode);
  8632. +
  8633. + /* If failed, RFS-log can't rollback due to media error */
  8634. + if (rfs_log_end(dir->i_sb, ret))
  8635. + return -EIO;
  8636. +
  8637. + return ret;
  8638. +}
  8639. +
  8640. +/**
  8641. + * change a directory
  8642. + * @param r_info argument to move
  8643. + * @return return 0 on success, errno on failure
  8644. + */
  8645. +static int move_to_dir(struct rename_info *r_info)
  8646. +{
  8647. + struct super_block *sb = r_info->old_dir->i_sb;
  8648. + unsigned int old_index = RFS_I(r_info->old_inode)->index;
  8649. + unsigned int *new_index = r_info->new_index;
  8650. + struct buffer_head *old_bh = NULL;
  8651. + struct buffer_head *new_bh = NULL;
  8652. + struct rfs_dir_entry *old_ep = NULL;
  8653. + struct rfs_dir_entry *new_ep = NULL;
  8654. + unsigned int old_type;
  8655. + int ret = 0;
  8656. +
  8657. + old_ep = get_entry(r_info->old_dir, old_index, &old_bh);
  8658. + if (IS_ERR(old_ep)) {
  8659. + ret = PTR_ERR(old_ep);
  8660. + goto out;
  8661. + }
  8662. +
  8663. + old_type = entry_type(old_ep);
  8664. + if (old_type == TYPE_DIR || old_type == TYPE_FILE ||
  8665. + old_type == TYPE_SYMLINK)
  8666. + ret = build_entry(r_info->new_dir, NULL, START_CLUSTER(old_ep),
  8667. + old_type, r_info->new_name);
  8668. + else
  8669. + ret = -EINVAL; /* out-of-range input */
  8670. + if (ret < 0)
  8671. + goto out;
  8672. +
  8673. + *new_index = (unsigned int) ret;
  8674. +
  8675. + /* update mtime of new entry */
  8676. + new_ep = get_entry(r_info->new_dir, *new_index, &new_bh);
  8677. + if (IS_ERR(new_ep)) {
  8678. + ret = PTR_ERR(new_ep);
  8679. + goto out;
  8680. + }
  8681. +
  8682. + SET16(new_ep->mtime, GET16(old_ep->mtime));
  8683. + SET16(new_ep->mdate, GET16(old_ep->mdate));
  8684. + SET32(new_ep->size, GET32(old_ep->size));
  8685. +
  8686. + rfs_mark_buffer_dirty(new_bh, sb);
  8687. +
  8688. + if (old_type == TYPE_DIR) {
  8689. + /* change pointer of parent dir */
  8690. + old_ep = get_entry(r_info->old_inode, 1, &old_bh);
  8691. + if (IS_ERR(old_ep)) {
  8692. + ret = PTR_ERR(old_ep);
  8693. + goto out;
  8694. + }
  8695. + if (ROOT_INO != r_info->new_dir->i_ino) {
  8696. +
  8697. + new_ep = get_entry(r_info->new_dir, 0, &new_bh);
  8698. + if (IS_ERR(new_ep)) {
  8699. + ret = PTR_ERR(new_ep);
  8700. + goto out;
  8701. + }
  8702. + memcpy(old_ep, new_ep, sizeof(struct rfs_dir_entry));
  8703. + memcpy(old_ep->name, DOTDOT, DOS_NAME_LENGTH);
  8704. + } else {
  8705. + SET16(old_ep->start_clu_lo, RFS_SB(sb)->root_clu);
  8706. + SET16(old_ep->start_clu_hi, RFS_SB(sb)->root_clu >> 16);
  8707. + set_entry_time(old_ep, ROOT_MTIME(sb));
  8708. + }
  8709. + rfs_mark_buffer_dirty(old_bh, sb);
  8710. + }
  8711. +
  8712. + /* delete old entry */
  8713. + ret = remove_entry(r_info->old_dir, old_index, &old_bh);
  8714. +out:
  8715. + brelse(new_bh);
  8716. + brelse(old_bh);
  8717. + return ret;
  8718. +}
  8719. +
  8720. +/**
  8721. + * change name or location of a file or directory
  8722. + * @param old_dir old parent directory
  8723. + * @param old_dentry old dentry
  8724. + * @param new_dir new parent directory
  8725. + * @param new_dentry new dentry
  8726. + * @return return 0 on success, errno on failure
  8727. + */
  8728. +static int rfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry)
  8729. +{
  8730. + struct inode *old_inode = old_dentry->d_inode;
  8731. + struct inode *new_inode = new_dentry->d_inode;
  8732. + struct qstr *old_qname = &old_dentry->d_name;
  8733. + struct qstr *new_qname = &new_dentry->d_name;
  8734. + struct buffer_head *old_bh = NULL, *new_bh = NULL;
  8735. + struct rfs_dir_entry *old_ep = NULL, *new_ep = NULL;
  8736. + struct rename_info r_info;
  8737. + unsigned long new_ino;
  8738. + unsigned int new_index = 0;
  8739. + int is_exist = FALSE;
  8740. + int ret;
  8741. +
  8742. + /* check the validity */
  8743. + if (IS_RDONLY(old_dir))
  8744. + return -EROFS;
  8745. +
  8746. + /* check the name length */
  8747. + if ((old_qname->len > NAME_MAX) ||
  8748. + (new_qname->len > NAME_MAX))
  8749. + return -ENAMETOOLONG;
  8750. +
  8751. + /* find old dir entry */
  8752. + old_ep = search_entry(old_dir, old_inode, &old_bh,
  8753. + old_qname->name, TYPE_ALL);
  8754. + if (IS_ERR(old_ep)) {
  8755. + ret = PTR_ERR(old_ep);
  8756. + brelse(old_bh);
  8757. + return ret;
  8758. + }
  8759. +
  8760. + if (old_ep->attr & ATTR_READONLY) {
  8761. + brelse(old_bh);
  8762. + return -EPERM;
  8763. + }
  8764. +
  8765. + brelse(old_bh);
  8766. +
  8767. + /* check permission */
  8768. + if (check_reserved_files(old_inode, NULL))
  8769. + return -EPERM;
  8770. +
  8771. + /* if new_inode is NULL, compare name */
  8772. + if (check_reserved_files(new_inode, new_qname->name))
  8773. + return -EPERM;
  8774. +
  8775. + if ((old_dir->i_ino != ROOT_INO) && (RFS_I(old_inode)->index < 2))
  8776. + return -EINVAL;
  8777. +
  8778. + /* find new dir entry if exists, remove it */
  8779. + new_ep = search_entry(new_dir, new_inode, &new_bh,
  8780. + new_qname->name, TYPE_ALL);
  8781. + if (!IS_ERR(new_ep)) {
  8782. + if (S_ISDIR(new_inode->i_mode)) {
  8783. + ret = is_dir_empty(new_inode);
  8784. + if (ret) {
  8785. + brelse(new_bh);
  8786. + return ret;
  8787. + }
  8788. + }
  8789. + /* mark is_exist for later deletion */
  8790. + is_exist = TRUE;
  8791. + }
  8792. + brelse(new_bh);
  8793. +
  8794. + /* fill rename info */
  8795. + r_info.old_dir = old_dir;
  8796. + r_info.old_inode = old_inode;
  8797. + r_info.new_dir = new_dir;
  8798. + r_info.new_index = &new_index;
  8799. + r_info.new_name = new_qname->name;
  8800. +
  8801. + /* RFS-log : start rename */
  8802. + if (rfs_log_start(old_dir->i_sb, RFS_LOG_RENAME, old_inode))
  8803. + return -EIO;
  8804. +
  8805. + ret = move_to_dir(&r_info);
  8806. + if (ret)
  8807. + goto end_log;
  8808. +
  8809. + /* delete destination, if exist */
  8810. + if (is_exist == TRUE) {
  8811. + ret = rfs_delete_entry(new_dir, new_inode);
  8812. + if (ret)
  8813. + goto end_log;
  8814. + }
  8815. +
  8816. + /* update inode fields */
  8817. + ret = rfs_iunique(new_dir, new_index, &new_ino);
  8818. + if (ret)
  8819. + goto end_log;
  8820. +
  8821. + remove_inode_hash(old_inode);
  8822. +
  8823. + /*
  8824. + * don't change the order of statements for
  8825. + * synchronization with rfs_sync_inode() in locked area
  8826. + */
  8827. + spin_lock(&RFS_I(old_inode)->write_lock);
  8828. + old_inode->i_ino = new_ino;
  8829. + RFS_I(old_inode)->p_start_clu = RFS_I(new_dir)->start_clu;
  8830. + RFS_I(old_inode)->index = new_index;
  8831. + spin_unlock(&RFS_I(old_inode)->write_lock);
  8832. +
  8833. + insert_inode_hash(old_inode);
  8834. + /*
  8835. + * we already reigsterd the inode to the transaction
  8836. + * in the above move_to_dir()
  8837. + */
  8838. + mark_inode_dirty(old_inode);
  8839. +
  8840. + if (old_dir != new_dir) {
  8841. + if (S_ISDIR(old_inode->i_mode)) {
  8842. + old_dir->i_nlink--;
  8843. + new_dir->i_nlink++;
  8844. + }
  8845. + new_dir->i_mtime = CURRENT_TIME;
  8846. + rfs_mark_inode_dirty(new_dir);
  8847. + }
  8848. +
  8849. + old_dir->i_mtime = CURRENT_TIME;
  8850. + rfs_mark_inode_dirty(old_dir);
  8851. +
  8852. +end_log:
  8853. + /* If failed, RFS-log can't rollback due to media error */
  8854. + if (rfs_log_end(old_dir->i_sb, ret))
  8855. + return -EIO;
  8856. +
  8857. + return ret;
  8858. +}
  8859. +
  8860. +/**
  8861. + * generate a symlink file
  8862. + * @param dir parent directory inode
  8863. + * @param dentry dentry corresponding with new symlink file
  8864. + * @param target full link of target
  8865. + * @return return 0 on success, errno on failure
  8866. + */
  8867. +static int rfs_symlink(struct inode *dir, struct dentry *dentry, const char *target)
  8868. +{
  8869. + struct inode *inode = NULL;
  8870. + int len = strlen(target) + 1;
  8871. + int ret;
  8872. + const char *target_last;
  8873. +
  8874. + /* check the validity */
  8875. + if (IS_RDONLY(dir))
  8876. + return -EROFS;
  8877. +
  8878. + /* check the system files */
  8879. + target_last = strrchr(target, SLASH);
  8880. + if (target_last == NULL)
  8881. + target_last = target;
  8882. + else
  8883. + target_last++;
  8884. +
  8885. + if (check_reserved_files(NULL, target_last))
  8886. + return -EPERM;
  8887. +
  8888. + /* RFS-log : start create-symlink */
  8889. + if (rfs_log_start(dir->i_sb, RFS_LOG_SYMLINK, dir))
  8890. + return -EIO;
  8891. +
  8892. + /* create a symlink file */
  8893. + inode = rfs_new_inode(dir, dentry, TYPE_SYMLINK);
  8894. + if (IS_ERR(inode)) {
  8895. + ret = PTR_ERR(inode);
  8896. + goto end_log;
  8897. + }
  8898. +
  8899. +#ifdef RFS_FOR_2_6
  8900. + ret = page_symlink(inode, target, len);
  8901. +#else
  8902. + ret = block_symlink(inode, target, len);
  8903. +#endif
  8904. + if (ret == -ENOSPC) {
  8905. + rfs_delete_entry(dir, inode);
  8906. + iput(inode);
  8907. + }
  8908. +
  8909. +end_log:
  8910. + /* for transaction sync, we remember the inode of symbolic link. */
  8911. + RFS_LOG_I(dir->i_sb)->symlink_inode = (ret) ? NULL : inode;
  8912. +
  8913. + /* If failed, RFS-log can't rollback due to media error */
  8914. + if (rfs_log_end(dir->i_sb, ret))
  8915. + return -EIO;
  8916. +
  8917. + if (!ret) /* attach inode to dentry */
  8918. + d_instantiate(dentry, inode);
  8919. +
  8920. + return ret;
  8921. +}
  8922. +
  8923. +struct inode_operations rfs_dir_inode_operations = {
  8924. + .create = rfs_create,
  8925. + .lookup = rfs_lookup,
  8926. + .unlink = rfs_unlink,
  8927. + .symlink = rfs_symlink,
  8928. + .mkdir = rfs_mkdir,
  8929. + .rmdir = rfs_rmdir,
  8930. + .rename = rfs_rename,
  8931. + .permission = rfs_permission,
  8932. + .setattr = rfs_setattr,
  8933. +};
  8934. +
  8935. diff -NurbB linux-2.6.17.14.orig/fs/rfs/rfs_24.c linux-2.6.17.14.rfs/fs/rfs/rfs_24.c
  8936. --- linux-2.6.17.14.orig/fs/rfs/rfs_24.c 1970-01-01 01:00:00.000000000 +0100
  8937. +++ linux-2.6.17.14.rfs/fs/rfs/rfs_24.c 2008-06-19 04:02:08.000000000 +0200
  8938. @@ -0,0 +1,344 @@
  8939. +/**
  8940. + * @file fs/rfs/rfs_24.c
  8941. + * @brief Kernel version 2.4 specified functions
  8942. + *
  8943. + *---------------------------------------------------------------------------*
  8944. + * *
  8945. + * COPYRIGHT 2003-2007 SAMSUNG ELECTRONICS CO., LTD. *
  8946. + * ALL RIGHTS RESERVED *
  8947. + * *
  8948. + * Permission is hereby granted to licensees of Samsung Electronics *
  8949. + * Co., Ltd. products to use or abstract this computer program only in *
  8950. + * accordance with the terms of the NAND FLASH MEMORY SOFTWARE LICENSE *
  8951. + * AGREEMENT for the sole purpose of implementing a product based on *
  8952. + * Samsung Electronics Co., Ltd. products. No other rights to reproduce, *
  8953. + * use, or disseminate this computer program, whether in part or in *
  8954. + * whole, are granted. *
  8955. + * *
  8956. + * Samsung Electronics Co., Ltd. makes no representation or warranties *
  8957. + * with respect to the performance of this computer program, and *
  8958. + * specifically disclaims any responsibility for any damages, *
  8959. + * special or consequential, connected with the use of this program. *
  8960. + * *
  8961. + *---------------------------------------------------------------------------*
  8962. + *
  8963. + */
  8964. +
  8965. +#include <linux/fs.h>
  8966. +#include <linux/module.h>
  8967. +#include <linux/init.h>
  8968. +#include <linux/iobuf.h>
  8969. +#include <linux/rfs_fs.h>
  8970. +
  8971. +#include "rfs.h"
  8972. +#include "log.h"
  8973. +
  8974. +/**
  8975. + * prepare the blocks and map them
  8976. + * @param inode inode
  8977. + * @param page page pointer
  8978. + * @param from start offset within page
  8979. + * @param to last offset within page
  8980. + * @param get_block get_block funciton
  8981. + * @return return 0 on success, errno on failure
  8982. + */
  8983. +int rfs_block_prepare_write(struct inode * inode, struct page * page, unsigned from, unsigned to, get_block_t *get_block)
  8984. +{
  8985. + struct buffer_head *bh, *head;
  8986. + unsigned long block;
  8987. + unsigned block_start, block_end, blocksize, bbits;
  8988. + int err = 0;
  8989. + char *kaddr = kmap(page);
  8990. +
  8991. + bbits = inode->i_blkbits;
  8992. + blocksize = 1 << bbits;
  8993. +
  8994. + if (!page->buffers)
  8995. + create_empty_buffers(page, inode->i_dev, blocksize);
  8996. + head = page->buffers;
  8997. +
  8998. + block = page->index << (PAGE_CACHE_SHIFT - bbits); /* start block # */
  8999. +
  9000. + /* we allocate buffers and map them */
  9001. + for(bh = head, block_start = 0; bh != head || !block_start;
  9002. + block++, block_start = block_end + 1, bh = bh->b_this_page) {
  9003. + if (!bh) {
  9004. + err = -EIO;
  9005. + RFS_BUG("can't get buffer head\n");
  9006. + goto out;
  9007. + }
  9008. + block_end = block_start + blocksize - 1;
  9009. + if (block_end < from) {
  9010. + continue;
  9011. + } else if (block_start > to) {
  9012. + break;
  9013. + }
  9014. + clear_bit(BH_New, &bh->b_state);
  9015. +
  9016. + /* map new buffer if necessary*/
  9017. + if (!buffer_mapped(bh) || (inode->i_size <= (block<<(inode->i_sb->s_blocksize_bits)))) {
  9018. + err = get_block(inode, block, bh, 1);
  9019. + if (err) {
  9020. + DEBUG(DL1, "no block\n");
  9021. + goto out;
  9022. + }
  9023. + if (buffer_new(bh) && block_end > to) {
  9024. + memset(kaddr+to+1, 0, block_end-to);
  9025. + continue;
  9026. + }
  9027. + }
  9028. + if (!buffer_uptodate(bh) &&
  9029. + (block_start < from || block_end > to)) {
  9030. + ll_rw_block(READ, 1, &bh);
  9031. + wait_on_buffer(bh);
  9032. + if (!buffer_uptodate(bh)) {
  9033. + err = -EIO;
  9034. + goto out;
  9035. + }
  9036. + }
  9037. + }
  9038. +out:
  9039. + flush_dcache_page(page);
  9040. + kunmap_atomic(kaddr, KM_USER0);
  9041. + return err;
  9042. +}
  9043. +
  9044. +/**
  9045. + * block commit write
  9046. + * @param inode inode
  9047. + * @param page page pointer
  9048. + * @param from start offset within page
  9049. + * @param to last offset within page
  9050. + * @return return 0 on success, errno on failure
  9051. + */
  9052. +int rfs_block_commit_write(struct inode *inode, struct page *page,
  9053. + unsigned from, unsigned to)
  9054. +{
  9055. + unsigned block_start, block_end;
  9056. + unsigned blocksize;
  9057. + struct buffer_head *bh, *head;
  9058. +
  9059. + blocksize = 1 << inode->i_blkbits;
  9060. +
  9061. + for(bh = head = page->buffers, block_start = 0;
  9062. + bh != head || !block_start;
  9063. + block_start=block_end + 1, bh = bh->b_this_page) {
  9064. + block_end = block_start + blocksize - 1;
  9065. + if (block_end < from)
  9066. + continue;
  9067. + else if (block_start > to)
  9068. + break;
  9069. + else {
  9070. + set_bit(BH_Uptodate, &bh->b_state);
  9071. + __mark_buffer_dirty(bh);
  9072. + down(&RFS_I(inode)->data_mutex);
  9073. + buffer_insert_inode_data_queue(bh, inode);
  9074. + up(&RFS_I(inode)->data_mutex);
  9075. + }
  9076. + }
  9077. +
  9078. + return 0;
  9079. +}
  9080. +
  9081. +/**
  9082. + * wakeup function of logging process
  9083. + * @param __data : super block
  9084. + */
  9085. +void rfs_log_wakeup(unsigned long __data)
  9086. +{
  9087. + struct super_block *sb = (struct super_block *) __data;
  9088. + struct task_struct *p = RFS_SB(sb)->sleep_proc;
  9089. +
  9090. + mod_timer(&RFS_SB(sb)->timer, DATA_EXPIRES(jiffies));
  9091. + if (p->state == TASK_UNINTERRUPTIBLE)
  9092. + wake_up_process(p);
  9093. +}
  9094. +
  9095. +/**
  9096. + * wakeup function for a process committing data
  9097. + * @param __data : private inode
  9098. + */
  9099. +void rfs_data_wakeup(unsigned long __data)
  9100. +{
  9101. + struct rfs_inode_info *rfsi = (struct rfs_inode_info *) __data;
  9102. + struct task_struct *p = rfsi->sleep_proc;
  9103. +
  9104. + mod_timer(&rfsi->timer, DATA_EXPIRES(jiffies));
  9105. + if (p->state == TASK_UNINTERRUPTIBLE)
  9106. + wake_up_process(p);
  9107. +}
  9108. +
  9109. +/**
  9110. + * rfs_direct_IO - directly read/write from/to user space buffers without cache
  9111. + * @param rw read/write type
  9112. + * @param inode inode
  9113. + * @param iobuf iobuf
  9114. + * @param blocknr number of blocks
  9115. + * @param blocksize block size
  9116. + * @return write/read size on success, errno on failure
  9117. + */
  9118. +int rfs_direct_IO(int rw, struct inode *inode, struct kiobuf *iobuf, unsigned long blocknr, int blocksize)
  9119. +{
  9120. + struct super_block *sb = inode->i_sb;
  9121. + loff_t offset, old_size = inode->i_size;
  9122. + unsigned int alloc_clus = 0;
  9123. + int zerofilled = FALSE, ret;
  9124. +
  9125. + offset = blocknr << sb->s_blocksize_bits;
  9126. +
  9127. + if (rw == WRITE) {
  9128. + unsigned int clu_size, clu_bits;
  9129. + unsigned int req_clus, free_clus;
  9130. +
  9131. + clu_size = RFS_SB(sb)->cluster_size;
  9132. + clu_bits = RFS_SB(sb)->cluster_bits;
  9133. +
  9134. + /* compare the number of required clusters with free clusters */
  9135. + alloc_clus = (inode->i_size + clu_size - 1) >> clu_bits;
  9136. + req_clus = (offset + iobuf->length + clu_size - 1) >> clu_bits;
  9137. + if (req_clus > alloc_clus)
  9138. + req_clus -= alloc_clus; /* required clusters */
  9139. + else
  9140. + req_clus = 0;
  9141. +
  9142. + if (rfs_log_start(inode->i_sb, RFS_LOG_WRITE, inode))
  9143. + return -EIO;
  9144. +
  9145. + free_clus = GET_FREE_CLUS(RFS_SB(sb));
  9146. + if (req_clus > free_clus) {
  9147. + DEBUG(DL1, "req_clus = %d free_clus = %d \n",
  9148. + req_clus, free_clus);
  9149. + ret = -ENOSPC;
  9150. + goto end_log;
  9151. + }
  9152. +
  9153. + /* lseek case in direct IO */
  9154. + if (offset > old_size) {
  9155. + /*
  9156. + * NOTE: In spite of direc IO,
  9157. + * we use page cache for extend_with_zeorfill
  9158. + */
  9159. + ret = extend_with_zerofill(inode,
  9160. + (u32) old_size, (u32) offset);
  9161. + if (ret)
  9162. + goto end_log;
  9163. +
  9164. + inode->i_size = offset;
  9165. + set_mmu_private(inode, offset);
  9166. + zerofilled = TRUE;
  9167. + }
  9168. + }
  9169. +
  9170. + ret = generic_direct_IO(rw, inode, iobuf,
  9171. + blocknr, blocksize, rfs_get_block);
  9172. +
  9173. + if (rw == WRITE) {
  9174. + if (ret == -EINVAL) {
  9175. + int err;
  9176. +
  9177. + /*
  9178. + * free some clusters if only unaligned offset & length
  9179. + * of iobuf exists which were allocated at direct IO op
  9180. + */
  9181. + err = dealloc_clusters(inode, alloc_clus);
  9182. + if (!err) {
  9183. + inode->i_size = old_size;
  9184. + set_mmu_private(inode, old_size);
  9185. + }
  9186. +
  9187. + /* invalidate hint info */
  9188. + rfs_invalidate_hint(inode);
  9189. + }
  9190. +
  9191. +end_log:
  9192. + if (rfs_log_end(inode->i_sb, (ret >= 0) ? 0 : -EIO))
  9193. + return -EIO;
  9194. +
  9195. + if (!ret && zerofilled)
  9196. + ret = fsync_inode_data_buffers(inode);
  9197. + }
  9198. +
  9199. + return ret;
  9200. +}
  9201. +
  9202. +/**
  9203. + * build the super block
  9204. + * @param sb super block
  9205. + * @param data private data
  9206. + * @param silent verbose flag
  9207. + * @return return super block pointer on success, null on failure
  9208. + *
  9209. + * initialize the super block, system file such as logfile & poolfile and recovery error by sudden power off
  9210. + */
  9211. +static struct super_block *rfs_read_super(struct super_block *sb, void *data, int silent)
  9212. +{
  9213. + struct super_block *res = NULL;
  9214. + unsigned int used_clusters;
  9215. + int err;
  9216. +
  9217. + res = rfs_common_read_super(sb, data, silent);
  9218. + if (!res)
  9219. + return NULL;
  9220. +#ifdef CONFIG_RFS_VFAT
  9221. + RFS_SB(sb)->options.isvfat = TRUE;
  9222. +#else
  9223. + if (IS_FAT32(RFS_SB(res))) {
  9224. + DPRINTK("invalid fat type\n");
  9225. + return NULL;
  9226. + }
  9227. +
  9228. + sb->s_root->d_op = &rfs_dentry_operations;
  9229. + RFS_SB(sb)->options.isvfat = FALSE;
  9230. +#endif
  9231. + sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
  9232. +
  9233. + if (rfs_init_pool(sb)) {
  9234. + DPRINTK("fast unlink can not be supported\n");
  9235. + return NULL;
  9236. + }
  9237. +
  9238. + if (rfs_log_init(sb)) {
  9239. + DPRINTK("RFS-log : Not supported\n");
  9240. + return NULL;
  9241. + }
  9242. +
  9243. + if (rfs_remove_candidates(sb)) {
  9244. + DPRINTK("Can not remove candidate segments in pool file\n");
  9245. + return NULL;
  9246. + }
  9247. +
  9248. + /* update total number of used clusters */
  9249. + err = count_used_clusters(sb, &used_clusters);
  9250. + if (err) { /* I/O error */
  9251. + DPRINTK("FAT has something wrong\n");
  9252. + return NULL;
  9253. + }
  9254. +
  9255. + RFS_SB(sb)->num_used_clusters = used_clusters
  9256. + - (RFS_POOL_I(sb)->num_clusters - POOL_RESERVED_CLUSTER);
  9257. +
  9258. + return res;
  9259. +}
  9260. +
  9261. +static DECLARE_FSTYPE_DEV(rfs_fs_type, "rfs", rfs_read_super);
  9262. +
  9263. +/**
  9264. + * register RFS file system
  9265. + */
  9266. +static int __init init_rfs_fs(void)
  9267. +{
  9268. + return register_filesystem(&rfs_fs_type);
  9269. +}
  9270. +
  9271. +/**
  9272. + * unregister RFS file system
  9273. + */
  9274. +static void __exit exit_rfs_fs(void)
  9275. +{
  9276. + unregister_filesystem(&rfs_fs_type);
  9277. +}
  9278. +
  9279. +module_init(init_rfs_fs);
  9280. +module_exit(exit_rfs_fs);
  9281. +
  9282. +MODULE_LICENSE("Samsung, Proprietary");
  9283. diff -NurbB linux-2.6.17.14.orig/fs/rfs/rfs_26.c linux-2.6.17.14.rfs/fs/rfs/rfs_26.c
  9284. --- linux-2.6.17.14.orig/fs/rfs/rfs_26.c 1970-01-01 01:00:00.000000000 +0100
  9285. +++ linux-2.6.17.14.rfs/fs/rfs/rfs_26.c 2008-06-19 04:02:09.000000000 +0200
  9286. @@ -0,0 +1,407 @@
  9287. +/**
  9288. + * @file fs/rfs/rfs_26.c
  9289. + * @brief Kernel version 2.6 specified functions
  9290. + *
  9291. + *---------------------------------------------------------------------------*
  9292. + * *
  9293. + * COPYRIGHT 2003-2007 SAMSUNG ELECTRONICS CO., LTD. *
  9294. + * ALL RIGHTS RESERVED *
  9295. + * *
  9296. + * Permission is hereby granted to licensees of Samsung Electronics *
  9297. + * Co., Ltd. products to use or abstract this computer program only in *
  9298. + * accordance with the terms of the NAND FLASH MEMORY SOFTWARE LICENSE *
  9299. + * AGREEMENT for the sole purpose of implementing a product based on *
  9300. + * Samsung Electronics Co., Ltd. products. No other rights to reproduce, *
  9301. + * use, or disseminate this computer program, whether in part or in *
  9302. + * whole, are granted. *
  9303. + * *
  9304. + * Samsung Electronics Co., Ltd. makes no representation or warranties *
  9305. + * with respect to the performance of this computer program, and *
  9306. + * specifically disclaims any responsibility for any damages, *
  9307. + * special or consequential, connected with the use of this program. *
  9308. + * *
  9309. + *---------------------------------------------------------------------------*
  9310. + */
  9311. +
  9312. +#include <linux/fs.h>
  9313. +#include <linux/module.h>
  9314. +#include <linux/init.h>
  9315. +#include <linux/uio.h>
  9316. +#include <linux/writeback.h>
  9317. +#include <linux/rfs_fs.h>
  9318. +
  9319. +#include "rfs.h"
  9320. +#include "log.h"
  9321. +
  9322. +
  9323. +#ifdef RFS_FOR_2_6_17
  9324. +/*
  9325. + * In linux 2.6.17 or more, the callback function in direct io is changed.
  9326. + * Now, it is used to single get block instead of multiple get blocks.
  9327. + */
  9328. +#define rfs_get_blocks rfs_get_block
  9329. +
  9330. +#else /* !RFS_FOR_2_6_17 */
  9331. +/**
  9332. + * Function to translate a logical block into physical block
  9333. + * @param inode inode
  9334. + * @param iblock logical block number
  9335. + * @param max_blocks dummy variable new
  9336. + * @param bh_result buffer head pointer
  9337. + * @param create control flag
  9338. + * @return zero on success, negative value on failure
  9339. + *
  9340. + * This function is only invoked by direct IO
  9341. + */
  9342. +static int rfs_get_blocks(struct inode *inode, sector_t iblock, unsigned long max_blocks, struct buffer_head *bh_result, int create)
  9343. +{
  9344. + int ret;
  9345. +
  9346. + ret = rfs_get_block(inode, iblock, bh_result, create);
  9347. + if (!ret)
  9348. + bh_result->b_size = (1 << inode->i_blkbits);
  9349. + return ret;
  9350. +}
  9351. +#endif /* RFS_FOR_2_6_17 */
  9352. +
  9353. +#ifndef RFS_FOR_2_6_18
  9354. +/*
  9355. + * In linux 2.6.18 or more, struct writeback_control file is changed
  9356. + * from start, end to range_start, range_end
  9357. + */
  9358. +#define range_start start
  9359. +#define range_end end
  9360. +#endif /* !RFS_FOR_2_6_18 */
  9361. +
  9362. +/**
  9363. + * Write and wait upon the last page for inode
  9364. + * @param inode inode pointer
  9365. + * @return zero on success, negative value on failure
  9366. + *
  9367. + * This is a data integrity operation for a combination of
  9368. + * zerofill and direct IO write
  9369. + */
  9370. +static int sync_last_page(struct inode *inode)
  9371. +{
  9372. + loff_t lstart = (i_size_read(inode) - 1) & PAGE_CACHE_MASK;
  9373. + struct address_space *mapping = inode->i_mapping;
  9374. + struct writeback_control wbc = {
  9375. + .sync_mode = WB_SYNC_ALL,
  9376. + .range_start = lstart,
  9377. + .range_end = lstart + PAGE_CACHE_SIZE - 1,
  9378. + };
  9379. +
  9380. + /*
  9381. + * Note: There's race condition. We don't use page cache operation
  9382. + * directly.
  9383. + */
  9384. + return mapping->a_ops->writepages(mapping, &wbc);
  9385. +}
  9386. +
  9387. +#define rfs_flush_cache(iov, nr_segs) do { } while (0)
  9388. +
  9389. +/**
  9390. + * RFS function excuting direct I/O operation
  9391. + * @param rw I/O command
  9392. + * @param iocb VFS kiocb pointer
  9393. + * @param iov VFS iovc pointer
  9394. + * @param offset I/O offset
  9395. + * @param nr_segs the number segments
  9396. + * @return written or read date size on sucess, negative value on failure
  9397. + */
  9398. +ssize_t rfs_direct_IO(int rw, struct kiocb * iocb, const struct iovec *iov,
  9399. + loff_t offset, unsigned long nr_segs)
  9400. +{
  9401. + struct inode *inode = iocb->ki_filp->f_mapping->host;
  9402. + struct super_block *sb = inode->i_sb;
  9403. + int ret = 0;
  9404. +
  9405. +#ifdef CONFIG_GCOV_PROFILE
  9406. +/*
  9407. + * Note: We *MUST* use the correct API in direct IO.
  9408. + * It is correct place when use gcov
  9409. + */
  9410. +#define loff_t off_t
  9411. +#endif
  9412. +
  9413. + if (rw == WRITE) {
  9414. + unsigned int clu_size, clu_bits;
  9415. + unsigned int alloc_clus, req_clus, free_clus;
  9416. + size_t write_len = iov_length(iov, nr_segs);
  9417. + loff_t i_size = i_size_read(inode);
  9418. +
  9419. + clu_size = RFS_SB(sb)->cluster_size;
  9420. + clu_bits = RFS_SB(sb)->cluster_bits;
  9421. +
  9422. + /* compare the number of required clusters with free clusters */
  9423. + alloc_clus = (i_size + clu_size - 1) >> clu_bits;
  9424. + req_clus = (offset + write_len + clu_size - 1) >> clu_bits;
  9425. + if (req_clus > alloc_clus)
  9426. + req_clus -= alloc_clus;
  9427. + else
  9428. + req_clus = 0;
  9429. +
  9430. + if (rfs_log_start(inode->i_sb, RFS_LOG_WRITE, inode))
  9431. + return -EIO;
  9432. +
  9433. + free_clus = GET_FREE_CLUS(RFS_SB(sb));
  9434. + if (req_clus > free_clus) {
  9435. + DEBUG(DL1, "req_clus = %d free_clus = %d \n",
  9436. + req_clus, free_clus);
  9437. + ret = -ENOSPC;
  9438. + goto end_log;
  9439. + }
  9440. +
  9441. + /*
  9442. + * lseek case in direct IO
  9443. + * Note: We have to cast 'offset' as loff_t
  9444. + * to correct operation in kernel gcov
  9445. + * the loff_t means off_t in gcov mode
  9446. + */
  9447. + if ((loff_t) offset > i_size) {
  9448. + /*
  9449. + * NOTE: In spite of direc IO,
  9450. + * we use page cache for extend_with_zerofill
  9451. + */
  9452. + ret = extend_with_zerofill(inode,
  9453. + (u32) i_size,
  9454. + (u32) offset);
  9455. + if (ret)
  9456. + goto end_log;
  9457. +
  9458. + i_size_write(inode, offset);
  9459. + set_mmu_private(inode, offset);
  9460. +
  9461. + ret = sync_last_page(inode);
  9462. + if (ret)
  9463. + /*
  9464. + * it is possible that real allocated clusters
  9465. + * and size in dir entry can be different
  9466. + */
  9467. + goto end_log;
  9468. + }
  9469. + }
  9470. +
  9471. + /* flush cache */
  9472. + rfs_flush_cache(iov, nr_segs);
  9473. +
  9474. + ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
  9475. + offset, nr_segs, rfs_get_blocks, NULL);
  9476. +
  9477. + if (rw == WRITE) {
  9478. +end_log:
  9479. + if (rfs_log_end(inode->i_sb, (ret >= 0) ? 0 : -EIO))
  9480. + return -EIO;
  9481. + }
  9482. +
  9483. + return ret;
  9484. +}
  9485. +
  9486. +#ifdef CONFIG_GCOV_PROFILE
  9487. +#undef loff_t
  9488. +#endif
  9489. +
  9490. +/**
  9491. + * Function to build super block structure
  9492. + * @param sb super block pointer
  9493. + * @param data pointer for an optional date
  9494. + * @param silent control flag for error message
  9495. + * @return zero on success, a negative error code on failure
  9496. + *
  9497. + * Initialize the super block, system file such as logfile & poolfile and recovery error by sudden power off
  9498. + */
  9499. +static int rfs_fill_super(struct super_block *sb, void *data, int silent)
  9500. +{
  9501. + unsigned int used_clusters;
  9502. + int err = 0;
  9503. +
  9504. + sb = rfs_common_read_super(sb, data, silent);
  9505. + if (!sb)
  9506. + return -EINVAL;
  9507. +
  9508. +#ifdef CONFIG_RFS_VFAT
  9509. + RFS_SB(sb)->options.isvfat = TRUE;
  9510. +#else
  9511. + if (IS_FAT32(RFS_SB(sb))) {
  9512. + DPRINTK("invalid fat type\n");
  9513. + return -EINVAL;
  9514. + }
  9515. +
  9516. + RFS_SB(sb)->options.isvfat = FALSE;
  9517. +
  9518. + sb->s_root->d_op = &rfs_dentry_operations;
  9519. +#endif
  9520. + sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
  9521. +
  9522. + if (rfs_init_pool(sb)) {
  9523. + DPRINTK("fast unlink can not be supported\n");
  9524. + return -EINVAL;
  9525. + }
  9526. +
  9527. + if (rfs_log_init(sb)) {
  9528. + DPRINTK("RFS-log : Not supported\n");
  9529. + return -EINVAL;
  9530. + }
  9531. +
  9532. + if (rfs_remove_candidates(sb)) {
  9533. + DPRINTK("Can not remove candidate segments in pool file\n");
  9534. + return -EIO;
  9535. + }
  9536. +
  9537. + /* update total number of used clusters */
  9538. + err = count_used_clusters(sb, &used_clusters);
  9539. + if (err) { /* I/O error */
  9540. + DPRINTK("FAT has something wrong\n");
  9541. + return err;
  9542. + }
  9543. +
  9544. + RFS_SB(sb)->num_used_clusters = used_clusters
  9545. + - (RFS_POOL_I(sb)->num_clusters - POOL_RESERVED_CLUSTER);
  9546. +
  9547. + return err;
  9548. +}
  9549. +
  9550. +/* local variable definition */
  9551. +static kmem_cache_t *rfs_inode_cachep = NULL;
  9552. +
  9553. +/* static function definition */
  9554. +/**
  9555. + * Function to initialized a newly create rfs specific inode structure
  9556. + * @param foo memory pointer for new inode structure
  9557. + * @param cachep a pointer for inode cache
  9558. + * @param flags control flag
  9559. + */
  9560. +static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
  9561. +{
  9562. + struct rfs_inode_info *ei = (struct rfs_inode_info *) foo;
  9563. +
  9564. + if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
  9565. + SLAB_CTOR_CONSTRUCTOR)
  9566. + inode_init_once(&ei->vfs_inode);
  9567. +}
  9568. +
  9569. +/**
  9570. + * Function to initialize an inode cache
  9571. + */
  9572. +static int __init rfs_init_inodecache(void)
  9573. +{
  9574. + rfs_inode_cachep = kmem_cache_create("rfs_inode_cache",
  9575. + sizeof(struct rfs_inode_info),
  9576. + 0, SLAB_RECLAIM_ACCOUNT,
  9577. + init_once, NULL);
  9578. + if (!rfs_inode_cachep)
  9579. + return -ENOMEM;
  9580. +
  9581. + return 0;
  9582. +}
  9583. +
  9584. +/**
  9585. + * Function to destroy an inode cache
  9586. + */
  9587. +static void rfs_destroy_inodecache(void)
  9588. +{
  9589. + /*
  9590. + * kmem_cache_destroy return type is changed
  9591. + * from 'int' to 'void' after 2.6.19
  9592. + */
  9593. + kmem_cache_destroy(rfs_inode_cachep);
  9594. +}
  9595. +
  9596. +/**
  9597. + * Function to allocate rfs specific inode and associate it with vfs inode
  9598. + * @param sb super block pointer
  9599. + * @return a pointer of new inode on success, NULL on failure
  9600. + */
  9601. +struct inode *rfs_alloc_inode(struct super_block *sb)
  9602. +{
  9603. + struct rfs_inode_info *new;
  9604. +
  9605. + new = kmem_cache_alloc(rfs_inode_cachep, SLAB_KERNEL);
  9606. + if (!new)
  9607. + return NULL;
  9608. +
  9609. + /* initialize rfs inode info, if necessary */
  9610. + new->i_state = RFS_I_ALLOC;
  9611. +
  9612. + return &new->vfs_inode;
  9613. +}
  9614. +/**
  9615. + * Function to deallocate rfs specific inode
  9616. + * @param inode inode pointer
  9617. + */
  9618. +void rfs_destroy_inode(struct inode *inode)
  9619. +{
  9620. + if (!inode)
  9621. + printk("inode is NULL \n");
  9622. +
  9623. + kmem_cache_free(rfs_inode_cachep, RFS_I(inode));
  9624. +}
  9625. +
  9626. +/**
  9627. + * Interface function for super block initialization
  9628. + * @param fs_type filesystem type
  9629. + * @param flags flag
  9630. + * @param dev_name name of file system
  9631. + * @param data private date
  9632. + * @return a pointer of super block on success, negative error code on failure
  9633. + */
  9634. +#ifdef RFS_FOR_2_6_18
  9635. +static int rfs_get_sb(struct file_system_type *fs_type,
  9636. + int flags, const char *dev_name, void *data, struct vfsmount *mnt)
  9637. +{
  9638. + return get_sb_bdev(fs_type, flags, dev_name, data, rfs_fill_super, mnt);
  9639. +}
  9640. +#else
  9641. +static struct super_block *rfs_get_sb(struct file_system_type *fs_type,
  9642. + int flags, const char *dev_name, void *data)
  9643. +{
  9644. + return get_sb_bdev(fs_type, flags, dev_name, data, rfs_fill_super);
  9645. +}
  9646. +#endif /* RFS_FOR_2_6_18 */
  9647. +
  9648. +/* rfs filesystem type defintion */
  9649. +static struct file_system_type rfs_fs_type = {
  9650. + .owner = THIS_MODULE,
  9651. + .name = "rfs",
  9652. + .get_sb = rfs_get_sb,
  9653. + .kill_sb = kill_block_super,
  9654. + .fs_flags = FS_REQUIRES_DEV,
  9655. +};
  9656. +
  9657. +/**
  9658. + * Init function for rfs
  9659. + */
  9660. +static int __init init_rfs_fs(void)
  9661. +{
  9662. + int err = 0;
  9663. +
  9664. + /* init inode cache */
  9665. + err = rfs_init_inodecache();
  9666. + if (err)
  9667. + goto fail_init;
  9668. +
  9669. + err = register_filesystem(&rfs_fs_type);
  9670. + if (err)
  9671. + goto fail_register;
  9672. +
  9673. + return 0;
  9674. +
  9675. +fail_register:
  9676. + rfs_destroy_inodecache();
  9677. +fail_init:
  9678. + return err;
  9679. +}
  9680. +
  9681. +/**
  9682. + * Exit function for rfs
  9683. + */
  9684. +static void __exit exit_rfs_fs(void)
  9685. +{
  9686. + rfs_destroy_inodecache();
  9687. + unregister_filesystem(&rfs_fs_type);
  9688. +}
  9689. +
  9690. +module_init(init_rfs_fs);
  9691. +module_exit(exit_rfs_fs);
  9692. +
  9693. +MODULE_LICENSE("Samsung, Proprietary");
  9694. diff -NurbB linux-2.6.17.14.orig/fs/rfs/rfs.h linux-2.6.17.14.rfs/fs/rfs/rfs.h
  9695. --- linux-2.6.17.14.orig/fs/rfs/rfs.h 1970-01-01 01:00:00.000000000 +0100
  9696. +++ linux-2.6.17.14.rfs/fs/rfs/rfs.h 2008-06-19 04:02:09.000000000 +0200
  9697. @@ -0,0 +1,279 @@
  9698. +/**
  9699. + * @file fs/rfs/rfs.h
  9700. + * @brief local header file for rfs
  9701. + *
  9702. + *---------------------------------------------------------------------------*
  9703. + * *
  9704. + * COPYRIGHT 2003-2007 SAMSUNG ELECTRONICS CO., LTD. *
  9705. + * ALL RIGHTS RESERVED *
  9706. + * *
  9707. + * Permission is hereby granted to licensees of Samsung Electronics *
  9708. + * Co., Ltd. products to use or abstract this computer program only in *
  9709. + * accordance with the terms of the NAND FLASH MEMORY SOFTWARE LICENSE *
  9710. + * AGREEMENT for the sole purpose of implementing a product based on *
  9711. + * Samsung Electronics Co., Ltd. products. No other rights to reproduce, *
  9712. + * use, or disseminate this computer program, whether in part or in *
  9713. + * whole, are granted. *
  9714. + * *
  9715. + * Samsung Electronics Co., Ltd. makes no representation or warranties *
  9716. + * with respect to the performance of this computer program, and *
  9717. + * specifically disclaims any responsibility for any damages, *
  9718. + * special or consequential, connected with the use of this program. *
  9719. + * *
  9720. + *---------------------------------------------------------------------------*
  9721. + *
  9722. + */
  9723. +
  9724. +#ifndef _RFS_H
  9725. +#define _RFS_H
  9726. +
  9727. +#include <linux/sched.h>
  9728. +#include <linux/version.h>
  9729. +#include <asm/semaphore.h>
  9730. +
  9731. +/*
  9732. + * kernel version macro
  9733. + */
  9734. +#undef RFS_FOR_2_4
  9735. +#undef RFS_FOR_2_6
  9736. +#undef RFS_FOR_2_6_17
  9737. +#undef RFS_FOR_2_6_18
  9738. +
  9739. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
  9740. +#define RFS_FOR_2_6 1
  9741. +#else
  9742. +#define RFS_FOR_2_4 1
  9743. +#endif
  9744. +
  9745. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
  9746. +#define RFS_FOR_2_6_18 1
  9747. +#endif
  9748. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
  9749. +#define RFS_FOR_2_6_17 1
  9750. +#endif
  9751. +
  9752. +
  9753. +typedef enum rfs_lock_type {
  9754. + RFS_FAT_LOCK,
  9755. + RFS_LOG_LOCK,
  9756. +} rfs_lock_type_t;
  9757. +
  9758. +/*
  9759. + * for locking
  9760. + */
  9761. +#define fat_lock(sb) rfs_down(RFS_SB(sb)->fat_mutex, RFS_FAT_LOCK)
  9762. +#define fat_unlock(sb) rfs_up(RFS_SB(sb)->fat_mutex, RFS_FAT_LOCK)
  9763. +#define init_fat_lock(sb) rfs_init_mutex(RFS_SB(sb)->fat_mutex, sb)
  9764. +
  9765. +#define lock_log(sb) rfs_down(RFS_LOG_I(sb)->log_mutex, RFS_LOG_LOCK)
  9766. +#define unlock_log(sb) rfs_up(RFS_LOG_I(sb)->log_mutex, RFS_LOG_LOCK)
  9767. +#define init_log_lock(sb) rfs_init_mutex(RFS_LOG_I(sb)->log_mutex, sb)
  9768. +#define get_log_lock_depth(sb) rfs_get_lock_depth(RFS_LOG_I(sb)->log_mutex)
  9769. +#define get_log_lock_owner(sb) rfs_get_lock_owner(RFS_LOG_I(sb)->log_mutex)
  9770. +
  9771. +#define IS_LOG_LOCK(type) ((type) == RFS_LOG_LOCK)
  9772. +
  9773. +/*
  9774. + * for debugging
  9775. + */
  9776. +#define DL0 (0) /* Quiet */
  9777. +#define DL1 (1) /* Audible */
  9778. +#define DL2 (2) /* Loud */
  9779. +#define DL3 (3) /* Noisy */
  9780. +
  9781. +#define DPRINTK(format, args...) \
  9782. +do { \
  9783. + printk("%s[%d]: " format, __func__ , __LINE__, ##args); \
  9784. +} while (0)
  9785. +
  9786. +#undef DEBUG
  9787. +
  9788. +#ifdef CONFIG_RFS_FAT_DEBUG
  9789. +
  9790. +#define DEBUG(n, format, arg...) \
  9791. +do { \
  9792. + if (n <= CONFIG_RFS_FAT_DEBUG_VERBOSE) { \
  9793. + printk("%s[%d]: " format "\n", \
  9794. + __func__, __LINE__, ##arg); \
  9795. + } \
  9796. +} while(0)
  9797. +
  9798. +#define RFS_BUG(format, args...) \
  9799. +do { \
  9800. + DPRINTK(format, ##args); \
  9801. + BUG(); \
  9802. +} while (0)
  9803. +
  9804. +#define RFS_BUG_ON(condition) \
  9805. +do { \
  9806. + BUG_ON(condition); \
  9807. +} while (0)
  9808. +
  9809. +#else
  9810. +
  9811. +#define DEBUG(n, arg...) do { } while (0)
  9812. +#define RFS_BUG(format, args...) DPRINTK(format, ##args)
  9813. +#define RFS_BUG_ON(condition) do { } while (0)
  9814. +
  9815. +#endif /* CONFIG_RFS_FAT_DEBUG */
  9816. +
  9817. +#define DATA_EXPIRES(j) ((j) + CONFIG_RFS_LOG_WAKEUP_DELAY)
  9818. +
  9819. +#define IS_INVAL_CLU(sbi, clu) \
  9820. + ((clu < VALID_CLU || clu >= (sbi)->num_clusters) ? 1 : 0)
  9821. +
  9822. +#define CHECK_RFS_INODE(inode, errno) \
  9823. +do { \
  9824. + if (inode->i_ino != ROOT_INO) { \
  9825. + if (RFS_I(inode)->p_start_clu >= \
  9826. + RFS_SB(inode->i_sb)->num_clusters \
  9827. + || RFS_I(inode)->start_clu < VALID_CLU) { \
  9828. + RFS_BUG("out of range (%u, %u, %u)", \
  9829. + RFS_I(inode)->index, \
  9830. + RFS_I(inode)->p_start_clu, \
  9831. + RFS_I(inode)->start_clu); \
  9832. + return errno; \
  9833. + } \
  9834. + } \
  9835. +} while (0)
  9836. +
  9837. +struct rfs_semaphore {
  9838. + struct semaphore mutex;
  9839. + pid_t owner;
  9840. + int depth;
  9841. + struct super_block *sb;
  9842. +};
  9843. +
  9844. +void rfs_truncate(struct inode *);
  9845. +int rfs_sync_inode(struct inode *, int, int);
  9846. +
  9847. +/**
  9848. + * down the mutex
  9849. + * @param lock a specific lock structure
  9850. + * @param type lock type
  9851. + * @return return the modified lock depth
  9852. +*/
  9853. +static inline int rfs_down(struct rfs_semaphore *lock, rfs_lock_type_t type)
  9854. +{
  9855. + if (lock->owner == current->pid && lock->depth >= 1) {
  9856. + /* recursive lock */
  9857. + lock->depth++;
  9858. + DEBUG(DL3, "owner = %d depth = %d", lock->owner, lock->depth);
  9859. + return lock->depth;
  9860. + }
  9861. +
  9862. + /* first acquire */
  9863. + down(&lock->mutex);
  9864. +
  9865. +#ifdef RFS_FOR_2_4
  9866. + if (IS_LOG_LOCK(type)) {
  9867. + /* register timer to avoid indefinite hang in wait_on_buffer */
  9868. + RFS_SB(lock->sb)->sleep_proc = current;
  9869. + RFS_SB(lock->sb)->timer.expires = DATA_EXPIRES(jiffies);
  9870. + add_timer(&RFS_SB(lock->sb)->timer);
  9871. + }
  9872. +#endif
  9873. +
  9874. + lock->owner = current->pid;
  9875. + lock->depth++;
  9876. +
  9877. + DEBUG(DL3, "owner = %d depth = %d", lock->owner, lock->depth);
  9878. +
  9879. + return lock->depth;
  9880. +}
  9881. +
  9882. +/**
  9883. + * up the mutex
  9884. + * @param lock a specific lock structure
  9885. + * @param type lock type
  9886. + * @return return the modified lock depth
  9887. + */
  9888. +static inline int rfs_up(struct rfs_semaphore *lock, rfs_lock_type_t type)
  9889. +{
  9890. + if (lock->depth > 1) {
  9891. + lock->depth--;
  9892. + } else {
  9893. + DEBUG(DL3, "owner = %d depth = %d", lock->owner, lock->depth);
  9894. +
  9895. + lock->owner = -1;
  9896. + lock->depth--;
  9897. +
  9898. +#ifdef RFS_FOR_2_4
  9899. + if (IS_LOG_LOCK(type))
  9900. + del_timer_sync(&RFS_SB(lock->sb)->timer);
  9901. +#endif
  9902. +
  9903. + up(&lock->mutex);
  9904. + }
  9905. + return lock->depth;
  9906. +}
  9907. +
  9908. +#ifdef RFS_FOR_2_4
  9909. +/**
  9910. + * down data mutex of ordered transaction for kernel2.4
  9911. + * @param rfsi a native inode info
  9912. + */
  9913. +static inline void rfs_data_down(struct rfs_inode_info *rfsi)
  9914. +{
  9915. + down(&rfsi->data_mutex);
  9916. +
  9917. + /* register timer to avoid indefinite hang in wait_on_buffer */
  9918. + rfsi->sleep_proc = current;
  9919. + rfsi->timer.expires = DATA_EXPIRES(jiffies);
  9920. + add_timer(&rfsi->timer);
  9921. +}
  9922. +
  9923. +/**
  9924. + * up data mutex of ordered transaction for kernel2.4
  9925. + * @param rfsi a private inode
  9926. + */
  9927. +static inline void rfs_data_up(struct rfs_inode_info *rfsi)
  9928. +{
  9929. + del_timer_sync(&rfsi->timer);
  9930. + up(&rfsi->data_mutex);
  9931. +}
  9932. +#endif
  9933. +
  9934. +/**
  9935. + * init the mutex
  9936. + * @param lock a specific lock structure
  9937. + * @param sb super block
  9938. +*/
  9939. +static inline void rfs_init_mutex(struct rfs_semaphore *lock,
  9940. + struct super_block *sb)
  9941. +{
  9942. + init_MUTEX(&lock->mutex);
  9943. + lock->owner = -1;
  9944. + lock->depth = 0;
  9945. + lock->sb = sb;
  9946. +}
  9947. +
  9948. +/**
  9949. + * get the current depth
  9950. + * @param lock a specific lock structure
  9951. + * @return return the current lock depth
  9952. + */
  9953. +static inline int rfs_get_lock_depth(struct rfs_semaphore *lock)
  9954. +{
  9955. + return lock->depth;
  9956. +}
  9957. +
  9958. +/**
  9959. + * get the current lock owner
  9960. + * @param lock a specific lock structure
  9961. + * @return return the current lock owner
  9962. + */
  9963. +static inline int rfs_get_lock_owner(struct rfs_semaphore *lock)
  9964. +{
  9965. + return lock->owner;
  9966. +}
  9967. +
  9968. +inline static struct buffer_head * rfs_bread(struct super_block *sb,
  9969. + int block, int rfs_state)
  9970. +{
  9971. + struct buffer_head *bh;
  9972. + bh = sb_bread(sb, block);
  9973. +
  9974. + return bh;
  9975. +}
  9976. +#endif /* _RFS_H */
  9977. diff -NurbB linux-2.6.17.14.orig/fs/rfs/super.c linux-2.6.17.14.rfs/fs/rfs/super.c
  9978. --- linux-2.6.17.14.orig/fs/rfs/super.c 1970-01-01 01:00:00.000000000 +0100
  9979. +++ linux-2.6.17.14.rfs/fs/rfs/super.c 2008-06-19 04:02:09.000000000 +0200
  9980. @@ -0,0 +1,668 @@
  9981. +/**
  9982. + * @file fs/rfs/super.c
  9983. + * @brief super block and init functions
  9984. + *
  9985. + *---------------------------------------------------------------------------*
  9986. + * *
  9987. + * COPYRIGHT 2003-2007 SAMSUNG ELECTRONICS CO., LTD. *
  9988. + * ALL RIGHTS RESERVED *
  9989. + * *
  9990. + * Permission is hereby granted to licensees of Samsung Electronics *
  9991. + * Co., Ltd. products to use or abstract this computer program only in *
  9992. + * accordance with the terms of the NAND FLASH MEMORY SOFTWARE LICENSE *
  9993. + * AGREEMENT for the sole purpose of implementing a product based on *
  9994. + * Samsung Electronics Co., Ltd. products. No other rights to reproduce, *
  9995. + * use, or disseminate this computer program, whether in part or in *
  9996. + * whole, are granted. *
  9997. + * *
  9998. + * Samsung Electronics Co., Ltd. makes no representation or warranties *
  9999. + * with respect to the performance of this computer program, and *
  10000. + * specifically disclaims any responsibility for any damages, *
  10001. + * special or consequential, connected with the use of this program. *
  10002. + * *
  10003. + *---------------------------------------------------------------------------*
  10004. + *
  10005. + */
  10006. +
  10007. +#include <linux/fs.h>
  10008. +#include <linux/bitops.h>
  10009. +#include <linux/blkdev.h>
  10010. +#include <linux/rfs_fs.h>
  10011. +#include <linux/nls.h>
  10012. +
  10013. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
  10014. +#include <linux/parser.h>
  10015. +#include <linux/writeback.h>
  10016. +#include <linux/statfs.h>
  10017. +#endif
  10018. +
  10019. +#include "rfs.h"
  10020. +#include "log.h"
  10021. +
  10022. +#ifdef RFS_FOR_2_6
  10023. +enum {
  10024. + opt_codepage, opt_err,
  10025. +};
  10026. +
  10027. +static match_table_t rfs_tokens = {
  10028. + {opt_codepage, "codepage=%s"},
  10029. + {opt_err, NULL}
  10030. +};
  10031. +#endif
  10032. +
  10033. +#ifdef CONFIG_RFS_NLS
  10034. +static const char rfs_default_codepage[] = CONFIG_RFS_DEFAULT_CODEPAGE;
  10035. +#endif
  10036. +
  10037. +/**
  10038. + * write the super block especially commit the previous transaction and flush the fat cache
  10039. + * @param sb super block
  10040. + */
  10041. +static void rfs_write_super(struct super_block *sb)
  10042. +{
  10043. + if ((sb->s_flags & MS_RDONLY))
  10044. + return;
  10045. +
  10046. + rfs_log_force_commit(sb, NULL);
  10047. +
  10048. + sb->s_dirt = 0;
  10049. +}
  10050. +
  10051. +/**
  10052. + * get statistics on a file system
  10053. + * @param sb super block
  10054. + * @param stat structure to fill stat info
  10055. + * @return return 0
  10056. + */
  10057. +#ifdef RFS_FOR_2_6_18
  10058. +static int rfs_statfs(struct dentry *dentry, struct kstatfs *stat)
  10059. +#elif RFS_FOR_2_6
  10060. +static int rfs_statfs(struct super_block *sb, struct kstatfs *stat)
  10061. +#else
  10062. +static int rfs_statfs(struct super_block *sb, struct statfs *stat)
  10063. +#endif
  10064. +{
  10065. +#ifdef RFS_FOR_2_6_18
  10066. + struct super_block *sb = dentry->d_sb;
  10067. +#endif
  10068. + int used_clusters = RFS_SB(sb)->num_used_clusters;
  10069. +
  10070. + stat->f_type = RFS_MAGIC;
  10071. + stat->f_bsize = RFS_SB(sb)->cluster_size;
  10072. + stat->f_blocks = RFS_SB(sb)->num_clusters;
  10073. + stat->f_bfree = RFS_SB(sb)->num_clusters - used_clusters;
  10074. + stat->f_bavail = stat->f_bfree;
  10075. + stat->f_namelen = MAX_NAME_LENGTH;
  10076. +
  10077. + return 0;
  10078. +}
  10079. +
  10080. +/**
  10081. + * allow to remount to make a writable file system readonly
  10082. + * @param sb super block
  10083. + * @param flags to chang the mount flags
  10084. + * @param data private data
  10085. + * @return return 0
  10086. + */
  10087. +static int rfs_remount(struct super_block *sb, int *flags, char *data)
  10088. +{
  10089. + if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY)) {
  10090. + if (*flags & MS_RDONLY) {
  10091. + sb->s_flags |= MS_RDONLY;
  10092. + *flags |= MS_RDONLY;
  10093. + }
  10094. + } else {
  10095. + if (!(sb->s_flags & MS_RDONLY)) {
  10096. + sb->s_flags &= ~MS_RDONLY;
  10097. + *flags &= ~MS_RDONLY;
  10098. + }
  10099. + }
  10100. +
  10101. + *flags |= MS_NOATIME | MS_NODIRATIME;
  10102. +
  10103. + return 0;
  10104. +}
  10105. +
  10106. +/**
  10107. + * release the super block
  10108. + * @param sb super block
  10109. + *
  10110. + * release log, internal fat cache, and the pool file memory
  10111. + */
  10112. +static void rfs_put_super(struct super_block *sb)
  10113. +{
  10114. +#ifdef RFS_FOR_2_6
  10115. + struct rfs_sb_info *sbi = RFS_SB(sb);
  10116. +#endif
  10117. +
  10118. + /* It precedes rfs_fcache_release because
  10119. + it enventually calls rfs_fcache_sync */
  10120. + rfs_log_cleanup(sb);
  10121. +
  10122. + rfs_fcache_release(sb);
  10123. +
  10124. + rfs_release_pool(sb);
  10125. +
  10126. + kfree(RFS_SB(sb)->fat_mutex);
  10127. +
  10128. +#ifdef RFS_FOR_2_6
  10129. + if (!sbi) {
  10130. + RFS_BUG("rfs-specific sb is corrrupted\n");
  10131. + return;
  10132. + }
  10133. +
  10134. + sb->s_fs_info = NULL;
  10135. + kfree(sbi);
  10136. +#endif
  10137. + return;
  10138. +}
  10139. +
  10140. +static struct super_operations rfs_sops = {
  10141. +#ifdef RFS_FOR_2_6
  10142. + .alloc_inode = rfs_alloc_inode,
  10143. + .destroy_inode = rfs_destroy_inode,
  10144. +#endif
  10145. +#ifdef CONFIG_RFS_IGET4
  10146. + .read_inode2 = rfs_read_inode2,
  10147. +#endif
  10148. + .write_inode = rfs_write_inode,
  10149. + .delete_inode = rfs_delete_inode,
  10150. + .put_super = rfs_put_super,
  10151. + .write_super = rfs_write_super,
  10152. + .statfs = rfs_statfs,
  10153. + .remount_fs = rfs_remount,
  10154. +};
  10155. +
  10156. +/**
  10157. + * get the partition boot record of the super block
  10158. + * @param sb super block
  10159. + * @param[out] res buffer head contains pbr info which will be released by caller
  10160. + * @param[out] pbr_sector number of pbr sector
  10161. + * @return return 0 on success, errno on failure
  10162. + */
  10163. +static int get_pbr_info(struct super_block *sb, struct buffer_head **res, unsigned int *pbr_sector)
  10164. +{
  10165. + struct buffer_head *bh;
  10166. + struct mbr *mbr_p;
  10167. + struct pbr *pbr_p;
  10168. + struct part_entry *pte_p;
  10169. + unsigned int start_sector;
  10170. +
  10171. + /* read MBR sector */
  10172. + bh = rfs_bread(sb, 0, BH_RFS_MBR);
  10173. + if (!bh) { /* I/O error */
  10174. + DPRINTK("unable to read MBR sector \n");
  10175. + return -EIO;
  10176. + }
  10177. +
  10178. + mbr_p = (struct mbr *) bh->b_data;
  10179. +
  10180. + if ((u16) SIGNATURE != GET16(mbr_p->signature)) {
  10181. + DPRINTK("invalid MBR signature (%x != %x)\n",
  10182. + SIGNATURE, GET16(mbr_p->signature));
  10183. + brelse(bh);
  10184. + return -EINVAL;
  10185. + }
  10186. +
  10187. + /* get partition entry */
  10188. + pte_p = (struct part_entry *) mbr_p->partition;
  10189. + start_sector = GET32(pte_p->start_sector);
  10190. + brelse(bh);
  10191. +
  10192. + /* read PBR sector */
  10193. + bh = rfs_bread(sb, start_sector, BH_RFS_MBR);
  10194. + if (!bh) { /* I/O error */
  10195. + DPRINTK("unable to read PBR sector \n");
  10196. + return -EIO;
  10197. + }
  10198. +
  10199. + pbr_p = (struct pbr *) bh->b_data;
  10200. + if ((u16) SIGNATURE != GET16(pbr_p->signature)) {
  10201. + DPRINTK("invalid boot sector signature (%x != %x)\n",
  10202. + SIGNATURE, GET16(pbr_p->signature));
  10203. + brelse(bh);
  10204. + return -EINVAL;
  10205. + }
  10206. +
  10207. + /* set return value */
  10208. + *res = bh;
  10209. + *pbr_sector = start_sector;
  10210. +
  10211. + return 0;
  10212. +}
  10213. +
  10214. +/**
  10215. + * parse the mount options
  10216. + * @param sb super block
  10217. + * @param options mount options
  10218. + * @return zero on success
  10219. + */
  10220. +int parse_option(struct super_block *sb, char *options)
  10221. +{
  10222. +#ifdef RFS_FOR_2_6
  10223. + substring_t args[MAX_OPT_ARGS];
  10224. +#endif
  10225. + struct rfs_mount_info *opts = &(RFS_SB(sb)->options);
  10226. + char *codepage;
  10227. + char *p;
  10228. +
  10229. + opts->codepage = NULL;
  10230. +
  10231. + if (!options)
  10232. + goto out;
  10233. +
  10234. +#ifdef RFS_FOR_2_6
  10235. + while ((p = strsep(&options, ",")) != NULL) {
  10236. + int token;
  10237. + if (!*p)
  10238. + continue;
  10239. +
  10240. + token = match_token(p, rfs_tokens, args);
  10241. +
  10242. + switch (token) {
  10243. + /* NLS codepage used in disk */
  10244. + case opt_codepage:
  10245. + codepage = match_strdup(&args[0]);
  10246. + if (!codepage)
  10247. + return -ENOENT;
  10248. + opts->codepage = codepage;
  10249. + break;
  10250. + default:
  10251. + return -EINVAL;
  10252. + }
  10253. + }
  10254. +#else
  10255. + p = strtok(options, ",");
  10256. + if (p == NULL)
  10257. + goto out;
  10258. +
  10259. + do {
  10260. + if (!strncmp(p, "codepage=", 9)) {
  10261. + codepage = strchr(p, '=');
  10262. + if (!codepage)
  10263. + return -ENOENT;
  10264. + opts->codepage = codepage + 1;
  10265. + } else {
  10266. + return -EINVAL;
  10267. + }
  10268. + } while((p = strtok(NULL, ",")) != NULL);
  10269. +#endif
  10270. +
  10271. +out:
  10272. +#ifdef CONFIG_RFS_NLS
  10273. + if (opts->codepage == NULL) {
  10274. + if (strcmp(rfs_default_codepage, "")) {
  10275. + opts->codepage = (char *) rfs_default_codepage;
  10276. + DEBUG(DL0, "Use default codepage %s\n", opts->codepage);
  10277. + } else {
  10278. + DPRINTK("If you configure the NLS, you must select codepage\n");
  10279. + return -EINVAL;
  10280. + }
  10281. + }
  10282. +#endif
  10283. + return 0;
  10284. +}
  10285. +
  10286. +/**
  10287. + * fill up the RFS-specific super block
  10288. + * @param sb super block
  10289. + * @param old_blksize original block size of block device
  10290. + * @param[out] new_blksize new block size of the file system will be set
  10291. + * @return return 0 on success, errno on failure
  10292. + *
  10293. + * choose a minimum value between cluster size and block size of block device
  10294. + */
  10295. +static int rfs_build_sb(struct super_block *sb, unsigned long old_blksize, unsigned long *new_blksize)
  10296. +{
  10297. + struct buffer_head *bh;
  10298. + struct pbr *pbr_p;
  10299. + struct bpb *bpb_p;
  10300. + unsigned int pbr_sector = 0;
  10301. + unsigned short sector_size, sector_bits;
  10302. + unsigned int num_sectors, num_reserved, fat_sectors, root_sectors;
  10303. + unsigned int fat_start_sector, root_start_sector, data_start_sector;
  10304. + unsigned int num_root_entries = MAX_ROOT_DENTRY, root_clu = 0;
  10305. + unsigned int sectors_per_blk, sectors_per_blk_bits;
  10306. + unsigned int num_blks, block_size;
  10307. + loff_t device_size = sb->s_bdev->bd_inode->i_size;
  10308. +
  10309. + /* get PBR sector */
  10310. + if (get_pbr_info(sb, &bh, &pbr_sector))
  10311. + return -EINVAL;
  10312. +
  10313. + /* fill private info of sb */
  10314. + pbr_p = (struct pbr *) bh->b_data;
  10315. + bpb_p = (struct bpb *) pbr_p->bpb;
  10316. +
  10317. + /* get logical sector size */
  10318. + sector_size = GET16(bpb_p->sector_size);
  10319. + if (!sector_size || ((u32) sector_size > PAGE_CACHE_SIZE)) {
  10320. + DPRINTK("invalid logical sector size : %d\n", sector_size);
  10321. + brelse(bh);
  10322. + return -EINVAL;
  10323. + }
  10324. + sector_bits = ffs(sector_size) - 1;
  10325. +
  10326. + /* get reserved, fat, root sectors */
  10327. + num_reserved = GET16(bpb_p->num_reserved);
  10328. + fat_sectors = GET16(bpb_p->num_fat_sectors);
  10329. + root_sectors = GET16(bpb_p->num_root_entries) << DENTRY_SIZE_BITS;
  10330. + root_sectors = ((root_sectors - 1) >> sector_bits) + 1;
  10331. + if (!fat_sectors && !GET16(bpb_p->num_root_entries)) {
  10332. + /* when fat32 */
  10333. + RFS_SB(sb)->fat_bits = FAT32;
  10334. + fat_sectors = GET32(bpb_p->num_fat32_sectors);
  10335. + root_clu = GET32(bpb_p->root_cluster);
  10336. + root_sectors = 0;
  10337. + num_root_entries = 0;
  10338. + }
  10339. +
  10340. + /* get each area's start sector number */
  10341. + fat_start_sector = pbr_sector + num_reserved;
  10342. + root_start_sector = fat_start_sector + fat_sectors * bpb_p->num_fats;
  10343. + data_start_sector = root_start_sector + root_sectors;
  10344. +
  10345. + /* get total number of sectors on volume */
  10346. + num_sectors = GET16(bpb_p->num_sectors);
  10347. + if (!num_sectors)
  10348. + num_sectors = GET32(bpb_p->num_huge_sectors);
  10349. + /* check whether it is bigger than device size or it is not available */
  10350. + if (!num_sectors || ((num_sectors << sector_bits) > device_size)) {
  10351. + DPRINTK("invalid number of sectors : %u\n", num_sectors);
  10352. + brelse(bh);
  10353. + return -EINVAL;
  10354. + }
  10355. +
  10356. + /* set cluster size */
  10357. + RFS_SB(sb)->cluster_size = bpb_p->sectors_per_clu << sector_bits;
  10358. + RFS_SB(sb)->cluster_bits = ffs(RFS_SB(sb)->cluster_size) - 1;
  10359. +
  10360. + /* get new block size */
  10361. + if (old_blksize > RFS_SB(sb)->cluster_size)
  10362. + block_size = RFS_SB(sb)->cluster_size;
  10363. + else
  10364. + block_size = old_blksize;
  10365. +
  10366. + /*
  10367. + * block size is sector size if block device's block size is not set,
  10368. + * logical sector size is bigger than block size to set,
  10369. + * or start sector of data area is not aligned
  10370. + */
  10371. + if (!block_size || sector_size > block_size ||
  10372. + (data_start_sector << sector_bits) & (block_size - 1))
  10373. + block_size = sector_size;
  10374. +
  10375. + sectors_per_blk = block_size >> sector_bits;
  10376. + sectors_per_blk_bits = ffs(sectors_per_blk) - 1;
  10377. +
  10378. + /* set number of blocks per cluster */
  10379. + RFS_SB(sb)->blks_per_clu = bpb_p->sectors_per_clu >>
  10380. + sectors_per_blk_bits;
  10381. + RFS_SB(sb)->blks_per_clu_bits = ffs(RFS_SB(sb)->blks_per_clu) - 1;
  10382. +
  10383. + /* set start address of fat table area */
  10384. + RFS_SB(sb)->fat_start_addr = fat_start_sector << sector_bits;
  10385. +
  10386. + /* set start address of root directory */
  10387. + RFS_SB(sb)->root_start_addr = root_start_sector << sector_bits;
  10388. + /*
  10389. + * NOTE: although total dir entries in root dir are bigger than 512
  10390. + * RFS only used 512 entries in root dir
  10391. + */
  10392. + RFS_SB(sb)->root_end_addr = RFS_SB(sb)->root_start_addr +
  10393. + (num_root_entries << DENTRY_SIZE_BITS);
  10394. +
  10395. + /* set start block number of data area */
  10396. + RFS_SB(sb)->data_start = data_start_sector >> sectors_per_blk_bits;
  10397. +
  10398. + /* set total number of clusters */
  10399. + num_blks = (num_sectors - data_start_sector) >> sectors_per_blk_bits;
  10400. + RFS_SB(sb)->num_clusters = (num_blks >> RFS_SB(sb)->blks_per_clu_bits)
  10401. + + 2; /* clu 0 & clu 1 */
  10402. +
  10403. + /* set fat type */
  10404. + if (!RFS_SB(sb)->fat_bits) {
  10405. + if (RFS_SB(sb)->num_clusters >= FAT12_THRESHOLD &&
  10406. + RFS_SB(sb)->num_clusters < FAT16_THRESHOLD)
  10407. + RFS_SB(sb)->fat_bits = FAT16;
  10408. + else {
  10409. + DPRINTK("invalid fat type\n");
  10410. + brelse(bh);
  10411. + return -EINVAL;
  10412. + }
  10413. + }
  10414. +
  10415. + /* set root dir's first cluster number, etc. */
  10416. + RFS_SB(sb)->root_clu = root_clu;
  10417. + RFS_SB(sb)->search_ptr = VALID_CLU; /* clu 0 & 1 are reserved */
  10418. +
  10419. + /* release buffer head contains pbr sector */
  10420. + brelse(bh);
  10421. +
  10422. + /* init semaphore for fat table */
  10423. + RFS_SB(sb)->fat_mutex = kmalloc(sizeof(struct rfs_semaphore), GFP_KERNEL);
  10424. + if (!(RFS_SB(sb)->fat_mutex)) { /* memory error */
  10425. + DEBUG(DL0, "memory allocation failed");
  10426. + return -ENOMEM;
  10427. + }
  10428. +
  10429. + init_fat_lock(sb);
  10430. +
  10431. + /* init list for map destroy */
  10432. + INIT_LIST_HEAD(&RFS_SB(sb)->free_chunks);
  10433. +
  10434. + /* new block size of block device will be set */
  10435. + *new_blksize = block_size;
  10436. +
  10437. + /* NLS support */
  10438. +#ifdef CONFIG_RFS_NLS
  10439. + if (RFS_SB(sb)->options.codepage) {
  10440. + RFS_SB(sb)->nls_disk = load_nls(RFS_SB(sb)->options.codepage);
  10441. + if (!RFS_SB(sb)->nls_disk) {
  10442. + DPRINTK("RFS: %s not found\n", RFS_SB(sb)->options.codepage);
  10443. + return -EINVAL;
  10444. + }
  10445. + }
  10446. +#endif
  10447. +
  10448. +#ifdef RFS_FOR_2_4
  10449. + init_timer(&RFS_SB(sb)->timer);
  10450. + RFS_SB(sb)->timer.function = rfs_log_wakeup;
  10451. + RFS_SB(sb)->timer.data = (unsigned long) sb;
  10452. +#endif
  10453. + RFS_SB(sb)->highest_d_ino = (num_sectors << sector_bits) >> DENTRY_SIZE_BITS;
  10454. +
  10455. + return 0;
  10456. +}
  10457. +
  10458. +/**
  10459. + * fill up the root inode
  10460. + * @param inode root inode
  10461. + * @return return 0 on success, errno on failure
  10462. + */
  10463. +static int fill_root_inode(struct inode *inode)
  10464. +{
  10465. + struct super_block *sb = inode->i_sb;
  10466. + unsigned int last_clu;
  10467. + int err = 0, num_clusters = 0;
  10468. +
  10469. + inode->i_ino = ROOT_INO;
  10470. + inode->i_mode = S_IFDIR | 0777;
  10471. + inode->i_uid = 0;
  10472. + inode->i_gid = 0;
  10473. +
  10474. + inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
  10475. + inode->i_blksize = sb->s_blocksize;
  10476. + inode->i_version = 0;
  10477. +
  10478. + insert_inode_hash(inode);
  10479. +
  10480. + inode->i_op = &rfs_dir_inode_operations;
  10481. + inode->i_fop = &rfs_dir_operations;
  10482. +
  10483. + RFS_I(inode)->start_clu = RFS_SB(sb)->root_clu;
  10484. + RFS_I(inode)->p_start_clu = RFS_SB(sb)->root_clu;
  10485. + RFS_I(inode)->index = 0;
  10486. +
  10487. + if (!IS_FAT32(RFS_SB(sb))) {
  10488. + inode->i_size = RFS_SB(sb)->cluster_size;
  10489. + } else {
  10490. + num_clusters = find_last_cluster(inode, &last_clu);
  10491. + if (num_clusters <= 0) {
  10492. + err = num_clusters;
  10493. + DPRINTK("No last cluster (err : %d)\n", err);
  10494. + return -EIO;
  10495. + }
  10496. + inode->i_size = num_clusters
  10497. + << RFS_SB(sb)->cluster_bits;
  10498. + /* update last cluster */
  10499. + RFS_I(inode)->last_clu = last_clu;
  10500. + }
  10501. +
  10502. + inode->i_nlink = count_subdir(sb, RFS_I(inode)->start_clu);
  10503. + inode->i_blocks = (inode->i_size + SECTOR_SIZE - 1) >> SECTOR_BITS;
  10504. +
  10505. + set_mmu_private(inode, inode->i_size);
  10506. +
  10507. + spin_lock_init(&RFS_I(inode)->write_lock);
  10508. +#ifdef RFS_FOR_2_4
  10509. + init_MUTEX(&RFS_I(inode)->data_mutex);
  10510. + init_timer(&RFS_I(inode)->timer);
  10511. + RFS_I(inode)->timer.function = rfs_data_wakeup;
  10512. + RFS_I(inode)->timer.data = (unsigned long) RFS_I(inode);
  10513. +#endif
  10514. +
  10515. + return 0;
  10516. +}
  10517. +
  10518. +/**
  10519. + * read the super block (disk such as MBR) of RFS and initialize super block (incore)
  10520. + * @param sb super block
  10521. + * @param data private data
  10522. + * @param silent verbose flag
  10523. + * @return return super block pointer on success, null on failure
  10524. + */
  10525. +struct super_block *rfs_common_read_super(struct super_block *sb,
  10526. + void *data, int silent)
  10527. +{
  10528. + struct inode *root_inode = NULL;
  10529. + unsigned long new_blksize, old_blksize;
  10530. + int err;
  10531. +
  10532. +#ifdef RFS_FOR_2_6
  10533. + struct rfs_sb_info *sbi;
  10534. +
  10535. + sbi = kmalloc(sizeof(struct rfs_sb_info), GFP_KERNEL);
  10536. + if (!sbi) /* memory error */
  10537. + goto failed_mount;
  10538. +
  10539. + /* initialize sbi with 0x00 */
  10540. + /* log_info and pool_info must be initialized with 0 */
  10541. + memset(sbi, 0x00, sizeof(struct rfs_sb_info));
  10542. + sb->s_fs_info = sbi;
  10543. +
  10544. + old_blksize = block_size(sb->s_bdev);
  10545. +#else
  10546. + old_blksize = block_size(sb->s_dev);
  10547. +#endif
  10548. + sb_min_blocksize(sb, 512);
  10549. +
  10550. + /* parsing mount options */
  10551. + if (parse_option(sb, data) < 0)
  10552. + goto failed_mount;
  10553. +
  10554. + /* fill the RFS-specific info of sb */
  10555. + if (rfs_build_sb(sb, old_blksize, &new_blksize) < 0)
  10556. + goto failed_mount;
  10557. +
  10558. +
  10559. +
  10560. + /* setup the rest superblock info */
  10561. + if (!sb_set_blocksize(sb, new_blksize)) {
  10562. + DPRINTK("unable to set blocksize\n");
  10563. + goto failed_mount;
  10564. + }
  10565. +
  10566. + sb->s_maxbytes = 0xFFFFFFFF; /* maximum file size */
  10567. + sb->s_op = &rfs_sops;
  10568. + sb->s_magic = RFS_MAGIC;
  10569. + sb->s_dirt = 0;
  10570. +
  10571. + RFS_SB(sb)->fcache_array = NULL;
  10572. + if (rfs_fcache_init(sb)) { /* memory error */
  10573. + DPRINTK("unable to init fat cache\n");
  10574. + goto release_fcache;
  10575. + }
  10576. +
  10577. + /* allocate root inode & fill it */
  10578. + if (!(root_inode = new_inode(sb)))
  10579. + goto release_fcache;
  10580. +
  10581. + err = fill_root_inode(root_inode);
  10582. + if (err) {
  10583. + iput(root_inode);
  10584. + goto release_fcache;
  10585. + }
  10586. +
  10587. + if (!(sb->s_root = d_alloc_root(root_inode))) {
  10588. + iput(root_inode);
  10589. + goto release_fcache;
  10590. + }
  10591. +
  10592. + return sb;
  10593. +
  10594. +release_fcache:
  10595. + /* release fcache */
  10596. + if (RFS_SB(sb)->fcache_array)
  10597. + kfree(RFS_SB(sb)->fcache_array);
  10598. +failed_mount:
  10599. + if (RFS_SB(sb)->fat_mutex)
  10600. + kfree(RFS_SB(sb)->fat_mutex);
  10601. +#ifdef RFS_FOR_2_6
  10602. + if (sbi)
  10603. + kfree(sbi);
  10604. +#endif
  10605. +
  10606. + return NULL;
  10607. +}
  10608. +
  10609. +/**
  10610. + * flush all dirty buffers of the file system include fat cache
  10611. + * @param sb super block
  10612. + * @return return 0
  10613. + */
  10614. +int rfs_sync_vol(struct super_block *sb)
  10615. +{
  10616. + /* fat cache sync */
  10617. + fat_lock(sb);
  10618. + rfs_fcache_sync(sb, 0);
  10619. + fat_unlock(sb);
  10620. +
  10621. + /* fat cache is dirty without waiting flush. So sync device */
  10622. +#ifdef RFS_FOR_2_6
  10623. + sync_blockdev(sb->s_bdev);
  10624. +#else
  10625. + fsync_no_super(sb->s_dev);
  10626. +#endif
  10627. + return 0;
  10628. +}
  10629. +
  10630. +#ifdef _RFS_INTERNAL_UNUSED_LOG
  10631. +/**
  10632. + * flush all dirty buffers of a transaction
  10633. + * @param sb super block
  10634. + * @return return 0 on success
  10635. + */
  10636. +int rfs_sync_transaction(struct super_block *sb)
  10637. +{
  10638. + int ret = 0;
  10639. +
  10640. + if (RFS_LOG_I(sb)->type != RFS_LOG_UNLINK &&
  10641. + RFS_LOG_I(sb)->type != RFS_LOG_DEL_INODE)
  10642. + ret = rfs_sync_inode(RFS_LOG_I(sb)->inode, 1, 0);
  10643. +
  10644. + ret |= rfs_meta_commit(sb);
  10645. +
  10646. + return ret;
  10647. +}
  10648. +#endif
  10649. diff -NurbB linux-2.6.17.14.orig/include/linux/rfs_fs.h linux-2.6.17.14.rfs/include/linux/rfs_fs.h
  10650. --- linux-2.6.17.14.orig/include/linux/rfs_fs.h 1970-01-01 01:00:00.000000000 +0100
  10651. +++ linux-2.6.17.14.rfs/include/linux/rfs_fs.h 2008-06-19 04:03:51.000000000 +0200
  10652. @@ -0,0 +1,508 @@
  10653. +/**
  10654. + * @file include/linux/rfs_fs.h
  10655. + * @brief common header file for RFS
  10656. + *
  10657. + *---------------------------------------------------------------------------*
  10658. + * *
  10659. + * COPYRIGHT 2003-2007 SAMSUNG ELECTRONICS CO., LTD. *
  10660. + * ALL RIGHTS RESERVED *
  10661. + * *
  10662. + * Permission is hereby granted to licensees of Samsung Electronics *
  10663. + * Co., Ltd. products to use or abstract this computer program only in *
  10664. + * accordance with the terms of the NAND FLASH MEMORY SOFTWARE LICENSE *
  10665. + * AGREEMENT for the sole purpose of implementing a product based on *
  10666. + * Samsung Electronics Co., Ltd. products. No other rights to reproduce, *
  10667. + * use, or disseminate this computer program, whether in part or in *
  10668. + * whole, are granted. *
  10669. + * *
  10670. + * Samsung Electronics Co., Ltd. makes no representation or warranties *
  10671. + * with respect to the performance of this computer program, and *
  10672. + * specifically disclaims any responsibility for any damages, *
  10673. + * special or consequential, connected with the use of this program. *
  10674. + * *
  10675. + *---------------------------------------------------------------------------*
  10676. + */
  10677. +
  10678. +#ifndef _LINUX_RFS_FS_H
  10679. +#define _LINUX_RFS_FS_H
  10680. +
  10681. +#include <linux/version.h>
  10682. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
  10683. +#include <linux/buffer_head.h>
  10684. +#include <linux/rfs_fs_i.h>
  10685. +#include <linux/rfs_fs_sb.h>
  10686. +#else
  10687. +#include <linux/locks.h>
  10688. +#endif
  10689. +#include <linux/byteorder/generic.h>
  10690. +#include <linux/xsr_if.h>
  10691. +
  10692. +/*
  10693. + * Constand and Mecro definition
  10694. + */
  10695. +#define ROOT_INO 1
  10696. +
  10697. +#define RFS_MAGIC (0x2003BAB1L)
  10698. +
  10699. +#define DOS_NAME_LENGTH 11
  10700. +#define EXT_UNAME_LENGTH 13
  10701. +#define SHORT_NAME_LENGTH 8
  10702. +#define UNICODE_NAME_LENGTH 256
  10703. +#define MAX_NAME_LENGTH UNICODE_NAME_LENGTH
  10704. +#define MAX_TOTAL_LENGTH 260
  10705. +
  10706. +#define DELETE_MARK ((u8) 0xE5)
  10707. +#define EXT_END_MARK ((u8) 0x40)
  10708. +
  10709. +#define KANJI_LEAD ((u8)(0xE5))
  10710. +#define REPLACE_KANJI ((u8)(0x05))
  10711. +
  10712. +#define SPACE ((u8)(0x20)) /* ' ' */
  10713. +#define PERIOD ((u8)(0x2E)) /* '.' */
  10714. +#define UNDERSCORE ((u8)(0x5F)) /* '_' */
  10715. +#define TILDE ((u8)(0x7E)) /* '~' */
  10716. +
  10717. +#define PRIMARY_LOWER ((u8)(0x08))
  10718. +#define EXTENSION_LOWER ((u8)(0x10))
  10719. +#define PRIMARY_UPPER ((u8)(0x07))
  10720. +#define EXTENSION_UPPER ((u8)(0x0E0))
  10721. +#define UPPER_N_LOWER ((u8)(0x0FF))
  10722. +
  10723. +#define primary_masked(mixed) (mixed & 0x00F)
  10724. +#define extension_masked(mixed) (mixed & 0x0F0)
  10725. +
  10726. +#define SIGNATURE 0xAA55
  10727. +
  10728. +#define DENTRY_SIZE 32 /* MS-DOS FAT Compatible */
  10729. +#define DENTRY_SIZE_BITS 5
  10730. +#define MAX_ROOT_DENTRY 511 /* 0 ~ 511 */
  10731. +#define MAX_DIR_DENTRY 65536
  10732. +
  10733. +#define SECTOR_SIZE 512
  10734. +#define SECTOR_BITS 9
  10735. +#define SECTOR_MASK (SECTOR_SIZE - 1)
  10736. +
  10737. +/* attribute(FAT type) */
  10738. +#define ATTR_NORMAL ((u8) 0x00)
  10739. +#define ATTR_READONLY ((u8) 0x01)
  10740. +#define ATTR_HIDDEN ((u8) 0x02)
  10741. +#define ATTR_SYSTEM ((u8) 0x04)
  10742. +#define ATTR_VOLUME ((u8) 0x08)
  10743. +#define ATTR_EXTEND ((u8) 0x0F)
  10744. +#define ATTR_SUBDIR ((u8) 0x10)
  10745. +#define ATTR_ARCHIVE ((u8) 0x20)
  10746. +
  10747. +/* type of directory entry(internal type) */
  10748. +#define TYPE_UNUSED ((u32) 0x00)
  10749. +#define TYPE_DELETED ((u32) 0x01)
  10750. +#define TYPE_FILE ((u32) 0x02)
  10751. +#define TYPE_DIR ((u32) 0x03)
  10752. +#define TYPE_EXTEND ((u32) 0x04)
  10753. +#define TYPE_ALL ((u32) 0x05)
  10754. +#define TYPE_UNKNOWN ((u32) 0x06)
  10755. +#define TYPE_SYMLINK ((u32) 0x07)
  10756. +#define TYPE_VOLUME ((u32) 0x08)
  10757. +
  10758. +#define SYMLINK_MARK ((u8) 0xE2) /* symlink */
  10759. +
  10760. +/* FAT type */
  10761. +#define FAT16 16
  10762. +#define FAT32 32
  10763. +
  10764. +#define IS_FAT16(sbi) ((sbi)->fat_bits == FAT16)
  10765. +#define IS_FAT32(sbi) ((sbi)->fat_bits == FAT32)
  10766. +#define IS_VFAT(sbi) ((sbi)->options.isvfat == TRUE)
  10767. +
  10768. +/* threshold value(# of clusters) to determin the FAT type */
  10769. +#define FAT12_THRESHOLD 4087 /* 4085 + clu 0 + clu 1 */
  10770. +#define FAT16_THRESHOLD 65527 /* 65525 + clu 0 + clu 1 */
  10771. +#define FAT32_THRESHOLD 268435447 /* 268435445 + clu 0 + clu 1*/
  10772. +
  10773. +/* related with cluster */
  10774. +#define CLU_TAIL ((unsigned int) (~0))
  10775. +#define CLU_FREE ((unsigned int) (0))
  10776. +
  10777. +#define VALID_CLU 2
  10778. +
  10779. +/* fast unlink */
  10780. +#define RFS_POOL_FILE_NAME "RFS_POOL.SY$"
  10781. +#define RFS_POOL_FILE_LEN 12
  10782. +#define POOL_RESERVED_CLUSTER 1
  10783. +
  10784. +#define SHRINK_POOL_SIZE 0
  10785. +#define EXPAND_POOL_SIZE 1
  10786. +#define SET_POOL_SIZE 2
  10787. +
  10788. +/* Internal error code */
  10789. +#define INVALID_ENTRY 131
  10790. +#define INTERNAL_EOF 132
  10791. +
  10792. +/* Miscellaneous definition */
  10793. +#define TRUE 1
  10794. +#define FALSE 0
  10795. +#define DOT ". "
  10796. +#define DOTDOT ".. "
  10797. +
  10798. +/* REVISIT: It's not fixed since it is changed from int to unsigned int */
  10799. +#define NOT_ASSIGNED (~0)
  10800. +
  10801. +/* macro */
  10802. +/* REVISIT : We need endian handling */
  10803. +#define GET16(x) le16_to_cpu(x)
  10804. +#define GET32(x) le32_to_cpu(x)
  10805. +#define GET64(x) le64_to_cpu(x)
  10806. +
  10807. +#define SET64(dst, src) \
  10808. +do { \
  10809. + (dst) = cpu_to_le64(src); \
  10810. +} while (0)
  10811. +
  10812. +#define SET32(dst, src) \
  10813. +do { \
  10814. + (dst) = cpu_to_le32(src); \
  10815. +} while (0)
  10816. +
  10817. +#define SET16(dst, src) \
  10818. +do { \
  10819. + (dst) = cpu_to_le16(src); \
  10820. +} while (0)
  10821. +
  10822. +#define GET_FREE_CLUS(sbi) ((sbi)->num_clusters - (sbi)->num_used_clusters)
  10823. +
  10824. +#define START_CLUSTER(x) \
  10825. + (((GET16((x)->start_clu_hi)) << 16) | GET16((x)->start_clu_lo))
  10826. +#define START_BLOCK(x, sb) \
  10827. + (((x - VALID_CLU) << RFS_SB(sb)->blks_per_clu_bits) + \
  10828. + RFS_SB(sb)->data_start)
  10829. +
  10830. +#define IS_FREE(name) (((name[0] == DELETE_MARK) || (name[0] == 0x0))? 1 : 0 )
  10831. +
  10832. +#define IS_XSR(x) (MAJOR(x) == XSR_BLK_DEVICE_FTL ? 1 : 0)
  10833. +
  10834. +/* function macro */
  10835. +#ifdef CONFIG_RFS_VFAT
  10836. +#define find_entry find_entry_long
  10837. +#define build_entry build_entry_long
  10838. +#else
  10839. +#define find_entry find_entry_short
  10840. +#define build_entry build_entry_short
  10841. +#endif
  10842. +
  10843. +#define rfs_mark_buffer_dirty(x, sb) mark_buffer_tr_dirty(x, sb)
  10844. +#define rfs_mark_inode_dirty(x) mark_inode_tr_dirty(x)
  10845. +
  10846. +/*
  10847. + * structure of partition entry (DISK)
  10848. + */
  10849. +struct part_entry {
  10850. + u8 def_boot;
  10851. + u8 bgn_head;
  10852. + u8 bgn_sector;
  10853. + u8 bgn_cylinder;
  10854. + u8 sys_type;
  10855. + u8 end_head;
  10856. + u8 end_sector;
  10857. + u8 end_cylinder;
  10858. + u32 start_sector;
  10859. + u32 num_sectors;
  10860. +} __attribute__ ((packed));
  10861. +
  10862. +/*
  10863. + * structure of master boot record (DISK)
  10864. + */
  10865. +struct mbr {
  10866. + u8 boot_code[446];
  10867. + u8 partition[64];
  10868. + u16 signature;
  10869. +} __attribute__ ((packed));
  10870. +
  10871. +/*
  10872. + * structure of BIOS Parameter Block (DISK)
  10873. + */
  10874. +struct bpb {
  10875. + u16 sector_size;
  10876. + u8 sectors_per_clu;
  10877. + u16 num_reserved;
  10878. + u8 num_fats;
  10879. + u16 num_root_entries;
  10880. + u16 num_sectors;
  10881. + u8 media_type;
  10882. + u16 num_fat_sectors;
  10883. + u16 sectors_in_track;
  10884. + u16 num_heads;
  10885. + u32 num_hidden_sectors;
  10886. + u32 num_huge_sectors;
  10887. +
  10888. + u32 num_fat32_sectors;
  10889. + u16 ext_flags;
  10890. + u16 version;
  10891. + u32 root_cluster;
  10892. + u16 fsinfo_sector;
  10893. + u16 backup_sector;
  10894. + u8 reserved[12];
  10895. +} __attribute__ ((packed));
  10896. +
  10897. +/*
  10898. + * structure of additional BPB data (DISK)
  10899. + */
  10900. +struct ext_bpb {
  10901. + u8 phy_drv_no;
  10902. + u8 reserved;
  10903. + u8 ext_signature;
  10904. + u8 vol_serial[4];
  10905. + u8 vol_label[11];
  10906. + u8 vol_type[8];
  10907. +} __attribute__ ((packed));
  10908. +
  10909. +/*
  10910. + * structure of Parition Boot Record (DISK)
  10911. + */
  10912. +struct pbr {
  10913. + u8 jmp_boot[3];
  10914. + u8 oem_name[8];
  10915. + u8 bpb[25];
  10916. + union {
  10917. + struct {
  10918. + u8 ext_bpb[26];
  10919. + u8 boot_code[446];
  10920. + } fat16;
  10921. + struct {
  10922. + u8 bpb[28];
  10923. + u8 ext_bpb[26];
  10924. + u8 boot_code[418];
  10925. + } fat32;
  10926. + } u;
  10927. + u8 boot_code[2];
  10928. + u16 signature;
  10929. +} __attribute__ ((packed));
  10930. +
  10931. +/*
  10932. + * structure of dir entry data on the disk (DISK)
  10933. + */
  10934. +struct rfs_dir_entry {
  10935. + u8 name[DOS_NAME_LENGTH]; /* 8.3 name */
  10936. + u8 attr;
  10937. + u8 sysid;
  10938. + u8 cmsec; /* create time in milliseconds */
  10939. + u16 ctime; /* create time */
  10940. + u16 cdate; /* create date */
  10941. + u16 adate; /* access date */
  10942. + u16 start_clu_hi; /* high 16-bits of start cluster */
  10943. + u16 mtime; /* modify time */
  10944. + u16 mdate; /* modify date */
  10945. + u16 start_clu_lo; /* low 16-bits of start cluster */
  10946. + u32 size;
  10947. +} __attribute__ ((packed));
  10948. +
  10949. +/*
  10950. + * structure of extentry entry data on the disk (DISK)
  10951. + * extentry entry is needed for long file name
  10952. + */
  10953. +struct rfs_ext_entry {
  10954. + u8 entry_offset;
  10955. + u16 uni_0_4[5]; /* unicode 0 ~ 4 */
  10956. + u8 attr;
  10957. + u8 sysid;
  10958. + u8 checksum;
  10959. + u16 uni_5_10[6]; /* unicode 5 ~ 10 */
  10960. + u16 start_clu; /* aligned */
  10961. + u16 uni_11_12[2]; /* unicode 11 ~ 12 */
  10962. +} __attribute__ ((packed));
  10963. +
  10964. +/*
  10965. + * hint info for fast unlink (DISK/INCORE)
  10966. + */
  10967. +struct rfs_pool_info {
  10968. + u32 index; /* index of pool file dir entry */
  10969. + u32 blocknr; /* pool file dir entry is saved in this block */
  10970. + u32 start_cluster; /* start cluster number of pool file */
  10971. + u32 last_cluster; /* last cluster number in deleted segment */
  10972. + u32 num_clusters; /* number of clusters except candidate segs */
  10973. + u32 c_start_cluster; /* start clu # in candidate segment list */
  10974. + u32 c_last_cluster; /* last clu # in candidate segment list */
  10975. + struct list_head c_list; /* head for candidate segment list */
  10976. +};
  10977. +
  10978. +enum rfs_state_bits {
  10979. + BH_RFS_LOG_START = BH_PrivateStart,
  10980. + BH_RFS_LOG_COMMIT,
  10981. + BH_RFS_LOG,
  10982. + BH_RFS_FAT,
  10983. + BH_RFS_POOL_BLOCK,
  10984. + BH_RFS_ROOT,
  10985. + BH_RFS_DIR,
  10986. + BH_RFS_MBR,
  10987. + BH_RFS_DATA,
  10988. +};
  10989. +
  10990. +#ifdef CONFIG_RFS_IGET4
  10991. +/*
  10992. + * structure for read_inode2 (INCORE)
  10993. + */
  10994. +struct rfs_iget4_args {
  10995. + struct rfs_dir_entry *ep;
  10996. + u32 p_start_clu;
  10997. + u32 index;
  10998. +};
  10999. +#endif
  11000. +
  11001. +/* status flag: [3] max n_tail [2] min n_tail [1] lossy, [0] mix */
  11002. +#define get_lossy(status) ((status >> 8) & 0xFF)
  11003. +#define get_mix(status) (u8) (status & 0xFF)
  11004. +
  11005. +#define put_lossy(status, lossy) \
  11006. +do { status |= ((lossy & 0xFF) << 8); \
  11007. +} while(0)
  11008. +#define put_mix(status, mix) \
  11009. +do { status |= (mix & 0xFF); \
  11010. +} while(0)
  11011. +
  11012. +/*
  11013. + * vector operations
  11014. + */
  11015. +
  11016. +/* inode.c */
  11017. +int rfs_iunique (struct inode *, unsigned int, unsigned long *);
  11018. +int fill_inode (struct inode *, struct rfs_dir_entry *, unsigned int, unsigned int);
  11019. +struct inode *rfs_new_inode (struct inode *, struct dentry *, unsigned int);
  11020. +void rfs_delete_inode (struct inode *);
  11021. +int rfs_delete_entry (struct inode *, struct inode *);
  11022. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
  11023. +int rfs_write_inode (struct inode *, int);
  11024. +#else
  11025. +void rfs_write_inode (struct inode *, int);
  11026. +#endif
  11027. +#ifdef CONFIG_RFS_IGET4
  11028. +void rfs_read_inode2 (struct inode *, void *);
  11029. +#endif
  11030. +
  11031. +static inline void set_mmu_private(struct inode *inode, loff_t value)
  11032. +{
  11033. + struct super_block *sb = inode->i_sb;
  11034. +
  11035. + RFS_I(inode)->mmu_private = value;
  11036. + if (RFS_I(inode)->mmu_private & (sb->s_blocksize - 1)) {
  11037. + RFS_I(inode)->mmu_private |= (sb->s_blocksize -1);
  11038. + RFS_I(inode)->mmu_private++;
  11039. + }
  11040. +}
  11041. +
  11042. +/* super.c */
  11043. +struct super_block *rfs_common_read_super (struct super_block *, void *, int);
  11044. +int rfs_sync_vol(struct super_block *);
  11045. +
  11046. +/* file.c */
  11047. +int extend_with_zerofill (struct inode *, unsigned int, unsigned int);
  11048. +int rfs_setattr (struct dentry *, struct iattr *);
  11049. +int rfs_bmap (struct inode *, long, unsigned long *);
  11050. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
  11051. +int rfs_get_block (struct inode *, sector_t, struct buffer_head *, int);
  11052. +int rfs_permission (struct inode *, int, struct nameidata *);
  11053. +#else
  11054. +int rfs_get_block (struct inode *, long, struct buffer_head *, int);
  11055. +int rfs_permission (struct inode *, int);
  11056. +#endif
  11057. +void rfs_invalidate_hint(struct inode *);
  11058. +
  11059. +/* namei.c */
  11060. +int build_entry_short (struct inode *, struct inode *, unsigned int, unsigned int, const char *);
  11061. +int build_entry_long (struct inode *, struct inode *, unsigned int, unsigned int, const char *);
  11062. +int check_reserved_files (struct inode *, const char *);
  11063. +
  11064. +/* dir.c */
  11065. +int is_dir_empty (struct inode *);
  11066. +int init_new_dir (struct inode *);
  11067. +int count_subdir (struct super_block *, unsigned int);
  11068. +
  11069. +/* dos.c */
  11070. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
  11071. +void set_entry_time (struct rfs_dir_entry *, struct timespec);
  11072. +#else
  11073. +void set_entry_time (struct rfs_dir_entry *, time_t);
  11074. +#endif
  11075. +unsigned int entry_type (struct rfs_dir_entry *);
  11076. +unsigned int entry_time (unsigned short, unsigned short);
  11077. +void init_dir_entry (struct inode *, struct rfs_dir_entry *, unsigned int, unsigned int, const u8 *, unsigned char *);
  11078. +int init_ext_entry (struct rfs_ext_entry *, unsigned int, unsigned int, const u16 *, unsigned char);
  11079. +unsigned char calc_checksum (const u8 *);
  11080. +int mk_dosname (struct inode *dir, const char *name, u8 *dosname, unsigned char *mixed, u16 *uname);
  11081. +int get_uname_from_entry (struct inode *, unsigned int , unsigned short *);
  11082. +struct rfs_dir_entry *get_entry (struct inode *, unsigned int, struct buffer_head **);
  11083. +struct rfs_dir_entry *get_entry_with_cluster (struct super_block *, unsigned int, unsigned int, struct buffer_head **);
  11084. +int find_entry_short (struct inode *, const char *, struct buffer_head **, unsigned int);
  11085. +int find_entry_long (struct inode *, const char *, struct buffer_head **, unsigned int);
  11086. +int remove_entry (struct inode *, unsigned int, struct buffer_head **);
  11087. +
  11088. +/* cluster.c */
  11089. +int fat_read (struct super_block *, unsigned int, unsigned int *);
  11090. +int fat_write (struct super_block *, unsigned int, unsigned int);
  11091. +int alloc_cluster (struct inode *, unsigned int *);
  11092. +int rfs_map_destroy (struct super_block *);
  11093. +int free_chain (struct inode *, unsigned int, unsigned int, unsigned int *);
  11094. +int count_num_clusters (struct inode *);
  11095. +int dealloc_clusters (struct inode *, unsigned int);
  11096. +int count_used_clusters (struct super_block *, unsigned int *);
  11097. +int append_new_cluster(struct inode *, unsigned int, unsigned int);
  11098. +int find_free_cluster(struct inode *, unsigned int *);
  11099. +int find_last_cluster(struct inode *, unsigned int *);
  11100. +int find_cluster(struct super_block *, unsigned int, unsigned int, unsigned int *, unsigned int *);
  11101. +
  11102. +int rfs_fcache_init (struct super_block *);
  11103. +void rfs_fcache_release (struct super_block *);
  11104. +void rfs_fcache_sync (struct super_block *, int);
  11105. +
  11106. +int rfs_init_pool (struct super_block *);
  11107. +void rfs_release_pool (struct super_block *);
  11108. +int rfs_shrink_pool_chain (struct super_block *, unsigned int *,
  11109. + unsigned int, unsigned int *, unsigned int *);
  11110. +int rfs_get_pool (struct super_block *, unsigned int, unsigned int);
  11111. +int rfs_attach_candidate (struct inode *);
  11112. +int rfs_detach_candidate (struct inode *);
  11113. +int rfs_remove_candidates (struct super_block *);
  11114. +int rfs_update_pool_block (struct super_block *);
  11115. +int rfs_update_pool_entry (struct super_block *, unsigned int, int);
  11116. +
  11117. +static inline struct rfs_pool_info *RFS_POOL_I(struct super_block *sb)
  11118. +{
  11119. + return (struct rfs_pool_info *)(RFS_SB(sb)->pool_info);
  11120. +}
  11121. +
  11122. +/* code_convert.c */
  11123. +void convert_dosname_to_cstring (char *, const u8 *, unsigned char);
  11124. +int convert_uname_to_cstring (char *, const u16 *, struct nls_table *);
  11125. +int convert_cstring_to_dosname(u8 *, const char *, unsigned int *, unsigned int);
  11126. +int create_fatname(const char *, u8 *, u16 *, unsigned int *, struct nls_table *, unsigned int);
  11127. +
  11128. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
  11129. +/* rfs_26.c : Linux 2.6 dependent operations */
  11130. +struct inode *rfs_alloc_inode (struct super_block *);
  11131. +void rfs_destroy_inode (struct inode *);
  11132. +#else
  11133. +/* rfs_24.c : Linux 2.4 dependent operations */
  11134. +void rfs_log_wakeup (unsigned long __data);
  11135. +void rfs_data_wakeup (unsigned long __data);
  11136. +int rfs_block_prepare_write(struct inode *inode, struct page *page, unsigned from, unsigned to, get_block_t *get_block);
  11137. +int rfs_block_commit_write(struct inode *inode, struct page *page, unsigned from, unsigned to);
  11138. +#endif
  11139. +
  11140. +/* dir.c */
  11141. +extern struct file_operations rfs_dir_operations;
  11142. +
  11143. +/* file.c */
  11144. +extern struct inode_operations rfs_file_inode_operations;
  11145. +extern struct file_operations rfs_file_operations;
  11146. +
  11147. +/* inode.c */
  11148. +extern struct address_space_operations rfs_aops;
  11149. +
  11150. +/* namei.c */
  11151. +extern struct inode_operations rfs_dir_inode_operations;
  11152. +extern struct dentry_operations rfs_dentry_operations;
  11153. +
  11154. +/* symlink.c */
  11155. +extern struct inode_operations rfs_symlink_inode_operations;
  11156. +
  11157. +/* for transaction sync */
  11158. +extern void mark_buffer_tr_dirty(struct buffer_head *bh, struct super_block *sb);
  11159. +extern void mark_inode_tr_dirty(struct inode *inode);
  11160. +#endif /* _LINUX_RFS_FS_H */
  11161. diff -NurbB linux-2.6.17.14.orig/include/linux/rfs_fs_i.h linux-2.6.17.14.rfs/include/linux/rfs_fs_i.h
  11162. --- linux-2.6.17.14.orig/include/linux/rfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100
  11163. +++ linux-2.6.17.14.rfs/include/linux/rfs_fs_i.h 2008-06-19 04:03:44.000000000 +0200
  11164. @@ -0,0 +1,79 @@
  11165. +/**
  11166. + * @file include/linux/rfs_fs_i.h
  11167. + * @brief header file for RFS inode
  11168. + *
  11169. + *---------------------------------------------------------------------------*
  11170. + * *
  11171. + * COPYRIGHT 2003-2007 SAMSUNG ELECTRONICS CO., LTD. *
  11172. + * ALL RIGHTS RESERVED *
  11173. + * *
  11174. + * Permission is hereby granted to licensees of Samsung Electronics *
  11175. + * Co., Ltd. products to use or abstract this computer program only in *
  11176. + * accordance with the terms of the NAND FLASH MEMORY SOFTWARE LICENSE *
  11177. + * AGREEMENT for the sole purpose of implementing a product based on *
  11178. + * Samsung Electronics Co., Ltd. products. No other rights to reproduce, *
  11179. + * use, or disseminate this computer program, whether in part or in *
  11180. + * whole, are granted. *
  11181. + * *
  11182. + * Samsung Electronics Co., Ltd. makes no representation or warranties *
  11183. + * with respect to the performance of this computer program, and *
  11184. + * specifically disclaims any responsibility for any damages, *
  11185. + * special or consequential, connected with the use of this program. *
  11186. + * *
  11187. + *---------------------------------------------------------------------------*
  11188. + */
  11189. +
  11190. +#ifndef _LINUX_RFS_FS_I
  11191. +#define _LINUX_RFS_FS_I
  11192. +
  11193. +#include <linux/timer.h>
  11194. +
  11195. +/*
  11196. + * RFS file system inode data in memory (in-core)
  11197. + */
  11198. +
  11199. +struct rfs_inode_info {
  11200. + __u32 start_clu; /* start cluster of inode */
  11201. + __u32 p_start_clu; /* parent directory start cluster */
  11202. + __u32 index; /* dir entry index(position) in directory */
  11203. + __u32 last_clu; /* last cluster number */
  11204. + __u8 i_state; /* rfs-specific inode state */
  11205. +
  11206. + /* hint for quick search */
  11207. + __u32 hint_last_clu;
  11208. + __u32 hint_last_offset;
  11209. +
  11210. + /* truncate point */
  11211. + unsigned long trunc_start;
  11212. +
  11213. + spinlock_t write_lock;
  11214. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
  11215. + /* total block size that inode allocated */
  11216. + loff_t mmu_private;
  11217. + struct inode vfs_inode;
  11218. +#else
  11219. + /* total block size that inode allocated */
  11220. + unsigned long mmu_private;
  11221. +
  11222. + /* ordered transaction */
  11223. + struct semaphore data_mutex;
  11224. + struct timer_list timer;
  11225. + struct task_struct *sleep_proc;
  11226. +#endif
  11227. +};
  11228. +
  11229. +/* get inode info */
  11230. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
  11231. +static inline struct rfs_inode_info *RFS_I(struct inode *inode)
  11232. +{
  11233. + return container_of(inode, struct rfs_inode_info, vfs_inode);
  11234. +}
  11235. +#else
  11236. +#define RFS_I(i) (&((i)->u.rfs_i))
  11237. +#endif
  11238. +
  11239. +/* rfs-specific inode state */
  11240. +#define RFS_I_ALLOC 0x00
  11241. +#define RFS_I_FREE 0x01
  11242. +
  11243. +#endif
  11244. diff -NurbB linux-2.6.17.14.orig/include/linux/rfs_fs_sb.h linux-2.6.17.14.rfs/include/linux/rfs_fs_sb.h
  11245. --- linux-2.6.17.14.orig/include/linux/rfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100
  11246. +++ linux-2.6.17.14.rfs/include/linux/rfs_fs_sb.h 2008-06-19 04:04:09.000000000 +0200
  11247. @@ -0,0 +1,98 @@
  11248. +/**
  11249. + * @file include/linux/rfs_fs_sb.h
  11250. + * @brief header file for RFS superblock
  11251. + *
  11252. + *---------------------------------------------------------------------------*
  11253. + * *
  11254. + * COPYRIGHT 2003-2007 SAMSUNG ELECTRONICS CO., LTD. *
  11255. + * ALL RIGHTS RESERVED *
  11256. + * *
  11257. + * Permission is hereby granted to licensees of Samsung Electronics *
  11258. + * Co., Ltd. products to use or abstract this computer program only in *
  11259. + * accordance with the terms of the NAND FLASH MEMORY SOFTWARE LICENSE *
  11260. + * AGREEMENT for the sole purpose of implementing a product based on *
  11261. + * Samsung Electronics Co., Ltd. products. No other rights to reproduce, *
  11262. + * use, or disseminate this computer program, whether in part or in *
  11263. + * whole, are granted. *
  11264. + * *
  11265. + * Samsung Electronics Co., Ltd. makes no representation or warranties *
  11266. + * with respect to the performance of this computer program, and *
  11267. + * specifically disclaims any responsibility for any damages, *
  11268. + * special or consequential, connected with the use of this program. *
  11269. + * *
  11270. + *---------------------------------------------------------------------------*
  11271. + */
  11272. +
  11273. +#ifndef _LINUX_RFS_FS_SB
  11274. +#define _LINUX_RFS_FS_SB
  11275. +
  11276. +#include <asm/semaphore.h>
  11277. +/*
  11278. + * RFS file system superblock data in memory(in-core)
  11279. + */
  11280. +
  11281. +/* rfs mount options */
  11282. +struct rfs_mount_info {
  11283. + char *codepage;
  11284. + __u32 isvfat;
  11285. +};
  11286. +
  11287. +/* rfs private data structure of sb */
  11288. +struct rfs_sb_info {
  11289. + __u32 fat_bits; /* FAT bits (12, 16 or 32) */
  11290. + __u32 blks_per_clu;
  11291. + __u32 blks_per_clu_bits;
  11292. + __u32 cluster_size;
  11293. + __u32 cluster_bits;
  11294. + __u32 num_clusters;
  11295. +
  11296. + __u32 fat_start_addr; /* start address of first FAT table */
  11297. +
  11298. + __u32 root_start_addr; /* start address of root directory */
  11299. + __u32 root_end_addr; /* end address of root directory */
  11300. +
  11301. + __u32 data_start; /* start block of data area */
  11302. +
  11303. + __u32 root_clu; /* root dir cluster, FAT16 = 0 */
  11304. + __u32 search_ptr; /* cluster search pointer */
  11305. + __u32 num_used_clusters; /* the number of used clusters */
  11306. +
  11307. + /* for FAT table */
  11308. + void *fat_mutex;
  11309. +
  11310. + struct rfs_mount_info options;
  11311. +
  11312. + /* RFS internal FAT cache */
  11313. + struct list_head fcache_lru_list;
  11314. + struct rfs_fcache *fcache_array;
  11315. +
  11316. + struct nls_table *nls_disk;
  11317. +
  11318. + /* fields for log */
  11319. + void *log_info; /* private for log structure */
  11320. +
  11321. + /* hint info for fast unlink */
  11322. + void *pool_info;
  11323. +
  11324. + /* chunk list for map destroy */
  11325. + struct list_head free_chunks;
  11326. +
  11327. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
  11328. + struct task_struct *sleep_proc;
  11329. + struct timer_list timer;
  11330. +#endif
  11331. +
  11332. + unsigned long highest_d_ino;
  11333. +};
  11334. +
  11335. +/* get super block info */
  11336. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
  11337. +static inline struct rfs_sb_info *RFS_SB(struct super_block *sb)
  11338. +{
  11339. + return sb->s_fs_info;
  11340. +}
  11341. +#else
  11342. +#define RFS_SB(s) (&((s)->u.rfs_sb))
  11343. +#endif
  11344. +
  11345. +#endif
  11346. diff -NurbB linux-2.6.17.14.orig/include/linux/xsr_if.h linux-2.6.17.14.rfs/include/linux/xsr_if.h
  11347. --- linux-2.6.17.14.orig/include/linux/xsr_if.h 1970-01-01 01:00:00.000000000 +0100
  11348. +++ linux-2.6.17.14.rfs/include/linux/xsr_if.h 2008-06-19 04:03:36.000000000 +0200
  11349. @@ -0,0 +1,151 @@
  11350. +/**
  11351. + * @file include/linux/xsr_if.h
  11352. + * @brief XSR interface to export commands and macros to utils, fat
  11353. + *
  11354. + *---------------------------------------------------------------------------*
  11355. + * *
  11356. + * COPYRIGHT 2003-2007 SAMSUNG ELECTRONICS CO., LTD. *
  11357. + * ALL RIGHTS RESERVED *
  11358. + * *
  11359. + * Permission is hereby granted to licensees of Samsung Electronics *
  11360. + * Co., Ltd. products to use or abstract this computer program only in *
  11361. + * accordance with the terms of the NAND FLASH MEMORY SOFTWARE LICENSE *
  11362. + * AGREEMENT for the sole purpose of implementing a product based on *
  11363. + * Samsung Electronics Co., Ltd. products. No other rights to reproduce, *
  11364. + * use, or disseminate this computer program, whether in part or in *
  11365. + * whole, are granted. *
  11366. + * *
  11367. + * Samsung Electronics Co., Ltd. makes no representation or warranties *
  11368. + * with respect to the performance of this computer program, and *
  11369. + * specifically disclaims any responsibility for any damages, *
  11370. + * special or consequential, connected with the use of this program. *
  11371. + * *
  11372. + *---------------------------------------------------------------------------*
  11373. + */
  11374. +#ifndef _XSR_IF_H_
  11375. +#define _XSR_IF_H_
  11376. +
  11377. +#ifndef __KERNEL__
  11378. +/*Warning*/
  11379. +/*If you modify BML, you must check this definition*/
  11380. +/*****************************************************************************/
  11381. +/* Partition Entry ID of BML_LoadPIEntry() */
  11382. +/* Partition Entry ID from 0 to 0x0FFFFFFF is reserved in BML */
  11383. +/* Following ID is the pre-defined value and User can use Partition Entry ID */
  11384. +/* from PARTITION_USER_DEF_BASE */
  11385. +/*****************************************************************************/
  11386. +#define PARTITION_ID_NBL1 0 /* NAND bootloader stage 1 */
  11387. +#define PARTITION_ID_NBL2 1 /* NAND bootloader stage 2 */
  11388. +#define PARTITION_ID_NBL3 2 /* NAND bootloader stage 3 */
  11389. +#define PARTITION_ID_COPIEDOS 3 /* OS image copied from NAND
  11390. + flash memory to RAM */
  11391. +#define PARTITION_ID_DEMANDONOS 4 /* OS image loaded on demand */
  11392. +
  11393. +#define PARTITION_ID_FILESYSTEM 8 /* file system 0 */
  11394. +#define PARTITION_ID_FILESYSTEM1 9 /* file system 1 */
  11395. +#define PARTITION_ID_FILESYSTEM2 10 /* file system 2 */
  11396. +#define PARTITION_ID_FILESYSTEM3 11 /* file system 3 */
  11397. +#define PARTITION_ID_FILESYSTEM4 12 /* file system 4 */
  11398. +#define PARTITION_ID_FILESYSTEM5 13 /* file system 5 */
  11399. +#define PARTITION_ID_FILESYSTEM6 14 /* file system 6 */
  11400. +#define PARTITION_ID_FILESYSTEM7 15 /* file system 7 */
  11401. +#define PARTITION_ID_FILESYSTEM8 16 /* file system 8 */
  11402. +#define PARTITION_ID_FILESYSTEM9 17 /* file system 9 */
  11403. +#define PARTITION_ID_FILESYSTEM10 18 /* file system 10 */
  11404. +#define PARTITION_ID_FILESYSTEM11 19 /* file system 11 */
  11405. +#define PARTITION_ID_FILESYSTEM12 20 /* file system 12 */
  11406. +#define PARTITION_ID_FILESYSTEM13 21 /* file system 13 */
  11407. +#define PARTITION_ID_FILESYSTEM14 22 /* file system 14 */
  11408. +
  11409. +#define PARTITION_USER_DEF_BASE 0x10000000 /* partition id base for
  11410. + user definition */
  11411. +
  11412. +/*****************************************************************************/
  11413. +/* value of nAttr of XSRPartEntry structure */
  11414. +/* nAttr can be 'BML_PI_ATTR_FROZEN + BML_PI_ATTR_RO' or */
  11415. +/* 'BML_PI_ATTR_RO' or */
  11416. +/* 'BML_PI_ATTR_RW'. */
  11417. +/* other value is invalid attribute. */
  11418. +/*****************************************************************************/
  11419. +#define BML_PI_ATTR_FROZEN 0x00000020
  11420. +#define BML_PI_ATTR_RO 0x00000002
  11421. +#define BML_PI_ATTR_RW 0x00000001
  11422. +
  11423. +#endif
  11424. +
  11425. +
  11426. +/**
  11427. + * This file define some macro and it will shared user and kernel
  11428. + */
  11429. +#ifdef CONFIG_XSR_DUAL_DEVICE
  11430. +#define XSR_MAX_DEVICES 2
  11431. +#else
  11432. +#define XSR_MAX_DEVICES 1
  11433. +#endif
  11434. +
  11435. +/* this is support 15 partition*/
  11436. +#define MASK(x) ((1U << (x)) -1)
  11437. +#define PARTN_BITS 4
  11438. +#define PARTN_MASK MASK(PARTN_BITS)
  11439. +#define MAX_FLASH_PARTITIONS ((0x1<< PARTN_BITS) - 1)
  11440. +#define MAX_PAGE_SIZE 2048
  11441. +#define MAX_OOB_SIZE 64
  11442. +
  11443. +/* Device major number*/
  11444. +#define XSR_BLK_DEVICE_RAW 137
  11445. +#define XSR_BLK_DEVICE_FTL 138
  11446. +/* distinguish chip and partition during dump and restore */
  11447. +#define XSR_CHIP 0xaabb
  11448. +#define XSR_PART 0xaacc
  11449. +#define MAGIC_STR_SIZE 8
  11450. +/* BML level ioctl commands */
  11451. +#define BML_GET_DEV_INFO 0x8A21
  11452. +#define BML_GET_PARTITION 0x8A22
  11453. +#define BML_SET_PARTITION 0x8A23
  11454. +#define BML_FORMAT 0x8A24
  11455. +#define BML_ERASE_ALL 0x8A25
  11456. +#define BML_ERASE_PARTITION 0x8A26
  11457. +#define BML_DUMP 0x8A27
  11458. +#define BML_RESTORE 0x8A28
  11459. +#define BML_UNLOCK_ALL 0x8A29
  11460. +#define BML_SET_RW_AREA 0x8A2A
  11461. +
  11462. +typedef struct {
  11463. + unsigned int offset;
  11464. + unsigned char mbuf[MAX_PAGE_SIZE];
  11465. + unsigned char sbuf[MAX_OOB_SIZE];
  11466. +} BML_PAGEINFO_T;
  11467. +
  11468. +typedef struct {
  11469. + int phy_blk_size; /* in bytes expect spare*/
  11470. + int num_blocks;
  11471. + int page_msize; /* main size in page */
  11472. + int page_ssize; /* spare size in page */
  11473. +} BML_DEVINFO_T;
  11474. +
  11475. +typedef struct {
  11476. + int num_parts;
  11477. + int part_size[MAX_FLASH_PARTITIONS]; /* in number of blocks */
  11478. + int part_id[MAX_FLASH_PARTITIONS]; /* device class */
  11479. + int part_attr[MAX_FLASH_PARTITIONS]; /* device class */
  11480. +} BML_PARTTAB_T;
  11481. +
  11482. +/* STL level ioctl commands */
  11483. +#define STL_FORMAT 0x8A01 /* FTL format */
  11484. +#define STL_GET_DEV_INFO 0x8A02 /* FTL stat */
  11485. +#define STL_CLEAN 0x8A03 /* FTL clean */
  11486. +#define STL_SYNC 0x8A13 /* FTL sync */
  11487. +#define STL_MAPDESTROY 0x8A14 /* FTL mapdestroy */
  11488. +
  11489. +typedef struct {
  11490. + unsigned int total_sectors;
  11491. + unsigned int page_size;
  11492. +}stl_info_t;
  11493. +
  11494. +typedef struct {
  11495. + unsigned int fill_factor;
  11496. + unsigned int nr_reserved_units;
  11497. + unsigned int blocks_per_unit;
  11498. +}stl_config_t;
  11499. +
  11500. +#endif /* _XSR_IF_H_ */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement