diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/jffs2/fs.c | 14 |
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 | } |