diff options
Diffstat (limited to 'fs/exofs')
-rw-r--r-- | fs/exofs/exofs.h | 3 | ||||
-rw-r--r-- | fs/exofs/file.c | 1 | ||||
-rw-r--r-- | fs/exofs/inode.c | 127 | ||||
-rw-r--r-- | fs/exofs/ios.c | 2 | ||||
-rw-r--r-- | fs/exofs/super.c | 2 |
5 files changed, 56 insertions, 79 deletions
diff --git a/fs/exofs/exofs.h b/fs/exofs/exofs.h index 22721b2fd890..2dc925fa1010 100644 --- a/fs/exofs/exofs.h +++ b/fs/exofs/exofs.h | |||
@@ -256,7 +256,6 @@ static inline int exofs_oi_read(struct exofs_i_info *oi, | |||
256 | } | 256 | } |
257 | 257 | ||
258 | /* inode.c */ | 258 | /* inode.c */ |
259 | void exofs_truncate(struct inode *inode); | ||
260 | int exofs_setattr(struct dentry *, struct iattr *); | 259 | int exofs_setattr(struct dentry *, struct iattr *); |
261 | int exofs_write_begin(struct file *file, struct address_space *mapping, | 260 | int exofs_write_begin(struct file *file, struct address_space *mapping, |
262 | loff_t pos, unsigned len, unsigned flags, | 261 | loff_t pos, unsigned len, unsigned flags, |
@@ -264,7 +263,7 @@ int exofs_write_begin(struct file *file, struct address_space *mapping, | |||
264 | extern struct inode *exofs_iget(struct super_block *, unsigned long); | 263 | extern struct inode *exofs_iget(struct super_block *, unsigned long); |
265 | struct inode *exofs_new_inode(struct inode *, int); | 264 | struct inode *exofs_new_inode(struct inode *, int); |
266 | extern int exofs_write_inode(struct inode *, struct writeback_control *wbc); | 265 | extern int exofs_write_inode(struct inode *, struct writeback_control *wbc); |
267 | extern void exofs_delete_inode(struct inode *); | 266 | extern void exofs_evict_inode(struct inode *); |
268 | 267 | ||
269 | /* dir.c: */ | 268 | /* dir.c: */ |
270 | int exofs_add_link(struct dentry *, struct inode *); | 269 | int exofs_add_link(struct dentry *, struct inode *); |
diff --git a/fs/exofs/file.c b/fs/exofs/file.c index aa1fd1a372cf..68cb23e3bb98 100644 --- a/fs/exofs/file.c +++ b/fs/exofs/file.c | |||
@@ -91,6 +91,5 @@ const struct file_operations exofs_file_operations = { | |||
91 | }; | 91 | }; |
92 | 92 | ||
93 | const struct inode_operations exofs_file_inode_operations = { | 93 | const struct inode_operations exofs_file_inode_operations = { |
94 | .truncate = exofs_truncate, | ||
95 | .setattr = exofs_setattr, | 94 | .setattr = exofs_setattr, |
96 | }; | 95 | }; |
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index fbf9f34554e0..eb7368ebd8cd 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c | |||
@@ -694,6 +694,13 @@ static int exofs_writepage(struct page *page, struct writeback_control *wbc) | |||
694 | return write_exec(&pcol); | 694 | return write_exec(&pcol); |
695 | } | 695 | } |
696 | 696 | ||
697 | /* i_mutex held using inode->i_size directly */ | ||
698 | static void _write_failed(struct inode *inode, loff_t to) | ||
699 | { | ||
700 | if (to > inode->i_size) | ||
701 | truncate_pagecache(inode, to, inode->i_size); | ||
702 | } | ||
703 | |||
697 | int exofs_write_begin(struct file *file, struct address_space *mapping, | 704 | int exofs_write_begin(struct file *file, struct address_space *mapping, |
698 | loff_t pos, unsigned len, unsigned flags, | 705 | loff_t pos, unsigned len, unsigned flags, |
699 | struct page **pagep, void **fsdata) | 706 | struct page **pagep, void **fsdata) |
@@ -707,7 +714,7 @@ int exofs_write_begin(struct file *file, struct address_space *mapping, | |||
707 | fsdata); | 714 | fsdata); |
708 | if (ret) { | 715 | if (ret) { |
709 | EXOFS_DBGMSG("simple_write_begin faild\n"); | 716 | EXOFS_DBGMSG("simple_write_begin faild\n"); |
710 | return ret; | 717 | goto out; |
711 | } | 718 | } |
712 | 719 | ||
713 | page = *pagep; | 720 | page = *pagep; |
@@ -722,6 +729,9 @@ int exofs_write_begin(struct file *file, struct address_space *mapping, | |||
722 | EXOFS_DBGMSG("__readpage_filler faild\n"); | 729 | EXOFS_DBGMSG("__readpage_filler faild\n"); |
723 | } | 730 | } |
724 | } | 731 | } |
732 | out: | ||
733 | if (unlikely(ret)) | ||
734 | _write_failed(mapping->host, pos + len); | ||
725 | 735 | ||
726 | return ret; | 736 | return ret; |
727 | } | 737 | } |
@@ -747,6 +757,10 @@ static int exofs_write_end(struct file *file, struct address_space *mapping, | |||
747 | int ret; | 757 | int ret; |
748 | 758 | ||
749 | ret = simple_write_end(file, mapping,pos, len, copied, page, fsdata); | 759 | ret = simple_write_end(file, mapping,pos, len, copied, page, fsdata); |
760 | if (unlikely(ret)) | ||
761 | _write_failed(inode, pos + len); | ||
762 | |||
763 | /* TODO: once simple_write_end marks inode dirty remove */ | ||
750 | if (i_size != inode->i_size) | 764 | if (i_size != inode->i_size) |
751 | mark_inode_dirty(inode); | 765 | mark_inode_dirty(inode); |
752 | return ret; | 766 | return ret; |
@@ -803,87 +817,55 @@ static inline int exofs_inode_is_fast_symlink(struct inode *inode) | |||
803 | return S_ISLNK(inode->i_mode) && (oi->i_data[0] != 0); | 817 | return S_ISLNK(inode->i_mode) && (oi->i_data[0] != 0); |
804 | } | 818 | } |
805 | 819 | ||
806 | /* | ||
807 | * get_block_t - Fill in a buffer_head | ||
808 | * An OSD takes care of block allocation so we just fake an allocation by | ||
809 | * putting in the inode's sector_t in the buffer_head. | ||
810 | * TODO: What about the case of create==0 and @iblock does not exist in the | ||
811 | * object? | ||
812 | */ | ||
813 | static int exofs_get_block(struct inode *inode, sector_t iblock, | ||
814 | struct buffer_head *bh_result, int create) | ||
815 | { | ||
816 | map_bh(bh_result, inode->i_sb, iblock); | ||
817 | return 0; | ||
818 | } | ||
819 | |||
820 | const struct osd_attr g_attr_logical_length = ATTR_DEF( | 820 | const struct osd_attr g_attr_logical_length = ATTR_DEF( |
821 | OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8); | 821 | OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8); |
822 | 822 | ||
823 | static int _do_truncate(struct inode *inode) | 823 | static int _do_truncate(struct inode *inode, loff_t newsize) |
824 | { | 824 | { |
825 | struct exofs_i_info *oi = exofs_i(inode); | 825 | struct exofs_i_info *oi = exofs_i(inode); |
826 | loff_t isize = i_size_read(inode); | ||
827 | int ret; | 826 | int ret; |
828 | 827 | ||
829 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; | 828 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; |
830 | 829 | ||
831 | nobh_truncate_page(inode->i_mapping, isize, exofs_get_block); | 830 | ret = exofs_oi_truncate(oi, (u64)newsize); |
831 | if (likely(!ret)) | ||
832 | truncate_setsize(inode, newsize); | ||
832 | 833 | ||
833 | ret = exofs_oi_truncate(oi, (u64)isize); | 834 | EXOFS_DBGMSG("(0x%lx) size=0x%llx ret=>%d\n", |
834 | EXOFS_DBGMSG("(0x%lx) size=0x%llx\n", inode->i_ino, isize); | 835 | inode->i_ino, newsize, ret); |
835 | return ret; | 836 | return ret; |
836 | } | 837 | } |
837 | 838 | ||
838 | /* | 839 | /* |
839 | * Truncate a file to the specified size - all we have to do is set the size | 840 | * Set inode attributes - update size attribute on OSD if needed, |
840 | * attribute. We make sure the object exists first. | 841 | * otherwise just call generic functions. |
841 | */ | ||
842 | void exofs_truncate(struct inode *inode) | ||
843 | { | ||
844 | struct exofs_i_info *oi = exofs_i(inode); | ||
845 | int ret; | ||
846 | |||
847 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) | ||
848 | || S_ISLNK(inode->i_mode))) | ||
849 | return; | ||
850 | if (exofs_inode_is_fast_symlink(inode)) | ||
851 | return; | ||
852 | if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) | ||
853 | return; | ||
854 | |||
855 | /* if we are about to truncate an object, and it hasn't been | ||
856 | * created yet, wait | ||
857 | */ | ||
858 | if (unlikely(wait_obj_created(oi))) | ||
859 | goto fail; | ||
860 | |||
861 | ret = _do_truncate(inode); | ||
862 | if (ret) | ||
863 | goto fail; | ||
864 | |||
865 | out: | ||
866 | mark_inode_dirty(inode); | ||
867 | return; | ||
868 | fail: | ||
869 | make_bad_inode(inode); | ||
870 | goto out; | ||
871 | } | ||
872 | |||
873 | /* | ||
874 | * Set inode attributes - just call generic functions. | ||
875 | */ | 842 | */ |
876 | int exofs_setattr(struct dentry *dentry, struct iattr *iattr) | 843 | int exofs_setattr(struct dentry *dentry, struct iattr *iattr) |
877 | { | 844 | { |
878 | struct inode *inode = dentry->d_inode; | 845 | struct inode *inode = dentry->d_inode; |
879 | int error; | 846 | int error; |
880 | 847 | ||
848 | /* if we are about to modify an object, and it hasn't been | ||
849 | * created yet, wait | ||
850 | */ | ||
851 | error = wait_obj_created(exofs_i(inode)); | ||
852 | if (unlikely(error)) | ||
853 | return error; | ||
854 | |||
881 | error = inode_change_ok(inode, iattr); | 855 | error = inode_change_ok(inode, iattr); |
882 | if (error) | 856 | if (unlikely(error)) |
883 | return error; | 857 | return error; |
884 | 858 | ||
885 | error = inode_setattr(inode, iattr); | 859 | if ((iattr->ia_valid & ATTR_SIZE) && |
886 | return error; | 860 | iattr->ia_size != i_size_read(inode)) { |
861 | error = _do_truncate(inode, iattr->ia_size); | ||
862 | if (unlikely(error)) | ||
863 | return error; | ||
864 | } | ||
865 | |||
866 | setattr_copy(inode, iattr); | ||
867 | mark_inode_dirty(inode); | ||
868 | return 0; | ||
887 | } | 869 | } |
888 | 870 | ||
889 | static const struct osd_attr g_attr_inode_file_layout = ATTR_DEF( | 871 | static const struct osd_attr g_attr_inode_file_layout = ATTR_DEF( |
@@ -1320,7 +1302,7 @@ static void delete_done(struct exofs_io_state *ios, void *p) | |||
1320 | * from the OSD here. We make sure the object was created before we try and | 1302 | * from the OSD here. We make sure the object was created before we try and |
1321 | * delete it. | 1303 | * delete it. |
1322 | */ | 1304 | */ |
1323 | void exofs_delete_inode(struct inode *inode) | 1305 | void exofs_evict_inode(struct inode *inode) |
1324 | { | 1306 | { |
1325 | struct exofs_i_info *oi = exofs_i(inode); | 1307 | struct exofs_i_info *oi = exofs_i(inode); |
1326 | struct super_block *sb = inode->i_sb; | 1308 | struct super_block *sb = inode->i_sb; |
@@ -1330,30 +1312,27 @@ void exofs_delete_inode(struct inode *inode) | |||
1330 | 1312 | ||
1331 | truncate_inode_pages(&inode->i_data, 0); | 1313 | truncate_inode_pages(&inode->i_data, 0); |
1332 | 1314 | ||
1333 | if (is_bad_inode(inode)) | 1315 | /* TODO: should do better here */ |
1316 | if (inode->i_nlink || is_bad_inode(inode)) | ||
1334 | goto no_delete; | 1317 | goto no_delete; |
1335 | 1318 | ||
1336 | mark_inode_dirty(inode); | ||
1337 | exofs_update_inode(inode, inode_needs_sync(inode)); | ||
1338 | |||
1339 | inode->i_size = 0; | 1319 | inode->i_size = 0; |
1340 | if (inode->i_blocks) | 1320 | end_writeback(inode); |
1341 | exofs_truncate(inode); | ||
1342 | 1321 | ||
1343 | clear_inode(inode); | 1322 | /* if we are deleting an obj that hasn't been created yet, wait */ |
1323 | if (!obj_created(oi)) { | ||
1324 | BUG_ON(!obj_2bcreated(oi)); | ||
1325 | wait_event(oi->i_wq, obj_created(oi)); | ||
1326 | /* ignore the error attempt a remove anyway */ | ||
1327 | } | ||
1344 | 1328 | ||
1329 | /* Now Remove the OSD objects */ | ||
1345 | ret = exofs_get_io_state(&sbi->layout, &ios); | 1330 | ret = exofs_get_io_state(&sbi->layout, &ios); |
1346 | if (unlikely(ret)) { | 1331 | if (unlikely(ret)) { |
1347 | EXOFS_ERR("%s: exofs_get_io_state failed\n", __func__); | 1332 | EXOFS_ERR("%s: exofs_get_io_state failed\n", __func__); |
1348 | return; | 1333 | return; |
1349 | } | 1334 | } |
1350 | 1335 | ||
1351 | /* if we are deleting an obj that hasn't been created yet, wait */ | ||
1352 | if (!obj_created(oi)) { | ||
1353 | BUG_ON(!obj_2bcreated(oi)); | ||
1354 | wait_event(oi->i_wq, obj_created(oi)); | ||
1355 | } | ||
1356 | |||
1357 | ios->obj.id = exofs_oi_objno(oi); | 1336 | ios->obj.id = exofs_oi_objno(oi); |
1358 | ios->done = delete_done; | 1337 | ios->done = delete_done; |
1359 | ios->private = sbi; | 1338 | ios->private = sbi; |
@@ -1369,5 +1348,5 @@ void exofs_delete_inode(struct inode *inode) | |||
1369 | return; | 1348 | return; |
1370 | 1349 | ||
1371 | no_delete: | 1350 | no_delete: |
1372 | clear_inode(inode); | 1351 | end_writeback(inode); |
1373 | } | 1352 | } |
diff --git a/fs/exofs/ios.c b/fs/exofs/ios.c index 5a1960500c8a..6550bf70e41d 100644 --- a/fs/exofs/ios.c +++ b/fs/exofs/ios.c | |||
@@ -579,7 +579,7 @@ static int _sbi_write_mirror(struct exofs_io_state *ios, int cur_comp) | |||
579 | } else { | 579 | } else { |
580 | bio = master_dev->bio; | 580 | bio = master_dev->bio; |
581 | /* FIXME: bio_set_dir() */ | 581 | /* FIXME: bio_set_dir() */ |
582 | bio->bi_rw |= (1 << BIO_RW); | 582 | bio->bi_rw |= REQ_WRITE; |
583 | } | 583 | } |
584 | 584 | ||
585 | osd_req_write(or, &ios->obj, per_dev->offset, bio, | 585 | osd_req_write(or, &ios->obj, per_dev->offset, bio, |
diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 50cb1745e29c..047e92fa3af8 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c | |||
@@ -742,7 +742,7 @@ static const struct super_operations exofs_sops = { | |||
742 | .alloc_inode = exofs_alloc_inode, | 742 | .alloc_inode = exofs_alloc_inode, |
743 | .destroy_inode = exofs_destroy_inode, | 743 | .destroy_inode = exofs_destroy_inode, |
744 | .write_inode = exofs_write_inode, | 744 | .write_inode = exofs_write_inode, |
745 | .delete_inode = exofs_delete_inode, | 745 | .evict_inode = exofs_evict_inode, |
746 | .put_super = exofs_put_super, | 746 | .put_super = exofs_put_super, |
747 | .write_super = exofs_write_super, | 747 | .write_super = exofs_write_super, |
748 | .sync_fs = exofs_sync_fs, | 748 | .sync_fs = exofs_sync_fs, |