aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exofs
diff options
context:
space:
mode:
authorBoaz Harrosh <bharrosh@panasas.com>2010-06-09 11:23:18 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2010-08-09 16:47:41 -0400
commit2f246fd0f126f3b3c23a4e6b7109350e83356bd6 (patch)
tree10cc6c830e4ffcc116faaf886e72dd3f0b73d849 /fs/exofs
parent41cce647f8dbe26941bed2158fad0839aab7a294 (diff)
exofs: New truncate sequence
These changes are crafted based on the similar conversion done to ext2 by Nick Piggin. * Remove the deprecated ->truncate vector. Let exofs_setattr take care of on-disk size updates. * Call truncate_pagecache on the unused pages if write_begin/end fails. * Cleanup exofs_delete_inode that did stupid inode writes and updates on an inode that will be removed. * And finally get rid of exofs_get_block. We never had any blocks it was all for calling nobh_truncate_page. nobh_truncate_page is not actually needed in exofs since the last page is complete and gone, just like all the other pages. There is no partial blocks in exofs. I've tested with this patch, and there are no apparent failures, so far. CC: Nick Piggin <npiggin@suse.de> CC: Christoph Hellwig <hch@lst.de> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/exofs')
-rw-r--r--fs/exofs/exofs.h1
-rw-r--r--fs/exofs/file.c1
-rw-r--r--fs/exofs/inode.c115
3 files changed, 42 insertions, 75 deletions
diff --git a/fs/exofs/exofs.h b/fs/exofs/exofs.h
index 22721b2fd890..0706ce996c84 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 */
259void exofs_truncate(struct inode *inode);
260int exofs_setattr(struct dentry *, struct iattr *); 259int exofs_setattr(struct dentry *, struct iattr *);
261int exofs_write_begin(struct file *file, struct address_space *mapping, 260int 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,
diff --git a/fs/exofs/file.c b/fs/exofs/file.c
index fef6899be397..f9bfe2b501d5 100644
--- a/fs/exofs/file.c
+++ b/fs/exofs/file.c
@@ -86,6 +86,5 @@ const struct file_operations exofs_file_operations = {
86}; 86};
87 87
88const struct inode_operations exofs_file_inode_operations = { 88const struct inode_operations exofs_file_inode_operations = {
89 .truncate = exofs_truncate,
90 .setattr = exofs_setattr, 89 .setattr = exofs_setattr,
91}; 90};
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c
index 4bfc1f4fd013..ccd0ce3eea75 100644
--- a/fs/exofs/inode.c
+++ b/fs/exofs/inode.c
@@ -697,6 +697,13 @@ static int exofs_writepage(struct page *page, struct writeback_control *wbc)
697 return write_exec(&pcol); 697 return write_exec(&pcol);
698} 698}
699 699
700/* i_mutex held using inode->i_size directly */
701static void _write_failed(struct inode *inode, loff_t to)
702{
703 if (to > inode->i_size)
704 truncate_pagecache(inode, to, inode->i_size);
705}
706
700int exofs_write_begin(struct file *file, struct address_space *mapping, 707int exofs_write_begin(struct file *file, struct address_space *mapping,
701 loff_t pos, unsigned len, unsigned flags, 708 loff_t pos, unsigned len, unsigned flags,
702 struct page **pagep, void **fsdata) 709 struct page **pagep, void **fsdata)
@@ -710,7 +717,7 @@ int exofs_write_begin(struct file *file, struct address_space *mapping,
710 fsdata); 717 fsdata);
711 if (ret) { 718 if (ret) {
712 EXOFS_DBGMSG("simple_write_begin faild\n"); 719 EXOFS_DBGMSG("simple_write_begin faild\n");
713 return ret; 720 goto out;
714 } 721 }
715 722
716 page = *pagep; 723 page = *pagep;
@@ -725,6 +732,9 @@ int exofs_write_begin(struct file *file, struct address_space *mapping,
725 EXOFS_DBGMSG("__readpage_filler faild\n"); 732 EXOFS_DBGMSG("__readpage_filler faild\n");
726 } 733 }
727 } 734 }
735out:
736 if (unlikely(ret))
737 _write_failed(mapping->host, pos + len);
728 738
729 return ret; 739 return ret;
730} 740}
@@ -750,6 +760,10 @@ static int exofs_write_end(struct file *file, struct address_space *mapping,
750 int ret; 760 int ret;
751 761
752 ret = simple_write_end(file, mapping,pos, len, copied, page, fsdata); 762 ret = simple_write_end(file, mapping,pos, len, copied, page, fsdata);
763 if (unlikely(ret))
764 _write_failed(inode, pos + len);
765
766 /* TODO: once simple_write_end marks inode dirty remove */
753 if (i_size != inode->i_size) 767 if (i_size != inode->i_size)
754 mark_inode_dirty(inode); 768 mark_inode_dirty(inode);
755 return ret; 769 return ret;
@@ -808,91 +822,49 @@ static inline int exofs_inode_is_fast_symlink(struct inode *inode)
808 return S_ISLNK(inode->i_mode) && (oi->i_data[0] != 0); 822 return S_ISLNK(inode->i_mode) && (oi->i_data[0] != 0);
809} 823}
810 824
811/*
812 * get_block_t - Fill in a buffer_head
813 * An OSD takes care of block allocation so we just fake an allocation by
814 * putting in the inode's sector_t in the buffer_head.
815 * TODO: What about the case of create==0 and @iblock does not exist in the
816 * object?
817 */
818static int exofs_get_block(struct inode *inode, sector_t iblock,
819 struct buffer_head *bh_result, int create)
820{
821 map_bh(bh_result, inode->i_sb, iblock);
822 return 0;
823}
824
825const struct osd_attr g_attr_logical_length = ATTR_DEF( 825const struct osd_attr g_attr_logical_length = ATTR_DEF(
826 OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8); 826 OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8);
827 827
828static int _do_truncate(struct inode *inode) 828static int _do_truncate(struct inode *inode, loff_t newsize)
829{ 829{
830 struct exofs_i_info *oi = exofs_i(inode); 830 struct exofs_i_info *oi = exofs_i(inode);
831 loff_t isize = i_size_read(inode);
832 int ret; 831 int ret;
833 832
834 inode->i_mtime = inode->i_ctime = CURRENT_TIME; 833 inode->i_mtime = inode->i_ctime = CURRENT_TIME;
835 834
836 nobh_truncate_page(inode->i_mapping, isize, exofs_get_block); 835 ret = exofs_oi_truncate(oi, (u64)newsize);
836 if (likely(!ret))
837 truncate_setsize(inode, newsize);
837 838
838 ret = exofs_oi_truncate(oi, (u64)isize); 839 EXOFS_DBGMSG("(0x%lx) size=0x%llx ret=>%d\n",
839 EXOFS_DBGMSG("(0x%lx) size=0x%llx\n", inode->i_ino, isize); 840 inode->i_ino, newsize, ret);
840 return ret; 841 return ret;
841} 842}
842 843
843/* 844/*
844 * Truncate a file to the specified size - all we have to do is set the size 845 * Set inode attributes - update size attribute on OSD if needed,
845 * attribute. We make sure the object exists first. 846 * otherwise just call generic functions.
846 */
847void exofs_truncate(struct inode *inode)
848{
849 struct exofs_i_info *oi = exofs_i(inode);
850 int ret;
851
852 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
853 || S_ISLNK(inode->i_mode)))
854 return;
855 if (exofs_inode_is_fast_symlink(inode))
856 return;
857 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
858 return;
859
860 /* if we are about to truncate an object, and it hasn't been
861 * created yet, wait
862 */
863 if (unlikely(wait_obj_created(oi)))
864 goto fail;
865
866 ret = _do_truncate(inode);
867 if (ret)
868 goto fail;
869
870out:
871 mark_inode_dirty(inode);
872 return;
873fail:
874 make_bad_inode(inode);
875 goto out;
876}
877
878/*
879 * Set inode attributes - just call generic functions.
880 */ 847 */
881int exofs_setattr(struct dentry *dentry, struct iattr *iattr) 848int exofs_setattr(struct dentry *dentry, struct iattr *iattr)
882{ 849{
883 struct inode *inode = dentry->d_inode; 850 struct inode *inode = dentry->d_inode;
884 int error; 851 int error;
885 852
853 /* if we are about to modify an object, and it hasn't been
854 * created yet, wait
855 */
856 error = wait_obj_created(exofs_i(inode));
857 if (unlikely(error))
858 return error;
859
886 error = inode_change_ok(inode, iattr); 860 error = inode_change_ok(inode, iattr);
887 if (error) 861 if (unlikely(error))
888 return error; 862 return error;
889 863
890 if ((iattr->ia_valid & ATTR_SIZE) && 864 if ((iattr->ia_valid & ATTR_SIZE) &&
891 iattr->ia_size != i_size_read(inode)) { 865 iattr->ia_size != i_size_read(inode)) {
892 int error; 866 error = _do_truncate(inode, iattr->ia_size);
893 867 if (unlikely(error))
894 error = vmtruncate(inode, iattr->ia_size);
895 if (error)
896 return error; 868 return error;
897 } 869 }
898 870
@@ -1345,28 +1317,25 @@ void exofs_delete_inode(struct inode *inode)
1345 1317
1346 truncate_inode_pages(&inode->i_data, 0); 1318 truncate_inode_pages(&inode->i_data, 0);
1347 1319
1320 /* TODO: should do better here */
1348 if (is_bad_inode(inode)) 1321 if (is_bad_inode(inode))
1349 goto no_delete; 1322 goto no_delete;
1350 1323
1351 mark_inode_dirty(inode);
1352 exofs_update_inode(inode, inode_needs_sync(inode));
1353
1354 inode->i_size = 0; 1324 inode->i_size = 0;
1355 if (inode->i_blocks)
1356 exofs_truncate(inode);
1357
1358 clear_inode(inode); 1325 clear_inode(inode);
1359 1326
1360 ret = exofs_get_io_state(&sbi->layout, &ios);
1361 if (unlikely(ret)) {
1362 EXOFS_ERR("%s: exofs_get_io_state failed\n", __func__);
1363 return;
1364 }
1365
1366 /* if we are deleting an obj that hasn't been created yet, wait */ 1327 /* if we are deleting an obj that hasn't been created yet, wait */
1367 if (!obj_created(oi)) { 1328 if (!obj_created(oi)) {
1368 BUG_ON(!obj_2bcreated(oi)); 1329 BUG_ON(!obj_2bcreated(oi));
1369 wait_event(oi->i_wq, obj_created(oi)); 1330 wait_event(oi->i_wq, obj_created(oi));
1331 /* ignore the error attempt a remove anyway */
1332 }
1333
1334 /* Now Remove the OSD objects */
1335 ret = exofs_get_io_state(&sbi->layout, &ios);
1336 if (unlikely(ret)) {
1337 EXOFS_ERR("%s: exofs_get_io_state failed\n", __func__);
1338 return;
1370 } 1339 }
1371 1340
1372 ios->obj.id = exofs_oi_objno(oi); 1341 ios->obj.id = exofs_oi_objno(oi);