struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
struct f2fs_checkpoint *cp = F2FS_CKPT(sbi);
unsigned long long cp_blk_no;
- u32 flags = CP_UMOUNT_FLAG;
+ u32 flags = c.alloc_failed ? CP_FSCK_FLAG: CP_UMOUNT_FLAG;
block_t orphan_blks = 0;
+ block_t cp_blocks;
u32 i;
int ret;
u_int32_t crc = 0;
if (is_set_ckpt_flags(cp, CP_DISABLED_FLAG))
flags |= CP_DISABLED_FLAG;
- set_cp(cp_pack_total_block_count, 8 + orphan_blks + get_sb(cp_payload));
+ if (flags & CP_UMOUNT_FLAG)
+ cp_blocks = 8;
+ else
+ cp_blocks = 5;
+
+ set_cp(cp_pack_total_block_count, cp_blocks +
+ orphan_blks + get_sb(cp_payload));
flags = update_nat_bits_flags(sb, cp, flags);
flags |= CP_NOCRC_RECOVERY_FLAG;
for (i = 0; i < NO_CHECK_TYPE; i++) {
struct curseg_info *curseg = CURSEG_I(sbi, i);
+ if (!(flags & CP_UMOUNT_FLAG) && IS_NODESEG(i))
+ continue;
+
ret = dev_write_block(curseg->sum_blk, cp_blk_no++);
ASSERT(ret >= 0);
}
/* segment.c */
void reserve_new_block(struct f2fs_sb_info *, block_t *,
struct f2fs_summary *, int);
-void new_data_block(struct f2fs_sb_info *, void *,
+int new_data_block(struct f2fs_sb_info *, void *,
struct dnode_of_data *, int);
int f2fs_build_file(struct f2fs_sb_info *, struct dentry *);
void f2fs_alloc_nid(struct f2fs_sb_info *, nid_t *, int);
u64 f2fs_write(struct f2fs_sb_info *, nid_t, u8 *, u64, pgoff_t);
void f2fs_filesize_update(struct f2fs_sb_info *, nid_t, u64);
-void get_dnode_of_data(struct f2fs_sb_info *, struct dnode_of_data *,
+int get_dnode_of_data(struct f2fs_sb_info *, struct dnode_of_data *,
pgoff_t, int);
void make_dentry_ptr(struct f2fs_dentry_ptr *, struct f2fs_node *, void *, int);
int f2fs_create(struct f2fs_sb_info *, struct dentry *);
print_dquot("write", dq);
dq->dq_h = qh;
update_grace_times(dq);
- qh->qh_ops->commit_dquot(dq);
+ if (qh->qh_ops->commit_dquot(dq))
+ break;
}
}
}
return level;
}
-void get_dnode_of_data(struct f2fs_sb_info *sbi, struct dnode_of_data *dn,
+int get_dnode_of_data(struct f2fs_sb_info *sbi, struct dnode_of_data *dn,
pgoff_t index, int mode)
{
int offset[4];
for (i = 1; i <= level; i++) {
if (!nids[i] && mode == ALLOC_NODE) {
+ struct f2fs_checkpoint *cp = F2FS_CKPT(sbi);
+
+ if (!is_set_ckpt_flags(cp, CP_UMOUNT_FLAG)) {
+ c.alloc_failed = 1;
+ return -EINVAL;
+ }
f2fs_alloc_nid(sbi, &nids[i], 0);
dn->nid = nids[i];
dn->ofs_in_node = offset[level];
dn->data_blkaddr = datablock_addr(dn->node_blk, dn->ofs_in_node);
dn->node_blkaddr = nblk[level];
+ return 0;
}
written = f2fs_write(qf->sbi, qf->ino, buf, size, offset);
if (qf->filesize < offset + written)
qf->filesize = offset + written;
-
+ if (written != size)
+ return -EIO;
return written;
}
if (newson && ret >= 0) {
ref[get_index(dquot->dq_id, depth)] =
cpu_to_le32(newblk);
- write_blk(h, *treeblk, buf);
+ ret = write_blk(h, *treeblk, buf);
+ if (ret)
+ goto out_buf;
} else if (newact && ret < 0) {
put_free_dqblk(h, buf, *treeblk);
}
}
/* Wrapper for inserting quota structure into tree */
-static void dq_insert_tree(struct quota_handle *h, struct dquot *dquot)
+static int dq_insert_tree(struct quota_handle *h, struct dquot *dquot)
{
unsigned int tmp = QT_TREEOFF;
+ int err;
- if (do_insert_tree(h, dquot, &tmp, 0) < 0)
+ err = do_insert_tree(h, dquot, &tmp, 0);
+ if (err < 0)
log_err("Cannot write quota (id %u): %s",
(unsigned int) dquot->dq_id, strerror(errno));
+ return err;
}
/* Write dquot to file */
-void qtree_write_dquot(struct dquot *dquot)
+int qtree_write_dquot(struct dquot *dquot)
{
errcode_t retval;
unsigned int ret;
struct qtree_mem_dqinfo *info =
&dquot->dq_h->qh_info.u.v2_mdqi.dqi_qtree;
-
log_debug("writing ddquot 1: off=%llu, info->dqi_entry_size=%u",
dquot->dq_dqb.u.v2_mdqb.dqb_off,
info->dqi_entry_size);
retval = quota_get_mem(info->dqi_entry_size, &ddquot);
if (retval) {
- errno = ENOMEM;
log_err("Quota write failed (id %u): %s",
(unsigned int)dquot->dq_id, strerror(errno));
- return;
+ return -ENOMEM;
}
memset(ddquot, 0, info->dqi_entry_size);
if (!dquot->dq_dqb.u.v2_mdqb.dqb_off) {
- dq_insert_tree(dquot->dq_h, dquot);
+ if (dq_insert_tree(dquot->dq_h, dquot)) {
+ quota_free_mem(&ddquot);
+ return -EIO;
+ }
}
info->dqi_ops->mem2disk_dqblk(ddquot, dquot);
log_debug("writing ddquot 2: off=%llu, info->dqi_entry_size=%u",
info->dqi_entry_size);
if (ret != info->dqi_entry_size) {
- if (ret > 0)
- errno = ENOSPC;
log_err("Quota write failed (id %u): %s",
(unsigned int)dquot->dq_id, strerror(errno));
+ return ret;
}
quota_free_mem(&ddquot);
+ return 0;
}
/* Free dquot entry in data block */
* manipulation */
};
-void qtree_write_dquot(struct dquot *dquot);
+int qtree_write_dquot(struct dquot *dquot);
struct dquot *qtree_read_dquot(struct quota_handle *h, qid_t id);
void qtree_delete_dquot(struct dquot *dquot);
int qtree_entry_unused(struct qtree_mem_dqinfo *info, char *disk);
{
qtree_delete_dquot(dquot);
} else {
- qtree_write_dquot(dquot);
+ return qtree_write_dquot(dquot);
}
return 0;
}
update_sum_entry(sbi, *to, sum);
}
-void new_data_block(struct f2fs_sb_info *sbi, void *block,
+int new_data_block(struct f2fs_sb_info *sbi, void *block,
struct dnode_of_data *dn, int type)
{
struct f2fs_summary sum;
struct node_info ni;
unsigned int blkaddr = datablock_addr(dn->node_blk, dn->ofs_in_node);
+ struct f2fs_checkpoint *cp = F2FS_CKPT(sbi);
+
+ if (!is_set_ckpt_flags(cp, CP_UMOUNT_FLAG)) {
+ c.alloc_failed = 1;
+ return -EINVAL;
+ }
ASSERT(dn->node_blk);
memset(block, 0, BLOCK_SZ);
else if (blkaddr == NEW_ADDR)
dn->idirty = 1;
set_data_blkaddr(dn);
+ return 0;
}
u64 f2fs_read(struct f2fs_sb_info *sbi, nid_t ino, u8 *buffer,
block_t blkaddr;
void* index_node = NULL;
int idirty = 0;
+ int err;
/* Memory allocation for block buffer and inode. */
blk_buffer = calloc(BLOCK_SZ, 2);
while (count > 0) {
if (remained_blkentries == 0) {
set_new_dnode(&dn, inode, NULL, ino);
- get_dnode_of_data(sbi, &dn, F2FS_BYTES_TO_BLK(offset),
- ALLOC_NODE);
+ err = get_dnode_of_data(sbi, &dn,
+ F2FS_BYTES_TO_BLK(offset), ALLOC_NODE);
+ if (err)
+ break;
idirty |= dn.idirty;
if (index_node)
free(index_node);
blkaddr = datablock_addr(dn.node_blk, dn.ofs_in_node);
if (blkaddr == NULL_ADDR || blkaddr == NEW_ADDR) {
- new_data_block(sbi, blk_buffer, &dn, CURSEG_WARM_DATA);
+ err = new_data_block(sbi, blk_buffer,
+ &dn, CURSEG_WARM_DATA);
+ if (err)
+ break;
blkaddr = dn.data_blkaddr;
}
int fix_on;
int defset;
int bug_on;
+ int alloc_failed;
int auto_fix;
int quota_fix;
int preen_mode;