in core/ms_block.c [1117:1163]
static int msb_update_block(struct msb_data *msb, u16 lba,
struct scatterlist *sg, int offset)
{
u16 pba, new_pba;
int error, try;
pba = msb->lba_to_pba_table[lba];
dbg_verbose("start of a block update at lba %d, pba %d", lba, pba);
if (pba != MS_BLOCK_INVALID) {
dbg_verbose("setting the update flag on the block");
msb_set_overwrite_flag(msb, pba, 0,
0xFF & ~MEMSTICK_OVERWRITE_UDST);
}
for (try = 0; try < 3; try++) {
new_pba = msb_get_free_block(msb,
msb_get_zone_from_lba(lba));
if (new_pba == MS_BLOCK_INVALID) {
error = -EIO;
goto out;
}
dbg_verbose("block update: writing updated block to the pba %d",
new_pba);
error = msb_write_block(msb, new_pba, lba, sg, offset);
if (error == -EBADMSG) {
msb_mark_bad(msb, new_pba);
continue;
}
if (error)
goto out;
dbg_verbose("block update: erasing the old block");
msb_erase_block(msb, pba);
msb->lba_to_pba_table[lba] = new_pba;
return 0;
}
out:
if (error) {
pr_err("block update error after %d tries, switching to r/o mode", try);
msb->read_only = true;
}
return error;
}