file.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:24k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/fs/affs/file.c
  3.  *
  4.  *  (c) 1996  Hans-Joachim Widmaier - Rewritten
  5.  *
  6.  *  (C) 1993  Ray Burr - Modified for Amiga FFS filesystem.
  7.  *
  8.  *  (C) 1992  Eric Youngdale Modified for ISO 9660 filesystem.
  9.  *
  10.  *  (C) 1991  Linus Torvalds - minix filesystem
  11.  *
  12.  *  affs regular file handling primitives
  13.  */
  14. #include <asm/div64.h>
  15. #include <asm/uaccess.h>
  16. #include <asm/system.h>
  17. #include <linux/sched.h>
  18. #include <linux/affs_fs.h>
  19. #include <linux/fcntl.h>
  20. #include <linux/kernel.h>
  21. #include <linux/errno.h>
  22. #include <linux/slab.h>
  23. #include <linux/stat.h>
  24. #include <linux/locks.h>
  25. #include <linux/smp_lock.h>
  26. #include <linux/dirent.h>
  27. #include <linux/fs.h>
  28. #include <linux/amigaffs.h>
  29. #include <linux/mm.h>
  30. #include <linux/pagemap.h>
  31. #if PAGE_SIZE < 4096
  32. #error PAGE_SIZE must be at least 4096
  33. #endif
  34. static int affs_grow_extcache(struct inode *inode, u32 lc_idx);
  35. static struct buffer_head *affs_alloc_extblock(struct inode *inode, struct buffer_head *bh, u32 ext);
  36. static inline struct buffer_head *affs_get_extblock(struct inode *inode, u32 ext);
  37. static struct buffer_head *affs_get_extblock_slow(struct inode *inode, u32 ext);
  38. static int affs_get_block(struct inode *inode, long block, struct buffer_head *bh_result, int create);
  39. static ssize_t affs_file_write(struct file *filp, const char *buf, size_t count, loff_t *ppos);
  40. static int affs_file_open(struct inode *inode, struct file *filp);
  41. static int affs_file_release(struct inode *inode, struct file *filp);
  42. struct file_operations affs_file_operations = {
  43. llseek: generic_file_llseek,
  44. read: generic_file_read,
  45. write: affs_file_write,
  46. mmap: generic_file_mmap,
  47. open: affs_file_open,
  48. release: affs_file_release,
  49. fsync: file_fsync,
  50. };
  51. struct inode_operations affs_file_inode_operations = {
  52. truncate: affs_truncate,
  53. setattr: affs_notify_change,
  54. };
  55. static int
  56. affs_file_open(struct inode *inode, struct file *filp)
  57. {
  58. if (atomic_read(&filp->f_count) != 1)
  59. return 0;
  60. pr_debug("AFFS: open(%d)n", AFFS_INODE->i_opencnt);
  61. AFFS_INODE->i_opencnt++;
  62. return 0;
  63. }
  64. static int
  65. affs_file_release(struct inode *inode, struct file *filp)
  66. {
  67. if (atomic_read(&filp->f_count) != 0)
  68. return 0;
  69. pr_debug("AFFS: release(%d)n", AFFS_INODE->i_opencnt);
  70. AFFS_INODE->i_opencnt--;
  71. if (!AFFS_INODE->i_opencnt)
  72. affs_free_prealloc(inode);
  73. return 0;
  74. }
  75. static int
  76. affs_grow_extcache(struct inode *inode, u32 lc_idx)
  77. {
  78. struct super_block *sb = inode->i_sb;
  79. struct buffer_head *bh;
  80. u32 lc_max;
  81. int i, j, key;
  82. if (!AFFS_INODE->i_lc) {
  83. char *ptr = (char *)get_zeroed_page(GFP_NOFS);
  84. if (!ptr)
  85. return -ENOMEM;
  86. AFFS_INODE->i_lc = (u32 *)ptr;
  87. AFFS_INODE->i_ac = (struct affs_ext_key *)(ptr + AFFS_CACHE_SIZE / 2);
  88. }
  89. lc_max = AFFS_LC_SIZE << AFFS_INODE->i_lc_shift;
  90. if (AFFS_INODE->i_extcnt > lc_max) {
  91. u32 lc_shift, lc_mask, tmp, off;
  92. /* need to recalculate linear cache, start from old size */
  93. lc_shift = AFFS_INODE->i_lc_shift;
  94. tmp = (AFFS_INODE->i_extcnt / AFFS_LC_SIZE) >> lc_shift;
  95. for (; tmp; tmp >>= 1)
  96. lc_shift++;
  97. lc_mask = (1 << lc_shift) - 1;
  98. /* fix idx and old size to new shift */
  99. lc_idx >>= (lc_shift - AFFS_INODE->i_lc_shift);
  100. AFFS_INODE->i_lc_size >>= (lc_shift - AFFS_INODE->i_lc_shift);
  101. /* first shrink old cache to make more space */
  102. off = 1 << (lc_shift - AFFS_INODE->i_lc_shift);
  103. for (i = 1, j = off; j < AFFS_LC_SIZE; i++, j += off)
  104. AFFS_INODE->i_ac[i] = AFFS_INODE->i_ac[j];
  105. AFFS_INODE->i_lc_shift = lc_shift;
  106. AFFS_INODE->i_lc_mask = lc_mask;
  107. }
  108. /* fill cache to the needed index */
  109. i = AFFS_INODE->i_lc_size;
  110. AFFS_INODE->i_lc_size = lc_idx + 1;
  111. for (; i <= lc_idx; i++) {
  112. if (!i) {
  113. AFFS_INODE->i_lc[0] = inode->i_ino;
  114. continue;
  115. }
  116. key = AFFS_INODE->i_lc[i - 1];
  117. j = AFFS_INODE->i_lc_mask + 1;
  118. // unlock cache
  119. for (; j > 0; j--) {
  120. bh = affs_bread(sb, key);
  121. if (!bh)
  122. goto err;
  123. key = be32_to_cpu(AFFS_TAIL(sb, bh)->extension);
  124. affs_brelse(bh);
  125. }
  126. // lock cache
  127. AFFS_INODE->i_lc[i] = key;
  128. }
  129. return 0;
  130. err:
  131. // lock cache
  132. return -EIO;
  133. }
  134. static struct buffer_head *
  135. affs_alloc_extblock(struct inode *inode, struct buffer_head *bh, u32 ext)
  136. {
  137. struct super_block *sb = inode->i_sb;
  138. struct buffer_head *new_bh;
  139. u32 blocknr, tmp;
  140. blocknr = affs_alloc_block(inode, bh->b_blocknr);
  141. if (!blocknr)
  142. return ERR_PTR(-ENOSPC);
  143. new_bh = affs_getzeroblk(sb, blocknr);
  144. if (!new_bh) {
  145. affs_free_block(sb, blocknr);
  146. return ERR_PTR(-EIO);
  147. }
  148. AFFS_HEAD(new_bh)->ptype = cpu_to_be32(T_LIST);
  149. AFFS_HEAD(new_bh)->key = cpu_to_be32(blocknr);
  150. AFFS_TAIL(sb, new_bh)->stype = cpu_to_be32(ST_FILE);
  151. AFFS_TAIL(sb, new_bh)->parent = cpu_to_be32(inode->i_ino);
  152. affs_fix_checksum(sb, new_bh);
  153. mark_buffer_dirty_inode(new_bh, inode);
  154. tmp = be32_to_cpu(AFFS_TAIL(sb, bh)->extension);
  155. if (tmp)
  156. affs_warning(sb, "alloc_ext", "previous extension set (%x)", tmp);
  157. AFFS_TAIL(sb, bh)->extension = cpu_to_be32(blocknr);
  158. affs_adjust_checksum(bh, blocknr - tmp);
  159. mark_buffer_dirty_inode(bh, inode);
  160. AFFS_INODE->i_extcnt++;
  161. mark_inode_dirty(inode);
  162. return new_bh;
  163. }
  164. static inline struct buffer_head *
  165. affs_get_extblock(struct inode *inode, u32 ext)
  166. {
  167. /* inline the simplest case: same extended block as last time */
  168. struct buffer_head *bh = AFFS_INODE->i_ext_bh;
  169. if (ext == AFFS_INODE->i_ext_last)
  170. atomic_inc(&bh->b_count);
  171. else
  172. /* we have to do more (not inlined) */
  173. bh = affs_get_extblock_slow(inode, ext);
  174. return bh;
  175. }
  176. static struct buffer_head *
  177. affs_get_extblock_slow(struct inode *inode, u32 ext)
  178. {
  179. struct super_block *sb = inode->i_sb;
  180. struct buffer_head *bh;
  181. u32 ext_key;
  182. u32 lc_idx, lc_off, ac_idx;
  183. u32 tmp, idx;
  184. if (ext == AFFS_INODE->i_ext_last + 1) {
  185. /* read the next extended block from the current one */
  186. bh = AFFS_INODE->i_ext_bh;
  187. ext_key = be32_to_cpu(AFFS_TAIL(sb, bh)->extension);
  188. if (ext < AFFS_INODE->i_extcnt)
  189. goto read_ext;
  190. if (ext > AFFS_INODE->i_extcnt)
  191. BUG();
  192. bh = affs_alloc_extblock(inode, bh, ext);
  193. if (IS_ERR(bh))
  194. return bh;
  195. goto store_ext;
  196. }
  197. if (ext == 0) {
  198. /* we seek back to the file header block */
  199. ext_key = inode->i_ino;
  200. goto read_ext;
  201. }
  202. if (ext >= AFFS_INODE->i_extcnt) {
  203. struct buffer_head *prev_bh;
  204. /* allocate a new extended block */
  205. if (ext > AFFS_INODE->i_extcnt)
  206. BUG();
  207. /* get previous extended block */
  208. prev_bh = affs_get_extblock(inode, ext - 1);
  209. if (IS_ERR(prev_bh))
  210. return prev_bh;
  211. bh = affs_alloc_extblock(inode, prev_bh, ext);
  212. affs_brelse(prev_bh);
  213. if (IS_ERR(bh))
  214. return bh;
  215. goto store_ext;
  216. }
  217. again:
  218. /* check if there is an extended cache and whether it's large enough */
  219. lc_idx = ext >> AFFS_INODE->i_lc_shift;
  220. lc_off = ext & AFFS_INODE->i_lc_mask;
  221. if (lc_idx >= AFFS_INODE->i_lc_size) {
  222. int err;
  223. err = affs_grow_extcache(inode, lc_idx);
  224. if (err)
  225. return ERR_PTR(err);
  226. goto again;
  227. }
  228. /* every n'th key we find in the linear cache */
  229. if (!lc_off) {
  230. ext_key = AFFS_INODE->i_lc[lc_idx];
  231. goto read_ext;
  232. }
  233. /* maybe it's still in the associative cache */
  234. ac_idx = (ext - lc_idx - 1) & AFFS_AC_MASK;
  235. if (AFFS_INODE->i_ac[ac_idx].ext == ext) {
  236. ext_key = AFFS_INODE->i_ac[ac_idx].key;
  237. goto read_ext;
  238. }
  239. /* try to find one of the previous extended blocks */
  240. tmp = ext;
  241. idx = ac_idx;
  242. while (--tmp, --lc_off > 0) {
  243. idx = (idx - 1) & AFFS_AC_MASK;
  244. if (AFFS_INODE->i_ac[idx].ext == tmp) {
  245. ext_key = AFFS_INODE->i_ac[idx].key;
  246. goto find_ext;
  247. }
  248. }
  249. /* fall back to the linear cache */
  250. ext_key = AFFS_INODE->i_lc[lc_idx];
  251. find_ext:
  252. /* read all extended blocks until we find the one we need */
  253. //unlock cache
  254. do {
  255. bh = affs_bread(sb, ext_key);
  256. if (!bh)
  257. goto err_bread;
  258. ext_key = be32_to_cpu(AFFS_TAIL(sb, bh)->extension);
  259. affs_brelse(bh);
  260. tmp++;
  261. } while (tmp < ext);
  262. //lock cache
  263. /* store it in the associative cache */
  264. // recalculate ac_idx?
  265. AFFS_INODE->i_ac[ac_idx].ext = ext;
  266. AFFS_INODE->i_ac[ac_idx].key = ext_key;
  267. read_ext:
  268. /* finally read the right extended block */
  269. //unlock cache
  270. bh = affs_bread(sb, ext_key);
  271. if (!bh)
  272. goto err_bread;
  273. //lock cache
  274. store_ext:
  275. /* release old cached extended block and store the new one */
  276. affs_brelse(AFFS_INODE->i_ext_bh);
  277. AFFS_INODE->i_ext_last = ext;
  278. AFFS_INODE->i_ext_bh = bh;
  279. atomic_inc(&bh->b_count);
  280. return bh;
  281. err_bread:
  282. affs_brelse(bh);
  283. return ERR_PTR(-EIO);
  284. }
  285. static int
  286. affs_get_block(struct inode *inode, long block, struct buffer_head *bh_result, int create)
  287. {
  288. struct super_block *sb = inode->i_sb;
  289. struct buffer_head *ext_bh;
  290. u32  ext;
  291. pr_debug("AFFS: get_block(%u, %ld)n", (u32)inode->i_ino, block);
  292. if (block < 0)
  293. goto err_small;
  294. if (block >= AFFS_INODE->i_blkcnt) {
  295. if (block > AFFS_INODE->i_blkcnt || !create)
  296. goto err_big;
  297. } else
  298. create = 0;
  299. //lock cache
  300. affs_lock_ext(inode);
  301. ext = block / AFFS_SB->s_hashsize;
  302. block -= ext * AFFS_SB->s_hashsize;
  303. ext_bh = affs_get_extblock(inode, ext);
  304. if (IS_ERR(ext_bh))
  305. goto err_ext;
  306. bh_result->b_blocknr = be32_to_cpu(AFFS_BLOCK(sb, ext_bh, block));
  307. bh_result->b_dev = inode->i_dev;
  308. bh_result->b_state |= (1UL << BH_Mapped);
  309. if (create) {
  310. u32 blocknr = affs_alloc_block(inode, ext_bh->b_blocknr);
  311. if (!blocknr)
  312. goto err_alloc;
  313. bh_result->b_state |= (1UL << BH_New);
  314. AFFS_INODE->mmu_private += AFFS_SB->s_data_blksize;
  315. AFFS_INODE->i_blkcnt++;
  316. /* store new block */
  317. if (bh_result->b_blocknr)
  318. affs_warning(sb, "get_block", "block already set (%x)", bh_result->b_blocknr);
  319. AFFS_BLOCK(sb, ext_bh, block) = cpu_to_be32(blocknr);
  320. AFFS_HEAD(ext_bh)->block_count = cpu_to_be32(block + 1);
  321. affs_adjust_checksum(ext_bh, blocknr - bh_result->b_blocknr + 1);
  322. bh_result->b_blocknr = blocknr;
  323. if (!block) {
  324. /* insert first block into header block */
  325. u32 tmp = be32_to_cpu(AFFS_HEAD(ext_bh)->first_data);
  326. if (tmp)
  327. affs_warning(sb, "get_block", "first block already set (%d)", tmp);
  328. AFFS_HEAD(ext_bh)->first_data = cpu_to_be32(blocknr);
  329. affs_adjust_checksum(ext_bh, blocknr - tmp);
  330. }
  331. }
  332. affs_brelse(ext_bh);
  333. //unlock cache
  334. affs_unlock_ext(inode);
  335. return 0;
  336. err_small:
  337. affs_error(inode->i_sb,"get_block","Block < 0");
  338. return -EIO;
  339. err_big:
  340. affs_error(inode->i_sb,"get_block","strange block request %d", block);
  341. return -EIO;
  342. err_ext:
  343. // unlock cache
  344. affs_unlock_ext(inode);
  345. return PTR_ERR(ext_bh);
  346. err_alloc:
  347. brelse(ext_bh);
  348. bh_result->b_state &= ~(1UL << BH_Mapped);
  349. // unlock cache
  350. affs_unlock_ext(inode);
  351. return -ENOSPC;
  352. }
  353. static int affs_writepage(struct page *page)
  354. {
  355. return block_write_full_page(page, affs_get_block);
  356. }
  357. static int affs_readpage(struct file *file, struct page *page)
  358. {
  359. return block_read_full_page(page, affs_get_block);
  360. }
  361. static int affs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
  362. {
  363. return cont_prepare_write(page, from, to, affs_get_block,
  364. &page->mapping->host->u.affs_i.mmu_private);
  365. }
  366. static int _affs_bmap(struct address_space *mapping, long block)
  367. {
  368. return generic_block_bmap(mapping,block,affs_get_block);
  369. }
  370. struct address_space_operations affs_aops = {
  371. readpage: affs_readpage,
  372. writepage: affs_writepage,
  373. sync_page: block_sync_page,
  374. prepare_write: affs_prepare_write,
  375. commit_write: generic_commit_write,
  376. bmap: _affs_bmap
  377. };
  378. static inline struct buffer_head *
  379. affs_bread_ino(struct inode *inode, int block, int create)
  380. {
  381. struct buffer_head *bh, tmp_bh;
  382. int err;
  383. tmp_bh.b_state = 0;
  384. err = affs_get_block(inode, block, &tmp_bh, create);
  385. if (!err) {
  386. bh = affs_bread(inode->i_sb, tmp_bh.b_blocknr);
  387. if (bh) {
  388. bh->b_state |= tmp_bh.b_state;
  389. return bh;
  390. }
  391. err = -EIO;
  392. }
  393. return ERR_PTR(err);
  394. }
  395. static inline struct buffer_head *
  396. affs_getzeroblk_ino(struct inode *inode, int block)
  397. {
  398. struct buffer_head *bh, tmp_bh;
  399. int err;
  400. tmp_bh.b_state = 0;
  401. err = affs_get_block(inode, block, &tmp_bh, 1);
  402. if (!err) {
  403. bh = affs_getzeroblk(inode->i_sb, tmp_bh.b_blocknr);
  404. if (bh) {
  405. bh->b_state |= tmp_bh.b_state;
  406. return bh;
  407. }
  408. err = -EIO;
  409. }
  410. return ERR_PTR(err);
  411. }
  412. static inline struct buffer_head *
  413. affs_getemptyblk_ino(struct inode *inode, int block)
  414. {
  415. struct buffer_head *bh, tmp_bh;
  416. int err;
  417. tmp_bh.b_state = 0;
  418. err = affs_get_block(inode, block, &tmp_bh, 1);
  419. if (!err) {
  420. bh = affs_getemptyblk(inode->i_sb, tmp_bh.b_blocknr);
  421. if (bh) {
  422. bh->b_state |= tmp_bh.b_state;
  423. return bh;
  424. }
  425. err = -EIO;
  426. }
  427. return ERR_PTR(err);
  428. }
  429. static ssize_t
  430. affs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
  431. {
  432. ssize_t retval;
  433. retval = generic_file_write (file, buf, count, ppos);
  434. if (retval >0) {
  435. struct inode *inode = file->f_dentry->d_inode;
  436. inode->i_ctime = inode->i_mtime = CURRENT_TIME;
  437. mark_inode_dirty(inode);
  438. }
  439. return retval;
  440. }
  441. static int
  442. affs_do_readpage_ofs(struct file *file, struct page *page, unsigned from, unsigned to)
  443. {
  444. struct inode *inode = page->mapping->host;
  445. struct super_block *sb = inode->i_sb;
  446. struct buffer_head *bh;
  447. char *data;
  448. u32 bidx, boff, bsize;
  449. u32 tmp;
  450. pr_debug("AFFS: read_page(%u, %ld, %d, %d)n", (u32)inode->i_ino, page->index, from, to);
  451. if (from > to || to > PAGE_CACHE_SIZE)
  452. BUG();
  453. data = page_address(page);
  454. bsize = AFFS_SB->s_data_blksize;
  455. tmp = (page->index << PAGE_CACHE_SHIFT) + from;
  456. bidx = tmp / bsize;
  457. boff = tmp % bsize;
  458. while (from < to) {
  459. bh = affs_bread_ino(inode, bidx, 0);
  460. if (IS_ERR(bh))
  461. return PTR_ERR(bh);
  462. tmp = min(bsize - boff, to - from);
  463. if (from + tmp > to || tmp > bsize)
  464. BUG();
  465. memcpy(data + from, AFFS_DATA(bh) + boff, tmp);
  466. affs_brelse(bh);
  467. bidx++;
  468. from += tmp;
  469. boff = 0;
  470. }
  471. return 0;
  472. }
  473. static int
  474. affs_extent_file_ofs(struct inode *inode, u32 newsize)
  475. {
  476. struct super_block *sb = inode->i_sb;
  477. struct buffer_head *bh, *prev_bh;
  478. u32 bidx, boff;
  479. u32 size, bsize;
  480. u32 tmp;
  481. pr_debug("AFFS: extent_file(%u, %d)n", (u32)inode->i_ino, newsize);
  482. bsize = AFFS_SB->s_data_blksize;
  483. bh = NULL;
  484. size = AFFS_INODE->mmu_private;
  485. bidx = size / bsize;
  486. boff = size % bsize;
  487. if (boff) {
  488. bh = affs_bread_ino(inode, bidx, 0);
  489. if (IS_ERR(bh))
  490. return PTR_ERR(bh);
  491. tmp = min(bsize - boff, newsize - size);
  492. if (boff + tmp > bsize || tmp > bsize)
  493. BUG();
  494. memset(AFFS_DATA(bh) + boff, 0, tmp);
  495. AFFS_DATA_HEAD(bh)->size = cpu_to_be32(be32_to_cpu(AFFS_DATA_HEAD(bh)->size) + tmp);
  496. affs_fix_checksum(sb, bh);
  497. mark_buffer_dirty_inode(bh, inode);
  498. size += tmp;
  499. bidx++;
  500. } else if (bidx) {
  501. bh = affs_bread_ino(inode, bidx - 1, 0);
  502. if (IS_ERR(bh))
  503. return PTR_ERR(bh);
  504. }
  505. while (size < newsize) {
  506. prev_bh = bh;
  507. bh = affs_getzeroblk_ino(inode, bidx);
  508. if (IS_ERR(bh))
  509. goto out;
  510. tmp = min(bsize, newsize - size);
  511. if (tmp > bsize)
  512. BUG();
  513. AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);
  514. AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino);
  515. AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx);
  516. AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp);
  517. affs_fix_checksum(sb, bh);
  518. bh->b_state &= ~(1UL << BH_New);
  519. mark_buffer_dirty_inode(bh, inode);
  520. if (prev_bh) {
  521. u32 tmp = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
  522. if (tmp)
  523. affs_warning(sb, "extent_file_ofs", "next block already set for %d (%d)", bidx, tmp);
  524. AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
  525. affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp);
  526. mark_buffer_dirty_inode(prev_bh, inode);
  527. affs_brelse(prev_bh);
  528. }
  529. size += bsize;
  530. bidx++;
  531. }
  532. affs_brelse(bh);
  533. inode->i_size = AFFS_INODE->mmu_private = newsize;
  534. return 0;
  535. out:
  536. inode->i_size = AFFS_INODE->mmu_private = size;
  537. return PTR_ERR(bh);
  538. }
  539. static int
  540. affs_readpage_ofs(struct file *file, struct page *page)
  541. {
  542. struct inode *inode = page->mapping->host;
  543. u32 to;
  544. int err;
  545. pr_debug("AFFS: read_page(%u, %ld)n", (u32)inode->i_ino, page->index);
  546. to = PAGE_CACHE_SIZE;
  547. if (((page->index + 1) << PAGE_CACHE_SHIFT) > inode->i_size) {
  548. to = inode->i_size & ~PAGE_CACHE_MASK;
  549. memset(page_address(page) + to, 0, PAGE_CACHE_SIZE - to);
  550. }
  551. err = affs_do_readpage_ofs(file, page, 0, to);
  552. if (!err)
  553. SetPageUptodate(page);
  554. UnlockPage(page);
  555. return err;
  556. }
  557. static int affs_prepare_write_ofs(struct file *file, struct page *page, unsigned from, unsigned to)
  558. {
  559. struct inode *inode = page->mapping->host;
  560. u32 size, offset;
  561. u32 tmp;
  562. int err = 0;
  563. pr_debug("AFFS: prepare_write(%u, %ld, %d, %d)n", (u32)inode->i_ino, page->index, from, to);
  564. offset = page->index << PAGE_CACHE_SHIFT;
  565. if (offset + from > AFFS_INODE->mmu_private) {
  566. err = affs_extent_file_ofs(inode, offset + from);
  567. if (err)
  568. return err;
  569. }
  570. size = inode->i_size;
  571. if (Page_Uptodate(page))
  572. return 0;
  573. if (from) {
  574. err = affs_do_readpage_ofs(file, page, 0, from);
  575. if (err)
  576. return err;
  577. }
  578. if (to < PAGE_CACHE_SIZE) {
  579. memset(page_address(page) + to, 0, PAGE_CACHE_SIZE - to);
  580. if (size > offset + to) {
  581. if (size < offset + PAGE_CACHE_SIZE)
  582. tmp = size & ~PAGE_CACHE_MASK;
  583. else
  584. tmp = PAGE_CACHE_SIZE;
  585. err = affs_do_readpage_ofs(file, page, to, tmp);
  586. }
  587. }
  588. return err;
  589. }
  590. static int affs_commit_write_ofs(struct file *file, struct page *page, unsigned from, unsigned to)
  591. {
  592. struct inode *inode = page->mapping->host;
  593. struct super_block *sb = inode->i_sb;
  594. struct buffer_head *bh, *prev_bh;
  595. char *data;
  596. u32 bidx, boff, bsize;
  597. u32 tmp;
  598. int written;
  599. pr_debug("AFFS: commit_write(%u, %ld, %d, %d)n", (u32)inode->i_ino, page->index, from, to);
  600. bsize = AFFS_SB->s_data_blksize;
  601. data = page_address(page);
  602. bh = NULL;
  603. written = 0;
  604. tmp = (page->index << PAGE_CACHE_SHIFT) + from;
  605. bidx = tmp / bsize;
  606. boff = tmp % bsize;
  607. if (boff) {
  608. bh = affs_bread_ino(inode, bidx, 0);
  609. if (IS_ERR(bh))
  610. return PTR_ERR(bh);
  611. tmp = min(bsize - boff, to - from);
  612. if (boff + tmp > bsize || tmp > bsize)
  613. BUG();
  614. memcpy(AFFS_DATA(bh) + boff, data + from, tmp);
  615. AFFS_DATA_HEAD(bh)->size = cpu_to_be32(be32_to_cpu(AFFS_DATA_HEAD(bh)->size) + tmp);
  616. affs_fix_checksum(sb, bh);
  617. mark_buffer_dirty_inode(bh, inode);
  618. written += tmp;
  619. from += tmp;
  620. bidx++;
  621. } else if (bidx) {
  622. bh = affs_bread_ino(inode, bidx - 1, 0);
  623. if (IS_ERR(bh))
  624. return PTR_ERR(bh);
  625. }
  626. while (from + bsize <= to) {
  627. prev_bh = bh;
  628. bh = affs_getemptyblk_ino(inode, bidx);
  629. if (IS_ERR(bh))
  630. goto out;
  631. memcpy(AFFS_DATA(bh), data + from, bsize);
  632. if (bh->b_state & (1UL << BH_New)) {
  633. AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);
  634. AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino);
  635. AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx);
  636. AFFS_DATA_HEAD(bh)->size = cpu_to_be32(bsize);
  637. AFFS_DATA_HEAD(bh)->next = 0;
  638. bh->b_state &= ~(1UL << BH_New);
  639. if (prev_bh) {
  640. u32 tmp = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
  641. if (tmp)
  642. affs_warning(sb, "commit_write_ofs", "next block already set for %d (%d)", bidx, tmp);
  643. AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
  644. affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp);
  645. mark_buffer_dirty_inode(prev_bh, inode);
  646. }
  647. }
  648. affs_brelse(prev_bh);
  649. affs_fix_checksum(sb, bh);
  650. mark_buffer_dirty_inode(bh, inode);
  651. written += bsize;
  652. from += bsize;
  653. bidx++;
  654. }
  655. if (from < to) {
  656. prev_bh = bh;
  657. bh = affs_bread_ino(inode, bidx, 1);
  658. if (IS_ERR(bh))
  659. goto out;
  660. tmp = min(bsize, to - from);
  661. if (tmp > bsize)
  662. BUG();
  663. memcpy(AFFS_DATA(bh), data + from, tmp);
  664. if (bh->b_state & (1UL << BH_New)) {
  665. AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);
  666. AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino);
  667. AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx);
  668. AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp);
  669. AFFS_DATA_HEAD(bh)->next = 0;
  670. bh->b_state &= ~(1UL << BH_New);
  671. if (prev_bh) {
  672. u32 tmp = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
  673. if (tmp)
  674. affs_warning(sb, "commit_write_ofs", "next block already set for %d (%d)", bidx, tmp);
  675. AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
  676. affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp);
  677. mark_buffer_dirty_inode(prev_bh, inode);
  678. }
  679. } else if (be32_to_cpu(AFFS_DATA_HEAD(bh)->size) < tmp)
  680. AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp);
  681. affs_brelse(prev_bh);
  682. affs_fix_checksum(sb, bh);
  683. mark_buffer_dirty_inode(bh, inode);
  684. written += tmp;
  685. from += tmp;
  686. bidx++;
  687. }
  688. SetPageUptodate(page);
  689. done:
  690. affs_brelse(bh);
  691. tmp = (page->index << PAGE_CACHE_SHIFT) + from;
  692. if (tmp > inode->i_size)
  693. inode->i_size = AFFS_INODE->mmu_private = tmp;
  694. return written;
  695. out:
  696. bh = prev_bh;
  697. if (!written)
  698. written = PTR_ERR(bh);
  699. goto done;
  700. }
  701. struct address_space_operations affs_aops_ofs = {
  702. readpage: affs_readpage_ofs,
  703. //writepage: affs_writepage_ofs,
  704. //sync_page: affs_sync_page_ofs,
  705. prepare_write: affs_prepare_write_ofs,
  706. commit_write: affs_commit_write_ofs
  707. };
  708. /* Free any preallocated blocks. */
  709. void
  710. affs_free_prealloc(struct inode *inode)
  711. {
  712. struct super_block *sb = inode->i_sb;
  713. pr_debug("AFFS: free_prealloc(ino=%lu)n", inode->i_ino);
  714. while (inode->u.affs_i.i_pa_cnt) {
  715. inode->u.affs_i.i_pa_cnt--;
  716. affs_free_block(sb, ++inode->u.affs_i.i_lastalloc);
  717. }
  718. }
  719. /* Truncate (or enlarge) a file to the requested size. */
  720. void
  721. affs_truncate(struct inode *inode)
  722. {
  723. struct super_block *sb = inode->i_sb;
  724. u32 ext, ext_key;
  725. u32 last_blk, blkcnt, blk;
  726. u32 size;
  727. struct buffer_head *ext_bh;
  728. int i;
  729. pr_debug("AFFS: truncate(inode=%d, oldsize=%u, newsize=%u)n",
  730.  (u32)inode->i_ino, (u32)AFFS_INODE->mmu_private, (u32)inode->i_size);
  731. last_blk = 0;
  732. ext = 0;
  733. if (inode->i_size) {
  734. last_blk = ((u32)inode->i_size - 1) / AFFS_SB->s_data_blksize;
  735. ext = last_blk / AFFS_SB->s_hashsize;
  736. }
  737. if (inode->i_size > AFFS_INODE->mmu_private) {
  738. struct address_space *mapping = inode->i_mapping;
  739. struct page *page;
  740. u32 size = inode->i_size - 1;
  741. int res;
  742. page = grab_cache_page(mapping, size >> PAGE_CACHE_SHIFT);
  743. if (!page)
  744. return;
  745. size = (size & (PAGE_CACHE_SIZE - 1)) + 1;
  746. res = mapping->a_ops->prepare_write(NULL, page, size, size);
  747. if (!res)
  748. res = mapping->a_ops->commit_write(NULL, page, size, size);
  749. UnlockPage(page);
  750. page_cache_release(page);
  751. mark_inode_dirty(inode);
  752. return;
  753. } else if (inode->i_size == AFFS_INODE->mmu_private)
  754. return;
  755. // lock cache
  756. ext_bh = affs_get_extblock(inode, ext);
  757. if (IS_ERR(ext_bh)) {
  758. affs_warning(sb, "truncate", "unexpected read error for ext block %u (%d)",
  759.      ext, PTR_ERR(ext_bh));
  760. return;
  761. }
  762. if (AFFS_INODE->i_lc) {
  763. /* clear linear cache */
  764. i = (ext + 1) >> AFFS_INODE->i_lc_shift;
  765. if (AFFS_INODE->i_lc_size > i) {
  766. AFFS_INODE->i_lc_size = i;
  767. for (; i < AFFS_LC_SIZE; i++)
  768. AFFS_INODE->i_lc[i] = 0;
  769. }
  770. /* clear associative cache */
  771. for (i = 0; i < AFFS_AC_SIZE; i++)
  772. if (AFFS_INODE->i_ac[i].ext >= ext)
  773. AFFS_INODE->i_ac[i].ext = 0;
  774. }
  775. ext_key = be32_to_cpu(AFFS_TAIL(sb, ext_bh)->extension);
  776. blkcnt = AFFS_INODE->i_blkcnt;
  777. i = 0;
  778. blk = last_blk;
  779. if (inode->i_size) {
  780. i = last_blk % AFFS_SB->s_hashsize + 1;
  781. blk++;
  782. } else
  783. AFFS_HEAD(ext_bh)->first_data = 0;
  784. size = AFFS_SB->s_hashsize;
  785. if (size > blkcnt - blk + i)
  786. size = blkcnt - blk + i;
  787. for (; i < size; i++, blk++) {
  788. affs_free_block(sb, be32_to_cpu(AFFS_BLOCK(sb, ext_bh, i)));
  789. AFFS_BLOCK(sb, ext_bh, i) = 0;
  790. }
  791. AFFS_TAIL(sb, ext_bh)->extension = 0;
  792. affs_fix_checksum(sb, ext_bh);
  793. mark_buffer_dirty_inode(ext_bh, inode);
  794. affs_brelse(ext_bh);
  795. if (inode->i_size) {
  796. AFFS_INODE->i_blkcnt = last_blk + 1;
  797. AFFS_INODE->i_extcnt = ext + 1;
  798. if (AFFS_SB->s_flags & SF_OFS) {
  799. struct buffer_head *bh = affs_bread_ino(inode, last_blk, 0);
  800. u32 tmp;
  801. if (IS_ERR(bh)) {
  802. affs_warning(sb, "truncate", "unexpected read error for last block %u (%d)",
  803.      last_blk, PTR_ERR(bh));
  804. return;
  805. }
  806. tmp = be32_to_cpu(AFFS_DATA_HEAD(bh)->next);
  807. AFFS_DATA_HEAD(bh)->next = 0;
  808. affs_adjust_checksum(bh, -tmp);
  809. affs_brelse(bh);
  810. }
  811. } else {
  812. AFFS_INODE->i_blkcnt = 0;
  813. AFFS_INODE->i_extcnt = 1;
  814. }
  815. AFFS_INODE->mmu_private = inode->i_size;
  816. // unlock cache
  817. while (ext_key) {
  818. ext_bh = affs_bread(sb, ext_key);
  819. size = AFFS_SB->s_hashsize;
  820. if (size > blkcnt - blk)
  821. size = blkcnt - blk;
  822. for (i = 0; i < size; i++, blk++)
  823. affs_free_block(sb, be32_to_cpu(AFFS_BLOCK(sb, ext_bh, i)));
  824. affs_free_block(sb, ext_key);
  825. ext_key = be32_to_cpu(AFFS_TAIL(sb, ext_bh)->extension);
  826. affs_brelse(ext_bh);
  827. }
  828. affs_free_prealloc(inode);
  829. }