|
@@ -391,31 +391,28 @@ out:
|
|
static int ocfs2_commit_write(struct file *file, struct page *page,
|
|
static int ocfs2_commit_write(struct file *file, struct page *page,
|
|
unsigned from, unsigned to)
|
|
unsigned from, unsigned to)
|
|
{
|
|
{
|
|
- int ret, extending = 0, locklevel = 0;
|
|
|
|
- loff_t new_i_size;
|
|
|
|
|
|
+ int ret;
|
|
struct buffer_head *di_bh = NULL;
|
|
struct buffer_head *di_bh = NULL;
|
|
struct inode *inode = page->mapping->host;
|
|
struct inode *inode = page->mapping->host;
|
|
struct ocfs2_journal_handle *handle = NULL;
|
|
struct ocfs2_journal_handle *handle = NULL;
|
|
|
|
+ struct ocfs2_dinode *di;
|
|
|
|
|
|
mlog_entry("(0x%p, 0x%p, %u, %u)\n", file, page, from, to);
|
|
mlog_entry("(0x%p, 0x%p, %u, %u)\n", file, page, from, to);
|
|
|
|
|
|
/* NOTE: ocfs2_file_aio_write has ensured that it's safe for
|
|
/* NOTE: ocfs2_file_aio_write has ensured that it's safe for
|
|
- * us to sample inode->i_size here without the metadata lock:
|
|
|
|
|
|
+ * us to continue here without rechecking the I/O against
|
|
|
|
+ * changed inode values.
|
|
*
|
|
*
|
|
* 1) We're currently holding the inode alloc lock, so no
|
|
* 1) We're currently holding the inode alloc lock, so no
|
|
* nodes can change it underneath us.
|
|
* nodes can change it underneath us.
|
|
*
|
|
*
|
|
* 2) We've had to take the metadata lock at least once
|
|
* 2) We've had to take the metadata lock at least once
|
|
- * already to check for extending writes, hence insuring
|
|
|
|
- * that our current copy is also up to date.
|
|
|
|
|
|
+ * already to check for extending writes, suid removal, etc.
|
|
|
|
+ * The meta data update code then ensures that we don't get a
|
|
|
|
+ * stale inode allocation image (i_size, i_clusters, etc).
|
|
*/
|
|
*/
|
|
- new_i_size = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
|
|
|
|
- if (new_i_size > i_size_read(inode)) {
|
|
|
|
- extending = 1;
|
|
|
|
- locklevel = 1;
|
|
|
|
- }
|
|
|
|
|
|
|
|
- ret = ocfs2_meta_lock_with_page(inode, NULL, &di_bh, locklevel, page);
|
|
|
|
|
|
+ ret = ocfs2_meta_lock_with_page(inode, NULL, &di_bh, 1, page);
|
|
if (ret != 0) {
|
|
if (ret != 0) {
|
|
mlog_errno(ret);
|
|
mlog_errno(ret);
|
|
goto out;
|
|
goto out;
|
|
@@ -427,23 +424,20 @@ static int ocfs2_commit_write(struct file *file, struct page *page,
|
|
goto out_unlock_meta;
|
|
goto out_unlock_meta;
|
|
}
|
|
}
|
|
|
|
|
|
- if (extending) {
|
|
|
|
- handle = ocfs2_start_walk_page_trans(inode, page, from, to);
|
|
|
|
- if (IS_ERR(handle)) {
|
|
|
|
- ret = PTR_ERR(handle);
|
|
|
|
- handle = NULL;
|
|
|
|
- goto out_unlock_data;
|
|
|
|
- }
|
|
|
|
|
|
+ handle = ocfs2_start_walk_page_trans(inode, page, from, to);
|
|
|
|
+ if (IS_ERR(handle)) {
|
|
|
|
+ ret = PTR_ERR(handle);
|
|
|
|
+ goto out_unlock_data;
|
|
|
|
+ }
|
|
|
|
|
|
- /* Mark our buffer early. We'd rather catch this error up here
|
|
|
|
- * as opposed to after a successful commit_write which would
|
|
|
|
- * require us to set back inode->i_size. */
|
|
|
|
- ret = ocfs2_journal_access(handle, inode, di_bh,
|
|
|
|
- OCFS2_JOURNAL_ACCESS_WRITE);
|
|
|
|
- if (ret < 0) {
|
|
|
|
- mlog_errno(ret);
|
|
|
|
- goto out_commit;
|
|
|
|
- }
|
|
|
|
|
|
+ /* Mark our buffer early. We'd rather catch this error up here
|
|
|
|
+ * as opposed to after a successful commit_write which would
|
|
|
|
+ * require us to set back inode->i_size. */
|
|
|
|
+ ret = ocfs2_journal_access(handle, inode, di_bh,
|
|
|
|
+ OCFS2_JOURNAL_ACCESS_WRITE);
|
|
|
|
+ if (ret < 0) {
|
|
|
|
+ mlog_errno(ret);
|
|
|
|
+ goto out_commit;
|
|
}
|
|
}
|
|
|
|
|
|
/* might update i_size */
|
|
/* might update i_size */
|
|
@@ -453,37 +447,28 @@ static int ocfs2_commit_write(struct file *file, struct page *page,
|
|
goto out_commit;
|
|
goto out_commit;
|
|
}
|
|
}
|
|
|
|
|
|
- if (extending) {
|
|
|
|
- loff_t size = (u64) i_size_read(inode);
|
|
|
|
- struct ocfs2_dinode *di =
|
|
|
|
- (struct ocfs2_dinode *)di_bh->b_data;
|
|
|
|
|
|
+ di = (struct ocfs2_dinode *)di_bh->b_data;
|
|
|
|
|
|
- /* ocfs2_mark_inode_dirty is too heavy to use here. */
|
|
|
|
- inode->i_blocks = ocfs2_align_bytes_to_sectors(size);
|
|
|
|
- inode->i_ctime = inode->i_mtime = CURRENT_TIME;
|
|
|
|
|
|
+ /* ocfs2_mark_inode_dirty() is too heavy to use here. */
|
|
|
|
+ inode->i_mtime = inode->i_ctime = CURRENT_TIME;
|
|
|
|
+ di->i_mtime = di->i_ctime = cpu_to_le64(inode->i_mtime.tv_sec);
|
|
|
|
+ di->i_mtime_nsec = di->i_ctime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
|
|
|
|
|
|
- di->i_size = cpu_to_le64(size);
|
|
|
|
- di->i_ctime = di->i_mtime =
|
|
|
|
- cpu_to_le64(inode->i_mtime.tv_sec);
|
|
|
|
- di->i_ctime_nsec = di->i_mtime_nsec =
|
|
|
|
- cpu_to_le32(inode->i_mtime.tv_nsec);
|
|
|
|
|
|
+ inode->i_blocks = ocfs2_align_bytes_to_sectors((u64)(i_size_read(inode)));
|
|
|
|
+ di->i_size = cpu_to_le64((u64)i_size_read(inode));
|
|
|
|
|
|
- ret = ocfs2_journal_dirty(handle, di_bh);
|
|
|
|
- if (ret < 0) {
|
|
|
|
- mlog_errno(ret);
|
|
|
|
- goto out_commit;
|
|
|
|
- }
|
|
|
|
|
|
+ ret = ocfs2_journal_dirty(handle, di_bh);
|
|
|
|
+ if (ret < 0) {
|
|
|
|
+ mlog_errno(ret);
|
|
|
|
+ goto out_commit;
|
|
}
|
|
}
|
|
|
|
|
|
- BUG_ON(extending && (i_size_read(inode) != new_i_size));
|
|
|
|
-
|
|
|
|
out_commit:
|
|
out_commit:
|
|
- if (handle)
|
|
|
|
- ocfs2_commit_trans(handle);
|
|
|
|
|
|
+ ocfs2_commit_trans(handle);
|
|
out_unlock_data:
|
|
out_unlock_data:
|
|
ocfs2_data_unlock(inode, 1);
|
|
ocfs2_data_unlock(inode, 1);
|
|
out_unlock_meta:
|
|
out_unlock_meta:
|
|
- ocfs2_meta_unlock(inode, locklevel);
|
|
|
|
|
|
+ ocfs2_meta_unlock(inode, 1);
|
|
out:
|
|
out:
|
|
if (di_bh)
|
|
if (di_bh)
|
|
brelse(di_bh);
|
|
brelse(di_bh);
|