Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *  linux/fs/affs/file.c
0004  *
0005  *  (c) 1996  Hans-Joachim Widmaier - Rewritten
0006  *
0007  *  (C) 1993  Ray Burr - Modified for Amiga FFS filesystem.
0008  *
0009  *  (C) 1992  Eric Youngdale Modified for ISO 9660 filesystem.
0010  *
0011  *  (C) 1991  Linus Torvalds - minix filesystem
0012  *
0013  *  affs regular file handling primitives
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         /* need to recalculate linear cache, start from old size */
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         /* fix idx and old size to new shift */
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         /* first shrink old cache to make more space */
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     /* fill cache to the needed index */
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         // unlock cache
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         // lock cache
0108         AFFS_I(inode)->i_lc[i] = key;
0109     }
0110 
0111     return 0;
0112 
0113 err:
0114     // lock cache
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     /* inline the simplest case: same extended block as last time */
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         /* we have to do more (not inlined) */
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         /* read the next extended block from the current one */
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         /* we seek back to the file header block */
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         /* allocate a new extended block */
0202         BUG_ON(ext > AFFS_I(inode)->i_extcnt);
0203 
0204         /* get previous extended block */
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     /* check if there is an extended cache and whether it's large enough */
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     /* every n'th key we find in the linear cache */
0230     if (!lc_off) {
0231         ext_key = AFFS_I(inode)->i_lc[lc_idx];
0232         goto read_ext;
0233     }
0234 
0235     /* maybe it's still in the associative cache */
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     /* try to find one of the previous extended blocks */
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     /* fall back to the linear cache */
0254     ext_key = AFFS_I(inode)->i_lc[lc_idx];
0255 find_ext:
0256     /* read all extended blocks until we find the one we need */
0257     //unlock cache
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     //lock cache
0267 
0268     /* store it in the associative cache */
0269     // recalculate ac_idx?
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     /* finally read the right extended block */
0275     //unlock cache
0276     bh = affs_bread(sb, ext_key);
0277     if (!bh)
0278         goto err_bread;
0279     //lock cache
0280 
0281 store_ext:
0282     /* release old cached extended block and store the new one */
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     //lock cache
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         /* store new block */
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             /* insert first block into header block */
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     //unlock cache
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     // unlock cache
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     // unlock cache
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     /* Clear Archived bit on file writes, as AmigaOS would do */
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         /* XXX: this probably leaves a too-big i_size in case of
0662          * failure. Should really be updating i_size at write_end time
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     /* XXX: inefficient but safe in the face of short writes */
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      * XXX: not sure if this can handle short copies (len < copied), but
0704      * we don't have to, because the page should always be uptodate here,
0705      * due to write_begin.
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     /* Clear Archived bit on file writes, as AmigaOS would do */
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     //.writepage = affs_writepage_ofs,
0839     .write_begin = affs_write_begin_ofs,
0840     .write_end = affs_write_end_ofs
0841 };
0842 
0843 /* Free any preallocated blocks. */
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 /* Truncate (or enlarge) a file to the requested size. */
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     // lock cache
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         /* clear linear cache */
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         /* clear associative cache */
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     // unlock cache
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 };