diff options
-rw-r--r-- | fs/ufs/dir.c | 55 | ||||
-rw-r--r-- | fs/ufs/inode.c | 23 | ||||
-rw-r--r-- | fs/ufs/util.h | 3 |
3 files changed, 58 insertions, 23 deletions
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c index 154452172f43..2410ec6002db 100644 --- a/fs/ufs/dir.c +++ b/fs/ufs/dir.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/time.h> | 19 | #include <linux/time.h> |
20 | #include <linux/fs.h> | 20 | #include <linux/fs.h> |
21 | #include <linux/ufs_fs.h> | 21 | #include <linux/ufs_fs.h> |
22 | #include <linux/swap.h> | ||
22 | 23 | ||
23 | #include "swab.h" | 24 | #include "swab.h" |
24 | #include "util.h" | 25 | #include "util.h" |
@@ -38,12 +39,18 @@ static inline int ufs_match(struct super_block *sb, int len, | |||
38 | return !memcmp(name, de->d_name, len); | 39 | return !memcmp(name, de->d_name, len); |
39 | } | 40 | } |
40 | 41 | ||
41 | static int ufs_commit_chunk(struct page *page, unsigned from, unsigned to) | 42 | static int ufs_commit_chunk(struct page *page, loff_t pos, unsigned len) |
42 | { | 43 | { |
43 | struct inode *dir = page->mapping->host; | 44 | struct address_space *mapping = page->mapping; |
45 | struct inode *dir = mapping->host; | ||
44 | int err = 0; | 46 | int err = 0; |
47 | |||
45 | dir->i_version++; | 48 | dir->i_version++; |
46 | page->mapping->a_ops->commit_write(NULL, page, from, to); | 49 | block_write_end(NULL, mapping, pos, len, len, page, NULL); |
50 | if (pos+len > dir->i_size) { | ||
51 | i_size_write(dir, pos+len); | ||
52 | mark_inode_dirty(dir); | ||
53 | } | ||
47 | if (IS_DIRSYNC(dir)) | 54 | if (IS_DIRSYNC(dir)) |
48 | err = write_one_page(page, 1); | 55 | err = write_one_page(page, 1); |
49 | else | 56 | else |
@@ -81,16 +88,20 @@ ino_t ufs_inode_by_name(struct inode *dir, struct dentry *dentry) | |||
81 | void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de, | 88 | void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de, |
82 | struct page *page, struct inode *inode) | 89 | struct page *page, struct inode *inode) |
83 | { | 90 | { |
84 | unsigned from = (char *) de - (char *) page_address(page); | 91 | loff_t pos = page_offset(page) + |
85 | unsigned to = from + fs16_to_cpu(dir->i_sb, de->d_reclen); | 92 | (char *) de - (char *) page_address(page); |
93 | unsigned len = fs16_to_cpu(dir->i_sb, de->d_reclen); | ||
86 | int err; | 94 | int err; |
87 | 95 | ||
88 | lock_page(page); | 96 | lock_page(page); |
89 | err = page->mapping->a_ops->prepare_write(NULL, page, from, to); | 97 | err = __ufs_write_begin(NULL, page->mapping, pos, len, |
98 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); | ||
90 | BUG_ON(err); | 99 | BUG_ON(err); |
100 | |||
91 | de->d_ino = cpu_to_fs32(dir->i_sb, inode->i_ino); | 101 | de->d_ino = cpu_to_fs32(dir->i_sb, inode->i_ino); |
92 | ufs_set_de_type(dir->i_sb, de, inode->i_mode); | 102 | ufs_set_de_type(dir->i_sb, de, inode->i_mode); |
93 | err = ufs_commit_chunk(page, from, to); | 103 | |
104 | err = ufs_commit_chunk(page, pos, len); | ||
94 | ufs_put_page(page); | 105 | ufs_put_page(page); |
95 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; | 106 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; |
96 | mark_inode_dirty(dir); | 107 | mark_inode_dirty(dir); |
@@ -312,7 +323,7 @@ int ufs_add_link(struct dentry *dentry, struct inode *inode) | |||
312 | unsigned long npages = ufs_dir_pages(dir); | 323 | unsigned long npages = ufs_dir_pages(dir); |
313 | unsigned long n; | 324 | unsigned long n; |
314 | char *kaddr; | 325 | char *kaddr; |
315 | unsigned from, to; | 326 | loff_t pos; |
316 | int err; | 327 | int err; |
317 | 328 | ||
318 | UFSD("ENTER, name %s, namelen %u\n", name, namelen); | 329 | UFSD("ENTER, name %s, namelen %u\n", name, namelen); |
@@ -367,9 +378,10 @@ int ufs_add_link(struct dentry *dentry, struct inode *inode) | |||
367 | return -EINVAL; | 378 | return -EINVAL; |
368 | 379 | ||
369 | got_it: | 380 | got_it: |
370 | from = (char*)de - (char*)page_address(page); | 381 | pos = page_offset(page) + |
371 | to = from + rec_len; | 382 | (char*)de - (char*)page_address(page); |
372 | err = page->mapping->a_ops->prepare_write(NULL, page, from, to); | 383 | err = __ufs_write_begin(NULL, page->mapping, pos, rec_len, |
384 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); | ||
373 | if (err) | 385 | if (err) |
374 | goto out_unlock; | 386 | goto out_unlock; |
375 | if (de->d_ino) { | 387 | if (de->d_ino) { |
@@ -386,7 +398,7 @@ got_it: | |||
386 | de->d_ino = cpu_to_fs32(sb, inode->i_ino); | 398 | de->d_ino = cpu_to_fs32(sb, inode->i_ino); |
387 | ufs_set_de_type(sb, de, inode->i_mode); | 399 | ufs_set_de_type(sb, de, inode->i_mode); |
388 | 400 | ||
389 | err = ufs_commit_chunk(page, from, to); | 401 | err = ufs_commit_chunk(page, pos, rec_len); |
390 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; | 402 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; |
391 | 403 | ||
392 | mark_inode_dirty(dir); | 404 | mark_inode_dirty(dir); |
@@ -509,6 +521,7 @@ int ufs_delete_entry(struct inode *inode, struct ufs_dir_entry *dir, | |||
509 | char *kaddr = page_address(page); | 521 | char *kaddr = page_address(page); |
510 | unsigned from = ((char*)dir - kaddr) & ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1); | 522 | unsigned from = ((char*)dir - kaddr) & ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1); |
511 | unsigned to = ((char*)dir - kaddr) + fs16_to_cpu(sb, dir->d_reclen); | 523 | unsigned to = ((char*)dir - kaddr) + fs16_to_cpu(sb, dir->d_reclen); |
524 | loff_t pos; | ||
512 | struct ufs_dir_entry *pde = NULL; | 525 | struct ufs_dir_entry *pde = NULL; |
513 | struct ufs_dir_entry *de = (struct ufs_dir_entry *) (kaddr + from); | 526 | struct ufs_dir_entry *de = (struct ufs_dir_entry *) (kaddr + from); |
514 | int err; | 527 | int err; |
@@ -532,13 +545,16 @@ int ufs_delete_entry(struct inode *inode, struct ufs_dir_entry *dir, | |||
532 | } | 545 | } |
533 | if (pde) | 546 | if (pde) |
534 | from = (char*)pde - (char*)page_address(page); | 547 | from = (char*)pde - (char*)page_address(page); |
548 | |||
549 | pos = page_offset(page) + from; | ||
535 | lock_page(page); | 550 | lock_page(page); |
536 | err = mapping->a_ops->prepare_write(NULL, page, from, to); | 551 | err = __ufs_write_begin(NULL, mapping, pos, to - from, |
552 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); | ||
537 | BUG_ON(err); | 553 | BUG_ON(err); |
538 | if (pde) | 554 | if (pde) |
539 | pde->d_reclen = cpu_to_fs16(sb, to-from); | 555 | pde->d_reclen = cpu_to_fs16(sb, to - from); |
540 | dir->d_ino = 0; | 556 | dir->d_ino = 0; |
541 | err = ufs_commit_chunk(page, from, to); | 557 | err = ufs_commit_chunk(page, pos, to - from); |
542 | inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; | 558 | inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; |
543 | mark_inode_dirty(inode); | 559 | mark_inode_dirty(inode); |
544 | out: | 560 | out: |
@@ -559,14 +575,15 @@ int ufs_make_empty(struct inode * inode, struct inode *dir) | |||
559 | 575 | ||
560 | if (!page) | 576 | if (!page) |
561 | return -ENOMEM; | 577 | return -ENOMEM; |
562 | kmap(page); | 578 | |
563 | err = mapping->a_ops->prepare_write(NULL, page, 0, chunk_size); | 579 | err = __ufs_write_begin(NULL, mapping, 0, chunk_size, |
580 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); | ||
564 | if (err) { | 581 | if (err) { |
565 | unlock_page(page); | 582 | unlock_page(page); |
566 | goto fail; | 583 | goto fail; |
567 | } | 584 | } |
568 | 585 | ||
569 | 586 | kmap(page); | |
570 | base = (char*)page_address(page); | 587 | base = (char*)page_address(page); |
571 | memset(base, 0, PAGE_CACHE_SIZE); | 588 | memset(base, 0, PAGE_CACHE_SIZE); |
572 | 589 | ||
@@ -584,10 +601,10 @@ int ufs_make_empty(struct inode * inode, struct inode *dir) | |||
584 | de->d_reclen = cpu_to_fs16(sb, chunk_size - UFS_DIR_REC_LEN(1)); | 601 | de->d_reclen = cpu_to_fs16(sb, chunk_size - UFS_DIR_REC_LEN(1)); |
585 | ufs_set_de_namlen(sb, de, 2); | 602 | ufs_set_de_namlen(sb, de, 2); |
586 | strcpy (de->d_name, ".."); | 603 | strcpy (de->d_name, ".."); |
604 | kunmap(page); | ||
587 | 605 | ||
588 | err = ufs_commit_chunk(page, 0, chunk_size); | 606 | err = ufs_commit_chunk(page, 0, chunk_size); |
589 | fail: | 607 | fail: |
590 | kunmap(page); | ||
591 | page_cache_release(page); | 608 | page_cache_release(page); |
592 | return err; | 609 | return err; |
593 | } | 610 | } |
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index f18b79122fa3..d84d4b0f4779 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c | |||
@@ -558,24 +558,39 @@ static int ufs_writepage(struct page *page, struct writeback_control *wbc) | |||
558 | { | 558 | { |
559 | return block_write_full_page(page,ufs_getfrag_block,wbc); | 559 | return block_write_full_page(page,ufs_getfrag_block,wbc); |
560 | } | 560 | } |
561 | |||
561 | static int ufs_readpage(struct file *file, struct page *page) | 562 | static int ufs_readpage(struct file *file, struct page *page) |
562 | { | 563 | { |
563 | return block_read_full_page(page,ufs_getfrag_block); | 564 | return block_read_full_page(page,ufs_getfrag_block); |
564 | } | 565 | } |
565 | static int ufs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to) | 566 | |
567 | int __ufs_write_begin(struct file *file, struct address_space *mapping, | ||
568 | loff_t pos, unsigned len, unsigned flags, | ||
569 | struct page **pagep, void **fsdata) | ||
566 | { | 570 | { |
567 | return block_prepare_write(page,from,to,ufs_getfrag_block); | 571 | return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, |
572 | ufs_getfrag_block); | ||
568 | } | 573 | } |
574 | |||
575 | static int ufs_write_begin(struct file *file, struct address_space *mapping, | ||
576 | loff_t pos, unsigned len, unsigned flags, | ||
577 | struct page **pagep, void **fsdata) | ||
578 | { | ||
579 | *pagep = NULL; | ||
580 | return __ufs_write_begin(file, mapping, pos, len, flags, pagep, fsdata); | ||
581 | } | ||
582 | |||
569 | static sector_t ufs_bmap(struct address_space *mapping, sector_t block) | 583 | static sector_t ufs_bmap(struct address_space *mapping, sector_t block) |
570 | { | 584 | { |
571 | return generic_block_bmap(mapping,block,ufs_getfrag_block); | 585 | return generic_block_bmap(mapping,block,ufs_getfrag_block); |
572 | } | 586 | } |
587 | |||
573 | const struct address_space_operations ufs_aops = { | 588 | const struct address_space_operations ufs_aops = { |
574 | .readpage = ufs_readpage, | 589 | .readpage = ufs_readpage, |
575 | .writepage = ufs_writepage, | 590 | .writepage = ufs_writepage, |
576 | .sync_page = block_sync_page, | 591 | .sync_page = block_sync_page, |
577 | .prepare_write = ufs_prepare_write, | 592 | .write_begin = ufs_write_begin, |
578 | .commit_write = generic_commit_write, | 593 | .write_end = generic_write_end, |
579 | .bmap = ufs_bmap | 594 | .bmap = ufs_bmap |
580 | }; | 595 | }; |
581 | 596 | ||
diff --git a/fs/ufs/util.h b/fs/ufs/util.h index 06d344839c42..79a340a1909e 100644 --- a/fs/ufs/util.h +++ b/fs/ufs/util.h | |||
@@ -231,6 +231,9 @@ ufs_set_inode_gid(struct super_block *sb, struct ufs_inode *inode, u32 value) | |||
231 | 231 | ||
232 | extern dev_t ufs_get_inode_dev(struct super_block *, struct ufs_inode_info *); | 232 | extern dev_t ufs_get_inode_dev(struct super_block *, struct ufs_inode_info *); |
233 | extern void ufs_set_inode_dev(struct super_block *, struct ufs_inode_info *, dev_t); | 233 | extern void ufs_set_inode_dev(struct super_block *, struct ufs_inode_info *, dev_t); |
234 | extern int __ufs_write_begin(struct file *file, struct address_space *mapping, | ||
235 | loff_t pos, unsigned len, unsigned flags, | ||
236 | struct page **pagep, void **fsdata); | ||
234 | 237 | ||
235 | /* | 238 | /* |
236 | * These functions manipulate ufs buffers | 239 | * These functions manipulate ufs buffers |