|
@@ -56,12 +56,15 @@ int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint
|
|
|
/* jffs2_write_dnode - given a raw_inode, allocate a full_dnode for it,
|
|
|
write it to the flash, link it into the existing inode/fragment list */
|
|
|
|
|
|
-struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode)
|
|
|
+struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
|
|
|
+ struct jffs2_raw_inode *ri, const unsigned char *data,
|
|
|
+ uint32_t datalen, int alloc_mode)
|
|
|
|
|
|
{
|
|
|
struct jffs2_raw_node_ref *raw;
|
|
|
struct jffs2_full_dnode *fn;
|
|
|
size_t retlen;
|
|
|
+ uint32_t flash_ofs;
|
|
|
struct kvec vecs[2];
|
|
|
int ret;
|
|
|
int retried = 0;
|
|
@@ -77,8 +80,6 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
|
|
|
vecs[1].iov_base = (unsigned char *)data;
|
|
|
vecs[1].iov_len = datalen;
|
|
|
|
|
|
- jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
|
|
|
-
|
|
|
if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) {
|
|
|
printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08zx) + datalen (0x%08x)\n", je32_to_cpu(ri->totlen), sizeof(*ri), datalen);
|
|
|
}
|
|
@@ -102,7 +103,9 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
|
|
|
retry:
|
|
|
fn->raw = raw;
|
|
|
|
|
|
- raw->flash_offset = flash_ofs;
|
|
|
+ raw->flash_offset = flash_ofs = write_ofs(c);
|
|
|
+
|
|
|
+ jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
|
|
|
|
|
|
if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(ri->version) < f->highest_version)) {
|
|
|
BUG_ON(!retried);
|
|
@@ -122,16 +125,13 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
|
|
|
|
|
|
/* Mark the space as dirtied */
|
|
|
if (retlen) {
|
|
|
- /* Doesn't belong to any inode */
|
|
|
- raw->next_in_ino = NULL;
|
|
|
-
|
|
|
/* Don't change raw->size to match retlen. We may have
|
|
|
written the node header already, and only the data will
|
|
|
seem corrupted, in which case the scan would skip over
|
|
|
any node we write before the original intended end of
|
|
|
this node */
|
|
|
raw->flash_offset |= REF_OBSOLETE;
|
|
|
- jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*ri)+datalen));
|
|
|
+ jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*ri)+datalen), NULL);
|
|
|
jffs2_mark_node_obsolete(c, raw);
|
|
|
} else {
|
|
|
printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset);
|
|
@@ -150,19 +150,20 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
|
|
|
jffs2_dbg_acct_paranoia_check(c, jeb);
|
|
|
|
|
|
if (alloc_mode == ALLOC_GC) {
|
|
|
- ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &flash_ofs,
|
|
|
- &dummy, JFFS2_SUMMARY_INODE_SIZE);
|
|
|
+ ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &dummy,
|
|
|
+ JFFS2_SUMMARY_INODE_SIZE);
|
|
|
} else {
|
|
|
/* Locking pain */
|
|
|
up(&f->sem);
|
|
|
jffs2_complete_reservation(c);
|
|
|
|
|
|
- ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &flash_ofs,
|
|
|
- &dummy, alloc_mode, JFFS2_SUMMARY_INODE_SIZE);
|
|
|
+ ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &dummy,
|
|
|
+ alloc_mode, JFFS2_SUMMARY_INODE_SIZE);
|
|
|
down(&f->sem);
|
|
|
}
|
|
|
|
|
|
if (!ret) {
|
|
|
+ flash_ofs = write_ofs(c);
|
|
|
D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs));
|
|
|
|
|
|
jffs2_dbg_acct_sanity_check(c,jeb);
|
|
@@ -189,13 +190,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
|
|
|
} else {
|
|
|
raw->flash_offset |= REF_NORMAL;
|
|
|
}
|
|
|
- jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*ri)+datalen));
|
|
|
-
|
|
|
- /* Link into per-inode list */
|
|
|
- spin_lock(&c->erase_completion_lock);
|
|
|
- raw->next_in_ino = f->inocache->nodes;
|
|
|
- f->inocache->nodes = raw;
|
|
|
- spin_unlock(&c->erase_completion_lock);
|
|
|
+ jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*ri)+datalen), f->inocache);
|
|
|
|
|
|
D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x(%d) with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n",
|
|
|
flash_ofs, ref_flags(raw), je32_to_cpu(ri->dsize),
|
|
@@ -209,12 +204,15 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
|
|
|
return fn;
|
|
|
}
|
|
|
|
|
|
-struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_dirent *rd, const unsigned char *name, uint32_t namelen, uint32_t flash_ofs, int alloc_mode)
|
|
|
+struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
|
|
|
+ struct jffs2_raw_dirent *rd, const unsigned char *name,
|
|
|
+ uint32_t namelen, int alloc_mode)
|
|
|
{
|
|
|
struct jffs2_raw_node_ref *raw;
|
|
|
struct jffs2_full_dirent *fd;
|
|
|
size_t retlen;
|
|
|
struct kvec vecs[2];
|
|
|
+ uint32_t flash_ofs = write_ofs(c);
|
|
|
int retried = 0;
|
|
|
int ret;
|
|
|
|
|
@@ -275,9 +273,8 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
|
|
|
sizeof(*rd)+namelen, flash_ofs, ret, retlen);
|
|
|
/* Mark the space as dirtied */
|
|
|
if (retlen) {
|
|
|
- raw->next_in_ino = NULL;
|
|
|
raw->flash_offset |= REF_OBSOLETE;
|
|
|
- jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*rd)+namelen));
|
|
|
+ jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*rd)+namelen), NULL);
|
|
|
jffs2_mark_node_obsolete(c, raw);
|
|
|
} else {
|
|
|
printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset);
|
|
@@ -296,19 +293,20 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
|
|
|
jffs2_dbg_acct_paranoia_check(c, jeb);
|
|
|
|
|
|
if (alloc_mode == ALLOC_GC) {
|
|
|
- ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &flash_ofs,
|
|
|
- &dummy, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
|
|
|
+ ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &dummy,
|
|
|
+ JFFS2_SUMMARY_DIRENT_SIZE(namelen));
|
|
|
} else {
|
|
|
/* Locking pain */
|
|
|
up(&f->sem);
|
|
|
jffs2_complete_reservation(c);
|
|
|
|
|
|
- ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &flash_ofs,
|
|
|
- &dummy, alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
|
|
|
+ ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &dummy,
|
|
|
+ alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
|
|
|
down(&f->sem);
|
|
|
}
|
|
|
|
|
|
if (!ret) {
|
|
|
+ flash_ofs = write_ofs(c);
|
|
|
D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs));
|
|
|
jffs2_dbg_acct_sanity_check(c,jeb);
|
|
|
jffs2_dbg_acct_paranoia_check(c, jeb);
|
|
@@ -323,12 +321,7 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
|
|
|
}
|
|
|
/* Mark the space used */
|
|
|
raw->flash_offset |= REF_PRISTINE;
|
|
|
- jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*rd)+namelen));
|
|
|
-
|
|
|
- spin_lock(&c->erase_completion_lock);
|
|
|
- raw->next_in_ino = f->inocache->nodes;
|
|
|
- f->inocache->nodes = raw;
|
|
|
- spin_unlock(&c->erase_completion_lock);
|
|
|
+ jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*rd)+namelen), f->inocache);
|
|
|
|
|
|
if (retried) {
|
|
|
jffs2_dbg_acct_sanity_check(c,NULL);
|
|
@@ -354,14 +347,14 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
|
|
|
struct jffs2_full_dnode *fn;
|
|
|
unsigned char *comprbuf = NULL;
|
|
|
uint16_t comprtype = JFFS2_COMPR_NONE;
|
|
|
- uint32_t phys_ofs, alloclen;
|
|
|
+ uint32_t alloclen;
|
|
|
uint32_t datalen, cdatalen;
|
|
|
int retried = 0;
|
|
|
|
|
|
retry:
|
|
|
D2(printk(KERN_DEBUG "jffs2_commit_write() loop: 0x%x to write to 0x%x\n", writelen, offset));
|
|
|
|
|
|
- ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN, &phys_ofs,
|
|
|
+ ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN,
|
|
|
&alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
|
|
|
if (ret) {
|
|
|
D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret));
|
|
@@ -389,7 +382,7 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
|
|
|
ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
|
|
|
ri->data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen));
|
|
|
|
|
|
- fn = jffs2_write_dnode(c, f, ri, comprbuf, cdatalen, phys_ofs, ALLOC_NORETRY);
|
|
|
+ fn = jffs2_write_dnode(c, f, ri, comprbuf, cdatalen, ALLOC_NORETRY);
|
|
|
|
|
|
jffs2_free_comprbuf(comprbuf, buf);
|
|
|
|
|
@@ -443,13 +436,13 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
|
|
|
struct jffs2_raw_dirent *rd;
|
|
|
struct jffs2_full_dnode *fn;
|
|
|
struct jffs2_full_dirent *fd;
|
|
|
- uint32_t alloclen, phys_ofs;
|
|
|
+ uint32_t alloclen;
|
|
|
int ret;
|
|
|
|
|
|
/* Try to reserve enough space for both node and dirent.
|
|
|
* Just the node will do for now, though
|
|
|
*/
|
|
|
- ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL,
|
|
|
+ ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL,
|
|
|
JFFS2_SUMMARY_INODE_SIZE);
|
|
|
D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen));
|
|
|
if (ret) {
|
|
@@ -460,7 +453,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
|
|
|
ri->data_crc = cpu_to_je32(0);
|
|
|
ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
|
|
|
|
|
|
- fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL);
|
|
|
+ fn = jffs2_write_dnode(c, f, ri, NULL, 0, ALLOC_NORMAL);
|
|
|
|
|
|
D1(printk(KERN_DEBUG "jffs2_do_create created file with mode 0x%x\n",
|
|
|
jemode_to_cpu(ri->mode)));
|
|
@@ -479,7 +472,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
|
|
|
|
|
|
up(&f->sem);
|
|
|
jffs2_complete_reservation(c);
|
|
|
- ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen,
|
|
|
+ ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
|
|
|
ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
|
|
|
|
|
|
if (ret) {
|
|
@@ -511,7 +504,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
|
|
|
rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
|
|
|
rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
|
|
|
|
|
|
- fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL);
|
|
|
+ fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_NORMAL);
|
|
|
|
|
|
jffs2_free_raw_dirent(rd);
|
|
|
|
|
@@ -540,7 +533,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
|
|
|
{
|
|
|
struct jffs2_raw_dirent *rd;
|
|
|
struct jffs2_full_dirent *fd;
|
|
|
- uint32_t alloclen, phys_ofs;
|
|
|
+ uint32_t alloclen;
|
|
|
int ret;
|
|
|
|
|
|
if (1 /* alternative branch needs testing */ ||
|
|
@@ -551,7 +544,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
|
|
|
if (!rd)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen,
|
|
|
+ ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
|
|
|
ALLOC_DELETION, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
|
|
|
if (ret) {
|
|
|
jffs2_free_raw_dirent(rd);
|
|
@@ -575,7 +568,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
|
|
|
rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
|
|
|
rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
|
|
|
|
|
|
- fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_DELETION);
|
|
|
+ fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_DELETION);
|
|
|
|
|
|
jffs2_free_raw_dirent(rd);
|
|
|
|
|
@@ -654,14 +647,14 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint
|
|
|
{
|
|
|
struct jffs2_raw_dirent *rd;
|
|
|
struct jffs2_full_dirent *fd;
|
|
|
- uint32_t alloclen, phys_ofs;
|
|
|
+ uint32_t alloclen;
|
|
|
int ret;
|
|
|
|
|
|
rd = jffs2_alloc_raw_dirent();
|
|
|
if (!rd)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen,
|
|
|
+ ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
|
|
|
ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
|
|
|
if (ret) {
|
|
|
jffs2_free_raw_dirent(rd);
|
|
@@ -687,7 +680,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint
|
|
|
rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
|
|
|
rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
|
|
|
|
|
|
- fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL);
|
|
|
+ fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_NORMAL);
|
|
|
|
|
|
jffs2_free_raw_dirent(rd);
|
|
|
|