0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <linux/uio.h>
0017 #include <linux/blkdev.h>
0018 #include "affs.h"
0019
0020 static struct buffer_head *affs_get_extblock_slow(struct inode *inode, u32 ext);
0021
0022 static int
0023 affs_file_open(struct inode *inode, struct file *filp)
0024 {
0025 pr_debug("open(%lu,%d)\n",
0026 inode->i_ino, atomic_read(&AFFS_I(inode)->i_opencnt));
0027 atomic_inc(&AFFS_I(inode)->i_opencnt);
0028 return 0;
0029 }
0030
0031 static int
0032 affs_file_release(struct inode *inode, struct file *filp)
0033 {
0034 pr_debug("release(%lu, %d)\n",
0035 inode->i_ino, atomic_read(&AFFS_I(inode)->i_opencnt));
0036
0037 if (atomic_dec_and_test(&AFFS_I(inode)->i_opencnt)) {
0038 inode_lock(inode);
0039 if (inode->i_size != AFFS_I(inode)->mmu_private)
0040 affs_truncate(inode);
0041 affs_free_prealloc(inode);
0042 inode_unlock(inode);
0043 }
0044
0045 return 0;
0046 }
0047
0048 static int
0049 affs_grow_extcache(struct inode *inode, u32 lc_idx)
0050 {
0051 struct super_block *sb = inode->i_sb;
0052 struct buffer_head *bh;
0053 u32 lc_max;
0054 int i, j, key;
0055
0056 if (!AFFS_I(inode)->i_lc) {
0057 char *ptr = (char *)get_zeroed_page(GFP_NOFS);
0058 if (!ptr)
0059 return -ENOMEM;
0060 AFFS_I(inode)->i_lc = (u32 *)ptr;
0061 AFFS_I(inode)->i_ac = (struct affs_ext_key *)(ptr + AFFS_CACHE_SIZE / 2);
0062 }
0063
0064 lc_max = AFFS_LC_SIZE << AFFS_I(inode)->i_lc_shift;
0065
0066 if (AFFS_I(inode)->i_extcnt > lc_max) {
0067 u32 lc_shift, lc_mask, tmp, off;
0068
0069
0070 lc_shift = AFFS_I(inode)->i_lc_shift;
0071 tmp = (AFFS_I(inode)->i_extcnt / AFFS_LC_SIZE) >> lc_shift;
0072 for (; tmp; tmp >>= 1)
0073 lc_shift++;
0074 lc_mask = (1 << lc_shift) - 1;
0075
0076
0077 lc_idx >>= (lc_shift - AFFS_I(inode)->i_lc_shift);
0078 AFFS_I(inode)->i_lc_size >>= (lc_shift - AFFS_I(inode)->i_lc_shift);
0079
0080
0081 off = 1 << (lc_shift - AFFS_I(inode)->i_lc_shift);
0082 for (i = 1, j = off; j < AFFS_LC_SIZE; i++, j += off)
0083 AFFS_I(inode)->i_ac[i] = AFFS_I(inode)->i_ac[j];
0084
0085 AFFS_I(inode)->i_lc_shift = lc_shift;
0086 AFFS_I(inode)->i_lc_mask = lc_mask;
0087 }
0088
0089
0090 i = AFFS_I(inode)->i_lc_size;
0091 AFFS_I(inode)->i_lc_size = lc_idx + 1;
0092 for (; i <= lc_idx; i++) {
0093 if (!i) {
0094 AFFS_I(inode)->i_lc[0] = inode->i_ino;
0095 continue;
0096 }
0097 key = AFFS_I(inode)->i_lc[i - 1];
0098 j = AFFS_I(inode)->i_lc_mask + 1;
0099
0100 for (; j > 0; j--) {
0101 bh = affs_bread(sb, key);
0102 if (!bh)
0103 goto err;
0104 key = be32_to_cpu(AFFS_TAIL(sb, bh)->extension);
0105 affs_brelse(bh);
0106 }
0107
0108 AFFS_I(inode)->i_lc[i] = key;
0109 }
0110
0111 return 0;
0112
0113 err:
0114
0115 return -EIO;
0116 }
0117
0118 static struct buffer_head *
0119 affs_alloc_extblock(struct inode *inode, struct buffer_head *bh, u32 ext)
0120 {
0121 struct super_block *sb = inode->i_sb;
0122 struct buffer_head *new_bh;
0123 u32 blocknr, tmp;
0124
0125 blocknr = affs_alloc_block(inode, bh->b_blocknr);
0126 if (!blocknr)
0127 return ERR_PTR(-ENOSPC);
0128
0129 new_bh = affs_getzeroblk(sb, blocknr);
0130 if (!new_bh) {
0131 affs_free_block(sb, blocknr);
0132 return ERR_PTR(-EIO);
0133 }
0134
0135 AFFS_HEAD(new_bh)->ptype = cpu_to_be32(T_LIST);
0136 AFFS_HEAD(new_bh)->key = cpu_to_be32(blocknr);
0137 AFFS_TAIL(sb, new_bh)->stype = cpu_to_be32(ST_FILE);
0138 AFFS_TAIL(sb, new_bh)->parent = cpu_to_be32(inode->i_ino);
0139 affs_fix_checksum(sb, new_bh);
0140
0141 mark_buffer_dirty_inode(new_bh, inode);
0142
0143 tmp = be32_to_cpu(AFFS_TAIL(sb, bh)->extension);
0144 if (tmp)
0145 affs_warning(sb, "alloc_ext", "previous extension set (%x)", tmp);
0146 AFFS_TAIL(sb, bh)->extension = cpu_to_be32(blocknr);
0147 affs_adjust_checksum(bh, blocknr - tmp);
0148 mark_buffer_dirty_inode(bh, inode);
0149
0150 AFFS_I(inode)->i_extcnt++;
0151 mark_inode_dirty(inode);
0152
0153 return new_bh;
0154 }
0155
0156 static inline struct buffer_head *
0157 affs_get_extblock(struct inode *inode, u32 ext)
0158 {
0159
0160 struct buffer_head *bh = AFFS_I(inode)->i_ext_bh;
0161 if (ext == AFFS_I(inode)->i_ext_last)
0162 get_bh(bh);
0163 else
0164
0165 bh = affs_get_extblock_slow(inode, ext);
0166
0167 return bh;
0168 }
0169
0170 static struct buffer_head *
0171 affs_get_extblock_slow(struct inode *inode, u32 ext)
0172 {
0173 struct super_block *sb = inode->i_sb;
0174 struct buffer_head *bh;
0175 u32 ext_key;
0176 u32 lc_idx, lc_off, ac_idx;
0177 u32 tmp, idx;
0178
0179 if (ext == AFFS_I(inode)->i_ext_last + 1) {
0180
0181 bh = AFFS_I(inode)->i_ext_bh;
0182 ext_key = be32_to_cpu(AFFS_TAIL(sb, bh)->extension);
0183 if (ext < AFFS_I(inode)->i_extcnt)
0184 goto read_ext;
0185 BUG_ON(ext > AFFS_I(inode)->i_extcnt);
0186 bh = affs_alloc_extblock(inode, bh, ext);
0187 if (IS_ERR(bh))
0188 return bh;
0189 goto store_ext;
0190 }
0191
0192 if (ext == 0) {
0193
0194 ext_key = inode->i_ino;
0195 goto read_ext;
0196 }
0197
0198 if (ext >= AFFS_I(inode)->i_extcnt) {
0199 struct buffer_head *prev_bh;
0200
0201
0202 BUG_ON(ext > AFFS_I(inode)->i_extcnt);
0203
0204
0205 prev_bh = affs_get_extblock(inode, ext - 1);
0206 if (IS_ERR(prev_bh))
0207 return prev_bh;
0208 bh = affs_alloc_extblock(inode, prev_bh, ext);
0209 affs_brelse(prev_bh);
0210 if (IS_ERR(bh))
0211 return bh;
0212 goto store_ext;
0213 }
0214
0215 again:
0216
0217 lc_idx = ext >> AFFS_I(inode)->i_lc_shift;
0218 lc_off = ext & AFFS_I(inode)->i_lc_mask;
0219
0220 if (lc_idx >= AFFS_I(inode)->i_lc_size) {
0221 int err;
0222
0223 err = affs_grow_extcache(inode, lc_idx);
0224 if (err)
0225 return ERR_PTR(err);
0226 goto again;
0227 }
0228
0229
0230 if (!lc_off) {
0231 ext_key = AFFS_I(inode)->i_lc[lc_idx];
0232 goto read_ext;
0233 }
0234
0235
0236 ac_idx = (ext - lc_idx - 1) & AFFS_AC_MASK;
0237 if (AFFS_I(inode)->i_ac[ac_idx].ext == ext) {
0238 ext_key = AFFS_I(inode)->i_ac[ac_idx].key;
0239 goto read_ext;
0240 }
0241
0242
0243 tmp = ext;
0244 idx = ac_idx;
0245 while (--tmp, --lc_off > 0) {
0246 idx = (idx - 1) & AFFS_AC_MASK;
0247 if (AFFS_I(inode)->i_ac[idx].ext == tmp) {
0248 ext_key = AFFS_I(inode)->i_ac[idx].key;
0249 goto find_ext;
0250 }
0251 }
0252
0253
0254 ext_key = AFFS_I(inode)->i_lc[lc_idx];
0255 find_ext:
0256
0257
0258 do {
0259 bh = affs_bread(sb, ext_key);
0260 if (!bh)
0261 goto err_bread;
0262 ext_key = be32_to_cpu(AFFS_TAIL(sb, bh)->extension);
0263 affs_brelse(bh);
0264 tmp++;
0265 } while (tmp < ext);
0266
0267
0268
0269
0270 AFFS_I(inode)->i_ac[ac_idx].ext = ext;
0271 AFFS_I(inode)->i_ac[ac_idx].key = ext_key;
0272
0273 read_ext:
0274
0275
0276 bh = affs_bread(sb, ext_key);
0277 if (!bh)
0278 goto err_bread;
0279
0280
0281 store_ext:
0282
0283 affs_brelse(AFFS_I(inode)->i_ext_bh);
0284 AFFS_I(inode)->i_ext_last = ext;
0285 AFFS_I(inode)->i_ext_bh = bh;
0286 get_bh(bh);
0287
0288 return bh;
0289
0290 err_bread:
0291 affs_brelse(bh);
0292 return ERR_PTR(-EIO);
0293 }
0294
0295 static int
0296 affs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh_result, int create)
0297 {
0298 struct super_block *sb = inode->i_sb;
0299 struct buffer_head *ext_bh;
0300 u32 ext;
0301
0302 pr_debug("%s(%lu, %llu)\n", __func__, inode->i_ino,
0303 (unsigned long long)block);
0304
0305 BUG_ON(block > (sector_t)0x7fffffffUL);
0306
0307 if (block >= AFFS_I(inode)->i_blkcnt) {
0308 if (block > AFFS_I(inode)->i_blkcnt || !create)
0309 goto err_big;
0310 } else
0311 create = 0;
0312
0313
0314 affs_lock_ext(inode);
0315
0316 ext = (u32)block / AFFS_SB(sb)->s_hashsize;
0317 block -= ext * AFFS_SB(sb)->s_hashsize;
0318 ext_bh = affs_get_extblock(inode, ext);
0319 if (IS_ERR(ext_bh))
0320 goto err_ext;
0321 map_bh(bh_result, sb, (sector_t)be32_to_cpu(AFFS_BLOCK(sb, ext_bh, block)));
0322
0323 if (create) {
0324 u32 blocknr = affs_alloc_block(inode, ext_bh->b_blocknr);
0325 if (!blocknr)
0326 goto err_alloc;
0327 set_buffer_new(bh_result);
0328 AFFS_I(inode)->mmu_private += AFFS_SB(sb)->s_data_blksize;
0329 AFFS_I(inode)->i_blkcnt++;
0330
0331
0332 if (bh_result->b_blocknr)
0333 affs_warning(sb, "get_block",
0334 "block already set (%llx)",
0335 (unsigned long long)bh_result->b_blocknr);
0336 AFFS_BLOCK(sb, ext_bh, block) = cpu_to_be32(blocknr);
0337 AFFS_HEAD(ext_bh)->block_count = cpu_to_be32(block + 1);
0338 affs_adjust_checksum(ext_bh, blocknr - bh_result->b_blocknr + 1);
0339 bh_result->b_blocknr = blocknr;
0340
0341 if (!block) {
0342
0343 u32 tmp = be32_to_cpu(AFFS_HEAD(ext_bh)->first_data);
0344 if (tmp)
0345 affs_warning(sb, "get_block", "first block already set (%d)", tmp);
0346 AFFS_HEAD(ext_bh)->first_data = cpu_to_be32(blocknr);
0347 affs_adjust_checksum(ext_bh, blocknr - tmp);
0348 }
0349 }
0350
0351 affs_brelse(ext_bh);
0352
0353 affs_unlock_ext(inode);
0354 return 0;
0355
0356 err_big:
0357 affs_error(inode->i_sb, "get_block", "strange block request %llu",
0358 (unsigned long long)block);
0359 return -EIO;
0360 err_ext:
0361
0362 affs_unlock_ext(inode);
0363 return PTR_ERR(ext_bh);
0364 err_alloc:
0365 brelse(ext_bh);
0366 clear_buffer_mapped(bh_result);
0367 bh_result->b_bdev = NULL;
0368
0369 affs_unlock_ext(inode);
0370 return -ENOSPC;
0371 }
0372
0373 static int affs_writepage(struct page *page, struct writeback_control *wbc)
0374 {
0375 return block_write_full_page(page, affs_get_block, wbc);
0376 }
0377
0378 static int affs_read_folio(struct file *file, struct folio *folio)
0379 {
0380 return block_read_full_folio(folio, affs_get_block);
0381 }
0382
0383 static void affs_write_failed(struct address_space *mapping, loff_t to)
0384 {
0385 struct inode *inode = mapping->host;
0386
0387 if (to > inode->i_size) {
0388 truncate_pagecache(inode, inode->i_size);
0389 affs_truncate(inode);
0390 }
0391 }
0392
0393 static ssize_t
0394 affs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
0395 {
0396 struct file *file = iocb->ki_filp;
0397 struct address_space *mapping = file->f_mapping;
0398 struct inode *inode = mapping->host;
0399 size_t count = iov_iter_count(iter);
0400 loff_t offset = iocb->ki_pos;
0401 ssize_t ret;
0402
0403 if (iov_iter_rw(iter) == WRITE) {
0404 loff_t size = offset + count;
0405
0406 if (AFFS_I(inode)->mmu_private < size)
0407 return 0;
0408 }
0409
0410 ret = blockdev_direct_IO(iocb, inode, iter, affs_get_block);
0411 if (ret < 0 && iov_iter_rw(iter) == WRITE)
0412 affs_write_failed(mapping, offset + count);
0413 return ret;
0414 }
0415
0416 static int affs_write_begin(struct file *file, struct address_space *mapping,
0417 loff_t pos, unsigned len,
0418 struct page **pagep, void **fsdata)
0419 {
0420 int ret;
0421
0422 *pagep = NULL;
0423 ret = cont_write_begin(file, mapping, pos, len, pagep, fsdata,
0424 affs_get_block,
0425 &AFFS_I(mapping->host)->mmu_private);
0426 if (unlikely(ret))
0427 affs_write_failed(mapping, pos + len);
0428
0429 return ret;
0430 }
0431
0432 static int affs_write_end(struct file *file, struct address_space *mapping,
0433 loff_t pos, unsigned int len, unsigned int copied,
0434 struct page *page, void *fsdata)
0435 {
0436 struct inode *inode = mapping->host;
0437 int ret;
0438
0439 ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
0440
0441
0442 if (AFFS_I(inode)->i_protect & FIBF_ARCHIVED) {
0443 AFFS_I(inode)->i_protect &= ~FIBF_ARCHIVED;
0444 mark_inode_dirty(inode);
0445 }
0446
0447 return ret;
0448 }
0449
0450 static sector_t _affs_bmap(struct address_space *mapping, sector_t block)
0451 {
0452 return generic_block_bmap(mapping,block,affs_get_block);
0453 }
0454
0455 const struct address_space_operations affs_aops = {
0456 .dirty_folio = block_dirty_folio,
0457 .invalidate_folio = block_invalidate_folio,
0458 .read_folio = affs_read_folio,
0459 .writepage = affs_writepage,
0460 .write_begin = affs_write_begin,
0461 .write_end = affs_write_end,
0462 .direct_IO = affs_direct_IO,
0463 .bmap = _affs_bmap
0464 };
0465
0466 static inline struct buffer_head *
0467 affs_bread_ino(struct inode *inode, int block, int create)
0468 {
0469 struct buffer_head *bh, tmp_bh;
0470 int err;
0471
0472 tmp_bh.b_state = 0;
0473 err = affs_get_block(inode, block, &tmp_bh, create);
0474 if (!err) {
0475 bh = affs_bread(inode->i_sb, tmp_bh.b_blocknr);
0476 if (bh) {
0477 bh->b_state |= tmp_bh.b_state;
0478 return bh;
0479 }
0480 err = -EIO;
0481 }
0482 return ERR_PTR(err);
0483 }
0484
0485 static inline struct buffer_head *
0486 affs_getzeroblk_ino(struct inode *inode, int block)
0487 {
0488 struct buffer_head *bh, tmp_bh;
0489 int err;
0490
0491 tmp_bh.b_state = 0;
0492 err = affs_get_block(inode, block, &tmp_bh, 1);
0493 if (!err) {
0494 bh = affs_getzeroblk(inode->i_sb, tmp_bh.b_blocknr);
0495 if (bh) {
0496 bh->b_state |= tmp_bh.b_state;
0497 return bh;
0498 }
0499 err = -EIO;
0500 }
0501 return ERR_PTR(err);
0502 }
0503
0504 static inline struct buffer_head *
0505 affs_getemptyblk_ino(struct inode *inode, int block)
0506 {
0507 struct buffer_head *bh, tmp_bh;
0508 int err;
0509
0510 tmp_bh.b_state = 0;
0511 err = affs_get_block(inode, block, &tmp_bh, 1);
0512 if (!err) {
0513 bh = affs_getemptyblk(inode->i_sb, tmp_bh.b_blocknr);
0514 if (bh) {
0515 bh->b_state |= tmp_bh.b_state;
0516 return bh;
0517 }
0518 err = -EIO;
0519 }
0520 return ERR_PTR(err);
0521 }
0522
0523 static int
0524 affs_do_readpage_ofs(struct page *page, unsigned to, int create)
0525 {
0526 struct inode *inode = page->mapping->host;
0527 struct super_block *sb = inode->i_sb;
0528 struct buffer_head *bh;
0529 unsigned pos = 0;
0530 u32 bidx, boff, bsize;
0531 u32 tmp;
0532
0533 pr_debug("%s(%lu, %ld, 0, %d)\n", __func__, inode->i_ino,
0534 page->index, to);
0535 BUG_ON(to > PAGE_SIZE);
0536 bsize = AFFS_SB(sb)->s_data_blksize;
0537 tmp = page->index << PAGE_SHIFT;
0538 bidx = tmp / bsize;
0539 boff = tmp % bsize;
0540
0541 while (pos < to) {
0542 bh = affs_bread_ino(inode, bidx, create);
0543 if (IS_ERR(bh))
0544 return PTR_ERR(bh);
0545 tmp = min(bsize - boff, to - pos);
0546 BUG_ON(pos + tmp > to || tmp > bsize);
0547 memcpy_to_page(page, pos, AFFS_DATA(bh) + boff, tmp);
0548 affs_brelse(bh);
0549 bidx++;
0550 pos += tmp;
0551 boff = 0;
0552 }
0553 return 0;
0554 }
0555
0556 static int
0557 affs_extent_file_ofs(struct inode *inode, u32 newsize)
0558 {
0559 struct super_block *sb = inode->i_sb;
0560 struct buffer_head *bh, *prev_bh;
0561 u32 bidx, boff;
0562 u32 size, bsize;
0563 u32 tmp;
0564
0565 pr_debug("%s(%lu, %d)\n", __func__, inode->i_ino, newsize);
0566 bsize = AFFS_SB(sb)->s_data_blksize;
0567 bh = NULL;
0568 size = AFFS_I(inode)->mmu_private;
0569 bidx = size / bsize;
0570 boff = size % bsize;
0571 if (boff) {
0572 bh = affs_bread_ino(inode, bidx, 0);
0573 if (IS_ERR(bh))
0574 return PTR_ERR(bh);
0575 tmp = min(bsize - boff, newsize - size);
0576 BUG_ON(boff + tmp > bsize || tmp > bsize);
0577 memset(AFFS_DATA(bh) + boff, 0, tmp);
0578 be32_add_cpu(&AFFS_DATA_HEAD(bh)->size, tmp);
0579 affs_fix_checksum(sb, bh);
0580 mark_buffer_dirty_inode(bh, inode);
0581 size += tmp;
0582 bidx++;
0583 } else if (bidx) {
0584 bh = affs_bread_ino(inode, bidx - 1, 0);
0585 if (IS_ERR(bh))
0586 return PTR_ERR(bh);
0587 }
0588
0589 while (size < newsize) {
0590 prev_bh = bh;
0591 bh = affs_getzeroblk_ino(inode, bidx);
0592 if (IS_ERR(bh))
0593 goto out;
0594 tmp = min(bsize, newsize - size);
0595 BUG_ON(tmp > bsize);
0596 AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);
0597 AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino);
0598 AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx);
0599 AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp);
0600 affs_fix_checksum(sb, bh);
0601 bh->b_state &= ~(1UL << BH_New);
0602 mark_buffer_dirty_inode(bh, inode);
0603 if (prev_bh) {
0604 u32 tmp_next = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
0605
0606 if (tmp_next)
0607 affs_warning(sb, "extent_file_ofs",
0608 "next block already set for %d (%d)",
0609 bidx, tmp_next);
0610 AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
0611 affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp_next);
0612 mark_buffer_dirty_inode(prev_bh, inode);
0613 affs_brelse(prev_bh);
0614 }
0615 size += bsize;
0616 bidx++;
0617 }
0618 affs_brelse(bh);
0619 inode->i_size = AFFS_I(inode)->mmu_private = newsize;
0620 return 0;
0621
0622 out:
0623 inode->i_size = AFFS_I(inode)->mmu_private = newsize;
0624 return PTR_ERR(bh);
0625 }
0626
0627 static int
0628 affs_read_folio_ofs(struct file *file, struct folio *folio)
0629 {
0630 struct page *page = &folio->page;
0631 struct inode *inode = page->mapping->host;
0632 u32 to;
0633 int err;
0634
0635 pr_debug("%s(%lu, %ld)\n", __func__, inode->i_ino, page->index);
0636 to = PAGE_SIZE;
0637 if (((page->index + 1) << PAGE_SHIFT) > inode->i_size) {
0638 to = inode->i_size & ~PAGE_MASK;
0639 memset(page_address(page) + to, 0, PAGE_SIZE - to);
0640 }
0641
0642 err = affs_do_readpage_ofs(page, to, 0);
0643 if (!err)
0644 SetPageUptodate(page);
0645 unlock_page(page);
0646 return err;
0647 }
0648
0649 static int affs_write_begin_ofs(struct file *file, struct address_space *mapping,
0650 loff_t pos, unsigned len,
0651 struct page **pagep, void **fsdata)
0652 {
0653 struct inode *inode = mapping->host;
0654 struct page *page;
0655 pgoff_t index;
0656 int err = 0;
0657
0658 pr_debug("%s(%lu, %llu, %llu)\n", __func__, inode->i_ino, pos,
0659 pos + len);
0660 if (pos > AFFS_I(inode)->mmu_private) {
0661
0662
0663
0664 err = affs_extent_file_ofs(inode, pos);
0665 if (err)
0666 return err;
0667 }
0668
0669 index = pos >> PAGE_SHIFT;
0670 page = grab_cache_page_write_begin(mapping, index);
0671 if (!page)
0672 return -ENOMEM;
0673 *pagep = page;
0674
0675 if (PageUptodate(page))
0676 return 0;
0677
0678
0679 err = affs_do_readpage_ofs(page, PAGE_SIZE, 1);
0680 if (err) {
0681 unlock_page(page);
0682 put_page(page);
0683 }
0684 return err;
0685 }
0686
0687 static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
0688 loff_t pos, unsigned len, unsigned copied,
0689 struct page *page, void *fsdata)
0690 {
0691 struct inode *inode = mapping->host;
0692 struct super_block *sb = inode->i_sb;
0693 struct buffer_head *bh, *prev_bh;
0694 char *data;
0695 u32 bidx, boff, bsize;
0696 unsigned from, to;
0697 u32 tmp;
0698 int written;
0699
0700 from = pos & (PAGE_SIZE - 1);
0701 to = from + len;
0702
0703
0704
0705
0706
0707
0708 pr_debug("%s(%lu, %llu, %llu)\n", __func__, inode->i_ino, pos,
0709 pos + len);
0710 bsize = AFFS_SB(sb)->s_data_blksize;
0711 data = page_address(page);
0712
0713 bh = NULL;
0714 written = 0;
0715 tmp = (page->index << PAGE_SHIFT) + from;
0716 bidx = tmp / bsize;
0717 boff = tmp % bsize;
0718 if (boff) {
0719 bh = affs_bread_ino(inode, bidx, 0);
0720 if (IS_ERR(bh)) {
0721 written = PTR_ERR(bh);
0722 goto err_first_bh;
0723 }
0724 tmp = min(bsize - boff, to - from);
0725 BUG_ON(boff + tmp > bsize || tmp > bsize);
0726 memcpy(AFFS_DATA(bh) + boff, data + from, tmp);
0727 be32_add_cpu(&AFFS_DATA_HEAD(bh)->size, tmp);
0728 affs_fix_checksum(sb, bh);
0729 mark_buffer_dirty_inode(bh, inode);
0730 written += tmp;
0731 from += tmp;
0732 bidx++;
0733 } else if (bidx) {
0734 bh = affs_bread_ino(inode, bidx - 1, 0);
0735 if (IS_ERR(bh)) {
0736 written = PTR_ERR(bh);
0737 goto err_first_bh;
0738 }
0739 }
0740 while (from + bsize <= to) {
0741 prev_bh = bh;
0742 bh = affs_getemptyblk_ino(inode, bidx);
0743 if (IS_ERR(bh))
0744 goto err_bh;
0745 memcpy(AFFS_DATA(bh), data + from, bsize);
0746 if (buffer_new(bh)) {
0747 AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);
0748 AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino);
0749 AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx);
0750 AFFS_DATA_HEAD(bh)->size = cpu_to_be32(bsize);
0751 AFFS_DATA_HEAD(bh)->next = 0;
0752 bh->b_state &= ~(1UL << BH_New);
0753 if (prev_bh) {
0754 u32 tmp_next = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
0755
0756 if (tmp_next)
0757 affs_warning(sb, "commit_write_ofs",
0758 "next block already set for %d (%d)",
0759 bidx, tmp_next);
0760 AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
0761 affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp_next);
0762 mark_buffer_dirty_inode(prev_bh, inode);
0763 }
0764 }
0765 affs_brelse(prev_bh);
0766 affs_fix_checksum(sb, bh);
0767 mark_buffer_dirty_inode(bh, inode);
0768 written += bsize;
0769 from += bsize;
0770 bidx++;
0771 }
0772 if (from < to) {
0773 prev_bh = bh;
0774 bh = affs_bread_ino(inode, bidx, 1);
0775 if (IS_ERR(bh))
0776 goto err_bh;
0777 tmp = min(bsize, to - from);
0778 BUG_ON(tmp > bsize);
0779 memcpy(AFFS_DATA(bh), data + from, tmp);
0780 if (buffer_new(bh)) {
0781 AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);
0782 AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino);
0783 AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx);
0784 AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp);
0785 AFFS_DATA_HEAD(bh)->next = 0;
0786 bh->b_state &= ~(1UL << BH_New);
0787 if (prev_bh) {
0788 u32 tmp_next = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
0789
0790 if (tmp_next)
0791 affs_warning(sb, "commit_write_ofs",
0792 "next block already set for %d (%d)",
0793 bidx, tmp_next);
0794 AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
0795 affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp_next);
0796 mark_buffer_dirty_inode(prev_bh, inode);
0797 }
0798 } else if (be32_to_cpu(AFFS_DATA_HEAD(bh)->size) < tmp)
0799 AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp);
0800 affs_brelse(prev_bh);
0801 affs_fix_checksum(sb, bh);
0802 mark_buffer_dirty_inode(bh, inode);
0803 written += tmp;
0804 from += tmp;
0805 bidx++;
0806 }
0807 SetPageUptodate(page);
0808
0809 done:
0810 affs_brelse(bh);
0811 tmp = (page->index << PAGE_SHIFT) + from;
0812 if (tmp > inode->i_size)
0813 inode->i_size = AFFS_I(inode)->mmu_private = tmp;
0814
0815
0816 if (AFFS_I(inode)->i_protect & FIBF_ARCHIVED) {
0817 AFFS_I(inode)->i_protect &= ~FIBF_ARCHIVED;
0818 mark_inode_dirty(inode);
0819 }
0820
0821 err_first_bh:
0822 unlock_page(page);
0823 put_page(page);
0824
0825 return written;
0826
0827 err_bh:
0828 bh = prev_bh;
0829 if (!written)
0830 written = PTR_ERR(bh);
0831 goto done;
0832 }
0833
0834 const struct address_space_operations affs_aops_ofs = {
0835 .dirty_folio = block_dirty_folio,
0836 .invalidate_folio = block_invalidate_folio,
0837 .read_folio = affs_read_folio_ofs,
0838
0839 .write_begin = affs_write_begin_ofs,
0840 .write_end = affs_write_end_ofs
0841 };
0842
0843
0844
0845 void
0846 affs_free_prealloc(struct inode *inode)
0847 {
0848 struct super_block *sb = inode->i_sb;
0849
0850 pr_debug("free_prealloc(ino=%lu)\n", inode->i_ino);
0851
0852 while (AFFS_I(inode)->i_pa_cnt) {
0853 AFFS_I(inode)->i_pa_cnt--;
0854 affs_free_block(sb, ++AFFS_I(inode)->i_lastalloc);
0855 }
0856 }
0857
0858
0859
0860 void
0861 affs_truncate(struct inode *inode)
0862 {
0863 struct super_block *sb = inode->i_sb;
0864 u32 ext, ext_key;
0865 u32 last_blk, blkcnt, blk;
0866 u32 size;
0867 struct buffer_head *ext_bh;
0868 int i;
0869
0870 pr_debug("truncate(inode=%lu, oldsize=%llu, newsize=%llu)\n",
0871 inode->i_ino, AFFS_I(inode)->mmu_private, inode->i_size);
0872
0873 last_blk = 0;
0874 ext = 0;
0875 if (inode->i_size) {
0876 last_blk = ((u32)inode->i_size - 1) / AFFS_SB(sb)->s_data_blksize;
0877 ext = last_blk / AFFS_SB(sb)->s_hashsize;
0878 }
0879
0880 if (inode->i_size > AFFS_I(inode)->mmu_private) {
0881 struct address_space *mapping = inode->i_mapping;
0882 struct page *page;
0883 void *fsdata;
0884 loff_t isize = inode->i_size;
0885 int res;
0886
0887 res = mapping->a_ops->write_begin(NULL, mapping, isize, 0, &page, &fsdata);
0888 if (!res)
0889 res = mapping->a_ops->write_end(NULL, mapping, isize, 0, 0, page, fsdata);
0890 else
0891 inode->i_size = AFFS_I(inode)->mmu_private;
0892 mark_inode_dirty(inode);
0893 return;
0894 } else if (inode->i_size == AFFS_I(inode)->mmu_private)
0895 return;
0896
0897
0898 ext_bh = affs_get_extblock(inode, ext);
0899 if (IS_ERR(ext_bh)) {
0900 affs_warning(sb, "truncate",
0901 "unexpected read error for ext block %u (%ld)",
0902 ext, PTR_ERR(ext_bh));
0903 return;
0904 }
0905 if (AFFS_I(inode)->i_lc) {
0906
0907 i = (ext + 1) >> AFFS_I(inode)->i_lc_shift;
0908 if (AFFS_I(inode)->i_lc_size > i) {
0909 AFFS_I(inode)->i_lc_size = i;
0910 for (; i < AFFS_LC_SIZE; i++)
0911 AFFS_I(inode)->i_lc[i] = 0;
0912 }
0913
0914 for (i = 0; i < AFFS_AC_SIZE; i++)
0915 if (AFFS_I(inode)->i_ac[i].ext >= ext)
0916 AFFS_I(inode)->i_ac[i].ext = 0;
0917 }
0918 ext_key = be32_to_cpu(AFFS_TAIL(sb, ext_bh)->extension);
0919
0920 blkcnt = AFFS_I(inode)->i_blkcnt;
0921 i = 0;
0922 blk = last_blk;
0923 if (inode->i_size) {
0924 i = last_blk % AFFS_SB(sb)->s_hashsize + 1;
0925 blk++;
0926 } else
0927 AFFS_HEAD(ext_bh)->first_data = 0;
0928 AFFS_HEAD(ext_bh)->block_count = cpu_to_be32(i);
0929 size = AFFS_SB(sb)->s_hashsize;
0930 if (size > blkcnt - blk + i)
0931 size = blkcnt - blk + i;
0932 for (; i < size; i++, blk++) {
0933 affs_free_block(sb, be32_to_cpu(AFFS_BLOCK(sb, ext_bh, i)));
0934 AFFS_BLOCK(sb, ext_bh, i) = 0;
0935 }
0936 AFFS_TAIL(sb, ext_bh)->extension = 0;
0937 affs_fix_checksum(sb, ext_bh);
0938 mark_buffer_dirty_inode(ext_bh, inode);
0939 affs_brelse(ext_bh);
0940
0941 if (inode->i_size) {
0942 AFFS_I(inode)->i_blkcnt = last_blk + 1;
0943 AFFS_I(inode)->i_extcnt = ext + 1;
0944 if (affs_test_opt(AFFS_SB(sb)->s_flags, SF_OFS)) {
0945 struct buffer_head *bh = affs_bread_ino(inode, last_blk, 0);
0946 u32 tmp;
0947 if (IS_ERR(bh)) {
0948 affs_warning(sb, "truncate",
0949 "unexpected read error for last block %u (%ld)",
0950 ext, PTR_ERR(bh));
0951 return;
0952 }
0953 tmp = be32_to_cpu(AFFS_DATA_HEAD(bh)->next);
0954 AFFS_DATA_HEAD(bh)->next = 0;
0955 affs_adjust_checksum(bh, -tmp);
0956 affs_brelse(bh);
0957 }
0958 } else {
0959 AFFS_I(inode)->i_blkcnt = 0;
0960 AFFS_I(inode)->i_extcnt = 1;
0961 }
0962 AFFS_I(inode)->mmu_private = inode->i_size;
0963
0964
0965 while (ext_key) {
0966 ext_bh = affs_bread(sb, ext_key);
0967 size = AFFS_SB(sb)->s_hashsize;
0968 if (size > blkcnt - blk)
0969 size = blkcnt - blk;
0970 for (i = 0; i < size; i++, blk++)
0971 affs_free_block(sb, be32_to_cpu(AFFS_BLOCK(sb, ext_bh, i)));
0972 affs_free_block(sb, ext_key);
0973 ext_key = be32_to_cpu(AFFS_TAIL(sb, ext_bh)->extension);
0974 affs_brelse(ext_bh);
0975 }
0976 affs_free_prealloc(inode);
0977 }
0978
0979 int affs_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
0980 {
0981 struct inode *inode = filp->f_mapping->host;
0982 int ret, err;
0983
0984 err = file_write_and_wait_range(filp, start, end);
0985 if (err)
0986 return err;
0987
0988 inode_lock(inode);
0989 ret = write_inode_now(inode, 0);
0990 err = sync_blockdev(inode->i_sb->s_bdev);
0991 if (!ret)
0992 ret = err;
0993 inode_unlock(inode);
0994 return ret;
0995 }
0996 const struct file_operations affs_file_operations = {
0997 .llseek = generic_file_llseek,
0998 .read_iter = generic_file_read_iter,
0999 .write_iter = generic_file_write_iter,
1000 .mmap = generic_file_mmap,
1001 .open = affs_file_open,
1002 .release = affs_file_release,
1003 .fsync = affs_file_fsync,
1004 .splice_read = generic_file_splice_read,
1005 };
1006
1007 const struct inode_operations affs_file_inode_operations = {
1008 .setattr = affs_notify_change,
1009 };