diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2006-01-09 14:18:33 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2006-01-09 14:18:33 -0500 |
commit | 0a3a98f6dd4e8f4d928a09302c0d1c56f2192ac3 (patch) | |
tree | 92f55e374a84d06ce8213a4540454760fdecf137 /fs/fat/file.c | |
parent | 8ef12c9f01afba47c2d33bb939085111ca0d0f7d (diff) | |
parent | 5367f2d67c7d0bf1faae90e6e7b4e2ac3c9b5e0f (diff) |
Merge Linus' tree.
Diffstat (limited to 'fs/fat/file.c')
-rw-r--r-- | fs/fat/file.c | 33 |
1 files changed, 29 insertions, 4 deletions
diff --git a/fs/fat/file.c b/fs/fat/file.c index 7134403d5be2..9b07c328a6fc 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/msdos_fs.h> | 11 | #include <linux/msdos_fs.h> |
12 | #include <linux/smp_lock.h> | 12 | #include <linux/smp_lock.h> |
13 | #include <linux/buffer_head.h> | 13 | #include <linux/buffer_head.h> |
14 | #include <linux/writeback.h> | ||
14 | 15 | ||
15 | int fat_generic_ioctl(struct inode *inode, struct file *filp, | 16 | int fat_generic_ioctl(struct inode *inode, struct file *filp, |
16 | unsigned int cmd, unsigned long arg) | 17 | unsigned int cmd, unsigned long arg) |
@@ -124,6 +125,24 @@ struct file_operations fat_file_operations = { | |||
124 | .sendfile = generic_file_sendfile, | 125 | .sendfile = generic_file_sendfile, |
125 | }; | 126 | }; |
126 | 127 | ||
128 | static int fat_cont_expand(struct inode *inode, loff_t size) | ||
129 | { | ||
130 | struct address_space *mapping = inode->i_mapping; | ||
131 | loff_t start = inode->i_size, count = size - inode->i_size; | ||
132 | int err; | ||
133 | |||
134 | err = generic_cont_expand_simple(inode, size); | ||
135 | if (err) | ||
136 | goto out; | ||
137 | |||
138 | inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; | ||
139 | mark_inode_dirty(inode); | ||
140 | if (IS_SYNC(inode)) | ||
141 | err = sync_page_range_nolock(inode, mapping, start, count); | ||
142 | out: | ||
143 | return err; | ||
144 | } | ||
145 | |||
127 | int fat_notify_change(struct dentry *dentry, struct iattr *attr) | 146 | int fat_notify_change(struct dentry *dentry, struct iattr *attr) |
128 | { | 147 | { |
129 | struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb); | 148 | struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb); |
@@ -132,11 +151,17 @@ int fat_notify_change(struct dentry *dentry, struct iattr *attr) | |||
132 | 151 | ||
133 | lock_kernel(); | 152 | lock_kernel(); |
134 | 153 | ||
135 | /* FAT cannot truncate to a longer file */ | 154 | /* |
155 | * Expand the file. Since inode_setattr() updates ->i_size | ||
156 | * before calling the ->truncate(), but FAT needs to fill the | ||
157 | * hole before it. | ||
158 | */ | ||
136 | if (attr->ia_valid & ATTR_SIZE) { | 159 | if (attr->ia_valid & ATTR_SIZE) { |
137 | if (attr->ia_size > inode->i_size) { | 160 | if (attr->ia_size > inode->i_size) { |
138 | error = -EPERM; | 161 | error = fat_cont_expand(inode, attr->ia_size); |
139 | goto out; | 162 | if (error || attr->ia_valid == ATTR_SIZE) |
163 | goto out; | ||
164 | attr->ia_valid &= ~ATTR_SIZE; | ||
140 | } | 165 | } |
141 | } | 166 | } |
142 | 167 | ||
@@ -173,7 +198,7 @@ out: | |||
173 | return error; | 198 | return error; |
174 | } | 199 | } |
175 | 200 | ||
176 | EXPORT_SYMBOL(fat_notify_change); | 201 | EXPORT_SYMBOL_GPL(fat_notify_change); |
177 | 202 | ||
178 | /* Free all clusters after the skip'th cluster. */ | 203 | /* Free all clusters after the skip'th cluster. */ |
179 | static int fat_free(struct inode *inode, int skip) | 204 | static int fat_free(struct inode *inode, int skip) |