diff options
Diffstat (limited to 'fs/sysv/dir.c')
-rw-r--r-- | fs/sysv/dir.c | 50 |
1 files changed, 30 insertions, 20 deletions
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c index e566b387fcf9..56f655254bfe 100644 --- a/fs/sysv/dir.c +++ b/fs/sysv/dir.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/pagemap.h> | 16 | #include <linux/pagemap.h> |
17 | #include <linux/highmem.h> | 17 | #include <linux/highmem.h> |
18 | #include <linux/smp_lock.h> | 18 | #include <linux/smp_lock.h> |
19 | #include <linux/swap.h> | ||
19 | #include "sysv.h" | 20 | #include "sysv.h" |
20 | 21 | ||
21 | static int sysv_readdir(struct file *, void *, filldir_t); | 22 | static int sysv_readdir(struct file *, void *, filldir_t); |
@@ -37,12 +38,17 @@ static inline unsigned long dir_pages(struct inode *inode) | |||
37 | return (inode->i_size+PAGE_CACHE_SIZE-1)>>PAGE_CACHE_SHIFT; | 38 | return (inode->i_size+PAGE_CACHE_SIZE-1)>>PAGE_CACHE_SHIFT; |
38 | } | 39 | } |
39 | 40 | ||
40 | static int dir_commit_chunk(struct page *page, unsigned from, unsigned to) | 41 | static int dir_commit_chunk(struct page *page, loff_t pos, unsigned len) |
41 | { | 42 | { |
42 | struct inode *dir = (struct inode *)page->mapping->host; | 43 | struct address_space *mapping = page->mapping; |
44 | struct inode *dir = mapping->host; | ||
43 | int err = 0; | 45 | int err = 0; |
44 | 46 | ||
45 | page->mapping->a_ops->commit_write(NULL, page, from, to); | 47 | block_write_end(NULL, mapping, pos, len, len, page, NULL); |
48 | if (pos+len > dir->i_size) { | ||
49 | i_size_write(dir, pos+len); | ||
50 | mark_inode_dirty(dir); | ||
51 | } | ||
46 | if (IS_DIRSYNC(dir)) | 52 | if (IS_DIRSYNC(dir)) |
47 | err = write_one_page(page, 1); | 53 | err = write_one_page(page, 1); |
48 | else | 54 | else |
@@ -186,7 +192,7 @@ int sysv_add_link(struct dentry *dentry, struct inode *inode) | |||
186 | unsigned long npages = dir_pages(dir); | 192 | unsigned long npages = dir_pages(dir); |
187 | unsigned long n; | 193 | unsigned long n; |
188 | char *kaddr; | 194 | char *kaddr; |
189 | unsigned from, to; | 195 | loff_t pos; |
190 | int err; | 196 | int err; |
191 | 197 | ||
192 | /* We take care of directory expansion in the same loop */ | 198 | /* We take care of directory expansion in the same loop */ |
@@ -212,16 +218,17 @@ int sysv_add_link(struct dentry *dentry, struct inode *inode) | |||
212 | return -EINVAL; | 218 | return -EINVAL; |
213 | 219 | ||
214 | got_it: | 220 | got_it: |
215 | from = (char*)de - (char*)page_address(page); | 221 | pos = page_offset(page) + |
216 | to = from + SYSV_DIRSIZE; | 222 | (char*)de - (char*)page_address(page); |
217 | lock_page(page); | 223 | lock_page(page); |
218 | err = page->mapping->a_ops->prepare_write(NULL, page, from, to); | 224 | err = __sysv_write_begin(NULL, page->mapping, pos, SYSV_DIRSIZE, |
225 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); | ||
219 | if (err) | 226 | if (err) |
220 | goto out_unlock; | 227 | goto out_unlock; |
221 | memcpy (de->name, name, namelen); | 228 | memcpy (de->name, name, namelen); |
222 | memset (de->name + namelen, 0, SYSV_DIRSIZE - namelen - 2); | 229 | memset (de->name + namelen, 0, SYSV_DIRSIZE - namelen - 2); |
223 | de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino); | 230 | de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino); |
224 | err = dir_commit_chunk(page, from, to); | 231 | err = dir_commit_chunk(page, pos, SYSV_DIRSIZE); |
225 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; | 232 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; |
226 | mark_inode_dirty(dir); | 233 | mark_inode_dirty(dir); |
227 | out_page: | 234 | out_page: |
@@ -238,15 +245,15 @@ int sysv_delete_entry(struct sysv_dir_entry *de, struct page *page) | |||
238 | struct address_space *mapping = page->mapping; | 245 | struct address_space *mapping = page->mapping; |
239 | struct inode *inode = (struct inode*)mapping->host; | 246 | struct inode *inode = (struct inode*)mapping->host; |
240 | char *kaddr = (char*)page_address(page); | 247 | char *kaddr = (char*)page_address(page); |
241 | unsigned from = (char*)de - kaddr; | 248 | loff_t pos = page_offset(page) + (char *)de - kaddr; |
242 | unsigned to = from + SYSV_DIRSIZE; | ||
243 | int err; | 249 | int err; |
244 | 250 | ||
245 | lock_page(page); | 251 | lock_page(page); |
246 | err = mapping->a_ops->prepare_write(NULL, page, from, to); | 252 | err = __sysv_write_begin(NULL, mapping, pos, SYSV_DIRSIZE, |
253 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); | ||
247 | BUG_ON(err); | 254 | BUG_ON(err); |
248 | de->inode = 0; | 255 | de->inode = 0; |
249 | err = dir_commit_chunk(page, from, to); | 256 | err = dir_commit_chunk(page, pos, SYSV_DIRSIZE); |
250 | dir_put_page(page); | 257 | dir_put_page(page); |
251 | inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; | 258 | inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; |
252 | mark_inode_dirty(inode); | 259 | mark_inode_dirty(inode); |
@@ -263,12 +270,13 @@ int sysv_make_empty(struct inode *inode, struct inode *dir) | |||
263 | 270 | ||
264 | if (!page) | 271 | if (!page) |
265 | return -ENOMEM; | 272 | return -ENOMEM; |
266 | kmap(page); | 273 | err = __sysv_write_begin(NULL, mapping, 0, 2 * SYSV_DIRSIZE, |
267 | err = mapping->a_ops->prepare_write(NULL, page, 0, 2 * SYSV_DIRSIZE); | 274 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); |
268 | if (err) { | 275 | if (err) { |
269 | unlock_page(page); | 276 | unlock_page(page); |
270 | goto fail; | 277 | goto fail; |
271 | } | 278 | } |
279 | kmap(page); | ||
272 | 280 | ||
273 | base = (char*)page_address(page); | 281 | base = (char*)page_address(page); |
274 | memset(base, 0, PAGE_CACHE_SIZE); | 282 | memset(base, 0, PAGE_CACHE_SIZE); |
@@ -280,9 +288,9 @@ int sysv_make_empty(struct inode *inode, struct inode *dir) | |||
280 | de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), dir->i_ino); | 288 | de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), dir->i_ino); |
281 | strcpy(de->name,".."); | 289 | strcpy(de->name,".."); |
282 | 290 | ||
291 | kunmap(page); | ||
283 | err = dir_commit_chunk(page, 0, 2 * SYSV_DIRSIZE); | 292 | err = dir_commit_chunk(page, 0, 2 * SYSV_DIRSIZE); |
284 | fail: | 293 | fail: |
285 | kunmap(page); | ||
286 | page_cache_release(page); | 294 | page_cache_release(page); |
287 | return err; | 295 | return err; |
288 | } | 296 | } |
@@ -336,16 +344,18 @@ not_empty: | |||
336 | void sysv_set_link(struct sysv_dir_entry *de, struct page *page, | 344 | void sysv_set_link(struct sysv_dir_entry *de, struct page *page, |
337 | struct inode *inode) | 345 | struct inode *inode) |
338 | { | 346 | { |
339 | struct inode *dir = (struct inode*)page->mapping->host; | 347 | struct address_space *mapping = page->mapping; |
340 | unsigned from = (char *)de-(char*)page_address(page); | 348 | struct inode *dir = mapping->host; |
341 | unsigned to = from + SYSV_DIRSIZE; | 349 | loff_t pos = page_offset(page) + |
350 | (char *)de-(char*)page_address(page); | ||
342 | int err; | 351 | int err; |
343 | 352 | ||
344 | lock_page(page); | 353 | lock_page(page); |
345 | err = page->mapping->a_ops->prepare_write(NULL, page, from, to); | 354 | err = __sysv_write_begin(NULL, mapping, pos, SYSV_DIRSIZE, |
355 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); | ||
346 | BUG_ON(err); | 356 | BUG_ON(err); |
347 | de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino); | 357 | de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino); |
348 | err = dir_commit_chunk(page, from, to); | 358 | err = dir_commit_chunk(page, pos, SYSV_DIRSIZE); |
349 | dir_put_page(page); | 359 | dir_put_page(page); |
350 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; | 360 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; |
351 | mark_inode_dirty(dir); | 361 | mark_inode_dirty(dir); |