You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2
* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2: (56 commits) ocfs2: Make cached block reads the common case. ocfs2: Kill the last naked wait_on_buffer() for cached reads. ocfs2: Move ocfs2_bread() into dir.c ocfs2: Simplify ocfs2_read_block() ocfs2: Require an inode for ocfs2_read_block(s)(). ocfs2: Separate out sync reads from ocfs2_read_blocks() ocfs2: Refactor xattr list and remove ocfs2_xattr_handler(). ocfs2: Calculate EA hash only by its suffix. ocfs2: Move trusted and user attribute support into xattr.c ocfs2: Uninline ocfs2_xattr_name_hash() ocfs2: Don't check for NULL before brelse() ocfs2: use smaller counters in ocfs2_remove_xattr_clusters_from_cache ocfs2: Documentation update for user_xattr / nouser_xattr mount options ocfs2: make la_debug_mutex static ocfs2: Remove pointless !! ocfs2: Add empty bucket support in xattr. ocfs2/xattr.c: Fix a bug when inserting xattr. ocfs2: Add xattr mount option in ocfs2_show_options() ocfs2: Switch over to JBD2. ocfs2: Add the 'inode64' mount option. ...
This commit is contained in:
+22
-12
@@ -220,17 +220,16 @@ config JBD
|
||||
tristate
|
||||
help
|
||||
This is a generic journalling layer for block devices. It is
|
||||
currently used by the ext3 and OCFS2 file systems, but it could
|
||||
also be used to add journal support to other file systems or block
|
||||
currently used by the ext3 file system, but it could also be
|
||||
used to add journal support to other file systems or block
|
||||
devices such as RAID or LVM.
|
||||
|
||||
If you are using the ext3 or OCFS2 file systems, you need to
|
||||
say Y here. If you are not using ext3 OCFS2 then you will probably
|
||||
want to say N.
|
||||
If you are using the ext3 file system, you need to say Y here.
|
||||
If you are not using ext3 then you will probably want to say N.
|
||||
|
||||
To compile this device as a module, choose M here: the module will be
|
||||
called jbd. If you are compiling ext3 or OCFS2 into the kernel,
|
||||
you cannot compile this code as a module.
|
||||
called jbd. If you are compiling ext3 into the kernel, you
|
||||
cannot compile this code as a module.
|
||||
|
||||
config JBD_DEBUG
|
||||
bool "JBD (ext3) debugging support"
|
||||
@@ -254,15 +253,16 @@ config JBD2
|
||||
help
|
||||
This is a generic journaling layer for block devices that support
|
||||
both 32-bit and 64-bit block numbers. It is currently used by
|
||||
the ext4 filesystem, but it could also be used to add
|
||||
the ext4 and OCFS2 filesystems, but it could also be used to add
|
||||
journal support to other file systems or block devices such
|
||||
as RAID or LVM.
|
||||
|
||||
If you are using ext4, you need to say Y here. If you are not
|
||||
using ext4 then you will probably want to say N.
|
||||
If you are using ext4 or OCFS2, you need to say Y here.
|
||||
If you are not using ext4 or OCFS2 then you will
|
||||
probably want to say N.
|
||||
|
||||
To compile this device as a module, choose M here. The module will be
|
||||
called jbd2. If you are compiling ext4 into the kernel,
|
||||
called jbd2. If you are compiling ext4 or OCFS2 into the kernel,
|
||||
you cannot compile this code as a module.
|
||||
|
||||
config JBD2_DEBUG
|
||||
@@ -448,7 +448,7 @@ config OCFS2_FS
|
||||
tristate "OCFS2 file system support"
|
||||
depends on NET && SYSFS
|
||||
select CONFIGFS_FS
|
||||
select JBD
|
||||
select JBD2
|
||||
select CRC32
|
||||
help
|
||||
OCFS2 is a general purpose extent based shared disk cluster file
|
||||
@@ -519,6 +519,16 @@ config OCFS2_DEBUG_FS
|
||||
this option for debugging only as it is likely to decrease
|
||||
performance of the filesystem.
|
||||
|
||||
config OCFS2_COMPAT_JBD
|
||||
bool "Use JBD for compatibility"
|
||||
depends on OCFS2_FS
|
||||
default n
|
||||
select JBD
|
||||
help
|
||||
The ocfs2 filesystem now uses JBD2 for its journalling. JBD2
|
||||
is backwards compatible with JBD. It is safe to say N here.
|
||||
However, if you really want to use the original JBD, say Y here.
|
||||
|
||||
endif # BLOCK
|
||||
|
||||
config DNOTIFY
|
||||
|
||||
+2
-1
@@ -34,7 +34,8 @@ ocfs2-objs := \
|
||||
symlink.o \
|
||||
sysfile.o \
|
||||
uptodate.o \
|
||||
ver.o
|
||||
ver.o \
|
||||
xattr.o
|
||||
|
||||
ocfs2_stackglue-objs := stackglue.o
|
||||
ocfs2_stack_o2cb-objs := stack_o2cb.o
|
||||
|
||||
+662
-251
File diff suppressed because it is too large
Load Diff
+79
-7
@@ -26,30 +26,102 @@
|
||||
#ifndef OCFS2_ALLOC_H
|
||||
#define OCFS2_ALLOC_H
|
||||
|
||||
|
||||
/*
|
||||
* For xattr tree leaf, we limit the leaf byte size to be 64K.
|
||||
*/
|
||||
#define OCFS2_MAX_XATTR_TREE_LEAF_SIZE 65536
|
||||
|
||||
/*
|
||||
* ocfs2_extent_tree and ocfs2_extent_tree_operations are used to abstract
|
||||
* the b-tree operations in ocfs2. Now all the b-tree operations are not
|
||||
* limited to ocfs2_dinode only. Any data which need to allocate clusters
|
||||
* to store can use b-tree. And it only needs to implement its ocfs2_extent_tree
|
||||
* and operation.
|
||||
*
|
||||
* ocfs2_extent_tree becomes the first-class object for extent tree
|
||||
* manipulation. Callers of the alloc.c code need to fill it via one of
|
||||
* the ocfs2_init_*_extent_tree() operations below.
|
||||
*
|
||||
* ocfs2_extent_tree contains info for the root of the b-tree, it must have a
|
||||
* root ocfs2_extent_list and a root_bh so that they can be used in the b-tree
|
||||
* functions.
|
||||
* ocfs2_extent_tree_operations abstract the normal operations we do for
|
||||
* the root of extent b-tree.
|
||||
*/
|
||||
struct ocfs2_extent_tree_operations;
|
||||
struct ocfs2_extent_tree {
|
||||
struct ocfs2_extent_tree_operations *et_ops;
|
||||
struct buffer_head *et_root_bh;
|
||||
struct ocfs2_extent_list *et_root_el;
|
||||
void *et_object;
|
||||
unsigned int et_max_leaf_clusters;
|
||||
};
|
||||
|
||||
/*
|
||||
* ocfs2_init_*_extent_tree() will fill an ocfs2_extent_tree from the
|
||||
* specified object buffer.
|
||||
*/
|
||||
void ocfs2_init_dinode_extent_tree(struct ocfs2_extent_tree *et,
|
||||
struct inode *inode,
|
||||
struct buffer_head *bh);
|
||||
void ocfs2_init_xattr_tree_extent_tree(struct ocfs2_extent_tree *et,
|
||||
struct inode *inode,
|
||||
struct buffer_head *bh);
|
||||
void ocfs2_init_xattr_value_extent_tree(struct ocfs2_extent_tree *et,
|
||||
struct inode *inode,
|
||||
struct buffer_head *bh,
|
||||
struct ocfs2_xattr_value_root *xv);
|
||||
|
||||
struct ocfs2_alloc_context;
|
||||
int ocfs2_insert_extent(struct ocfs2_super *osb,
|
||||
handle_t *handle,
|
||||
struct inode *inode,
|
||||
struct buffer_head *fe_bh,
|
||||
struct ocfs2_extent_tree *et,
|
||||
u32 cpos,
|
||||
u64 start_blk,
|
||||
u32 new_clusters,
|
||||
u8 flags,
|
||||
struct ocfs2_alloc_context *meta_ac);
|
||||
|
||||
enum ocfs2_alloc_restarted {
|
||||
RESTART_NONE = 0,
|
||||
RESTART_TRANS,
|
||||
RESTART_META
|
||||
};
|
||||
int ocfs2_add_clusters_in_btree(struct ocfs2_super *osb,
|
||||
struct inode *inode,
|
||||
u32 *logical_offset,
|
||||
u32 clusters_to_add,
|
||||
int mark_unwritten,
|
||||
struct ocfs2_extent_tree *et,
|
||||
handle_t *handle,
|
||||
struct ocfs2_alloc_context *data_ac,
|
||||
struct ocfs2_alloc_context *meta_ac,
|
||||
enum ocfs2_alloc_restarted *reason_ret);
|
||||
struct ocfs2_cached_dealloc_ctxt;
|
||||
int ocfs2_mark_extent_written(struct inode *inode, struct buffer_head *di_bh,
|
||||
int ocfs2_mark_extent_written(struct inode *inode,
|
||||
struct ocfs2_extent_tree *et,
|
||||
handle_t *handle, u32 cpos, u32 len, u32 phys,
|
||||
struct ocfs2_alloc_context *meta_ac,
|
||||
struct ocfs2_cached_dealloc_ctxt *dealloc);
|
||||
int ocfs2_remove_extent(struct inode *inode, struct buffer_head *di_bh,
|
||||
int ocfs2_remove_extent(struct inode *inode,
|
||||
struct ocfs2_extent_tree *et,
|
||||
u32 cpos, u32 len, handle_t *handle,
|
||||
struct ocfs2_alloc_context *meta_ac,
|
||||
struct ocfs2_cached_dealloc_ctxt *dealloc);
|
||||
int ocfs2_num_free_extents(struct ocfs2_super *osb,
|
||||
struct inode *inode,
|
||||
struct ocfs2_dinode *fe);
|
||||
/* how many new metadata chunks would an allocation need at maximum? */
|
||||
static inline int ocfs2_extend_meta_needed(struct ocfs2_dinode *fe)
|
||||
struct ocfs2_extent_tree *et);
|
||||
|
||||
/*
|
||||
* how many new metadata chunks would an allocation need at maximum?
|
||||
*
|
||||
* Please note that the caller must make sure that root_el is the root
|
||||
* of extent tree. So for an inode, it should be &fe->id2.i_list. Otherwise
|
||||
* the result may be wrong.
|
||||
*/
|
||||
static inline int ocfs2_extend_meta_needed(struct ocfs2_extent_list *root_el)
|
||||
{
|
||||
/*
|
||||
* Rather than do all the work of determining how much we need
|
||||
@@ -59,7 +131,7 @@ static inline int ocfs2_extend_meta_needed(struct ocfs2_dinode *fe)
|
||||
* new tree_depth==0 extent_block, and one block at the new
|
||||
* top-of-the tree.
|
||||
*/
|
||||
return le16_to_cpu(fe->id2.i_list.l_tree_depth) + 2;
|
||||
return le16_to_cpu(root_el->l_tree_depth) + 2;
|
||||
}
|
||||
|
||||
void ocfs2_dinode_new_extent_list(struct inode *inode, struct ocfs2_dinode *di);
|
||||
|
||||
+39
-21
@@ -68,9 +68,7 @@ static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock,
|
||||
goto bail;
|
||||
}
|
||||
|
||||
status = ocfs2_read_block(OCFS2_SB(inode->i_sb),
|
||||
OCFS2_I(inode)->ip_blkno,
|
||||
&bh, OCFS2_BH_CACHED, inode);
|
||||
status = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, &bh);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
@@ -128,8 +126,7 @@ static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock,
|
||||
err = 0;
|
||||
|
||||
bail:
|
||||
if (bh)
|
||||
brelse(bh);
|
||||
brelse(bh);
|
||||
|
||||
mlog_exit(err);
|
||||
return err;
|
||||
@@ -261,13 +258,11 @@ static int ocfs2_readpage_inline(struct inode *inode, struct page *page)
|
||||
{
|
||||
int ret;
|
||||
struct buffer_head *di_bh = NULL;
|
||||
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
||||
|
||||
BUG_ON(!PageLocked(page));
|
||||
BUG_ON(!(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL));
|
||||
|
||||
ret = ocfs2_read_block(osb, OCFS2_I(inode)->ip_blkno, &di_bh,
|
||||
OCFS2_BH_CACHED, inode);
|
||||
ret = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, &di_bh);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
@@ -485,11 +480,14 @@ handle_t *ocfs2_start_walk_page_trans(struct inode *inode,
|
||||
}
|
||||
|
||||
if (ocfs2_should_order_data(inode)) {
|
||||
ret = ocfs2_jbd2_file_inode(handle, inode);
|
||||
#ifdef CONFIG_OCFS2_COMPAT_JBD
|
||||
ret = walk_page_buffers(handle,
|
||||
page_buffers(page),
|
||||
from, to, NULL,
|
||||
ocfs2_journal_dirty_data);
|
||||
if (ret < 0)
|
||||
#endif
|
||||
if (ret < 0)
|
||||
mlog_errno(ret);
|
||||
}
|
||||
out:
|
||||
@@ -669,7 +667,7 @@ static void ocfs2_invalidatepage(struct page *page, unsigned long offset)
|
||||
{
|
||||
journal_t *journal = OCFS2_SB(page->mapping->host->i_sb)->journal->j_journal;
|
||||
|
||||
journal_invalidatepage(journal, page, offset);
|
||||
jbd2_journal_invalidatepage(journal, page, offset);
|
||||
}
|
||||
|
||||
static int ocfs2_releasepage(struct page *page, gfp_t wait)
|
||||
@@ -678,7 +676,7 @@ static int ocfs2_releasepage(struct page *page, gfp_t wait)
|
||||
|
||||
if (!page_has_buffers(page))
|
||||
return 0;
|
||||
return journal_try_to_free_buffers(journal, page, wait);
|
||||
return jbd2_journal_try_to_free_buffers(journal, page, wait);
|
||||
}
|
||||
|
||||
static ssize_t ocfs2_direct_IO(int rw,
|
||||
@@ -1074,11 +1072,15 @@ static void ocfs2_write_failure(struct inode *inode,
|
||||
tmppage = wc->w_pages[i];
|
||||
|
||||
if (page_has_buffers(tmppage)) {
|
||||
if (ocfs2_should_order_data(inode))
|
||||
if (ocfs2_should_order_data(inode)) {
|
||||
ocfs2_jbd2_file_inode(wc->w_handle, inode);
|
||||
#ifdef CONFIG_OCFS2_COMPAT_JBD
|
||||
walk_page_buffers(wc->w_handle,
|
||||
page_buffers(tmppage),
|
||||
from, to, NULL,
|
||||
ocfs2_journal_dirty_data);
|
||||
#endif
|
||||
}
|
||||
|
||||
block_commit_write(tmppage, from, to);
|
||||
}
|
||||
@@ -1242,6 +1244,7 @@ static int ocfs2_write_cluster(struct address_space *mapping,
|
||||
int ret, i, new, should_zero = 0;
|
||||
u64 v_blkno, p_blkno;
|
||||
struct inode *inode = mapping->host;
|
||||
struct ocfs2_extent_tree et;
|
||||
|
||||
new = phys == 0 ? 1 : 0;
|
||||
if (new || unwritten)
|
||||
@@ -1255,10 +1258,10 @@ static int ocfs2_write_cluster(struct address_space *mapping,
|
||||
* any additional semaphores or cluster locks.
|
||||
*/
|
||||
tmp_pos = cpos;
|
||||
ret = ocfs2_do_extend_allocation(OCFS2_SB(inode->i_sb), inode,
|
||||
&tmp_pos, 1, 0, wc->w_di_bh,
|
||||
wc->w_handle, data_ac,
|
||||
meta_ac, NULL);
|
||||
ret = ocfs2_add_inode_data(OCFS2_SB(inode->i_sb), inode,
|
||||
&tmp_pos, 1, 0, wc->w_di_bh,
|
||||
wc->w_handle, data_ac,
|
||||
meta_ac, NULL);
|
||||
/*
|
||||
* This shouldn't happen because we must have already
|
||||
* calculated the correct meta data allocation required. The
|
||||
@@ -1276,7 +1279,8 @@ static int ocfs2_write_cluster(struct address_space *mapping,
|
||||
goto out;
|
||||
}
|
||||
} else if (unwritten) {
|
||||
ret = ocfs2_mark_extent_written(inode, wc->w_di_bh,
|
||||
ocfs2_init_dinode_extent_tree(&et, inode, wc->w_di_bh);
|
||||
ret = ocfs2_mark_extent_written(inode, &et,
|
||||
wc->w_handle, cpos, 1, phys,
|
||||
meta_ac, &wc->w_dealloc);
|
||||
if (ret < 0) {
|
||||
@@ -1665,6 +1669,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
|
||||
struct ocfs2_alloc_context *data_ac = NULL;
|
||||
struct ocfs2_alloc_context *meta_ac = NULL;
|
||||
handle_t *handle;
|
||||
struct ocfs2_extent_tree et;
|
||||
|
||||
ret = ocfs2_alloc_write_ctxt(&wc, osb, pos, len, di_bh);
|
||||
if (ret) {
|
||||
@@ -1712,14 +1717,23 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
|
||||
* ocfs2_lock_allocators(). It greatly over-estimates
|
||||
* the work to be done.
|
||||
*/
|
||||
ret = ocfs2_lock_allocators(inode, di, clusters_to_alloc,
|
||||
extents_to_split, &data_ac, &meta_ac);
|
||||
mlog(0, "extend inode %llu, i_size = %lld, di->i_clusters = %u,"
|
||||
" clusters_to_add = %u, extents_to_split = %u\n",
|
||||
(unsigned long long)OCFS2_I(inode)->ip_blkno,
|
||||
(long long)i_size_read(inode), le32_to_cpu(di->i_clusters),
|
||||
clusters_to_alloc, extents_to_split);
|
||||
|
||||
ocfs2_init_dinode_extent_tree(&et, inode, wc->w_di_bh);
|
||||
ret = ocfs2_lock_allocators(inode, &et,
|
||||
clusters_to_alloc, extents_to_split,
|
||||
&data_ac, &meta_ac);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
credits = ocfs2_calc_extend_credits(inode->i_sb, di,
|
||||
credits = ocfs2_calc_extend_credits(inode->i_sb,
|
||||
&di->id2.i_list,
|
||||
clusters_to_alloc);
|
||||
|
||||
}
|
||||
@@ -1905,11 +1919,15 @@ int ocfs2_write_end_nolock(struct address_space *mapping,
|
||||
}
|
||||
|
||||
if (page_has_buffers(tmppage)) {
|
||||
if (ocfs2_should_order_data(inode))
|
||||
if (ocfs2_should_order_data(inode)) {
|
||||
ocfs2_jbd2_file_inode(wc->w_handle, inode);
|
||||
#ifdef CONFIG_OCFS2_COMPAT_JBD
|
||||
walk_page_buffers(wc->w_handle,
|
||||
page_buffers(tmppage),
|
||||
from, to, NULL,
|
||||
ocfs2_journal_dirty_data);
|
||||
#endif
|
||||
}
|
||||
block_commit_write(tmppage, from, to);
|
||||
}
|
||||
}
|
||||
|
||||
+104
-30
@@ -66,7 +66,7 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh,
|
||||
/* remove from dirty list before I/O. */
|
||||
clear_buffer_dirty(bh);
|
||||
|
||||
get_bh(bh); /* for end_buffer_write_sync() */
|
||||
get_bh(bh); /* for end_buffer_write_sync() */
|
||||
bh->b_end_io = end_buffer_write_sync;
|
||||
submit_bh(WRITE, bh);
|
||||
|
||||
@@ -88,22 +88,103 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr,
|
||||
struct buffer_head *bhs[], int flags,
|
||||
struct inode *inode)
|
||||
int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block,
|
||||
unsigned int nr, struct buffer_head *bhs[])
|
||||
{
|
||||
int status = 0;
|
||||
unsigned int i;
|
||||
struct buffer_head *bh;
|
||||
|
||||
if (!nr) {
|
||||
mlog(ML_BH_IO, "No buffers will be read!\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
for (i = 0 ; i < nr ; i++) {
|
||||
if (bhs[i] == NULL) {
|
||||
bhs[i] = sb_getblk(osb->sb, block++);
|
||||
if (bhs[i] == NULL) {
|
||||
status = -EIO;
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
bh = bhs[i];
|
||||
|
||||
if (buffer_jbd(bh)) {
|
||||
mlog(ML_ERROR,
|
||||
"trying to sync read a jbd "
|
||||
"managed bh (blocknr = %llu), skipping\n",
|
||||
(unsigned long long)bh->b_blocknr);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (buffer_dirty(bh)) {
|
||||
/* This should probably be a BUG, or
|
||||
* at least return an error. */
|
||||
mlog(ML_ERROR,
|
||||
"trying to sync read a dirty "
|
||||
"buffer! (blocknr = %llu), skipping\n",
|
||||
(unsigned long long)bh->b_blocknr);
|
||||
continue;
|
||||
}
|
||||
|
||||
lock_buffer(bh);
|
||||
if (buffer_jbd(bh)) {
|
||||
mlog(ML_ERROR,
|
||||
"block %llu had the JBD bit set "
|
||||
"while I was in lock_buffer!",
|
||||
(unsigned long long)bh->b_blocknr);
|
||||
BUG();
|
||||
}
|
||||
|
||||
clear_buffer_uptodate(bh);
|
||||
get_bh(bh); /* for end_buffer_read_sync() */
|
||||
bh->b_end_io = end_buffer_read_sync;
|
||||
submit_bh(READ, bh);
|
||||
}
|
||||
|
||||
for (i = nr; i > 0; i--) {
|
||||
bh = bhs[i - 1];
|
||||
|
||||
if (buffer_jbd(bh)) {
|
||||
mlog(ML_ERROR,
|
||||
"the journal got the buffer while it was "
|
||||
"locked for io! (blocknr = %llu)\n",
|
||||
(unsigned long long)bh->b_blocknr);
|
||||
BUG();
|
||||
}
|
||||
|
||||
wait_on_buffer(bh);
|
||||
if (!buffer_uptodate(bh)) {
|
||||
/* Status won't be cleared from here on out,
|
||||
* so we can safely record this and loop back
|
||||
* to cleanup the other buffers. */
|
||||
status = -EIO;
|
||||
put_bh(bh);
|
||||
bhs[i - 1] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bail:
|
||||
return status;
|
||||
}
|
||||
|
||||
int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
|
||||
struct buffer_head *bhs[], int flags)
|
||||
{
|
||||
int status = 0;
|
||||
struct super_block *sb;
|
||||
int i, ignore_cache = 0;
|
||||
struct buffer_head *bh;
|
||||
|
||||
mlog_entry("(block=(%llu), nr=(%d), flags=%d, inode=%p)\n",
|
||||
(unsigned long long)block, nr, flags, inode);
|
||||
mlog_entry("(inode=%p, block=(%llu), nr=(%d), flags=%d)\n",
|
||||
inode, (unsigned long long)block, nr, flags);
|
||||
|
||||
BUG_ON(!inode);
|
||||
BUG_ON((flags & OCFS2_BH_READAHEAD) &&
|
||||
(!inode || !(flags & OCFS2_BH_CACHED)));
|
||||
(flags & OCFS2_BH_IGNORE_CACHE));
|
||||
|
||||
if (osb == NULL || osb->sb == NULL || bhs == NULL) {
|
||||
if (bhs == NULL) {
|
||||
status = -EINVAL;
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
@@ -122,26 +203,19 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr,
|
||||
goto bail;
|
||||
}
|
||||
|
||||
sb = osb->sb;
|
||||
|
||||
if (flags & OCFS2_BH_CACHED && !inode)
|
||||
flags &= ~OCFS2_BH_CACHED;
|
||||
|
||||
if (inode)
|
||||
mutex_lock(&OCFS2_I(inode)->ip_io_mutex);
|
||||
mutex_lock(&OCFS2_I(inode)->ip_io_mutex);
|
||||
for (i = 0 ; i < nr ; i++) {
|
||||
if (bhs[i] == NULL) {
|
||||
bhs[i] = sb_getblk(sb, block++);
|
||||
bhs[i] = sb_getblk(inode->i_sb, block++);
|
||||
if (bhs[i] == NULL) {
|
||||
if (inode)
|
||||
mutex_unlock(&OCFS2_I(inode)->ip_io_mutex);
|
||||
mutex_unlock(&OCFS2_I(inode)->ip_io_mutex);
|
||||
status = -EIO;
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
bh = bhs[i];
|
||||
ignore_cache = 0;
|
||||
ignore_cache = (flags & OCFS2_BH_IGNORE_CACHE);
|
||||
|
||||
/* There are three read-ahead cases here which we need to
|
||||
* be concerned with. All three assume a buffer has
|
||||
@@ -167,26 +241,27 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr,
|
||||
* before our is-it-in-flight check.
|
||||
*/
|
||||
|
||||
if (flags & OCFS2_BH_CACHED &&
|
||||
!ocfs2_buffer_uptodate(inode, bh)) {
|
||||
if (!ignore_cache && !ocfs2_buffer_uptodate(inode, bh)) {
|
||||
mlog(ML_UPTODATE,
|
||||
"bh (%llu), inode %llu not uptodate\n",
|
||||
(unsigned long long)bh->b_blocknr,
|
||||
(unsigned long long)OCFS2_I(inode)->ip_blkno);
|
||||
/* We're using ignore_cache here to say
|
||||
* "go to disk" */
|
||||
ignore_cache = 1;
|
||||
}
|
||||
|
||||
/* XXX: Can we ever get this and *not* have the cached
|
||||
* flag set? */
|
||||
if (buffer_jbd(bh)) {
|
||||
if (!(flags & OCFS2_BH_CACHED) || ignore_cache)
|
||||
if (ignore_cache)
|
||||
mlog(ML_BH_IO, "trying to sync read a jbd "
|
||||
"managed bh (blocknr = %llu)\n",
|
||||
(unsigned long long)bh->b_blocknr);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(flags & OCFS2_BH_CACHED) || ignore_cache) {
|
||||
if (ignore_cache) {
|
||||
if (buffer_dirty(bh)) {
|
||||
/* This should probably be a BUG, or
|
||||
* at least return an error. */
|
||||
@@ -221,7 +296,7 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr,
|
||||
* previously read-ahead buffer may have
|
||||
* completed I/O while we were waiting for the
|
||||
* buffer lock. */
|
||||
if ((flags & OCFS2_BH_CACHED)
|
||||
if (!(flags & OCFS2_BH_IGNORE_CACHE)
|
||||
&& !(flags & OCFS2_BH_READAHEAD)
|
||||
&& ocfs2_buffer_uptodate(inode, bh)) {
|
||||
unlock_buffer(bh);
|
||||
@@ -265,15 +340,14 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr,
|
||||
/* Always set the buffer in the cache, even if it was
|
||||
* a forced read, or read-ahead which hasn't yet
|
||||
* completed. */
|
||||
if (inode)
|
||||
ocfs2_set_buffer_uptodate(inode, bh);
|
||||
ocfs2_set_buffer_uptodate(inode, bh);
|
||||
}
|
||||
if (inode)
|
||||
mutex_unlock(&OCFS2_I(inode)->ip_io_mutex);
|
||||
mutex_unlock(&OCFS2_I(inode)->ip_io_mutex);
|
||||
|
||||
mlog(ML_BH_IO, "block=(%llu), nr=(%d), cached=%s, flags=0x%x\n",
|
||||
(unsigned long long)block, nr,
|
||||
(!(flags & OCFS2_BH_CACHED) || ignore_cache) ? "no" : "yes", flags);
|
||||
((flags & OCFS2_BH_IGNORE_CACHE) || ignore_cache) ? "no" : "yes",
|
||||
flags);
|
||||
|
||||
bail:
|
||||
|
||||
|
||||
+10
-13
@@ -31,31 +31,29 @@
|
||||
void ocfs2_end_buffer_io_sync(struct buffer_head *bh,
|
||||
int uptodate);
|
||||
|
||||
static inline int ocfs2_read_block(struct ocfs2_super *osb,
|
||||
static inline int ocfs2_read_block(struct inode *inode,
|
||||
u64 off,
|
||||
struct buffer_head **bh,
|
||||
int flags,
|
||||
struct inode *inode);
|
||||
struct buffer_head **bh);
|
||||
|
||||
int ocfs2_write_block(struct ocfs2_super *osb,
|
||||
struct buffer_head *bh,
|
||||
struct inode *inode);
|
||||
int ocfs2_read_blocks(struct ocfs2_super *osb,
|
||||
int ocfs2_read_blocks(struct inode *inode,
|
||||
u64 block,
|
||||
int nr,
|
||||
struct buffer_head *bhs[],
|
||||
int flags,
|
||||
struct inode *inode);
|
||||
int flags);
|
||||
int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block,
|
||||
unsigned int nr, struct buffer_head *bhs[]);
|
||||
|
||||
int ocfs2_write_super_or_backup(struct ocfs2_super *osb,
|
||||
struct buffer_head *bh);
|
||||
|
||||
#define OCFS2_BH_CACHED 1
|
||||
#define OCFS2_BH_IGNORE_CACHE 1
|
||||
#define OCFS2_BH_READAHEAD 8
|
||||
|
||||
static inline int ocfs2_read_block(struct ocfs2_super * osb, u64 off,
|
||||
struct buffer_head **bh, int flags,
|
||||
struct inode *inode)
|
||||
static inline int ocfs2_read_block(struct inode *inode, u64 off,
|
||||
struct buffer_head **bh)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
@@ -65,8 +63,7 @@ static inline int ocfs2_read_block(struct ocfs2_super * osb, u64 off,
|
||||
goto bail;
|
||||
}
|
||||
|
||||
status = ocfs2_read_blocks(osb, off, 1, bh,
|
||||
flags, inode);
|
||||
status = ocfs2_read_blocks(inode, off, 1, bh, 0);
|
||||
|
||||
bail:
|
||||
return status;
|
||||
|
||||
@@ -109,6 +109,7 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = {
|
||||
define_mask(CONN),
|
||||
define_mask(QUORUM),
|
||||
define_mask(EXPORT),
|
||||
define_mask(XATTR),
|
||||
define_mask(ERROR),
|
||||
define_mask(NOTICE),
|
||||
define_mask(KTHREAD),
|
||||
|
||||
@@ -112,6 +112,7 @@
|
||||
#define ML_CONN 0x0000000004000000ULL /* net connection management */
|
||||
#define ML_QUORUM 0x0000000008000000ULL /* net connection quorum */
|
||||
#define ML_EXPORT 0x0000000010000000ULL /* ocfs2 export operations */
|
||||
#define ML_XATTR 0x0000000020000000ULL /* ocfs2 extended attributes */
|
||||
/* bits that are infrequently given and frequently matched in the high word */
|
||||
#define ML_ERROR 0x0000000100000000ULL /* sent to KERN_ERR */
|
||||
#define ML_NOTICE 0x0000000200000000ULL /* setn to KERN_NOTICE */
|
||||
|
||||
+73
-36
@@ -82,6 +82,49 @@ static int ocfs2_do_extend_dir(struct super_block *sb,
|
||||
struct ocfs2_alloc_context *meta_ac,
|
||||
struct buffer_head **new_bh);
|
||||
|
||||
static struct buffer_head *ocfs2_bread(struct inode *inode,
|
||||
int block, int *err, int reada)
|
||||
{
|
||||
struct buffer_head *bh = NULL;
|
||||
int tmperr;
|
||||
u64 p_blkno;
|
||||
int readflags = 0;
|
||||
|
||||
if (reada)
|
||||
readflags |= OCFS2_BH_READAHEAD;
|
||||
|
||||
if (((u64)block << inode->i_sb->s_blocksize_bits) >=
|
||||
i_size_read(inode)) {
|
||||
BUG_ON(!reada);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
down_read(&OCFS2_I(inode)->ip_alloc_sem);
|
||||
tmperr = ocfs2_extent_map_get_blocks(inode, block, &p_blkno, NULL,
|
||||
NULL);
|
||||
up_read(&OCFS2_I(inode)->ip_alloc_sem);
|
||||
if (tmperr < 0) {
|
||||
mlog_errno(tmperr);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
tmperr = ocfs2_read_blocks(inode, p_blkno, 1, &bh, readflags);
|
||||
if (tmperr < 0)
|
||||
goto fail;
|
||||
|
||||
tmperr = 0;
|
||||
|
||||
*err = 0;
|
||||
return bh;
|
||||
|
||||
fail:
|
||||
brelse(bh);
|
||||
bh = NULL;
|
||||
|
||||
*err = -EIO;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* bh passed here can be an inode block or a dir data block, depending
|
||||
* on the inode inline data flag.
|
||||
@@ -188,8 +231,7 @@ static struct buffer_head *ocfs2_find_entry_id(const char *name,
|
||||
struct ocfs2_dinode *di;
|
||||
struct ocfs2_inline_data *data;
|
||||
|
||||
ret = ocfs2_read_block(OCFS2_SB(dir->i_sb), OCFS2_I(dir)->ip_blkno,
|
||||
&di_bh, OCFS2_BH_CACHED, dir);
|
||||
ret = ocfs2_read_block(dir, OCFS2_I(dir)->ip_blkno, &di_bh);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
@@ -260,14 +302,13 @@ restart:
|
||||
}
|
||||
if ((bh = bh_use[ra_ptr++]) == NULL)
|
||||
goto next;
|
||||
wait_on_buffer(bh);
|
||||
if (!buffer_uptodate(bh)) {
|
||||
/* read error, skip block & hope for the best */
|
||||
if (ocfs2_read_block(dir, block, &bh)) {
|
||||
/* read error, skip block & hope for the best.
|
||||
* ocfs2_read_block() has released the bh. */
|
||||
ocfs2_error(dir->i_sb, "reading directory %llu, "
|
||||
"offset %lu\n",
|
||||
(unsigned long long)OCFS2_I(dir)->ip_blkno,
|
||||
block);
|
||||
brelse(bh);
|
||||
goto next;
|
||||
}
|
||||
i = ocfs2_search_dirblock(bh, dir, name, namelen,
|
||||
@@ -417,8 +458,7 @@ static inline int ocfs2_delete_entry_id(handle_t *handle,
|
||||
struct ocfs2_dinode *di;
|
||||
struct ocfs2_inline_data *data;
|
||||
|
||||
ret = ocfs2_read_block(OCFS2_SB(dir->i_sb), OCFS2_I(dir)->ip_blkno,
|
||||
&di_bh, OCFS2_BH_CACHED, dir);
|
||||
ret = ocfs2_read_block(dir, OCFS2_I(dir)->ip_blkno, &di_bh);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
@@ -596,8 +636,7 @@ static int ocfs2_dir_foreach_blk_id(struct inode *inode,
|
||||
struct ocfs2_inline_data *data;
|
||||
struct ocfs2_dir_entry *de;
|
||||
|
||||
ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), OCFS2_I(inode)->ip_blkno,
|
||||
&di_bh, OCFS2_BH_CACHED, inode);
|
||||
ret = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, &di_bh);
|
||||
if (ret) {
|
||||
mlog(ML_ERROR, "Unable to read inode block for dir %llu\n",
|
||||
(unsigned long long)OCFS2_I(inode)->ip_blkno);
|
||||
@@ -716,8 +755,7 @@ static int ocfs2_dir_foreach_blk_el(struct inode *inode,
|
||||
for (i = ra_sectors >> (sb->s_blocksize_bits - 9);
|
||||
i > 0; i--) {
|
||||
tmp = ocfs2_bread(inode, ++blk, &err, 1);
|
||||
if (tmp)
|
||||
brelse(tmp);
|
||||
brelse(tmp);
|
||||
}
|
||||
last_ra_blk = blk;
|
||||
ra_sectors = 8;
|
||||
@@ -899,10 +937,8 @@ int ocfs2_find_files_on_disk(const char *name,
|
||||
leave:
|
||||
if (status < 0) {
|
||||
*dirent = NULL;
|
||||
if (*dirent_bh) {
|
||||
brelse(*dirent_bh);
|
||||
*dirent_bh = NULL;
|
||||
}
|
||||
brelse(*dirent_bh);
|
||||
*dirent_bh = NULL;
|
||||
}
|
||||
|
||||
mlog_exit(status);
|
||||
@@ -951,8 +987,7 @@ int ocfs2_check_dir_for_entry(struct inode *dir,
|
||||
|
||||
ret = 0;
|
||||
bail:
|
||||
if (dirent_bh)
|
||||
brelse(dirent_bh);
|
||||
brelse(dirent_bh);
|
||||
|
||||
mlog_exit(ret);
|
||||
return ret;
|
||||
@@ -1127,8 +1162,7 @@ static int ocfs2_fill_new_dir_el(struct ocfs2_super *osb,
|
||||
|
||||
status = 0;
|
||||
bail:
|
||||
if (new_bh)
|
||||
brelse(new_bh);
|
||||
brelse(new_bh);
|
||||
|
||||
mlog_exit(status);
|
||||
return status;
|
||||
@@ -1192,6 +1226,9 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
|
||||
struct buffer_head *dirdata_bh = NULL;
|
||||
struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
|
||||
handle_t *handle;
|
||||
struct ocfs2_extent_tree et;
|
||||
|
||||
ocfs2_init_dinode_extent_tree(&et, dir, di_bh);
|
||||
|
||||
alloc = ocfs2_clusters_for_bytes(sb, bytes);
|
||||
|
||||
@@ -1305,8 +1342,8 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
|
||||
* This should never fail as our extent list is empty and all
|
||||
* related blocks have been journaled already.
|
||||
*/
|
||||
ret = ocfs2_insert_extent(osb, handle, dir, di_bh, 0, blkno, len, 0,
|
||||
NULL);
|
||||
ret = ocfs2_insert_extent(osb, handle, dir, &et, 0, blkno, len,
|
||||
0, NULL);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
goto out_commit;
|
||||
@@ -1337,8 +1374,8 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
|
||||
}
|
||||
blkno = ocfs2_clusters_to_blocks(dir->i_sb, bit_off);
|
||||
|
||||
ret = ocfs2_insert_extent(osb, handle, dir, di_bh, 1, blkno,
|
||||
len, 0, NULL);
|
||||
ret = ocfs2_insert_extent(osb, handle, dir, &et, 1,
|
||||
blkno, len, 0, NULL);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
goto out_commit;
|
||||
@@ -1383,9 +1420,9 @@ static int ocfs2_do_extend_dir(struct super_block *sb,
|
||||
if (extend) {
|
||||
u32 offset = OCFS2_I(dir)->ip_clusters;
|
||||
|
||||
status = ocfs2_do_extend_allocation(OCFS2_SB(sb), dir, &offset,
|
||||
1, 0, parent_fe_bh, handle,
|
||||
data_ac, meta_ac, NULL);
|
||||
status = ocfs2_add_inode_data(OCFS2_SB(sb), dir, &offset,
|
||||
1, 0, parent_fe_bh, handle,
|
||||
data_ac, meta_ac, NULL);
|
||||
BUG_ON(status == -EAGAIN);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
@@ -1430,12 +1467,14 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
|
||||
int credits, num_free_extents, drop_alloc_sem = 0;
|
||||
loff_t dir_i_size;
|
||||
struct ocfs2_dinode *fe = (struct ocfs2_dinode *) parent_fe_bh->b_data;
|
||||
struct ocfs2_extent_list *el = &fe->id2.i_list;
|
||||
struct ocfs2_alloc_context *data_ac = NULL;
|
||||
struct ocfs2_alloc_context *meta_ac = NULL;
|
||||
handle_t *handle = NULL;
|
||||
struct buffer_head *new_bh = NULL;
|
||||
struct ocfs2_dir_entry * de;
|
||||
struct super_block *sb = osb->sb;
|
||||
struct ocfs2_extent_tree et;
|
||||
|
||||
mlog_entry_void();
|
||||
|
||||
@@ -1479,7 +1518,8 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
|
||||
spin_lock(&OCFS2_I(dir)->ip_lock);
|
||||
if (dir_i_size == ocfs2_clusters_to_bytes(sb, OCFS2_I(dir)->ip_clusters)) {
|
||||
spin_unlock(&OCFS2_I(dir)->ip_lock);
|
||||
num_free_extents = ocfs2_num_free_extents(osb, dir, fe);
|
||||
ocfs2_init_dinode_extent_tree(&et, dir, parent_fe_bh);
|
||||
num_free_extents = ocfs2_num_free_extents(osb, dir, &et);
|
||||
if (num_free_extents < 0) {
|
||||
status = num_free_extents;
|
||||
mlog_errno(status);
|
||||
@@ -1487,7 +1527,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
|
||||
}
|
||||
|
||||
if (!num_free_extents) {
|
||||
status = ocfs2_reserve_new_metadata(osb, fe, &meta_ac);
|
||||
status = ocfs2_reserve_new_metadata(osb, el, &meta_ac);
|
||||
if (status < 0) {
|
||||
if (status != -ENOSPC)
|
||||
mlog_errno(status);
|
||||
@@ -1502,7 +1542,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
|
||||
goto bail;
|
||||
}
|
||||
|
||||
credits = ocfs2_calc_extend_credits(sb, fe, 1);
|
||||
credits = ocfs2_calc_extend_credits(sb, el, 1);
|
||||
} else {
|
||||
spin_unlock(&OCFS2_I(dir)->ip_lock);
|
||||
credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS;
|
||||
@@ -1568,8 +1608,7 @@ bail:
|
||||
if (meta_ac)
|
||||
ocfs2_free_alloc_context(meta_ac);
|
||||
|
||||
if (new_bh)
|
||||
brelse(new_bh);
|
||||
brelse(new_bh);
|
||||
|
||||
mlog_exit(status);
|
||||
return status;
|
||||
@@ -1696,8 +1735,7 @@ static int ocfs2_find_dir_space_el(struct inode *dir, const char *name,
|
||||
|
||||
status = 0;
|
||||
bail:
|
||||
if (bh)
|
||||
brelse(bh);
|
||||
brelse(bh);
|
||||
|
||||
mlog_exit(status);
|
||||
return status;
|
||||
@@ -1756,7 +1794,6 @@ int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb,
|
||||
*ret_de_bh = bh;
|
||||
bh = NULL;
|
||||
out:
|
||||
if (bh)
|
||||
brelse(bh);
|
||||
brelse(bh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+2
-7
@@ -2024,8 +2024,7 @@ static int ocfs2_inode_lock_update(struct inode *inode,
|
||||
} else {
|
||||
/* Boo, we have to go to disk. */
|
||||
/* read bh, cast, ocfs2_refresh_inode */
|
||||
status = ocfs2_read_block(OCFS2_SB(inode->i_sb), oi->ip_blkno,
|
||||
bh, OCFS2_BH_CACHED, inode);
|
||||
status = ocfs2_read_block(inode, oi->ip_blkno, bh);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail_refresh;
|
||||
@@ -2086,11 +2085,7 @@ static int ocfs2_assign_bh(struct inode *inode,
|
||||
return 0;
|
||||
}
|
||||
|
||||
status = ocfs2_read_block(OCFS2_SB(inode->i_sb),
|
||||
OCFS2_I(inode)->ip_blkno,
|
||||
ret_bh,
|
||||
OCFS2_BH_CACHED,
|
||||
inode);
|
||||
status = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, ret_bh);
|
||||
if (status < 0)
|
||||
mlog_errno(status);
|
||||
|
||||
|
||||
+64
-6
@@ -293,8 +293,7 @@ static int ocfs2_last_eb_is_empty(struct inode *inode,
|
||||
struct ocfs2_extent_block *eb;
|
||||
struct ocfs2_extent_list *el;
|
||||
|
||||
ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), last_eb_blk,
|
||||
&eb_bh, OCFS2_BH_CACHED, inode);
|
||||
ret = ocfs2_read_block(inode, last_eb_blk, &eb_bh);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
@@ -382,9 +381,9 @@ static int ocfs2_figure_hole_clusters(struct inode *inode,
|
||||
if (le64_to_cpu(eb->h_next_leaf_blk) == 0ULL)
|
||||
goto no_more_extents;
|
||||
|
||||
ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
|
||||
ret = ocfs2_read_block(inode,
|
||||
le64_to_cpu(eb->h_next_leaf_blk),
|
||||
&next_eb_bh, OCFS2_BH_CACHED, inode);
|
||||
&next_eb_bh);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
@@ -551,6 +550,66 @@ static void ocfs2_relative_extent_offsets(struct super_block *sb,
|
||||
*num_clusters = le16_to_cpu(rec->e_leaf_clusters) - coff;
|
||||
}
|
||||
|
||||
int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster,
|
||||
u32 *p_cluster, u32 *num_clusters,
|
||||
struct ocfs2_extent_list *el)
|
||||
{
|
||||
int ret = 0, i;
|
||||
struct buffer_head *eb_bh = NULL;
|
||||
struct ocfs2_extent_block *eb;
|
||||
struct ocfs2_extent_rec *rec;
|
||||
u32 coff;
|
||||
|
||||
if (el->l_tree_depth) {
|
||||
ret = ocfs2_find_leaf(inode, el, v_cluster, &eb_bh);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
eb = (struct ocfs2_extent_block *) eb_bh->b_data;
|
||||
el = &eb->h_list;
|
||||
|
||||
if (el->l_tree_depth) {
|
||||
ocfs2_error(inode->i_sb,
|
||||
"Inode %lu has non zero tree depth in "
|
||||
"xattr leaf block %llu\n", inode->i_ino,
|
||||
(unsigned long long)eb_bh->b_blocknr);
|
||||
ret = -EROFS;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
i = ocfs2_search_extent_list(el, v_cluster);
|
||||
if (i == -1) {
|
||||
ret = -EROFS;
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
} else {
|
||||
rec = &el->l_recs[i];
|
||||
BUG_ON(v_cluster < le32_to_cpu(rec->e_cpos));
|
||||
|
||||
if (!rec->e_blkno) {
|
||||
ocfs2_error(inode->i_sb, "Inode %lu has bad extent "
|
||||
"record (%u, %u, 0) in xattr", inode->i_ino,
|
||||
le32_to_cpu(rec->e_cpos),
|
||||
ocfs2_rec_clusters(el, rec));
|
||||
ret = -EROFS;
|
||||
goto out;
|
||||
}
|
||||
coff = v_cluster - le32_to_cpu(rec->e_cpos);
|
||||
*p_cluster = ocfs2_blocks_to_clusters(inode->i_sb,
|
||||
le64_to_cpu(rec->e_blkno));
|
||||
*p_cluster = *p_cluster + coff;
|
||||
if (num_clusters)
|
||||
*num_clusters = ocfs2_rec_clusters(el, rec) - coff;
|
||||
}
|
||||
out:
|
||||
if (eb_bh)
|
||||
brelse(eb_bh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ocfs2_get_clusters(struct inode *inode, u32 v_cluster,
|
||||
u32 *p_cluster, u32 *num_clusters,
|
||||
unsigned int *extent_flags)
|
||||
@@ -571,8 +630,7 @@ int ocfs2_get_clusters(struct inode *inode, u32 v_cluster,
|
||||
if (ret == 0)
|
||||
goto out;
|
||||
|
||||
ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), OCFS2_I(inode)->ip_blkno,
|
||||
&di_bh, OCFS2_BH_CACHED, inode);
|
||||
ret = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, &di_bh);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
|
||||
@@ -53,4 +53,8 @@ int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno,
|
||||
int ocfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
|
||||
u64 map_start, u64 map_len);
|
||||
|
||||
int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster,
|
||||
u32 *p_cluster, u32 *num_clusters,
|
||||
struct ocfs2_extent_list *el);
|
||||
|
||||
#endif /* _EXTENT_MAP_H */
|
||||
|
||||
+119
-216
@@ -55,6 +55,7 @@
|
||||
#include "mmap.h"
|
||||
#include "suballoc.h"
|
||||
#include "super.h"
|
||||
#include "xattr.h"
|
||||
|
||||
#include "buffer_head_io.h"
|
||||
|
||||
@@ -184,7 +185,7 @@ static int ocfs2_sync_file(struct file *file,
|
||||
goto bail;
|
||||
|
||||
journal = osb->journal->j_journal;
|
||||
err = journal_force_commit(journal);
|
||||
err = jbd2_journal_force_commit(journal);
|
||||
|
||||
bail:
|
||||
mlog_exit(err);
|
||||
@@ -488,7 +489,7 @@ bail:
|
||||
}
|
||||
|
||||
/*
|
||||
* extend allocation only here.
|
||||
* extend file allocation only here.
|
||||
* we'll update all the disk stuff, and oip->alloc_size
|
||||
*
|
||||
* expect stuff to be locked, a transaction started and enough data /
|
||||
@@ -497,189 +498,25 @@ bail:
|
||||
* Will return -EAGAIN, and a reason if a restart is needed.
|
||||
* If passed in, *reason will always be set, even in error.
|
||||
*/
|
||||
int ocfs2_do_extend_allocation(struct ocfs2_super *osb,
|
||||
struct inode *inode,
|
||||
u32 *logical_offset,
|
||||
u32 clusters_to_add,
|
||||
int mark_unwritten,
|
||||
struct buffer_head *fe_bh,
|
||||
handle_t *handle,
|
||||
struct ocfs2_alloc_context *data_ac,
|
||||
struct ocfs2_alloc_context *meta_ac,
|
||||
enum ocfs2_alloc_restarted *reason_ret)
|
||||
int ocfs2_add_inode_data(struct ocfs2_super *osb,
|
||||
struct inode *inode,
|
||||
u32 *logical_offset,
|
||||
u32 clusters_to_add,
|
||||
int mark_unwritten,
|
||||
struct buffer_head *fe_bh,
|
||||
handle_t *handle,
|
||||
struct ocfs2_alloc_context *data_ac,
|
||||
struct ocfs2_alloc_context *meta_ac,
|
||||
enum ocfs2_alloc_restarted *reason_ret)
|
||||
{
|
||||
int status = 0;
|
||||
int free_extents;
|
||||
struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data;
|
||||
enum ocfs2_alloc_restarted reason = RESTART_NONE;
|
||||
u32 bit_off, num_bits;
|
||||
u64 block;
|
||||
u8 flags = 0;
|
||||
int ret;
|
||||
struct ocfs2_extent_tree et;
|
||||
|
||||
BUG_ON(!clusters_to_add);
|
||||
|
||||
if (mark_unwritten)
|
||||
flags = OCFS2_EXT_UNWRITTEN;
|
||||
|
||||
free_extents = ocfs2_num_free_extents(osb, inode, fe);
|
||||
if (free_extents < 0) {
|
||||
status = free_extents;
|
||||
mlog_errno(status);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* there are two cases which could cause us to EAGAIN in the
|
||||
* we-need-more-metadata case:
|
||||
* 1) we haven't reserved *any*
|
||||
* 2) we are so fragmented, we've needed to add metadata too
|
||||
* many times. */
|
||||
if (!free_extents && !meta_ac) {
|
||||
mlog(0, "we haven't reserved any metadata!\n");
|
||||
status = -EAGAIN;
|
||||
reason = RESTART_META;
|
||||
goto leave;
|
||||
} else if ((!free_extents)
|
||||
&& (ocfs2_alloc_context_bits_left(meta_ac)
|
||||
< ocfs2_extend_meta_needed(fe))) {
|
||||
mlog(0, "filesystem is really fragmented...\n");
|
||||
status = -EAGAIN;
|
||||
reason = RESTART_META;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
status = __ocfs2_claim_clusters(osb, handle, data_ac, 1,
|
||||
clusters_to_add, &bit_off, &num_bits);
|
||||
if (status < 0) {
|
||||
if (status != -ENOSPC)
|
||||
mlog_errno(status);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
BUG_ON(num_bits > clusters_to_add);
|
||||
|
||||
/* reserve our write early -- insert_extent may update the inode */
|
||||
status = ocfs2_journal_access(handle, inode, fe_bh,
|
||||
OCFS2_JOURNAL_ACCESS_WRITE);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
block = ocfs2_clusters_to_blocks(osb->sb, bit_off);
|
||||
mlog(0, "Allocating %u clusters at block %u for inode %llu\n",
|
||||
num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno);
|
||||
status = ocfs2_insert_extent(osb, handle, inode, fe_bh,
|
||||
*logical_offset, block, num_bits,
|
||||
flags, meta_ac);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
status = ocfs2_journal_dirty(handle, fe_bh);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
clusters_to_add -= num_bits;
|
||||
*logical_offset += num_bits;
|
||||
|
||||
if (clusters_to_add) {
|
||||
mlog(0, "need to alloc once more, clusters = %u, wanted = "
|
||||
"%u\n", fe->i_clusters, clusters_to_add);
|
||||
status = -EAGAIN;
|
||||
reason = RESTART_TRANS;
|
||||
}
|
||||
|
||||
leave:
|
||||
mlog_exit(status);
|
||||
if (reason_ret)
|
||||
*reason_ret = reason;
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* For a given allocation, determine which allocators will need to be
|
||||
* accessed, and lock them, reserving the appropriate number of bits.
|
||||
*
|
||||
* Sparse file systems call this from ocfs2_write_begin_nolock()
|
||||
* and ocfs2_allocate_unwritten_extents().
|
||||
*
|
||||
* File systems which don't support holes call this from
|
||||
* ocfs2_extend_allocation().
|
||||
*/
|
||||
int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_dinode *di,
|
||||
u32 clusters_to_add, u32 extents_to_split,
|
||||
struct ocfs2_alloc_context **data_ac,
|
||||
struct ocfs2_alloc_context **meta_ac)
|
||||
{
|
||||
int ret = 0, num_free_extents;
|
||||
unsigned int max_recs_needed = clusters_to_add + 2 * extents_to_split;
|
||||
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
||||
|
||||
*meta_ac = NULL;
|
||||
if (data_ac)
|
||||
*data_ac = NULL;
|
||||
|
||||
BUG_ON(clusters_to_add != 0 && data_ac == NULL);
|
||||
|
||||
mlog(0, "extend inode %llu, i_size = %lld, di->i_clusters = %u, "
|
||||
"clusters_to_add = %u, extents_to_split = %u\n",
|
||||
(unsigned long long)OCFS2_I(inode)->ip_blkno, (long long)i_size_read(inode),
|
||||
le32_to_cpu(di->i_clusters), clusters_to_add, extents_to_split);
|
||||
|
||||
num_free_extents = ocfs2_num_free_extents(osb, inode, di);
|
||||
if (num_free_extents < 0) {
|
||||
ret = num_free_extents;
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sparse allocation file systems need to be more conservative
|
||||
* with reserving room for expansion - the actual allocation
|
||||
* happens while we've got a journal handle open so re-taking
|
||||
* a cluster lock (because we ran out of room for another
|
||||
* extent) will violate ordering rules.
|
||||
*
|
||||
* Most of the time we'll only be seeing this 1 cluster at a time
|
||||
* anyway.
|
||||
*
|
||||
* Always lock for any unwritten extents - we might want to
|
||||
* add blocks during a split.
|
||||
*/
|
||||
if (!num_free_extents ||
|
||||
(ocfs2_sparse_alloc(osb) && num_free_extents < max_recs_needed)) {
|
||||
ret = ocfs2_reserve_new_metadata(osb, di, meta_ac);
|
||||
if (ret < 0) {
|
||||
if (ret != -ENOSPC)
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (clusters_to_add == 0)
|
||||
goto out;
|
||||
|
||||
ret = ocfs2_reserve_clusters(osb, clusters_to_add, data_ac);
|
||||
if (ret < 0) {
|
||||
if (ret != -ENOSPC)
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
if (ret) {
|
||||
if (*meta_ac) {
|
||||
ocfs2_free_alloc_context(*meta_ac);
|
||||
*meta_ac = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* We cannot have an error and a non null *data_ac.
|
||||
*/
|
||||
}
|
||||
ocfs2_init_dinode_extent_tree(&et, inode, fe_bh);
|
||||
ret = ocfs2_add_clusters_in_btree(osb, inode, logical_offset,
|
||||
clusters_to_add, mark_unwritten,
|
||||
&et, handle,
|
||||
data_ac, meta_ac, reason_ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -698,6 +535,7 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
|
||||
struct ocfs2_alloc_context *meta_ac = NULL;
|
||||
enum ocfs2_alloc_restarted why;
|
||||
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
||||
struct ocfs2_extent_tree et;
|
||||
|
||||
mlog_entry("(clusters_to_add = %u)\n", clusters_to_add);
|
||||
|
||||
@@ -707,8 +545,7 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
|
||||
*/
|
||||
BUG_ON(mark_unwritten && !ocfs2_sparse_alloc(osb));
|
||||
|
||||
status = ocfs2_read_block(osb, OCFS2_I(inode)->ip_blkno, &bh,
|
||||
OCFS2_BH_CACHED, inode);
|
||||
status = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, &bh);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto leave;
|
||||
@@ -724,14 +561,21 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
|
||||
restart_all:
|
||||
BUG_ON(le32_to_cpu(fe->i_clusters) != OCFS2_I(inode)->ip_clusters);
|
||||
|
||||
status = ocfs2_lock_allocators(inode, fe, clusters_to_add, 0, &data_ac,
|
||||
&meta_ac);
|
||||
mlog(0, "extend inode %llu, i_size = %lld, di->i_clusters = %u, "
|
||||
"clusters_to_add = %u\n",
|
||||
(unsigned long long)OCFS2_I(inode)->ip_blkno,
|
||||
(long long)i_size_read(inode), le32_to_cpu(fe->i_clusters),
|
||||
clusters_to_add);
|
||||
ocfs2_init_dinode_extent_tree(&et, inode, bh);
|
||||
status = ocfs2_lock_allocators(inode, &et, clusters_to_add, 0,
|
||||
&data_ac, &meta_ac);
|
||||
if (status) {
|
||||
mlog_errno(status);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
credits = ocfs2_calc_extend_credits(osb->sb, fe, clusters_to_add);
|
||||
credits = ocfs2_calc_extend_credits(osb->sb, &fe->id2.i_list,
|
||||
clusters_to_add);
|
||||
handle = ocfs2_start_trans(osb, credits);
|
||||
if (IS_ERR(handle)) {
|
||||
status = PTR_ERR(handle);
|
||||
@@ -753,16 +597,16 @@ restarted_transaction:
|
||||
|
||||
prev_clusters = OCFS2_I(inode)->ip_clusters;
|
||||
|
||||
status = ocfs2_do_extend_allocation(osb,
|
||||
inode,
|
||||
&logical_start,
|
||||
clusters_to_add,
|
||||
mark_unwritten,
|
||||
bh,
|
||||
handle,
|
||||
data_ac,
|
||||
meta_ac,
|
||||
&why);
|
||||
status = ocfs2_add_inode_data(osb,
|
||||
inode,
|
||||
&logical_start,
|
||||
clusters_to_add,
|
||||
mark_unwritten,
|
||||
bh,
|
||||
handle,
|
||||
data_ac,
|
||||
meta_ac,
|
||||
&why);
|
||||
if ((status < 0) && (status != -EAGAIN)) {
|
||||
if (status != -ENOSPC)
|
||||
mlog_errno(status);
|
||||
@@ -789,7 +633,7 @@ restarted_transaction:
|
||||
mlog(0, "restarting transaction.\n");
|
||||
/* TODO: This can be more intelligent. */
|
||||
credits = ocfs2_calc_extend_credits(osb->sb,
|
||||
fe,
|
||||
&fe->id2.i_list,
|
||||
clusters_to_add);
|
||||
status = ocfs2_extend_trans(handle, credits);
|
||||
if (status < 0) {
|
||||
@@ -826,10 +670,8 @@ leave:
|
||||
restart_func = 0;
|
||||
goto restart_all;
|
||||
}
|
||||
if (bh) {
|
||||
brelse(bh);
|
||||
bh = NULL;
|
||||
}
|
||||
brelse(bh);
|
||||
bh = NULL;
|
||||
|
||||
mlog_exit(status);
|
||||
return status;
|
||||
@@ -1096,9 +938,15 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
goto bail_unlock;
|
||||
}
|
||||
|
||||
if (i_size_read(inode) > attr->ia_size)
|
||||
if (i_size_read(inode) > attr->ia_size) {
|
||||
if (ocfs2_should_order_data(inode)) {
|
||||
status = ocfs2_begin_ordered_truncate(inode,
|
||||
attr->ia_size);
|
||||
if (status)
|
||||
goto bail_unlock;
|
||||
}
|
||||
status = ocfs2_truncate_file(inode, bh, attr->ia_size);
|
||||
else
|
||||
} else
|
||||
status = ocfs2_extend_file(inode, bh, attr->ia_size);
|
||||
if (status < 0) {
|
||||
if (status != -ENOSPC)
|
||||
@@ -1140,8 +988,7 @@ bail_unlock_rw:
|
||||
if (size_change)
|
||||
ocfs2_rw_unlock(inode, 1);
|
||||
bail:
|
||||
if (bh)
|
||||
brelse(bh);
|
||||
brelse(bh);
|
||||
|
||||
mlog_exit(status);
|
||||
return status;
|
||||
@@ -1284,8 +1131,7 @@ static int ocfs2_write_remove_suid(struct inode *inode)
|
||||
struct buffer_head *bh = NULL;
|
||||
struct ocfs2_inode_info *oi = OCFS2_I(inode);
|
||||
|
||||
ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
|
||||
oi->ip_blkno, &bh, OCFS2_BH_CACHED, inode);
|
||||
ret = ocfs2_read_block(inode, oi->ip_blkno, &bh);
|
||||
if (ret < 0) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
@@ -1311,9 +1157,8 @@ static int ocfs2_allocate_unwritten_extents(struct inode *inode,
|
||||
struct buffer_head *di_bh = NULL;
|
||||
|
||||
if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
|
||||
ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
|
||||
OCFS2_I(inode)->ip_blkno, &di_bh,
|
||||
OCFS2_BH_CACHED, inode);
|
||||
ret = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno,
|
||||
&di_bh);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
@@ -1394,8 +1239,11 @@ static int __ocfs2_remove_inode_range(struct inode *inode,
|
||||
handle_t *handle;
|
||||
struct ocfs2_alloc_context *meta_ac = NULL;
|
||||
struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
|
||||
struct ocfs2_extent_tree et;
|
||||
|
||||
ret = ocfs2_lock_allocators(inode, di, 0, 1, NULL, &meta_ac);
|
||||
ocfs2_init_dinode_extent_tree(&et, inode, di_bh);
|
||||
|
||||
ret = ocfs2_lock_allocators(inode, &et, 0, 1, NULL, &meta_ac);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
return ret;
|
||||
@@ -1425,7 +1273,7 @@ static int __ocfs2_remove_inode_range(struct inode *inode,
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = ocfs2_remove_extent(inode, di_bh, cpos, len, handle, meta_ac,
|
||||
ret = ocfs2_remove_extent(inode, &et, cpos, len, handle, meta_ac,
|
||||
dealloc);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
@@ -2040,7 +1888,7 @@ out_dio:
|
||||
*/
|
||||
if (old_size != i_size_read(inode) ||
|
||||
old_clusters != OCFS2_I(inode)->ip_clusters) {
|
||||
ret = journal_force_commit(osb->journal->j_journal);
|
||||
ret = jbd2_journal_force_commit(osb->journal->j_journal);
|
||||
if (ret < 0)
|
||||
written = ret;
|
||||
}
|
||||
@@ -2227,6 +2075,10 @@ const struct inode_operations ocfs2_file_iops = {
|
||||
.setattr = ocfs2_setattr,
|
||||
.getattr = ocfs2_getattr,
|
||||
.permission = ocfs2_permission,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ocfs2_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.fallocate = ocfs2_fallocate,
|
||||
.fiemap = ocfs2_fiemap,
|
||||
};
|
||||
@@ -2237,6 +2089,10 @@ const struct inode_operations ocfs2_special_file_iops = {
|
||||
.permission = ocfs2_permission,
|
||||
};
|
||||
|
||||
/*
|
||||
* Other than ->lock, keep ocfs2_fops and ocfs2_dops in sync with
|
||||
* ocfs2_fops_no_plocks and ocfs2_dops_no_plocks!
|
||||
*/
|
||||
const struct file_operations ocfs2_fops = {
|
||||
.llseek = generic_file_llseek,
|
||||
.read = do_sync_read,
|
||||
@@ -2250,13 +2106,60 @@ const struct file_operations ocfs2_fops = {
|
||||
.unlocked_ioctl = ocfs2_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = ocfs2_compat_ioctl,
|
||||
#endif
|
||||
.lock = ocfs2_lock,
|
||||
.flock = ocfs2_flock,
|
||||
.splice_read = ocfs2_file_splice_read,
|
||||
.splice_write = ocfs2_file_splice_write,
|
||||
};
|
||||
|
||||
const struct file_operations ocfs2_dops = {
|
||||
.llseek = generic_file_llseek,
|
||||
.read = generic_read_dir,
|
||||
.readdir = ocfs2_readdir,
|
||||
.fsync = ocfs2_sync_file,
|
||||
.release = ocfs2_dir_release,
|
||||
.open = ocfs2_dir_open,
|
||||
.unlocked_ioctl = ocfs2_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = ocfs2_compat_ioctl,
|
||||
#endif
|
||||
.lock = ocfs2_lock,
|
||||
.flock = ocfs2_flock,
|
||||
};
|
||||
|
||||
/*
|
||||
* POSIX-lockless variants of our file_operations.
|
||||
*
|
||||
* These will be used if the underlying cluster stack does not support
|
||||
* posix file locking, if the user passes the "localflocks" mount
|
||||
* option, or if we have a local-only fs.
|
||||
*
|
||||
* ocfs2_flock is in here because all stacks handle UNIX file locks,
|
||||
* so we still want it in the case of no stack support for
|
||||
* plocks. Internally, it will do the right thing when asked to ignore
|
||||
* the cluster.
|
||||
*/
|
||||
const struct file_operations ocfs2_fops_no_plocks = {
|
||||
.llseek = generic_file_llseek,
|
||||
.read = do_sync_read,
|
||||
.write = do_sync_write,
|
||||
.mmap = ocfs2_mmap,
|
||||
.fsync = ocfs2_sync_file,
|
||||
.release = ocfs2_file_release,
|
||||
.open = ocfs2_file_open,
|
||||
.aio_read = ocfs2_file_aio_read,
|
||||
.aio_write = ocfs2_file_aio_write,
|
||||
.unlocked_ioctl = ocfs2_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = ocfs2_compat_ioctl,
|
||||
#endif
|
||||
.flock = ocfs2_flock,
|
||||
.splice_read = ocfs2_file_splice_read,
|
||||
.splice_write = ocfs2_file_splice_write,
|
||||
};
|
||||
|
||||
const struct file_operations ocfs2_dops = {
|
||||
const struct file_operations ocfs2_dops_no_plocks = {
|
||||
.llseek = generic_file_llseek,
|
||||
.read = generic_read_dir,
|
||||
.readdir = ocfs2_readdir,
|
||||
|
||||
+13
-19
@@ -28,9 +28,12 @@
|
||||
|
||||
extern const struct file_operations ocfs2_fops;
|
||||
extern const struct file_operations ocfs2_dops;
|
||||
extern const struct file_operations ocfs2_fops_no_plocks;
|
||||
extern const struct file_operations ocfs2_dops_no_plocks;
|
||||
extern const struct inode_operations ocfs2_file_iops;
|
||||
extern const struct inode_operations ocfs2_special_file_iops;
|
||||
struct ocfs2_alloc_context;
|
||||
enum ocfs2_alloc_restarted;
|
||||
|
||||
struct ocfs2_file_private {
|
||||
struct file *fp_file;
|
||||
@@ -38,27 +41,18 @@ struct ocfs2_file_private {
|
||||
struct ocfs2_lock_res fp_flock;
|
||||
};
|
||||
|
||||
enum ocfs2_alloc_restarted {
|
||||
RESTART_NONE = 0,
|
||||
RESTART_TRANS,
|
||||
RESTART_META
|
||||
};
|
||||
int ocfs2_do_extend_allocation(struct ocfs2_super *osb,
|
||||
struct inode *inode,
|
||||
u32 *logical_offset,
|
||||
u32 clusters_to_add,
|
||||
int mark_unwritten,
|
||||
struct buffer_head *fe_bh,
|
||||
handle_t *handle,
|
||||
struct ocfs2_alloc_context *data_ac,
|
||||
struct ocfs2_alloc_context *meta_ac,
|
||||
enum ocfs2_alloc_restarted *reason_ret);
|
||||
int ocfs2_add_inode_data(struct ocfs2_super *osb,
|
||||
struct inode *inode,
|
||||
u32 *logical_offset,
|
||||
u32 clusters_to_add,
|
||||
int mark_unwritten,
|
||||
struct buffer_head *fe_bh,
|
||||
handle_t *handle,
|
||||
struct ocfs2_alloc_context *data_ac,
|
||||
struct ocfs2_alloc_context *meta_ac,
|
||||
enum ocfs2_alloc_restarted *reason_ret);
|
||||
int ocfs2_extend_no_holes(struct inode *inode, u64 new_i_size,
|
||||
u64 zero_to);
|
||||
int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_dinode *di,
|
||||
u32 clusters_to_add, u32 extents_to_split,
|
||||
struct ocfs2_alloc_context **data_ac,
|
||||
struct ocfs2_alloc_context **meta_ac);
|
||||
int ocfs2_setattr(struct dentry *dentry, struct iattr *attr);
|
||||
int ocfs2_getattr(struct vfsmount *mnt, struct dentry *dentry,
|
||||
struct kstat *stat);
|
||||
|
||||
+31
-56
@@ -49,6 +49,7 @@
|
||||
#include "symlink.h"
|
||||
#include "sysfile.h"
|
||||
#include "uptodate.h"
|
||||
#include "xattr.h"
|
||||
|
||||
#include "buffer_head_io.h"
|
||||
|
||||
@@ -219,6 +220,7 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
|
||||
struct super_block *sb;
|
||||
struct ocfs2_super *osb;
|
||||
int status = -EINVAL;
|
||||
int use_plocks = 1;
|
||||
|
||||
mlog_entry("(0x%p, size:%llu)\n", inode,
|
||||
(unsigned long long)le64_to_cpu(fe->i_size));
|
||||
@@ -226,6 +228,10 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
|
||||
sb = inode->i_sb;
|
||||
osb = OCFS2_SB(sb);
|
||||
|
||||
if ((osb->s_mount_opt & OCFS2_MOUNT_LOCALFLOCKS) ||
|
||||
ocfs2_mount_local(osb) || !ocfs2_stack_supports_plocks())
|
||||
use_plocks = 0;
|
||||
|
||||
/* this means that read_inode cannot create a superblock inode
|
||||
* today. change if needed. */
|
||||
if (!OCFS2_IS_VALID_DINODE(fe) ||
|
||||
@@ -295,13 +301,19 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
|
||||
|
||||
switch (inode->i_mode & S_IFMT) {
|
||||
case S_IFREG:
|
||||
inode->i_fop = &ocfs2_fops;
|
||||
if (use_plocks)
|
||||
inode->i_fop = &ocfs2_fops;
|
||||
else
|
||||
inode->i_fop = &ocfs2_fops_no_plocks;
|
||||
inode->i_op = &ocfs2_file_iops;
|
||||
i_size_write(inode, le64_to_cpu(fe->i_size));
|
||||
break;
|
||||
case S_IFDIR:
|
||||
inode->i_op = &ocfs2_dir_iops;
|
||||
inode->i_fop = &ocfs2_dops;
|
||||
if (use_plocks)
|
||||
inode->i_fop = &ocfs2_dops;
|
||||
else
|
||||
inode->i_fop = &ocfs2_dops_no_plocks;
|
||||
i_size_write(inode, le64_to_cpu(fe->i_size));
|
||||
break;
|
||||
case S_IFLNK:
|
||||
@@ -448,8 +460,11 @@ static int ocfs2_read_locked_inode(struct inode *inode,
|
||||
}
|
||||
}
|
||||
|
||||
status = ocfs2_read_block(osb, args->fi_blkno, &bh, 0,
|
||||
can_lock ? inode : NULL);
|
||||
if (can_lock)
|
||||
status = ocfs2_read_blocks(inode, args->fi_blkno, 1, &bh,
|
||||
OCFS2_BH_IGNORE_CACHE);
|
||||
else
|
||||
status = ocfs2_read_blocks_sync(osb, args->fi_blkno, 1, &bh);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
@@ -522,6 +537,9 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb,
|
||||
* data and fast symlinks.
|
||||
*/
|
||||
if (fe->i_clusters) {
|
||||
if (ocfs2_should_order_data(inode))
|
||||
ocfs2_begin_ordered_truncate(inode, 0);
|
||||
|
||||
handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
|
||||
if (IS_ERR(handle)) {
|
||||
status = PTR_ERR(handle);
|
||||
@@ -730,6 +748,13 @@ static int ocfs2_wipe_inode(struct inode *inode,
|
||||
goto bail_unlock_dir;
|
||||
}
|
||||
|
||||
/*Free extended attribute resources associated with this inode.*/
|
||||
status = ocfs2_xattr_remove(inode, di_bh);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail_unlock_dir;
|
||||
}
|
||||
|
||||
status = ocfs2_remove_inode(inode, di_bh, orphan_dir_inode,
|
||||
orphan_dir_bh);
|
||||
if (status < 0)
|
||||
@@ -1081,6 +1106,8 @@ void ocfs2_clear_inode(struct inode *inode)
|
||||
oi->ip_last_trans = 0;
|
||||
oi->ip_dir_start_lookup = 0;
|
||||
oi->ip_blkno = 0ULL;
|
||||
jbd2_journal_release_jbd_inode(OCFS2_SB(inode->i_sb)->journal->j_journal,
|
||||
&oi->ip_jinode);
|
||||
|
||||
bail:
|
||||
mlog_exit_void();
|
||||
@@ -1106,58 +1133,6 @@ void ocfs2_drop_inode(struct inode *inode)
|
||||
mlog_exit_void();
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: this should probably be merged into ocfs2_get_block
|
||||
*
|
||||
* However, you now need to pay attention to the cont_prepare_write()
|
||||
* stuff in ocfs2_get_block (that is, ocfs2_get_block pretty much
|
||||
* expects never to extend).
|
||||
*/
|
||||
struct buffer_head *ocfs2_bread(struct inode *inode,
|
||||
int block, int *err, int reada)
|
||||
{
|
||||
struct buffer_head *bh = NULL;
|
||||
int tmperr;
|
||||
u64 p_blkno;
|
||||
int readflags = OCFS2_BH_CACHED;
|
||||
|
||||
if (reada)
|
||||
readflags |= OCFS2_BH_READAHEAD;
|
||||
|
||||
if (((u64)block << inode->i_sb->s_blocksize_bits) >=
|
||||
i_size_read(inode)) {
|
||||
BUG_ON(!reada);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
down_read(&OCFS2_I(inode)->ip_alloc_sem);
|
||||
tmperr = ocfs2_extent_map_get_blocks(inode, block, &p_blkno, NULL,
|
||||
NULL);
|
||||
up_read(&OCFS2_I(inode)->ip_alloc_sem);
|
||||
if (tmperr < 0) {
|
||||
mlog_errno(tmperr);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
tmperr = ocfs2_read_block(OCFS2_SB(inode->i_sb), p_blkno, &bh,
|
||||
readflags, inode);
|
||||
if (tmperr < 0)
|
||||
goto fail;
|
||||
|
||||
tmperr = 0;
|
||||
|
||||
*err = 0;
|
||||
return bh;
|
||||
|
||||
fail:
|
||||
if (bh) {
|
||||
brelse(bh);
|
||||
bh = NULL;
|
||||
}
|
||||
*err = -EIO;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called from our getattr.
|
||||
*/
|
||||
|
||||
+4
-2
@@ -40,6 +40,9 @@ struct ocfs2_inode_info
|
||||
/* protects allocation changes on this inode. */
|
||||
struct rw_semaphore ip_alloc_sem;
|
||||
|
||||
/* protects extended attribute changes on this inode */
|
||||
struct rw_semaphore ip_xattr_sem;
|
||||
|
||||
/* These fields are protected by ip_lock */
|
||||
spinlock_t ip_lock;
|
||||
u32 ip_open_count;
|
||||
@@ -68,6 +71,7 @@ struct ocfs2_inode_info
|
||||
struct ocfs2_extent_map ip_extent_map;
|
||||
|
||||
struct inode vfs_inode;
|
||||
struct jbd2_inode ip_jinode;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -113,8 +117,6 @@ extern struct kmem_cache *ocfs2_inode_cache;
|
||||
|
||||
extern const struct address_space_operations ocfs2_aops;
|
||||
|
||||
struct buffer_head *ocfs2_bread(struct inode *inode, int block,
|
||||
int *err, int reada);
|
||||
void ocfs2_clear_inode(struct inode *inode);
|
||||
void ocfs2_delete_inode(struct inode *inode);
|
||||
void ocfs2_drop_inode(struct inode *inode);
|
||||
|
||||
+1
-2
@@ -102,8 +102,7 @@ bail_unlock:
|
||||
bail:
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
|
||||
if (bh)
|
||||
brelse(bh);
|
||||
brelse(bh);
|
||||
|
||||
mlog_exit(status);
|
||||
return status;
|
||||
|
||||
+45
-44
@@ -215,9 +215,9 @@ static int ocfs2_commit_cache(struct ocfs2_super *osb)
|
||||
goto finally;
|
||||
}
|
||||
|
||||
journal_lock_updates(journal->j_journal);
|
||||
status = journal_flush(journal->j_journal);
|
||||
journal_unlock_updates(journal->j_journal);
|
||||
jbd2_journal_lock_updates(journal->j_journal);
|
||||
status = jbd2_journal_flush(journal->j_journal);
|
||||
jbd2_journal_unlock_updates(journal->j_journal);
|
||||
if (status < 0) {
|
||||
up_write(&journal->j_trans_barrier);
|
||||
mlog_errno(status);
|
||||
@@ -264,7 +264,7 @@ handle_t *ocfs2_start_trans(struct ocfs2_super *osb, int max_buffs)
|
||||
|
||||
down_read(&osb->journal->j_trans_barrier);
|
||||
|
||||
handle = journal_start(journal, max_buffs);
|
||||
handle = jbd2_journal_start(journal, max_buffs);
|
||||
if (IS_ERR(handle)) {
|
||||
up_read(&osb->journal->j_trans_barrier);
|
||||
|
||||
@@ -290,7 +290,7 @@ int ocfs2_commit_trans(struct ocfs2_super *osb,
|
||||
|
||||
BUG_ON(!handle);
|
||||
|
||||
ret = journal_stop(handle);
|
||||
ret = jbd2_journal_stop(handle);
|
||||
if (ret < 0)
|
||||
mlog_errno(ret);
|
||||
|
||||
@@ -304,7 +304,7 @@ int ocfs2_commit_trans(struct ocfs2_super *osb,
|
||||
* transaction. extend_trans will either extend the current handle by
|
||||
* nblocks, or commit it and start a new one with nblocks credits.
|
||||
*
|
||||
* This might call journal_restart() which will commit dirty buffers
|
||||
* This might call jbd2_journal_restart() which will commit dirty buffers
|
||||
* and then restart the transaction. Before calling
|
||||
* ocfs2_extend_trans(), any changed blocks should have been
|
||||
* dirtied. After calling it, all blocks which need to be changed must
|
||||
@@ -332,7 +332,7 @@ int ocfs2_extend_trans(handle_t *handle, int nblocks)
|
||||
#ifdef CONFIG_OCFS2_DEBUG_FS
|
||||
status = 1;
|
||||
#else
|
||||
status = journal_extend(handle, nblocks);
|
||||
status = jbd2_journal_extend(handle, nblocks);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
@@ -340,8 +340,10 @@ int ocfs2_extend_trans(handle_t *handle, int nblocks)
|
||||
#endif
|
||||
|
||||
if (status > 0) {
|
||||
mlog(0, "journal_extend failed, trying journal_restart\n");
|
||||
status = journal_restart(handle, nblocks);
|
||||
mlog(0,
|
||||
"jbd2_journal_extend failed, trying "
|
||||
"jbd2_journal_restart\n");
|
||||
status = jbd2_journal_restart(handle, nblocks);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
@@ -393,11 +395,11 @@ int ocfs2_journal_access(handle_t *handle,
|
||||
switch (type) {
|
||||
case OCFS2_JOURNAL_ACCESS_CREATE:
|
||||
case OCFS2_JOURNAL_ACCESS_WRITE:
|
||||
status = journal_get_write_access(handle, bh);
|
||||
status = jbd2_journal_get_write_access(handle, bh);
|
||||
break;
|
||||
|
||||
case OCFS2_JOURNAL_ACCESS_UNDO:
|
||||
status = journal_get_undo_access(handle, bh);
|
||||
status = jbd2_journal_get_undo_access(handle, bh);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -422,7 +424,7 @@ int ocfs2_journal_dirty(handle_t *handle,
|
||||
mlog_entry("(bh->b_blocknr=%llu)\n",
|
||||
(unsigned long long)bh->b_blocknr);
|
||||
|
||||
status = journal_dirty_metadata(handle, bh);
|
||||
status = jbd2_journal_dirty_metadata(handle, bh);
|
||||
if (status < 0)
|
||||
mlog(ML_ERROR, "Could not dirty metadata buffer. "
|
||||
"(bh->b_blocknr=%llu)\n",
|
||||
@@ -432,6 +434,7 @@ int ocfs2_journal_dirty(handle_t *handle,
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OCFS2_COMPAT_JBD
|
||||
int ocfs2_journal_dirty_data(handle_t *handle,
|
||||
struct buffer_head *bh)
|
||||
{
|
||||
@@ -443,8 +446,9 @@ int ocfs2_journal_dirty_data(handle_t *handle,
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define OCFS2_DEFAULT_COMMIT_INTERVAL (HZ * JBD_DEFAULT_MAX_COMMIT_AGE)
|
||||
#define OCFS2_DEFAULT_COMMIT_INTERVAL (HZ * JBD2_DEFAULT_MAX_COMMIT_AGE)
|
||||
|
||||
void ocfs2_set_journal_params(struct ocfs2_super *osb)
|
||||
{
|
||||
@@ -457,9 +461,9 @@ void ocfs2_set_journal_params(struct ocfs2_super *osb)
|
||||
spin_lock(&journal->j_state_lock);
|
||||
journal->j_commit_interval = commit_interval;
|
||||
if (osb->s_mount_opt & OCFS2_MOUNT_BARRIER)
|
||||
journal->j_flags |= JFS_BARRIER;
|
||||
journal->j_flags |= JBD2_BARRIER;
|
||||
else
|
||||
journal->j_flags &= ~JFS_BARRIER;
|
||||
journal->j_flags &= ~JBD2_BARRIER;
|
||||
spin_unlock(&journal->j_state_lock);
|
||||
}
|
||||
|
||||
@@ -524,14 +528,14 @@ int ocfs2_journal_init(struct ocfs2_journal *journal, int *dirty)
|
||||
mlog(0, "inode->ip_clusters = %u\n", OCFS2_I(inode)->ip_clusters);
|
||||
|
||||
/* call the kernels journal init function now */
|
||||
j_journal = journal_init_inode(inode);
|
||||
j_journal = jbd2_journal_init_inode(inode);
|
||||
if (j_journal == NULL) {
|
||||
mlog(ML_ERROR, "Linux journal layer error\n");
|
||||
status = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
mlog(0, "Returned from journal_init_inode\n");
|
||||
mlog(0, "Returned from jbd2_journal_init_inode\n");
|
||||
mlog(0, "j_journal->j_maxlen = %u\n", j_journal->j_maxlen);
|
||||
|
||||
*dirty = (le32_to_cpu(di->id1.journal1.ij_flags) &
|
||||
@@ -550,8 +554,7 @@ done:
|
||||
if (status < 0) {
|
||||
if (inode_lock)
|
||||
ocfs2_inode_unlock(inode, 1);
|
||||
if (bh != NULL)
|
||||
brelse(bh);
|
||||
brelse(bh);
|
||||
if (inode) {
|
||||
OCFS2_I(inode)->ip_open_count--;
|
||||
iput(inode);
|
||||
@@ -639,7 +642,7 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb)
|
||||
if (journal->j_state != OCFS2_JOURNAL_LOADED)
|
||||
goto done;
|
||||
|
||||
/* need to inc inode use count as journal_destroy will iput. */
|
||||
/* need to inc inode use count - jbd2_journal_destroy will iput. */
|
||||
if (!igrab(inode))
|
||||
BUG();
|
||||
|
||||
@@ -668,9 +671,9 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb)
|
||||
BUG_ON(atomic_read(&(osb->journal->j_num_trans)) != 0);
|
||||
|
||||
if (ocfs2_mount_local(osb)) {
|
||||
journal_lock_updates(journal->j_journal);
|
||||
status = journal_flush(journal->j_journal);
|
||||
journal_unlock_updates(journal->j_journal);
|
||||
jbd2_journal_lock_updates(journal->j_journal);
|
||||
status = jbd2_journal_flush(journal->j_journal);
|
||||
jbd2_journal_unlock_updates(journal->j_journal);
|
||||
if (status < 0)
|
||||
mlog_errno(status);
|
||||
}
|
||||
@@ -686,7 +689,7 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb)
|
||||
}
|
||||
|
||||
/* Shutdown the kernel journal system */
|
||||
journal_destroy(journal->j_journal);
|
||||
jbd2_journal_destroy(journal->j_journal);
|
||||
|
||||
OCFS2_I(inode)->ip_open_count--;
|
||||
|
||||
@@ -711,15 +714,15 @@ static void ocfs2_clear_journal_error(struct super_block *sb,
|
||||
{
|
||||
int olderr;
|
||||
|
||||
olderr = journal_errno(journal);
|
||||
olderr = jbd2_journal_errno(journal);
|
||||
if (olderr) {
|
||||
mlog(ML_ERROR, "File system error %d recorded in "
|
||||
"journal %u.\n", olderr, slot);
|
||||
mlog(ML_ERROR, "File system on device %s needs checking.\n",
|
||||
sb->s_id);
|
||||
|
||||
journal_ack_err(journal);
|
||||
journal_clear_err(journal);
|
||||
jbd2_journal_ack_err(journal);
|
||||
jbd2_journal_clear_err(journal);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -734,7 +737,7 @@ int ocfs2_journal_load(struct ocfs2_journal *journal, int local, int replayed)
|
||||
|
||||
osb = journal->j_osb;
|
||||
|
||||
status = journal_load(journal->j_journal);
|
||||
status = jbd2_journal_load(journal->j_journal);
|
||||
if (status < 0) {
|
||||
mlog(ML_ERROR, "Failed to load journal!\n");
|
||||
goto done;
|
||||
@@ -778,7 +781,7 @@ int ocfs2_journal_wipe(struct ocfs2_journal *journal, int full)
|
||||
|
||||
BUG_ON(!journal);
|
||||
|
||||
status = journal_wipe(journal->j_journal, full);
|
||||
status = jbd2_journal_wipe(journal->j_journal, full);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
@@ -847,9 +850,8 @@ static int ocfs2_force_read_journal(struct inode *inode)
|
||||
|
||||
/* We are reading journal data which should not
|
||||
* be put in the uptodate cache */
|
||||
status = ocfs2_read_blocks(OCFS2_SB(inode->i_sb),
|
||||
p_blkno, p_blocks, bhs, 0,
|
||||
NULL);
|
||||
status = ocfs2_read_blocks_sync(OCFS2_SB(inode->i_sb),
|
||||
p_blkno, p_blocks, bhs);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
@@ -865,8 +867,7 @@ static int ocfs2_force_read_journal(struct inode *inode)
|
||||
|
||||
bail:
|
||||
for(i = 0; i < CONCURRENT_JOURNAL_FILL; i++)
|
||||
if (bhs[i])
|
||||
brelse(bhs[i]);
|
||||
brelse(bhs[i]);
|
||||
mlog_exit(status);
|
||||
return status;
|
||||
}
|
||||
@@ -1133,7 +1134,8 @@ static int ocfs2_read_journal_inode(struct ocfs2_super *osb,
|
||||
}
|
||||
SET_INODE_JOURNAL(inode);
|
||||
|
||||
status = ocfs2_read_block(osb, OCFS2_I(inode)->ip_blkno, bh, 0, inode);
|
||||
status = ocfs2_read_blocks(inode, OCFS2_I(inode)->ip_blkno, 1, bh,
|
||||
OCFS2_BH_IGNORE_CACHE);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
@@ -1229,19 +1231,19 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb,
|
||||
}
|
||||
|
||||
mlog(0, "calling journal_init_inode\n");
|
||||
journal = journal_init_inode(inode);
|
||||
journal = jbd2_journal_init_inode(inode);
|
||||
if (journal == NULL) {
|
||||
mlog(ML_ERROR, "Linux journal layer error\n");
|
||||
status = -EIO;
|
||||
goto done;
|
||||
}
|
||||
|
||||
status = journal_load(journal);
|
||||
status = jbd2_journal_load(journal);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
if (!igrab(inode))
|
||||
BUG();
|
||||
journal_destroy(journal);
|
||||
jbd2_journal_destroy(journal);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -1249,9 +1251,9 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb,
|
||||
|
||||
/* wipe the journal */
|
||||
mlog(0, "flushing the journal.\n");
|
||||
journal_lock_updates(journal);
|
||||
status = journal_flush(journal);
|
||||
journal_unlock_updates(journal);
|
||||
jbd2_journal_lock_updates(journal);
|
||||
status = jbd2_journal_flush(journal);
|
||||
jbd2_journal_unlock_updates(journal);
|
||||
if (status < 0)
|
||||
mlog_errno(status);
|
||||
|
||||
@@ -1272,7 +1274,7 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb,
|
||||
if (!igrab(inode))
|
||||
BUG();
|
||||
|
||||
journal_destroy(journal);
|
||||
jbd2_journal_destroy(journal);
|
||||
|
||||
done:
|
||||
/* drop the lock on this nodes journal */
|
||||
@@ -1282,8 +1284,7 @@ done:
|
||||
if (inode)
|
||||
iput(inode);
|
||||
|
||||
if (bh)
|
||||
brelse(bh);
|
||||
brelse(bh);
|
||||
|
||||
mlog_exit(status);
|
||||
return status;
|
||||
|
||||
+43
-9
@@ -27,7 +27,12 @@
|
||||
#define OCFS2_JOURNAL_H
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/jbd.h>
|
||||
#ifndef CONFIG_OCFS2_COMPAT_JBD
|
||||
# include <linux/jbd2.h>
|
||||
#else
|
||||
# include <linux/jbd.h>
|
||||
# include "ocfs2_jbd_compat.h"
|
||||
#endif
|
||||
|
||||
enum ocfs2_journal_state {
|
||||
OCFS2_JOURNAL_FREE = 0,
|
||||
@@ -215,8 +220,8 @@ static inline void ocfs2_checkpoint_inode(struct inode *inode)
|
||||
* buffer. Will have to call ocfs2_journal_dirty once
|
||||
* we've actually dirtied it. Type is one of . or .
|
||||
* ocfs2_journal_dirty - Mark a journalled buffer as having dirty data.
|
||||
* ocfs2_journal_dirty_data - Indicate that a data buffer should go out before
|
||||
* the current handle commits.
|
||||
* ocfs2_jbd2_file_inode - Mark an inode so that its data goes out before
|
||||
* the current handle commits.
|
||||
*/
|
||||
|
||||
/* You must always start_trans with a number of buffs > 0, but it's
|
||||
@@ -268,8 +273,10 @@ int ocfs2_journal_access(handle_t *handle,
|
||||
*/
|
||||
int ocfs2_journal_dirty(handle_t *handle,
|
||||
struct buffer_head *bh);
|
||||
#ifdef CONFIG_OCFS2_COMPAT_JBD
|
||||
int ocfs2_journal_dirty_data(handle_t *handle,
|
||||
struct buffer_head *bh);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Credit Macros:
|
||||
@@ -283,6 +290,9 @@ int ocfs2_journal_dirty_data(handle_t *handle,
|
||||
/* simple file updates like chmod, etc. */
|
||||
#define OCFS2_INODE_UPDATE_CREDITS 1
|
||||
|
||||
/* extended attribute block update */
|
||||
#define OCFS2_XATTR_BLOCK_UPDATE_CREDITS 1
|
||||
|
||||
/* group extend. inode update and last group update. */
|
||||
#define OCFS2_GROUP_EXTEND_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
|
||||
|
||||
@@ -340,11 +350,23 @@ int ocfs2_journal_dirty_data(handle_t *handle,
|
||||
#define OCFS2_RENAME_CREDITS (3 * OCFS2_INODE_UPDATE_CREDITS + 3 \
|
||||
+ OCFS2_UNLINK_CREDITS)
|
||||
|
||||
/* global bitmap dinode, group desc., relinked group,
|
||||
* suballocator dinode, group desc., relinked group,
|
||||
* dinode, xattr block */
|
||||
#define OCFS2_XATTR_BLOCK_CREATE_CREDITS (OCFS2_SUBALLOC_ALLOC * 2 + \
|
||||
+ OCFS2_INODE_UPDATE_CREDITS \
|
||||
+ OCFS2_XATTR_BLOCK_UPDATE_CREDITS)
|
||||
|
||||
/*
|
||||
* Please note that the caller must make sure that root_el is the root
|
||||
* of extent tree. So for an inode, it should be &fe->id2.i_list. Otherwise
|
||||
* the result may be wrong.
|
||||
*/
|
||||
static inline int ocfs2_calc_extend_credits(struct super_block *sb,
|
||||
struct ocfs2_dinode *fe,
|
||||
struct ocfs2_extent_list *root_el,
|
||||
u32 bits_wanted)
|
||||
{
|
||||
int bitmap_blocks, sysfile_bitmap_blocks, dinode_blocks;
|
||||
int bitmap_blocks, sysfile_bitmap_blocks, extent_blocks;
|
||||
|
||||
/* bitmap dinode, group desc. + relinked group. */
|
||||
bitmap_blocks = OCFS2_SUBALLOC_ALLOC;
|
||||
@@ -355,16 +377,16 @@ static inline int ocfs2_calc_extend_credits(struct super_block *sb,
|
||||
* however many metadata chunks needed * a remaining suballoc
|
||||
* alloc. */
|
||||
sysfile_bitmap_blocks = 1 +
|
||||
(OCFS2_SUBALLOC_ALLOC - 1) * ocfs2_extend_meta_needed(fe);
|
||||
(OCFS2_SUBALLOC_ALLOC - 1) * ocfs2_extend_meta_needed(root_el);
|
||||
|
||||
/* this does not include *new* metadata blocks, which are
|
||||
* accounted for in sysfile_bitmap_blocks. fe +
|
||||
* accounted for in sysfile_bitmap_blocks. root_el +
|
||||
* prev. last_eb_blk + blocks along edge of tree.
|
||||
* calc_symlink_credits passes because we just need 1
|
||||
* credit for the dinode there. */
|
||||
dinode_blocks = 1 + 1 + le16_to_cpu(fe->id2.i_list.l_tree_depth);
|
||||
extent_blocks = 1 + 1 + le16_to_cpu(root_el->l_tree_depth);
|
||||
|
||||
return bitmap_blocks + sysfile_bitmap_blocks + dinode_blocks;
|
||||
return bitmap_blocks + sysfile_bitmap_blocks + extent_blocks;
|
||||
}
|
||||
|
||||
static inline int ocfs2_calc_symlink_credits(struct super_block *sb)
|
||||
@@ -415,4 +437,16 @@ static inline int ocfs2_calc_tree_trunc_credits(struct super_block *sb,
|
||||
return credits;
|
||||
}
|
||||
|
||||
static inline int ocfs2_jbd2_file_inode(handle_t *handle, struct inode *inode)
|
||||
{
|
||||
return jbd2_journal_file_inode(handle, &OCFS2_I(inode)->ip_jinode);
|
||||
}
|
||||
|
||||
static inline int ocfs2_begin_ordered_truncate(struct inode *inode,
|
||||
loff_t new_size)
|
||||
{
|
||||
return jbd2_journal_begin_ordered_truncate(&OCFS2_I(inode)->ip_jinode,
|
||||
new_size);
|
||||
}
|
||||
|
||||
#endif /* OCFS2_JOURNAL_H */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user