summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2008-03-13 16:45:24 +1100
committerStephen Rothwell <sfr@canb.auug.org.au>2008-03-13 16:45:24 +1100
commit26a9fe3d937ea501f9c0c100a1b0f159551fd963 (patch)
treedd79faaf499aa2acb90cdec30ecee3195ff144fe
parent0c98ec38a237d9374d8edddea82e55838ff71ac4 (diff)
parentdd919660aacdf4adfcd279556aa03e595f7f0fc2 (diff)
Merge commit 'mtd/master'
-rw-r--r--drivers/mtd/onenand/onenand_base.c32
-rw-r--r--fs/jffs2/fs.c14
2 files changed, 28 insertions, 18 deletions
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 8d7d21be1541..15a62db656de 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -2052,7 +2052,7 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
*
* Check lock status
*/
-static void onenand_check_lock_status(struct onenand_chip *this)
+static int onenand_check_lock_status(struct onenand_chip *this)
{
unsigned int value, block, status;
unsigned int end;
@@ -2070,9 +2070,13 @@ static void onenand_check_lock_status(struct onenand_chip *this)
/* Check lock status */
status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
- if (!(status & ONENAND_WP_US))
+ if (!(status & ONENAND_WP_US)) {
printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status);
+ return 0;
+ }
}
+
+ return 1;
}
/**
@@ -2081,9 +2085,11 @@ static void onenand_check_lock_status(struct onenand_chip *this)
*
* Unlock all blocks
*/
-static int onenand_unlock_all(struct mtd_info *mtd)
+static void onenand_unlock_all(struct mtd_info *mtd)
{
struct onenand_chip *this = mtd->priv;
+ loff_t ofs = 0;
+ size_t len = this->chipsize;
if (this->options & ONENAND_HAS_UNLOCK_ALL) {
/* Set start block address */
@@ -2099,23 +2105,19 @@ static int onenand_unlock_all(struct mtd_info *mtd)
& ONENAND_CTRL_ONGO)
continue;
+ /* Check lock status */
+ if (onenand_check_lock_status(this))
+ return;
+
/* Workaround for all block unlock in DDP */
if (ONENAND_IS_DDP(this)) {
- /* 1st block on another chip */
- loff_t ofs = this->chipsize >> 1;
- size_t len = mtd->erasesize;
-
- onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);
+ /* All blocks on another chip */
+ ofs = this->chipsize >> 1;
+ len = this->chipsize >> 1;
}
-
- onenand_check_lock_status(this);
-
- return 0;
}
- onenand_do_lock_cmd(mtd, 0x0, this->chipsize, ONENAND_CMD_UNLOCK);
-
- return 0;
+ onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);
}
#ifdef CONFIG_MTD_ONENAND_OTP
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index e26ea78c7892..9dafb53fb1d1 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -36,6 +36,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
unsigned int ivalid;
uint32_t alloclen;
int ret;
+ int alloc_type = ALLOC_NORMAL;
D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino));
@@ -115,6 +116,10 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
ri->compr = JFFS2_COMPR_ZERO;
ri->dsize = cpu_to_je32(iattr->ia_size - inode->i_size);
ri->offset = cpu_to_je32(inode->i_size);
+ } else if (ivalid & ATTR_SIZE && !iattr->ia_size) {
+ /* For truncate-to-zero, treat it as deletion because
+ it'll always be obsoleting all previous nodes */
+ alloc_type = ALLOC_DELETION;
}
ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
if (mdatalen)
@@ -122,7 +127,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
else
ri->data_crc = cpu_to_je32(0);
- new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, ALLOC_NORMAL);
+ new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, alloc_type);
if (S_ISLNK(inode->i_mode))
kfree(mdata);
@@ -149,6 +154,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) {
jffs2_add_full_dnode_to_inode(c, f, new_metadata);
inode->i_size = iattr->ia_size;
+ inode->i_blocks = (inode->i_size + 511) >> 9;
f->metadata = NULL;
} else {
f->metadata = new_metadata;
@@ -167,8 +173,10 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
We are protected from a simultaneous write() extending i_size
back past iattr->ia_size, because do_truncate() holds the
generic inode semaphore. */
- if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size)
- vmtruncate(inode, iattr->ia_size);
+ if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) {
+ vmtruncate(inode, iattr->ia_size);
+ inode->i_blocks = (inode->i_size + 511) >> 9;
+ }
return 0;
}