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