aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/jffs2/fs.c14
1 files changed, 11 insertions, 3 deletions
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)
36 unsigned int ivalid; 36 unsigned int ivalid;
37 uint32_t alloclen; 37 uint32_t alloclen;
38 int ret; 38 int ret;
39 int alloc_type = ALLOC_NORMAL;
39 40
40 D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino)); 41 D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino));
41 42
@@ -115,6 +116,10 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
115 ri->compr = JFFS2_COMPR_ZERO; 116 ri->compr = JFFS2_COMPR_ZERO;
116 ri->dsize = cpu_to_je32(iattr->ia_size - inode->i_size); 117 ri->dsize = cpu_to_je32(iattr->ia_size - inode->i_size);
117 ri->offset = cpu_to_je32(inode->i_size); 118 ri->offset = cpu_to_je32(inode->i_size);
119 } else if (ivalid & ATTR_SIZE && !iattr->ia_size) {
120 /* For truncate-to-zero, treat it as deletion because
121 it'll always be obsoleting all previous nodes */
122 alloc_type = ALLOC_DELETION;
118 } 123 }
119 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); 124 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
120 if (mdatalen) 125 if (mdatalen)
@@ -122,7 +127,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
122 else 127 else
123 ri->data_crc = cpu_to_je32(0); 128 ri->data_crc = cpu_to_je32(0);
124 129
125 new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, ALLOC_NORMAL); 130 new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, alloc_type);
126 if (S_ISLNK(inode->i_mode)) 131 if (S_ISLNK(inode->i_mode))
127 kfree(mdata); 132 kfree(mdata);
128 133
@@ -149,6 +154,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
149 if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) { 154 if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) {
150 jffs2_add_full_dnode_to_inode(c, f, new_metadata); 155 jffs2_add_full_dnode_to_inode(c, f, new_metadata);
151 inode->i_size = iattr->ia_size; 156 inode->i_size = iattr->ia_size;
157 inode->i_blocks = (inode->i_size + 511) >> 9;
152 f->metadata = NULL; 158 f->metadata = NULL;
153 } else { 159 } else {
154 f->metadata = new_metadata; 160 f->metadata = new_metadata;
@@ -167,8 +173,10 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
167 We are protected from a simultaneous write() extending i_size 173 We are protected from a simultaneous write() extending i_size
168 back past iattr->ia_size, because do_truncate() holds the 174 back past iattr->ia_size, because do_truncate() holds the
169 generic inode semaphore. */ 175 generic inode semaphore. */
170 if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) 176 if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) {
171 vmtruncate(inode, iattr->ia_size); 177 vmtruncate(inode, iattr->ia_size);
178 inode->i_blocks = (inode->i_size + 511) >> 9;
179 }
172 180
173 return 0; 181 return 0;
174} 182}