#define DEVT 5
struct erofs_bhops {
- bool (*flush)(struct erofs_buffer_head *bh);
+ int (*flush)(struct erofs_buffer_head *bh);
};
struct erofs_buffer_head {
(end ? list_next_entry(bh, list)->off : bh->off);
}
-static inline bool erofs_bh_flush_generic_end(struct erofs_buffer_head *bh)
+static inline int erofs_bh_flush_generic_end(struct erofs_buffer_head *bh)
{
list_del(&bh->list);
free(bh);
- return true;
+ return 0;
}
struct erofs_buffer_head *erofs_buffer_init(void);
int type, unsigned int size);
erofs_blk_t erofs_mapbh(struct erofs_buffer_block *bb);
-bool erofs_bflush(struct erofs_buffer_block *bb);
+int erofs_bflush(struct erofs_buffer_block *bb);
void erofs_bdrop(struct erofs_buffer_head *bh, bool tryrevoke);
erofs_blk_t erofs_total_metablocks(void);
/* last mapped buffer block to accelerate erofs_mapbh() */
static struct erofs_buffer_block *last_mapped_block = &blkh;
-static bool erofs_bh_flush_drop_directly(struct erofs_buffer_head *bh)
+static int erofs_bh_flush_drop_directly(struct erofs_buffer_head *bh)
{
return erofs_bh_flush_generic_end(bh);
}
.flush = erofs_bh_flush_drop_directly,
};
-static bool erofs_bh_flush_skip_write(struct erofs_buffer_head *bh)
+static int erofs_bh_flush_skip_write(struct erofs_buffer_head *bh)
{
- return false;
+ return -EBUSY;
}
const struct erofs_bhops erofs_skip_write_bhops = {
free(bb);
}
-bool erofs_bflush(struct erofs_buffer_block *bb)
+int erofs_bflush(struct erofs_buffer_block *bb)
{
const unsigned int blksiz = erofs_blksiz(&sbi);
struct erofs_buffer_block *p, *n;
struct erofs_buffer_head *bh, *nbh;
unsigned int padding;
bool skip = false;
+ int ret;
if (p == bb)
break;
blkaddr = __erofs_mapbh(p);
list_for_each_entry_safe(bh, nbh, &p->buffers.list, list) {
- /* flush and remove bh */
- if (!bh->op->flush(bh))
+ if (bh->op == &erofs_skip_write_bhops) {
skip = true;
+ continue;
+ }
+
+ /* flush and remove bh */
+ ret = bh->op->flush(bh);
+ if (ret < 0)
+ return ret;
}
if (skip)
erofs_dbg("block %u to %u flushed", p->blkaddr, blkaddr - 1);
erofs_bfree(p);
}
- return true;
+ return 0;
}
void erofs_bdrop(struct erofs_buffer_head *bh, bool tryrevoke)
erofs_bdrop(bh, true); /* revoke buffer */
err_free_meta:
free(compressmeta);
+ inode->compressmeta = NULL;
return ret;
}
list_for_each_entry_safe(d, t, &inode->i_subdirs, d_child)
free(d);
+ free(inode->compressmeta);
if (inode->eof_tailraw)
free(inode->eof_tailraw);
list_del(&inode->i_hash);
return write_uncompressed_file_from_fd(inode, fd);
}
-static bool erofs_bh_flush_write_inode(struct erofs_buffer_head *bh)
+static int erofs_bh_flush_write_inode(struct erofs_buffer_head *bh)
{
struct erofs_inode *const inode = bh->fsprivate;
struct erofs_sb_info *sbi = inode->sbi;
ret = dev_write(sbi, &u, off, inode->inode_isize);
if (ret)
- return false;
+ return ret;
off += inode->inode_isize;
if (inode->xattr_isize) {
char *xattrs = erofs_export_xattr_ibody(inode);
if (IS_ERR(xattrs))
- return false;
+ return PTR_ERR(xattrs);
ret = dev_write(sbi, xattrs, off, inode->xattr_isize);
free(xattrs);
if (ret)
- return false;
+ return ret;
off += inode->xattr_isize;
}
if (inode->datalayout == EROFS_INODE_CHUNK_BASED) {
ret = erofs_blob_write_chunk_indexes(inode, off);
if (ret)
- return false;
+ return ret;
} else {
/* write compression metadata */
off = roundup(off, 8);
ret = dev_write(sbi, inode->compressmeta, off,
inode->extent_isize);
if (ret)
- return false;
- free(inode->compressmeta);
+ return ret;
}
}
return 0;
}
-static bool erofs_bh_flush_write_inline(struct erofs_buffer_head *bh)
+static int erofs_bh_flush_write_inline(struct erofs_buffer_head *bh)
{
struct erofs_inode *const inode = bh->fsprivate;
const erofs_off_t off = erofs_btell(bh, false);
ret = dev_write(inode->sbi, inode->idata, off, inode->idata_size);
if (ret)
- return false;
+ return ret;
inode->idata_size = 0;
free(inode->idata);
}
/* flush all buffers except for the superblock */
- if (!erofs_bflush(NULL)) {
- err = -EIO;
+ err = erofs_bflush(NULL);
+ if (err)
goto exit;
- }
err = erofs_mkfs_update_super_block(sb_bh, root_nid, &nblocks,
packed_nid);
goto exit;
/* flush all remaining buffers */
- if (!erofs_bflush(NULL))
- err = -EIO;
- else
- err = dev_resize(&sbi, nblocks);
+ err = erofs_bflush(NULL);
+ if (err)
+ goto exit;
+
+ err = dev_resize(&sbi, nblocks);
if (!err && erofs_sb_has_sb_chksum(&sbi))
err = erofs_mkfs_superblock_csum_set();