From: Boaz Harrosh <bharrosh@panasas.com>
To: Christoph Hellwig <hch@lst.de>, Nick Piggin <npiggin@suse.de>,
linux-fsdevel <linux-fsdevel@vger.kernel.org>,
open-osd <osd-dev@open-osd.org>
Subject: [RFC] exofs: New truncate sequence
Date: Mon, 31 May 2010 15:30:02 +0300 [thread overview]
Message-ID: <4C03ABCA.4050602@panasas.com> (raw)
These changes are crafted based on the similar
conversion done to ext2 by Nick Piggin.
Please check me out I bound to have miss-looked
something.
- Remove the deprecated ->truncate vector, call a new
exofs_setsize for on-disk size update, from exofs_setattr
- 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.
[OK do I might need a partial read here upto i_size ???]
I've tested with this patch, and there are no apparent
failures, so far.
These patches are based on Al's vfs for-next branch, which
contain Nick's last patches. But they do not contain,
(and will lightly conflict with) latest Christoph's
patches. Christoph do you have a tree I can rebase on? or
maybe you want to take this patch into your patchset?
CC: Christoph Hellwig <hch@lst.de>
CC: Nick Piggin <npiggin@suse.de>
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
---
fs/exofs/exofs.h | 1 -
fs/exofs/file.c | 1 -
fs/exofs/inode.c | 115 +++++++++++++++++++++++++++---------------------------
3 files changed, 58 insertions(+), 59 deletions(-)
diff --git a/fs/exofs/exofs.h b/fs/exofs/exofs.h
index 22721b2..0706ce9 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,
}
/* inode.c */
-void exofs_truncate(struct inode *inode);
int exofs_setattr(struct dentry *, struct iattr *);
int exofs_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
diff --git a/fs/exofs/file.c b/fs/exofs/file.c
index fef6899..f9bfe2b 100644
--- a/fs/exofs/file.c
+++ b/fs/exofs/file.c
@@ -86,6 +86,5 @@ const struct file_operations exofs_file_operations = {
};
const struct inode_operations exofs_file_inode_operations = {
- .truncate = exofs_truncate,
.setattr = exofs_setattr,
};
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c
index 4bb6ef8..1c2666c 100644
--- a/fs/exofs/inode.c
+++ b/fs/exofs/inode.c
@@ -710,7 +710,7 @@ int exofs_write_begin(struct file *file, struct address_space *mapping,
fsdata);
if (ret) {
EXOFS_DBGMSG("simple_write_begin faild\n");
- return ret;
+ goto out;
}
page = *pagep;
@@ -725,7 +725,17 @@ int exofs_write_begin(struct file *file, struct address_space *mapping,
EXOFS_DBGMSG("__readpage_filler faild\n");
}
}
+out:
+ if (unlikely(ret)) {
+ struct inode *inode = mapping->host;
+ loff_t to = pos + len;
+ if (to > inode->i_size)
+ truncate_pagecache(inode, to, inode->i_size);
+
+ mark_inode_dirty(inode); /* write the new size */
+ return ret;
+ }
return ret;
}
@@ -750,6 +760,10 @@ static int exofs_write_end(struct file *file, struct address_space *mapping,
int ret;
ret = simple_write_end(file, mapping,pos, len, copied, page, fsdata);
+ if (unlikely(ret && pos + len > inode->i_size))
+ truncate_pagecache(inode, pos + len, inode->i_size);
+
+ /* TODO: once simple_write_end marks inode dirty remove */
if (i_size != inode->i_size)
mark_inode_dirty(inode);
return ret;
@@ -808,35 +822,18 @@ static inline int exofs_inode_is_fast_symlink(struct inode *inode)
return S_ISLNK(inode->i_mode) && (oi->i_data[0] != 0);
}
-/*
- * get_block_t - Fill in a buffer_head
- * An OSD takes care of block allocation so we just fake an allocation by
- * putting in the inode's sector_t in the buffer_head.
- * TODO: What about the case of create==0 and @iblock does not exist in the
- * object?
- */
-static int exofs_get_block(struct inode *inode, sector_t iblock,
- struct buffer_head *bh_result, int create)
-{
- map_bh(bh_result, inode->i_sb, iblock);
- return 0;
-}
-
const struct osd_attr g_attr_logical_length = ATTR_DEF(
OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8);
-static int _do_truncate(struct inode *inode)
+static int _do_truncate(struct inode *inode, loff_t newsize)
{
struct exofs_i_info *oi = exofs_i(inode);
- loff_t isize = i_size_read(inode);
int ret;
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- nobh_truncate_page(inode->i_mapping, isize, exofs_get_block);
-
- ret = exofs_oi_truncate(oi, (u64)isize);
- EXOFS_DBGMSG("(0x%lx) size=0x%llx\n", inode->i_ino, isize);
+ ret = exofs_oi_truncate(oi, (u64)newsize);
+ EXOFS_DBGMSG("(0x%lx) size=0x%llx\n", inode->i_ino, newsize);
return ret;
}
@@ -844,35 +841,28 @@ static int _do_truncate(struct inode *inode)
* Truncate a file to the specified size - all we have to do is set the size
* attribute. We make sure the object exists first.
*/
-void exofs_truncate(struct inode *inode)
+static int exofs_setsize(struct inode *inode, loff_t newsize)
{
- struct exofs_i_info *oi = exofs_i(inode);
- int ret;
+ loff_t oldsize;
+ int error;
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
- || S_ISLNK(inode->i_mode)))
- return;
+ error = inode_newsize_ok(inode, newsize);
+ if (error)
+ return error;
+
+ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+ S_ISLNK(inode->i_mode)))
+ return -EINVAL;
if (exofs_inode_is_fast_symlink(inode))
- return;
+ return -EINVAL;
if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
- return;
-
- /* if we are about to truncate an object, and it hasn't been
- * created yet, wait
- */
- if (unlikely(wait_obj_created(oi)))
- goto fail;
+ return -EPERM;
- ret = _do_truncate(inode);
- if (ret)
- goto fail;
+ oldsize = inode->i_size;
+ i_size_write(inode, newsize);
+ truncate_pagecache(inode, oldsize, newsize);
-out:
- mark_inode_dirty(inode);
- return;
-fail:
- make_bad_inode(inode);
- goto out;
+ return _do_truncate(inode, newsize);
}
/*
@@ -883,11 +873,25 @@ int exofs_setattr(struct dentry *dentry, struct iattr *iattr)
struct inode *inode = dentry->d_inode;
int error;
+ /* if we are about to modify an object, and it hasn't been
+ * created yet, wait
+ */
+ error = wait_obj_created(exofs_i(inode));
+ if (unlikely(error))
+ return error;
+
error = inode_change_ok(inode, iattr);
if (error)
return error;
- error = inode_setattr(inode, iattr);
+ if (iattr->ia_valid & ATTR_SIZE) {
+ error = exofs_setsize(inode, iattr->ia_size);
+ if (error)
+ return error;
+ }
+ generic_setattr(inode, iattr);
+ mark_inode_dirty(inode);
+
return error;
}
@@ -1335,28 +1339,25 @@ void exofs_delete_inode(struct inode *inode)
truncate_inode_pages(&inode->i_data, 0);
+ /* TODO: should do better here */
if (is_bad_inode(inode))
goto no_delete;
- mark_inode_dirty(inode);
- exofs_update_inode(inode, inode_needs_sync(inode));
-
inode->i_size = 0;
- if (inode->i_blocks)
- exofs_truncate(inode);
-
clear_inode(inode);
- ret = exofs_get_io_state(&sbi->layout, &ios);
- if (unlikely(ret)) {
- EXOFS_ERR("%s: exofs_get_io_state failed\n", __func__);
- return;
- }
-
/* if we are deleting an obj that hasn't been created yet, wait */
if (!obj_created(oi)) {
BUG_ON(!obj_2bcreated(oi));
wait_event(oi->i_wq, obj_created(oi));
+ /* ignore the error attempt a remove anyway */
+ }
+
+ /* Now Remove the OSD objects */
+ ret = exofs_get_io_state(&sbi->layout, &ios);
+ if (unlikely(ret)) {
+ EXOFS_ERR("%s: exofs_get_io_state failed\n", __func__);
+ return;
}
ios->obj.id = exofs_oi_objno(oi);
--
1.6.6.1
next reply other threads:[~2010-05-31 12:30 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-05-31 12:30 Boaz Harrosh [this message]
2010-05-31 13:44 ` [RFC] exofs: New truncate sequence Nick Piggin
2010-05-31 14:13 ` Boaz Harrosh
2010-05-31 14:33 ` Nick Piggin
2010-05-31 14:50 ` Boaz Harrosh
2010-05-31 15:09 ` Nick Piggin
2010-05-31 15:19 ` Boaz Harrosh
2010-06-01 10:08 ` Christoph Hellwig
2010-06-01 10:26 ` Boaz Harrosh
2010-06-01 10:44 ` Christoph Hellwig
2010-06-01 11:05 ` Boaz Harrosh
2010-06-01 11:06 ` Christoph Hellwig
2010-06-01 10:28 ` [PATCH ver2] " Boaz Harrosh
2010-06-01 10:43 ` Christoph Hellwig
2010-06-01 10:59 ` Boaz Harrosh
2010-06-01 11:06 ` Christoph Hellwig
2010-06-01 11:31 ` [PATCH ver3] " Boaz Harrosh
2010-06-01 11:36 ` Christoph Hellwig
2010-06-01 11:52 ` Boaz Harrosh
2010-06-01 15:09 ` Nick Piggin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4C03ABCA.4050602@panasas.com \
--to=bharrosh@panasas.com \
--cc=hch@lst.de \
--cc=linux-fsdevel@vger.kernel.org \
--cc=npiggin@suse.de \
--cc=osd-dev@open-osd.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.