提交 b64ada6b 编写于 作者: L Linus Torvalds

Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2

* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2: (85 commits)
  ocfs2: Use buffer IO if we are appending a file.
  ocfs2: add spinlock protection when dealing with lockres->purge.
  dlmglue.c: add missed mlog lines
  ocfs2: __ocfs2_abort() should not enable panic for local mounts
  ocfs2: Add ioctl for reflink.
  ocfs2: Enable refcount tree support.
  ocfs2: Implement ocfs2_reflink.
  ocfs2: Add preserve to reflink.
  ocfs2: Create reflinked file in orphan dir.
  ocfs2: Use proper parameter for some inode operation.
  ocfs2: Make transaction extend more efficient.
  ocfs2: Don't merge in 1st refcount ops of reflink.
  ocfs2: Modify removing xattr process for refcount.
  ocfs2: Add reflink support for xattr.
  ocfs2: Create an xattr indexed block if needed.
  ocfs2: Call refcount tree remove process properly.
  ocfs2: Attach xattr clusters to refcount tree.
  ocfs2: Abstract ocfs2 xattr tree extend rec iteration process.
  ocfs2: Abstract the creation of xattr block.
  ocfs2: Remove inode from ocfs2_xattr_bucket_get_name_value.
  ...
...@@ -28,6 +28,7 @@ ocfs2-objs := \ ...@@ -28,6 +28,7 @@ ocfs2-objs := \
locks.o \ locks.o \
mmap.o \ mmap.o \
namei.o \ namei.o \
refcounttree.o \
resize.o \ resize.o \
slot_map.o \ slot_map.o \
suballoc.o \ suballoc.o \
......
此差异已折叠。
...@@ -45,7 +45,8 @@ ...@@ -45,7 +45,8 @@
* *
* ocfs2_extent_tree contains info for the root of the b-tree, it must have a * 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 * root ocfs2_extent_list and a root_bh so that they can be used in the b-tree
* functions. With metadata ecc, we now call different journal_access * functions. It needs the ocfs2_caching_info structure associated with
* I/O on the tree. With metadata ecc, we now call different journal_access
* functions for each type of metadata, so it must have the * functions for each type of metadata, so it must have the
* root_journal_access function. * root_journal_access function.
* ocfs2_extent_tree_operations abstract the normal operations we do for * ocfs2_extent_tree_operations abstract the normal operations we do for
...@@ -56,6 +57,7 @@ struct ocfs2_extent_tree { ...@@ -56,6 +57,7 @@ struct ocfs2_extent_tree {
struct ocfs2_extent_tree_operations *et_ops; struct ocfs2_extent_tree_operations *et_ops;
struct buffer_head *et_root_bh; struct buffer_head *et_root_bh;
struct ocfs2_extent_list *et_root_el; struct ocfs2_extent_list *et_root_el;
struct ocfs2_caching_info *et_ci;
ocfs2_journal_access_func et_root_journal_access; ocfs2_journal_access_func et_root_journal_access;
void *et_object; void *et_object;
unsigned int et_max_leaf_clusters; unsigned int et_max_leaf_clusters;
...@@ -66,31 +68,32 @@ struct ocfs2_extent_tree { ...@@ -66,31 +68,32 @@ struct ocfs2_extent_tree {
* specified object buffer. * specified object buffer.
*/ */
void ocfs2_init_dinode_extent_tree(struct ocfs2_extent_tree *et, void ocfs2_init_dinode_extent_tree(struct ocfs2_extent_tree *et,
struct inode *inode, struct ocfs2_caching_info *ci,
struct buffer_head *bh); struct buffer_head *bh);
void ocfs2_init_xattr_tree_extent_tree(struct ocfs2_extent_tree *et, void ocfs2_init_xattr_tree_extent_tree(struct ocfs2_extent_tree *et,
struct inode *inode, struct ocfs2_caching_info *ci,
struct buffer_head *bh); struct buffer_head *bh);
struct ocfs2_xattr_value_buf; struct ocfs2_xattr_value_buf;
void ocfs2_init_xattr_value_extent_tree(struct ocfs2_extent_tree *et, void ocfs2_init_xattr_value_extent_tree(struct ocfs2_extent_tree *et,
struct inode *inode, struct ocfs2_caching_info *ci,
struct ocfs2_xattr_value_buf *vb); struct ocfs2_xattr_value_buf *vb);
void ocfs2_init_dx_root_extent_tree(struct ocfs2_extent_tree *et, void ocfs2_init_dx_root_extent_tree(struct ocfs2_extent_tree *et,
struct inode *inode, struct ocfs2_caching_info *ci,
struct buffer_head *bh); struct buffer_head *bh);
void ocfs2_init_refcount_extent_tree(struct ocfs2_extent_tree *et,
struct ocfs2_caching_info *ci,
struct buffer_head *bh);
/* /*
* Read an extent block into *bh. If *bh is NULL, a bh will be * Read an extent block into *bh. If *bh is NULL, a bh will be
* allocated. This is a cached read. The extent block will be validated * allocated. This is a cached read. The extent block will be validated
* with ocfs2_validate_extent_block(). * with ocfs2_validate_extent_block().
*/ */
int ocfs2_read_extent_block(struct inode *inode, u64 eb_blkno, int ocfs2_read_extent_block(struct ocfs2_caching_info *ci, u64 eb_blkno,
struct buffer_head **bh); struct buffer_head **bh);
struct ocfs2_alloc_context; struct ocfs2_alloc_context;
int ocfs2_insert_extent(struct ocfs2_super *osb, int ocfs2_insert_extent(handle_t *handle,
handle_t *handle,
struct inode *inode,
struct ocfs2_extent_tree *et, struct ocfs2_extent_tree *et,
u32 cpos, u32 cpos,
u64 start_blk, u64 start_blk,
...@@ -103,25 +106,36 @@ enum ocfs2_alloc_restarted { ...@@ -103,25 +106,36 @@ enum ocfs2_alloc_restarted {
RESTART_TRANS, RESTART_TRANS,
RESTART_META RESTART_META
}; };
int ocfs2_add_clusters_in_btree(struct ocfs2_super *osb, int ocfs2_add_clusters_in_btree(handle_t *handle,
struct inode *inode, struct ocfs2_extent_tree *et,
u32 *logical_offset, u32 *logical_offset,
u32 clusters_to_add, u32 clusters_to_add,
int mark_unwritten, int mark_unwritten,
struct ocfs2_extent_tree *et,
handle_t *handle,
struct ocfs2_alloc_context *data_ac, struct ocfs2_alloc_context *data_ac,
struct ocfs2_alloc_context *meta_ac, struct ocfs2_alloc_context *meta_ac,
enum ocfs2_alloc_restarted *reason_ret); enum ocfs2_alloc_restarted *reason_ret);
struct ocfs2_cached_dealloc_ctxt; struct ocfs2_cached_dealloc_ctxt;
struct ocfs2_path;
int ocfs2_split_extent(handle_t *handle,
struct ocfs2_extent_tree *et,
struct ocfs2_path *path,
int split_index,
struct ocfs2_extent_rec *split_rec,
struct ocfs2_alloc_context *meta_ac,
struct ocfs2_cached_dealloc_ctxt *dealloc);
int ocfs2_mark_extent_written(struct inode *inode, int ocfs2_mark_extent_written(struct inode *inode,
struct ocfs2_extent_tree *et, struct ocfs2_extent_tree *et,
handle_t *handle, u32 cpos, u32 len, u32 phys, handle_t *handle, u32 cpos, u32 len, u32 phys,
struct ocfs2_alloc_context *meta_ac, struct ocfs2_alloc_context *meta_ac,
struct ocfs2_cached_dealloc_ctxt *dealloc); struct ocfs2_cached_dealloc_ctxt *dealloc);
int ocfs2_remove_extent(struct inode *inode, int ocfs2_change_extent_flag(handle_t *handle,
struct ocfs2_extent_tree *et, struct ocfs2_extent_tree *et,
u32 cpos, u32 len, handle_t *handle, u32 cpos, u32 len, u32 phys,
struct ocfs2_alloc_context *meta_ac,
struct ocfs2_cached_dealloc_ctxt *dealloc,
int new_flags, int clear_flags);
int ocfs2_remove_extent(handle_t *handle, struct ocfs2_extent_tree *et,
u32 cpos, u32 len,
struct ocfs2_alloc_context *meta_ac, struct ocfs2_alloc_context *meta_ac,
struct ocfs2_cached_dealloc_ctxt *dealloc); struct ocfs2_cached_dealloc_ctxt *dealloc);
int ocfs2_remove_btree_range(struct inode *inode, int ocfs2_remove_btree_range(struct inode *inode,
...@@ -130,7 +144,6 @@ int ocfs2_remove_btree_range(struct inode *inode, ...@@ -130,7 +144,6 @@ int ocfs2_remove_btree_range(struct inode *inode,
struct ocfs2_cached_dealloc_ctxt *dealloc); struct ocfs2_cached_dealloc_ctxt *dealloc);
int ocfs2_num_free_extents(struct ocfs2_super *osb, int ocfs2_num_free_extents(struct ocfs2_super *osb,
struct inode *inode,
struct ocfs2_extent_tree *et); struct ocfs2_extent_tree *et);
/* /*
...@@ -195,6 +208,9 @@ static inline void ocfs2_init_dealloc_ctxt(struct ocfs2_cached_dealloc_ctxt *c) ...@@ -195,6 +208,9 @@ static inline void ocfs2_init_dealloc_ctxt(struct ocfs2_cached_dealloc_ctxt *c)
} }
int ocfs2_cache_cluster_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt, int ocfs2_cache_cluster_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
u64 blkno, unsigned int bit); u64 blkno, unsigned int bit);
int ocfs2_cache_block_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
int type, int slot, u64 blkno,
unsigned int bit);
static inline int ocfs2_dealloc_has_cluster(struct ocfs2_cached_dealloc_ctxt *c) static inline int ocfs2_dealloc_has_cluster(struct ocfs2_cached_dealloc_ctxt *c)
{ {
return c->c_global_allocator != NULL; return c->c_global_allocator != NULL;
...@@ -222,8 +238,9 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb, ...@@ -222,8 +238,9 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
int ocfs2_truncate_inline(struct inode *inode, struct buffer_head *di_bh, int ocfs2_truncate_inline(struct inode *inode, struct buffer_head *di_bh,
unsigned int start, unsigned int end, int trunc); unsigned int start, unsigned int end, int trunc);
int ocfs2_find_leaf(struct inode *inode, struct ocfs2_extent_list *root_el, int ocfs2_find_leaf(struct ocfs2_caching_info *ci,
u32 cpos, struct buffer_head **leaf_bh); struct ocfs2_extent_list *root_el, u32 cpos,
struct buffer_head **leaf_bh);
int ocfs2_search_extent_list(struct ocfs2_extent_list *el, u32 v_cluster); int ocfs2_search_extent_list(struct ocfs2_extent_list *el, u32 v_cluster);
/* /*
...@@ -254,4 +271,50 @@ static inline int ocfs2_is_empty_extent(struct ocfs2_extent_rec *rec) ...@@ -254,4 +271,50 @@ static inline int ocfs2_is_empty_extent(struct ocfs2_extent_rec *rec)
return !rec->e_leaf_clusters; return !rec->e_leaf_clusters;
} }
int ocfs2_grab_pages(struct inode *inode, loff_t start, loff_t end,
struct page **pages, int *num);
void ocfs2_map_and_dirty_page(struct inode *inode, handle_t *handle,
unsigned int from, unsigned int to,
struct page *page, int zero, u64 *phys);
/*
* Structures which describe a path through a btree, and functions to
* manipulate them.
*
* The idea here is to be as generic as possible with the tree
* manipulation code.
*/
struct ocfs2_path_item {
struct buffer_head *bh;
struct ocfs2_extent_list *el;
};
#define OCFS2_MAX_PATH_DEPTH 5
struct ocfs2_path {
int p_tree_depth;
ocfs2_journal_access_func p_root_access;
struct ocfs2_path_item p_node[OCFS2_MAX_PATH_DEPTH];
};
#define path_root_bh(_path) ((_path)->p_node[0].bh)
#define path_root_el(_path) ((_path)->p_node[0].el)
#define path_root_access(_path)((_path)->p_root_access)
#define path_leaf_bh(_path) ((_path)->p_node[(_path)->p_tree_depth].bh)
#define path_leaf_el(_path) ((_path)->p_node[(_path)->p_tree_depth].el)
#define path_num_items(_path) ((_path)->p_tree_depth + 1)
void ocfs2_reinit_path(struct ocfs2_path *path, int keep_root);
void ocfs2_free_path(struct ocfs2_path *path);
int ocfs2_find_path(struct ocfs2_caching_info *ci,
struct ocfs2_path *path,
u32 cpos);
struct ocfs2_path *ocfs2_new_path_from_path(struct ocfs2_path *path);
struct ocfs2_path *ocfs2_new_path_from_et(struct ocfs2_extent_tree *et);
int ocfs2_path_bh_journal_access(handle_t *handle,
struct ocfs2_caching_info *ci,
struct ocfs2_path *path,
int idx);
int ocfs2_journal_access_path(struct ocfs2_caching_info *ci,
handle_t *handle,
struct ocfs2_path *path);
#endif /* OCFS2_ALLOC_H */ #endif /* OCFS2_ALLOC_H */
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include "suballoc.h" #include "suballoc.h"
#include "super.h" #include "super.h"
#include "symlink.h" #include "symlink.h"
#include "refcounttree.h"
#include "buffer_head_io.h" #include "buffer_head_io.h"
...@@ -126,8 +127,8 @@ static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock, ...@@ -126,8 +127,8 @@ static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock,
return err; return err;
} }
static int ocfs2_get_block(struct inode *inode, sector_t iblock, int ocfs2_get_block(struct inode *inode, sector_t iblock,
struct buffer_head *bh_result, int create) struct buffer_head *bh_result, int create)
{ {
int err = 0; int err = 0;
unsigned int ext_flags; unsigned int ext_flags;
...@@ -590,6 +591,8 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock, ...@@ -590,6 +591,8 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock,
goto bail; goto bail;
} }
/* We should already CoW the refcounted extent. */
BUG_ON(ext_flags & OCFS2_EXT_REFCOUNTED);
/* /*
* get_more_blocks() expects us to describe a hole by clearing * get_more_blocks() expects us to describe a hole by clearing
* the mapped bit on bh_result(). * the mapped bit on bh_result().
...@@ -687,6 +690,10 @@ static ssize_t ocfs2_direct_IO(int rw, ...@@ -687,6 +690,10 @@ static ssize_t ocfs2_direct_IO(int rw,
if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
return 0; return 0;
/* Fallback to buffered I/O if we are appending. */
if (i_size_read(inode) <= offset)
return 0;
ret = blockdev_direct_IO_no_locking(rw, iocb, inode, ret = blockdev_direct_IO_no_locking(rw, iocb, inode,
inode->i_sb->s_bdev, iov, offset, inode->i_sb->s_bdev, iov, offset,
nr_segs, nr_segs,
...@@ -1259,7 +1266,8 @@ static int ocfs2_write_cluster(struct address_space *mapping, ...@@ -1259,7 +1266,8 @@ static int ocfs2_write_cluster(struct address_space *mapping,
goto out; goto out;
} }
} else if (unwritten) { } else if (unwritten) {
ocfs2_init_dinode_extent_tree(&et, inode, wc->w_di_bh); ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode),
wc->w_di_bh);
ret = ocfs2_mark_extent_written(inode, &et, ret = ocfs2_mark_extent_written(inode, &et,
wc->w_handle, cpos, 1, phys, wc->w_handle, cpos, 1, phys,
meta_ac, &wc->w_dealloc); meta_ac, &wc->w_dealloc);
...@@ -1448,6 +1456,9 @@ static int ocfs2_populate_write_desc(struct inode *inode, ...@@ -1448,6 +1456,9 @@ static int ocfs2_populate_write_desc(struct inode *inode,
goto out; goto out;
} }
/* We should already CoW the refcountd extent. */
BUG_ON(ext_flags & OCFS2_EXT_REFCOUNTED);
/* /*
* Assume worst case - that we're writing in * Assume worst case - that we're writing in
* the middle of the extent. * the middle of the extent.
...@@ -1528,7 +1539,7 @@ static int ocfs2_write_begin_inline(struct address_space *mapping, ...@@ -1528,7 +1539,7 @@ static int ocfs2_write_begin_inline(struct address_space *mapping,
goto out; goto out;
} }
ret = ocfs2_journal_access_di(handle, inode, wc->w_di_bh, ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), wc->w_di_bh,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
if (ret) { if (ret) {
ocfs2_commit_trans(osb, handle); ocfs2_commit_trans(osb, handle);
...@@ -1699,6 +1710,19 @@ int ocfs2_write_begin_nolock(struct address_space *mapping, ...@@ -1699,6 +1710,19 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
goto out; goto out;
} }
ret = ocfs2_check_range_for_refcount(inode, pos, len);
if (ret < 0) {
mlog_errno(ret);
goto out;
} else if (ret == 1) {
ret = ocfs2_refcount_cow(inode, di_bh,
wc->w_cpos, wc->w_clen, UINT_MAX);
if (ret) {
mlog_errno(ret);
goto out;
}
}
ret = ocfs2_populate_write_desc(inode, wc, &clusters_to_alloc, ret = ocfs2_populate_write_desc(inode, wc, &clusters_to_alloc,
&extents_to_split); &extents_to_split);
if (ret) { if (ret) {
...@@ -1726,7 +1750,8 @@ int ocfs2_write_begin_nolock(struct address_space *mapping, ...@@ -1726,7 +1750,8 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
(long long)i_size_read(inode), le32_to_cpu(di->i_clusters), (long long)i_size_read(inode), le32_to_cpu(di->i_clusters),
clusters_to_alloc, extents_to_split); clusters_to_alloc, extents_to_split);
ocfs2_init_dinode_extent_tree(&et, inode, wc->w_di_bh); ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode),
wc->w_di_bh);
ret = ocfs2_lock_allocators(inode, &et, ret = ocfs2_lock_allocators(inode, &et,
clusters_to_alloc, extents_to_split, clusters_to_alloc, extents_to_split,
&data_ac, &meta_ac); &data_ac, &meta_ac);
...@@ -1773,7 +1798,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping, ...@@ -1773,7 +1798,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
* We don't want this to fail in ocfs2_write_end(), so do it * We don't want this to fail in ocfs2_write_end(), so do it
* here. * here.
*/ */
ret = ocfs2_journal_access_di(handle, inode, wc->w_di_bh, ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), wc->w_di_bh,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
......
...@@ -57,6 +57,8 @@ int ocfs2_read_inline_data(struct inode *inode, struct page *page, ...@@ -57,6 +57,8 @@ int ocfs2_read_inline_data(struct inode *inode, struct page *page,
struct buffer_head *di_bh); struct buffer_head *di_bh);
int ocfs2_size_fits_inline_data(struct buffer_head *di_bh, u64 new_size); int ocfs2_size_fits_inline_data(struct buffer_head *di_bh, u64 new_size);
int ocfs2_get_block(struct inode *inode, sector_t iblock,
struct buffer_head *bh_result, int create);
/* all ocfs2_dio_end_io()'s fault */ /* all ocfs2_dio_end_io()'s fault */
#define ocfs2_iocb_is_rw_locked(iocb) \ #define ocfs2_iocb_is_rw_locked(iocb) \
test_bit(0, (unsigned long *)&iocb->private) test_bit(0, (unsigned long *)&iocb->private)
......
...@@ -52,12 +52,12 @@ enum ocfs2_state_bits { ...@@ -52,12 +52,12 @@ enum ocfs2_state_bits {
BUFFER_FNS(NeedsValidate, needs_validate); BUFFER_FNS(NeedsValidate, needs_validate);
int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh, int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh,
struct inode *inode) struct ocfs2_caching_info *ci)
{ {
int ret = 0; int ret = 0;
mlog_entry("(bh->b_blocknr = %llu, inode=%p)\n", mlog_entry("(bh->b_blocknr = %llu, ci=%p)\n",
(unsigned long long)bh->b_blocknr, inode); (unsigned long long)bh->b_blocknr, ci);
BUG_ON(bh->b_blocknr < OCFS2_SUPER_BLOCK_BLKNO); BUG_ON(bh->b_blocknr < OCFS2_SUPER_BLOCK_BLKNO);
BUG_ON(buffer_jbd(bh)); BUG_ON(buffer_jbd(bh));
...@@ -70,7 +70,7 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh, ...@@ -70,7 +70,7 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh,
goto out; goto out;
} }
mutex_lock(&OCFS2_I(inode)->ip_io_mutex); ocfs2_metadata_cache_io_lock(ci);
lock_buffer(bh); lock_buffer(bh);
set_buffer_uptodate(bh); set_buffer_uptodate(bh);
...@@ -85,7 +85,7 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh, ...@@ -85,7 +85,7 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh,
wait_on_buffer(bh); wait_on_buffer(bh);
if (buffer_uptodate(bh)) { if (buffer_uptodate(bh)) {
ocfs2_set_buffer_uptodate(inode, bh); ocfs2_set_buffer_uptodate(ci, bh);
} else { } else {
/* We don't need to remove the clustered uptodate /* We don't need to remove the clustered uptodate
* information for this bh as it's not marked locally * information for this bh as it's not marked locally
...@@ -94,7 +94,7 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh, ...@@ -94,7 +94,7 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh,
put_bh(bh); put_bh(bh);
} }
mutex_unlock(&OCFS2_I(inode)->ip_io_mutex); ocfs2_metadata_cache_io_unlock(ci);
out: out:
mlog_exit(ret); mlog_exit(ret);
return ret; return ret;
...@@ -177,7 +177,7 @@ int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block, ...@@ -177,7 +177,7 @@ int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block,
return status; return status;
} }
int ocfs2_read_blocks(struct inode *inode, u64 block, int nr, int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,
struct buffer_head *bhs[], int flags, struct buffer_head *bhs[], int flags,
int (*validate)(struct super_block *sb, int (*validate)(struct super_block *sb,
struct buffer_head *bh)) struct buffer_head *bh))
...@@ -185,11 +185,12 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr, ...@@ -185,11 +185,12 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
int status = 0; int status = 0;
int i, ignore_cache = 0; int i, ignore_cache = 0;
struct buffer_head *bh; struct buffer_head *bh;
struct super_block *sb = ocfs2_metadata_cache_get_super(ci);
mlog_entry("(inode=%p, block=(%llu), nr=(%d), flags=%d)\n", mlog_entry("(ci=%p, block=(%llu), nr=(%d), flags=%d)\n",
inode, (unsigned long long)block, nr, flags); ci, (unsigned long long)block, nr, flags);
BUG_ON(!inode); BUG_ON(!ci);
BUG_ON((flags & OCFS2_BH_READAHEAD) && BUG_ON((flags & OCFS2_BH_READAHEAD) &&
(flags & OCFS2_BH_IGNORE_CACHE)); (flags & OCFS2_BH_IGNORE_CACHE));
...@@ -212,12 +213,12 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr, ...@@ -212,12 +213,12 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
goto bail; goto bail;
} }
mutex_lock(&OCFS2_I(inode)->ip_io_mutex); ocfs2_metadata_cache_io_lock(ci);
for (i = 0 ; i < nr ; i++) { for (i = 0 ; i < nr ; i++) {
if (bhs[i] == NULL) { if (bhs[i] == NULL) {
bhs[i] = sb_getblk(inode->i_sb, block++); bhs[i] = sb_getblk(sb, block++);
if (bhs[i] == NULL) { if (bhs[i] == NULL) {
mutex_unlock(&OCFS2_I(inode)->ip_io_mutex); ocfs2_metadata_cache_io_unlock(ci);
status = -EIO; status = -EIO;
mlog_errno(status); mlog_errno(status);
goto bail; goto bail;
...@@ -250,11 +251,11 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr, ...@@ -250,11 +251,11 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
* before our is-it-in-flight check. * before our is-it-in-flight check.
*/ */
if (!ignore_cache && !ocfs2_buffer_uptodate(inode, bh)) { if (!ignore_cache && !ocfs2_buffer_uptodate(ci, bh)) {
mlog(ML_UPTODATE, mlog(ML_UPTODATE,
"bh (%llu), inode %llu not uptodate\n", "bh (%llu), owner %llu not uptodate\n",
(unsigned long long)bh->b_blocknr, (unsigned long long)bh->b_blocknr,
(unsigned long long)OCFS2_I(inode)->ip_blkno); (unsigned long long)ocfs2_metadata_cache_owner(ci));
/* We're using ignore_cache here to say /* We're using ignore_cache here to say
* "go to disk" */ * "go to disk" */
ignore_cache = 1; ignore_cache = 1;
...@@ -283,7 +284,7 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr, ...@@ -283,7 +284,7 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
* previously submitted request than we are * previously submitted request than we are
* done here. */ * done here. */
if ((flags & OCFS2_BH_READAHEAD) if ((flags & OCFS2_BH_READAHEAD)
&& ocfs2_buffer_read_ahead(inode, bh)) && ocfs2_buffer_read_ahead(ci, bh))
continue; continue;
lock_buffer(bh); lock_buffer(bh);
...@@ -305,7 +306,7 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr, ...@@ -305,7 +306,7 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
* buffer lock. */ * buffer lock. */
if (!(flags & OCFS2_BH_IGNORE_CACHE) if (!(flags & OCFS2_BH_IGNORE_CACHE)
&& !(flags & OCFS2_BH_READAHEAD) && !(flags & OCFS2_BH_READAHEAD)
&& ocfs2_buffer_uptodate(inode, bh)) { && ocfs2_buffer_uptodate(ci, bh)) {
unlock_buffer(bh); unlock_buffer(bh);
continue; continue;
} }
...@@ -327,7 +328,7 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr, ...@@ -327,7 +328,7 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
if (!(flags & OCFS2_BH_READAHEAD)) { if (!(flags & OCFS2_BH_READAHEAD)) {
/* We know this can't have changed as we hold the /* We know this can't have changed as we hold the
* inode sem. Avoid doing any work on the bh if the * owner sem. Avoid doing any work on the bh if the
* journal has it. */ * journal has it. */
if (!buffer_jbd(bh)) if (!buffer_jbd(bh))
wait_on_buffer(bh); wait_on_buffer(bh);
...@@ -351,7 +352,7 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr, ...@@ -351,7 +352,7 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
* that better not have changed */ * that better not have changed */
BUG_ON(buffer_jbd(bh)); BUG_ON(buffer_jbd(bh));
clear_buffer_needs_validate(bh); clear_buffer_needs_validate(bh);
status = validate(inode->i_sb, bh); status = validate(sb, bh);
if (status) { if (status) {
put_bh(bh); put_bh(bh);
bhs[i] = NULL; bhs[i] = NULL;
...@@ -363,9 +364,9 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr, ...@@ -363,9 +364,9 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
/* Always set the buffer in the cache, even if it was /* Always set the buffer in the cache, even if it was
* a forced read, or read-ahead which hasn't yet * a forced read, or read-ahead which hasn't yet
* completed. */ * completed. */
ocfs2_set_buffer_uptodate(inode, bh); ocfs2_set_buffer_uptodate(ci, bh);
} }
mutex_unlock(&OCFS2_I(inode)->ip_io_mutex); ocfs2_metadata_cache_io_unlock(ci);
mlog(ML_BH_IO, "block=(%llu), nr=(%d), cached=%s, flags=0x%x\n", mlog(ML_BH_IO, "block=(%llu), nr=(%d), cached=%s, flags=0x%x\n",
(unsigned long long)block, nr, (unsigned long long)block, nr,
...@@ -399,7 +400,7 @@ static void ocfs2_check_super_or_backup(struct super_block *sb, ...@@ -399,7 +400,7 @@ static void ocfs2_check_super_or_backup(struct super_block *sb,
/* /*
* Write super block and backups doesn't need to collaborate with journal, * Write super block and backups doesn't need to collaborate with journal,
* so we don't need to lock ip_io_mutex and inode doesn't need to bea passed * so we don't need to lock ip_io_mutex and ci doesn't need to bea passed
* into this function. * into this function.
*/ */
int ocfs2_write_super_or_backup(struct ocfs2_super *osb, int ocfs2_write_super_or_backup(struct ocfs2_super *osb,
......
...@@ -33,7 +33,7 @@ void ocfs2_end_buffer_io_sync(struct buffer_head *bh, ...@@ -33,7 +33,7 @@ void ocfs2_end_buffer_io_sync(struct buffer_head *bh,
int ocfs2_write_block(struct ocfs2_super *osb, int ocfs2_write_block(struct ocfs2_super *osb,
struct buffer_head *bh, struct buffer_head *bh,
struct inode *inode); struct ocfs2_caching_info *ci);
int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block, int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block,
unsigned int nr, struct buffer_head *bhs[]); unsigned int nr, struct buffer_head *bhs[]);
...@@ -44,7 +44,7 @@ int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block, ...@@ -44,7 +44,7 @@ int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block,
* be set even for a READAHEAD call, as it marks the buffer for later * be set even for a READAHEAD call, as it marks the buffer for later
* validation. * validation.
*/ */
int ocfs2_read_blocks(struct inode *inode, u64 block, int nr, int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,
struct buffer_head *bhs[], int flags, struct buffer_head *bhs[], int flags,
int (*validate)(struct super_block *sb, int (*validate)(struct super_block *sb,
struct buffer_head *bh)); struct buffer_head *bh));
...@@ -55,7 +55,7 @@ int ocfs2_write_super_or_backup(struct ocfs2_super *osb, ...@@ -55,7 +55,7 @@ int ocfs2_write_super_or_backup(struct ocfs2_super *osb,
#define OCFS2_BH_IGNORE_CACHE 1 #define OCFS2_BH_IGNORE_CACHE 1
#define OCFS2_BH_READAHEAD 8 #define OCFS2_BH_READAHEAD 8
static inline int ocfs2_read_block(struct inode *inode, u64 off, static inline int ocfs2_read_block(struct ocfs2_caching_info *ci, u64 off,
struct buffer_head **bh, struct buffer_head **bh,
int (*validate)(struct super_block *sb, int (*validate)(struct super_block *sb,
struct buffer_head *bh)) struct buffer_head *bh))
...@@ -68,7 +68,7 @@ static inline int ocfs2_read_block(struct inode *inode, u64 off, ...@@ -68,7 +68,7 @@ static inline int ocfs2_read_block(struct inode *inode, u64 off,
goto bail; goto bail;
} }
status = ocfs2_read_blocks(inode, off, 1, bh, 0, validate); status = ocfs2_read_blocks(ci, off, 1, bh, 0, validate);
bail: bail:
return status; return status;
......
...@@ -111,6 +111,7 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { ...@@ -111,6 +111,7 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = {
define_mask(EXPORT), define_mask(EXPORT),
define_mask(XATTR), define_mask(XATTR),
define_mask(QUOTA), define_mask(QUOTA),
define_mask(REFCOUNT),
define_mask(ERROR), define_mask(ERROR),
define_mask(NOTICE), define_mask(NOTICE),
define_mask(KTHREAD), define_mask(KTHREAD),
......
...@@ -113,6 +113,7 @@ ...@@ -113,6 +113,7 @@
#define ML_EXPORT 0x0000000010000000ULL /* ocfs2 export operations */ #define ML_EXPORT 0x0000000010000000ULL /* ocfs2 export operations */
#define ML_XATTR 0x0000000020000000ULL /* ocfs2 extended attributes */ #define ML_XATTR 0x0000000020000000ULL /* ocfs2 extended attributes */
#define ML_QUOTA 0x0000000040000000ULL /* ocfs2 quota operations */ #define ML_QUOTA 0x0000000040000000ULL /* ocfs2 quota operations */
#define ML_REFCOUNT 0x0000000080000000ULL /* refcount tree operations */
/* bits that are infrequently given and frequently matched in the high word */ /* bits that are infrequently given and frequently matched in the high word */
#define ML_ERROR 0x0000000100000000ULL /* sent to KERN_ERR */ #define ML_ERROR 0x0000000100000000ULL /* sent to KERN_ERR */
#define ML_NOTICE 0x0000000200000000ULL /* setn to KERN_NOTICE */ #define ML_NOTICE 0x0000000200000000ULL /* setn to KERN_NOTICE */
......
...@@ -176,7 +176,7 @@ static int ocfs2_dx_dir_link_trailer(struct inode *dir, handle_t *handle, ...@@ -176,7 +176,7 @@ static int ocfs2_dx_dir_link_trailer(struct inode *dir, handle_t *handle,
struct ocfs2_dx_root_block *dx_root; struct ocfs2_dx_root_block *dx_root;
struct ocfs2_dir_block_trailer *trailer; struct ocfs2_dir_block_trailer *trailer;
ret = ocfs2_journal_access_dr(handle, dir, dx_root_bh, ret = ocfs2_journal_access_dr(handle, INODE_CACHE(dir), dx_root_bh,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
...@@ -564,7 +564,8 @@ static int ocfs2_read_dir_block_direct(struct inode *dir, u64 phys, ...@@ -564,7 +564,8 @@ static int ocfs2_read_dir_block_direct(struct inode *dir, u64 phys,
int ret; int ret;
struct buffer_head *tmp = *bh; struct buffer_head *tmp = *bh;
ret = ocfs2_read_block(dir, phys, &tmp, ocfs2_validate_dir_block); ret = ocfs2_read_block(INODE_CACHE(dir), phys, &tmp,
ocfs2_validate_dir_block);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
goto out; goto out;
...@@ -622,7 +623,8 @@ static int ocfs2_read_dx_root(struct inode *dir, struct ocfs2_dinode *di, ...@@ -622,7 +623,8 @@ static int ocfs2_read_dx_root(struct inode *dir, struct ocfs2_dinode *di,
u64 blkno = le64_to_cpu(di->i_dx_root); u64 blkno = le64_to_cpu(di->i_dx_root);
struct buffer_head *tmp = *dx_root_bh; struct buffer_head *tmp = *dx_root_bh;
ret = ocfs2_read_block(dir, blkno, &tmp, ocfs2_validate_dx_root); ret = ocfs2_read_block(INODE_CACHE(dir), blkno, &tmp,
ocfs2_validate_dx_root);
/* If ocfs2_read_block() got us a new bh, pass it up. */ /* If ocfs2_read_block() got us a new bh, pass it up. */
if (!ret && !*dx_root_bh) if (!ret && !*dx_root_bh)
...@@ -662,7 +664,8 @@ static int ocfs2_read_dx_leaf(struct inode *dir, u64 blkno, ...@@ -662,7 +664,8 @@ static int ocfs2_read_dx_leaf(struct inode *dir, u64 blkno,
int ret; int ret;
struct buffer_head *tmp = *dx_leaf_bh; struct buffer_head *tmp = *dx_leaf_bh;
ret = ocfs2_read_block(dir, blkno, &tmp, ocfs2_validate_dx_leaf); ret = ocfs2_read_block(INODE_CACHE(dir), blkno, &tmp,
ocfs2_validate_dx_leaf);
/* If ocfs2_read_block() got us a new bh, pass it up. */ /* If ocfs2_read_block() got us a new bh, pass it up. */
if (!ret && !*dx_leaf_bh) if (!ret && !*dx_leaf_bh)
...@@ -680,7 +683,7 @@ static int ocfs2_read_dx_leaves(struct inode *dir, u64 start, int num, ...@@ -680,7 +683,7 @@ static int ocfs2_read_dx_leaves(struct inode *dir, u64 start, int num,
{ {
int ret; int ret;
ret = ocfs2_read_blocks(dir, start, num, dx_leaf_bhs, 0, ret = ocfs2_read_blocks(INODE_CACHE(dir), start, num, dx_leaf_bhs, 0,
ocfs2_validate_dx_leaf); ocfs2_validate_dx_leaf);
if (ret) if (ret)
mlog_errno(ret); mlog_errno(ret);
...@@ -802,7 +805,8 @@ static int ocfs2_dx_dir_lookup_rec(struct inode *inode, ...@@ -802,7 +805,8 @@ static int ocfs2_dx_dir_lookup_rec(struct inode *inode,
struct ocfs2_extent_rec *rec = NULL; struct ocfs2_extent_rec *rec = NULL;
if (el->l_tree_depth) { if (el->l_tree_depth) {
ret = ocfs2_find_leaf(inode, el, major_hash, &eb_bh); ret = ocfs2_find_leaf(INODE_CACHE(inode), el, major_hash,
&eb_bh);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
goto out; goto out;
...@@ -1133,7 +1137,8 @@ int ocfs2_update_entry(struct inode *dir, handle_t *handle, ...@@ -1133,7 +1137,8 @@ int ocfs2_update_entry(struct inode *dir, handle_t *handle,
if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
access = ocfs2_journal_access_di; access = ocfs2_journal_access_di;
ret = access(handle, dir, de_bh, OCFS2_JOURNAL_ACCESS_WRITE); ret = access(handle, INODE_CACHE(dir), de_bh,
OCFS2_JOURNAL_ACCESS_WRITE);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
goto out; goto out;
...@@ -1176,7 +1181,7 @@ static int __ocfs2_delete_entry(handle_t *handle, struct inode *dir, ...@@ -1176,7 +1181,7 @@ static int __ocfs2_delete_entry(handle_t *handle, struct inode *dir,
goto bail; goto bail;
} }
if (de == de_del) { if (de == de_del) {
status = access(handle, dir, bh, status = access(handle, INODE_CACHE(dir), bh,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
if (status < 0) { if (status < 0) {
status = -EIO; status = -EIO;
...@@ -1326,7 +1331,7 @@ static int ocfs2_delete_entry_dx(handle_t *handle, struct inode *dir, ...@@ -1326,7 +1331,7 @@ static int ocfs2_delete_entry_dx(handle_t *handle, struct inode *dir,
* the entry count needs to be updated. Also, we might be * the entry count needs to be updated. Also, we might be
* adding to the start of the free list. * adding to the start of the free list.
*/ */
ret = ocfs2_journal_access_dr(handle, dir, dx_root_bh, ret = ocfs2_journal_access_dr(handle, INODE_CACHE(dir), dx_root_bh,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
...@@ -1334,7 +1339,7 @@ static int ocfs2_delete_entry_dx(handle_t *handle, struct inode *dir, ...@@ -1334,7 +1339,7 @@ static int ocfs2_delete_entry_dx(handle_t *handle, struct inode *dir,
} }
if (!ocfs2_dx_root_inline(dx_root)) { if (!ocfs2_dx_root_inline(dx_root)) {
ret = ocfs2_journal_access_dl(handle, dir, ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir),
lookup->dl_dx_leaf_bh, lookup->dl_dx_leaf_bh,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
if (ret) { if (ret) {
...@@ -1493,7 +1498,7 @@ static int __ocfs2_dx_dir_leaf_insert(struct inode *dir, handle_t *handle, ...@@ -1493,7 +1498,7 @@ static int __ocfs2_dx_dir_leaf_insert(struct inode *dir, handle_t *handle,
int ret; int ret;
struct ocfs2_dx_leaf *dx_leaf; struct ocfs2_dx_leaf *dx_leaf;
ret = ocfs2_journal_access_dl(handle, dir, dx_leaf_bh, ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir), dx_leaf_bh,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
...@@ -1523,7 +1528,7 @@ static int ocfs2_dx_dir_insert(struct inode *dir, handle_t *handle, ...@@ -1523,7 +1528,7 @@ static int ocfs2_dx_dir_insert(struct inode *dir, handle_t *handle,
struct ocfs2_dx_root_block *dx_root; struct ocfs2_dx_root_block *dx_root;
struct buffer_head *dx_root_bh = lookup->dl_dx_root_bh; struct buffer_head *dx_root_bh = lookup->dl_dx_root_bh;
ret = ocfs2_journal_access_dr(handle, dir, dx_root_bh, ret = ocfs2_journal_access_dr(handle, INODE_CACHE(dir), dx_root_bh,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
...@@ -1645,11 +1650,13 @@ int __ocfs2_add_entry(handle_t *handle, ...@@ -1645,11 +1650,13 @@ int __ocfs2_add_entry(handle_t *handle,
*/ */
if (ocfs2_free_list_at_root(lookup)) { if (ocfs2_free_list_at_root(lookup)) {
bh = lookup->dl_dx_root_bh; bh = lookup->dl_dx_root_bh;
retval = ocfs2_journal_access_dr(handle, dir, bh, retval = ocfs2_journal_access_dr(handle,
INODE_CACHE(dir), bh,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
} else { } else {
bh = lookup->dl_prev_leaf_bh; bh = lookup->dl_prev_leaf_bh;
retval = ocfs2_journal_access_db(handle, dir, bh, retval = ocfs2_journal_access_db(handle,
INODE_CACHE(dir), bh,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
} }
if (retval) { if (retval) {
...@@ -1700,11 +1707,13 @@ int __ocfs2_add_entry(handle_t *handle, ...@@ -1700,11 +1707,13 @@ int __ocfs2_add_entry(handle_t *handle,
} }
if (insert_bh == parent_fe_bh) if (insert_bh == parent_fe_bh)
status = ocfs2_journal_access_di(handle, dir, status = ocfs2_journal_access_di(handle,
INODE_CACHE(dir),
insert_bh, insert_bh,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
else { else {
status = ocfs2_journal_access_db(handle, dir, status = ocfs2_journal_access_db(handle,
INODE_CACHE(dir),
insert_bh, insert_bh,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
...@@ -2280,7 +2289,7 @@ static int ocfs2_fill_new_dir_id(struct ocfs2_super *osb, ...@@ -2280,7 +2289,7 @@ static int ocfs2_fill_new_dir_id(struct ocfs2_super *osb,
struct ocfs2_inline_data *data = &di->id2.i_data; struct ocfs2_inline_data *data = &di->id2.i_data;
unsigned int size = le16_to_cpu(data->id_count); unsigned int size = le16_to_cpu(data->id_count);
ret = ocfs2_journal_access_di(handle, inode, di_bh, ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
...@@ -2332,9 +2341,9 @@ static int ocfs2_fill_new_dir_el(struct ocfs2_super *osb, ...@@ -2332,9 +2341,9 @@ static int ocfs2_fill_new_dir_el(struct ocfs2_super *osb,
goto bail; goto bail;
} }
ocfs2_set_new_buffer_uptodate(inode, new_bh); ocfs2_set_new_buffer_uptodate(INODE_CACHE(inode), new_bh);
status = ocfs2_journal_access_db(handle, inode, new_bh, status = ocfs2_journal_access_db(handle, INODE_CACHE(inode), new_bh,
OCFS2_JOURNAL_ACCESS_CREATE); OCFS2_JOURNAL_ACCESS_CREATE);
if (status < 0) { if (status < 0) {
mlog_errno(status); mlog_errno(status);
...@@ -2418,9 +2427,9 @@ static int ocfs2_dx_dir_attach_index(struct ocfs2_super *osb, ...@@ -2418,9 +2427,9 @@ static int ocfs2_dx_dir_attach_index(struct ocfs2_super *osb,
ret = -EIO; ret = -EIO;
goto out; goto out;
} }
ocfs2_set_new_buffer_uptodate(dir, dx_root_bh); ocfs2_set_new_buffer_uptodate(INODE_CACHE(dir), dx_root_bh);
ret = ocfs2_journal_access_dr(handle, dir, dx_root_bh, ret = ocfs2_journal_access_dr(handle, INODE_CACHE(dir), dx_root_bh,
OCFS2_JOURNAL_ACCESS_CREATE); OCFS2_JOURNAL_ACCESS_CREATE);
if (ret < 0) { if (ret < 0) {
mlog_errno(ret); mlog_errno(ret);
...@@ -2454,7 +2463,7 @@ static int ocfs2_dx_dir_attach_index(struct ocfs2_super *osb, ...@@ -2454,7 +2463,7 @@ static int ocfs2_dx_dir_attach_index(struct ocfs2_super *osb,
if (ret) if (ret)
mlog_errno(ret); mlog_errno(ret);
ret = ocfs2_journal_access_di(handle, dir, di_bh, ret = ocfs2_journal_access_di(handle, INODE_CACHE(dir), di_bh,
OCFS2_JOURNAL_ACCESS_CREATE); OCFS2_JOURNAL_ACCESS_CREATE);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
...@@ -2495,9 +2504,9 @@ static int ocfs2_dx_dir_format_cluster(struct ocfs2_super *osb, ...@@ -2495,9 +2504,9 @@ static int ocfs2_dx_dir_format_cluster(struct ocfs2_super *osb,
} }
dx_leaves[i] = bh; dx_leaves[i] = bh;
ocfs2_set_new_buffer_uptodate(dir, bh); ocfs2_set_new_buffer_uptodate(INODE_CACHE(dir), bh);
ret = ocfs2_journal_access_dl(handle, dir, bh, ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir), bh,
OCFS2_JOURNAL_ACCESS_CREATE); OCFS2_JOURNAL_ACCESS_CREATE);
if (ret < 0) { if (ret < 0) {
mlog_errno(ret); mlog_errno(ret);
...@@ -2582,7 +2591,6 @@ static int ocfs2_dx_dir_new_cluster(struct inode *dir, ...@@ -2582,7 +2591,6 @@ static int ocfs2_dx_dir_new_cluster(struct inode *dir,
{ {
int ret; int ret;
u64 phys_blkno; u64 phys_blkno;
struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
ret = __ocfs2_dx_dir_new_cluster(dir, cpos, handle, data_ac, dx_leaves, ret = __ocfs2_dx_dir_new_cluster(dir, cpos, handle, data_ac, dx_leaves,
num_dx_leaves, &phys_blkno); num_dx_leaves, &phys_blkno);
...@@ -2591,7 +2599,7 @@ static int ocfs2_dx_dir_new_cluster(struct inode *dir, ...@@ -2591,7 +2599,7 @@ static int ocfs2_dx_dir_new_cluster(struct inode *dir,
goto out; goto out;
} }
ret = ocfs2_insert_extent(osb, handle, dir, et, cpos, phys_blkno, 1, 0, ret = ocfs2_insert_extent(handle, et, cpos, phys_blkno, 1, 0,
meta_ac); meta_ac);
if (ret) if (ret)
mlog_errno(ret); mlog_errno(ret);
...@@ -2895,7 +2903,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh, ...@@ -2895,7 +2903,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
struct ocfs2_extent_tree dx_et; struct ocfs2_extent_tree dx_et;
int did_quota = 0, bytes_allocated = 0; int did_quota = 0, bytes_allocated = 0;
ocfs2_init_dinode_extent_tree(&et, dir, di_bh); ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(dir), di_bh);
alloc = ocfs2_clusters_for_bytes(sb, bytes); alloc = ocfs2_clusters_for_bytes(sb, bytes);
dx_alloc = 0; dx_alloc = 0;
...@@ -3005,9 +3013,9 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh, ...@@ -3005,9 +3013,9 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
goto out_commit; goto out_commit;
} }
ocfs2_set_new_buffer_uptodate(dir, dirdata_bh); ocfs2_set_new_buffer_uptodate(INODE_CACHE(dir), dirdata_bh);
ret = ocfs2_journal_access_db(handle, dir, dirdata_bh, ret = ocfs2_journal_access_db(handle, INODE_CACHE(dir), dirdata_bh,
OCFS2_JOURNAL_ACCESS_CREATE); OCFS2_JOURNAL_ACCESS_CREATE);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
...@@ -3060,7 +3068,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh, ...@@ -3060,7 +3068,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
* We let the later dirent insert modify c/mtime - to the user * We let the later dirent insert modify c/mtime - to the user
* the data hasn't changed. * the data hasn't changed.
*/ */
ret = ocfs2_journal_access_di(handle, dir, di_bh, ret = ocfs2_journal_access_di(handle, INODE_CACHE(dir), di_bh,
OCFS2_JOURNAL_ACCESS_CREATE); OCFS2_JOURNAL_ACCESS_CREATE);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
...@@ -3085,7 +3093,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh, ...@@ -3085,7 +3093,7 @@ 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 * This should never fail as our extent list is empty and all
* related blocks have been journaled already. * related blocks have been journaled already.
*/ */
ret = ocfs2_insert_extent(osb, handle, dir, &et, 0, blkno, len, ret = ocfs2_insert_extent(handle, &et, 0, blkno, len,
0, NULL); 0, NULL);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
...@@ -3117,8 +3125,10 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh, ...@@ -3117,8 +3125,10 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
ocfs2_dx_dir_index_root_block(dir, dx_root_bh, ocfs2_dx_dir_index_root_block(dir, dx_root_bh,
dirdata_bh); dirdata_bh);
} else { } else {
ocfs2_init_dx_root_extent_tree(&dx_et, dir, dx_root_bh); ocfs2_init_dx_root_extent_tree(&dx_et,
ret = ocfs2_insert_extent(osb, handle, dir, &dx_et, 0, INODE_CACHE(dir),
dx_root_bh);
ret = ocfs2_insert_extent(handle, &dx_et, 0,
dx_insert_blkno, 1, 0, NULL); dx_insert_blkno, 1, 0, NULL);
if (ret) if (ret)
mlog_errno(ret); mlog_errno(ret);
...@@ -3138,7 +3148,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh, ...@@ -3138,7 +3148,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
} }
blkno = ocfs2_clusters_to_blocks(dir->i_sb, bit_off); blkno = ocfs2_clusters_to_blocks(dir->i_sb, bit_off);
ret = ocfs2_insert_extent(osb, handle, dir, &et, 1, ret = ocfs2_insert_extent(handle, &et, 1,
blkno, len, 0, NULL); blkno, len, 0, NULL);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
...@@ -3337,8 +3347,9 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, ...@@ -3337,8 +3347,9 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
spin_lock(&OCFS2_I(dir)->ip_lock); spin_lock(&OCFS2_I(dir)->ip_lock);
if (dir_i_size == ocfs2_clusters_to_bytes(sb, OCFS2_I(dir)->ip_clusters)) { if (dir_i_size == ocfs2_clusters_to_bytes(sb, OCFS2_I(dir)->ip_clusters)) {
spin_unlock(&OCFS2_I(dir)->ip_lock); spin_unlock(&OCFS2_I(dir)->ip_lock);
ocfs2_init_dinode_extent_tree(&et, dir, parent_fe_bh); ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(dir),
num_free_extents = ocfs2_num_free_extents(osb, dir, &et); parent_fe_bh);
num_free_extents = ocfs2_num_free_extents(osb, &et);
if (num_free_extents < 0) { if (num_free_extents < 0) {
status = num_free_extents; status = num_free_extents;
mlog_errno(status); mlog_errno(status);
...@@ -3387,9 +3398,9 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, ...@@ -3387,9 +3398,9 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
goto bail; goto bail;
} }
ocfs2_set_new_buffer_uptodate(dir, new_bh); ocfs2_set_new_buffer_uptodate(INODE_CACHE(dir), new_bh);
status = ocfs2_journal_access_db(handle, dir, new_bh, status = ocfs2_journal_access_db(handle, INODE_CACHE(dir), new_bh,
OCFS2_JOURNAL_ACCESS_CREATE); OCFS2_JOURNAL_ACCESS_CREATE);
if (status < 0) { if (status < 0) {
mlog_errno(status); mlog_errno(status);
...@@ -3829,7 +3840,7 @@ static int ocfs2_dx_dir_rebalance(struct ocfs2_super *osb, struct inode *dir, ...@@ -3829,7 +3840,7 @@ static int ocfs2_dx_dir_rebalance(struct ocfs2_super *osb, struct inode *dir,
(unsigned long long)OCFS2_I(dir)->ip_blkno, (unsigned long long)OCFS2_I(dir)->ip_blkno,
(unsigned long long)leaf_blkno, insert_hash); (unsigned long long)leaf_blkno, insert_hash);
ocfs2_init_dx_root_extent_tree(&et, dir, dx_root_bh); ocfs2_init_dx_root_extent_tree(&et, INODE_CACHE(dir), dx_root_bh);
dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data; dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
/* /*
...@@ -3885,7 +3896,7 @@ static int ocfs2_dx_dir_rebalance(struct ocfs2_super *osb, struct inode *dir, ...@@ -3885,7 +3896,7 @@ static int ocfs2_dx_dir_rebalance(struct ocfs2_super *osb, struct inode *dir,
} }
did_quota = 1; did_quota = 1;
ret = ocfs2_journal_access_dl(handle, dir, dx_leaf_bh, ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir), dx_leaf_bh,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
...@@ -3949,7 +3960,8 @@ static int ocfs2_dx_dir_rebalance(struct ocfs2_super *osb, struct inode *dir, ...@@ -3949,7 +3960,8 @@ static int ocfs2_dx_dir_rebalance(struct ocfs2_super *osb, struct inode *dir,
} }
for (i = 0; i < num_dx_leaves; i++) { for (i = 0; i < num_dx_leaves; i++) {
ret = ocfs2_journal_access_dl(handle, dir, orig_dx_leaves[i], ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir),
orig_dx_leaves[i],
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
...@@ -4165,7 +4177,7 @@ static int ocfs2_expand_inline_dx_root(struct inode *dir, ...@@ -4165,7 +4177,7 @@ static int ocfs2_expand_inline_dx_root(struct inode *dir,
* failure to add the dx_root_bh to the journal won't result * failure to add the dx_root_bh to the journal won't result
* us losing clusters. * us losing clusters.
*/ */
ret = ocfs2_journal_access_dr(handle, dir, dx_root_bh, ret = ocfs2_journal_access_dr(handle, INODE_CACHE(dir), dx_root_bh,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
...@@ -4207,9 +4219,8 @@ static int ocfs2_expand_inline_dx_root(struct inode *dir, ...@@ -4207,9 +4219,8 @@ static int ocfs2_expand_inline_dx_root(struct inode *dir,
/* This should never fail considering we start with an empty /* This should never fail considering we start with an empty
* dx_root. */ * dx_root. */
ocfs2_init_dx_root_extent_tree(&et, dir, dx_root_bh); ocfs2_init_dx_root_extent_tree(&et, INODE_CACHE(dir), dx_root_bh);
ret = ocfs2_insert_extent(osb, handle, dir, &et, 0, ret = ocfs2_insert_extent(handle, &et, 0, insert_blkno, 1, 0, NULL);
insert_blkno, 1, 0, NULL);
if (ret) if (ret)
mlog_errno(ret); mlog_errno(ret);
did_quota = 0; did_quota = 0;
...@@ -4469,7 +4480,7 @@ static int ocfs2_dx_dir_remove_index(struct inode *dir, ...@@ -4469,7 +4480,7 @@ static int ocfs2_dx_dir_remove_index(struct inode *dir,
goto out_unlock; goto out_unlock;
} }
ret = ocfs2_journal_access_di(handle, dir, di_bh, ret = ocfs2_journal_access_di(handle, INODE_CACHE(dir), di_bh,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
...@@ -4532,7 +4543,7 @@ int ocfs2_dx_dir_truncate(struct inode *dir, struct buffer_head *di_bh) ...@@ -4532,7 +4543,7 @@ int ocfs2_dx_dir_truncate(struct inode *dir, struct buffer_head *di_bh)
if (ocfs2_dx_root_inline(dx_root)) if (ocfs2_dx_root_inline(dx_root))
goto remove_index; goto remove_index;
ocfs2_init_dx_root_extent_tree(&et, dir, dx_root_bh); ocfs2_init_dx_root_extent_tree(&et, INODE_CACHE(dir), dx_root_bh);
/* XXX: What if dr_clusters is too large? */ /* XXX: What if dr_clusters is too large? */
while (le32_to_cpu(dx_root->dr_clusters)) { while (le32_to_cpu(dx_root->dr_clusters)) {
...@@ -4565,7 +4576,7 @@ int ocfs2_dx_dir_truncate(struct inode *dir, struct buffer_head *di_bh) ...@@ -4565,7 +4576,7 @@ int ocfs2_dx_dir_truncate(struct inode *dir, struct buffer_head *di_bh)
goto out; goto out;
} }
ocfs2_remove_from_cache(dir, dx_root_bh); ocfs2_remove_from_cache(INODE_CACHE(dir), dx_root_bh);
out: out:
ocfs2_schedule_truncate_log_flush(osb, 1); ocfs2_schedule_truncate_log_flush(osb, 1);
ocfs2_run_deallocs(osb, &dealloc); ocfs2_run_deallocs(osb, &dealloc);
......
...@@ -212,14 +212,18 @@ static int dlm_purge_lockres(struct dlm_ctxt *dlm, ...@@ -212,14 +212,18 @@ static int dlm_purge_lockres(struct dlm_ctxt *dlm,
spin_lock(&dlm->spinlock); spin_lock(&dlm->spinlock);
} }
spin_lock(&res->spinlock);
if (!list_empty(&res->purge)) { if (!list_empty(&res->purge)) {
mlog(0, "removing lockres %.*s:%p from purgelist, " mlog(0, "removing lockres %.*s:%p from purgelist, "
"master = %d\n", res->lockname.len, res->lockname.name, "master = %d\n", res->lockname.len, res->lockname.name,
res, master); res, master);
list_del_init(&res->purge); list_del_init(&res->purge);
spin_unlock(&res->spinlock);
dlm_lockres_put(res); dlm_lockres_put(res);
dlm->purge_count--; dlm->purge_count--;
} } else
spin_unlock(&res->spinlock);
__dlm_unhash_lockres(res); __dlm_unhash_lockres(res);
/* lockres is not in the hash now. drop the flag and wake up /* lockres is not in the hash now. drop the flag and wake up
......
...@@ -53,6 +53,7 @@ ...@@ -53,6 +53,7 @@
#include "super.h" #include "super.h"
#include "uptodate.h" #include "uptodate.h"
#include "quota.h" #include "quota.h"
#include "refcounttree.h"
#include "buffer_head_io.h" #include "buffer_head_io.h"
...@@ -110,6 +111,11 @@ static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb, ...@@ -110,6 +111,11 @@ static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb,
static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres); static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres);
static int ocfs2_check_refcount_downconvert(struct ocfs2_lock_res *lockres,
int new_level);
static int ocfs2_refcount_convert_worker(struct ocfs2_lock_res *lockres,
int blocking);
#define mlog_meta_lvb(__level, __lockres) ocfs2_dump_meta_lvb_info(__level, __PRETTY_FUNCTION__, __LINE__, __lockres) #define mlog_meta_lvb(__level, __lockres) ocfs2_dump_meta_lvb_info(__level, __PRETTY_FUNCTION__, __LINE__, __lockres)
/* This aids in debugging situations where a bad LVB might be involved. */ /* This aids in debugging situations where a bad LVB might be involved. */
...@@ -278,6 +284,12 @@ static struct ocfs2_lock_res_ops ocfs2_qinfo_lops = { ...@@ -278,6 +284,12 @@ static struct ocfs2_lock_res_ops ocfs2_qinfo_lops = {
.flags = LOCK_TYPE_REQUIRES_REFRESH | LOCK_TYPE_USES_LVB, .flags = LOCK_TYPE_REQUIRES_REFRESH | LOCK_TYPE_USES_LVB,
}; };
static struct ocfs2_lock_res_ops ocfs2_refcount_block_lops = {
.check_downconvert = ocfs2_check_refcount_downconvert,
.downconvert_worker = ocfs2_refcount_convert_worker,
.flags = 0,
};
static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres) static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres)
{ {
return lockres->l_type == OCFS2_LOCK_TYPE_META || return lockres->l_type == OCFS2_LOCK_TYPE_META ||
...@@ -306,6 +318,12 @@ static inline struct ocfs2_mem_dqinfo *ocfs2_lock_res_qinfo(struct ocfs2_lock_re ...@@ -306,6 +318,12 @@ static inline struct ocfs2_mem_dqinfo *ocfs2_lock_res_qinfo(struct ocfs2_lock_re
return (struct ocfs2_mem_dqinfo *)lockres->l_priv; return (struct ocfs2_mem_dqinfo *)lockres->l_priv;
} }
static inline struct ocfs2_refcount_tree *
ocfs2_lock_res_refcount_tree(struct ocfs2_lock_res *res)
{
return container_of(res, struct ocfs2_refcount_tree, rf_lockres);
}
static inline struct ocfs2_super *ocfs2_get_lockres_osb(struct ocfs2_lock_res *lockres) static inline struct ocfs2_super *ocfs2_get_lockres_osb(struct ocfs2_lock_res *lockres)
{ {
if (lockres->l_ops->get_osb) if (lockres->l_ops->get_osb)
...@@ -693,6 +711,17 @@ void ocfs2_qinfo_lock_res_init(struct ocfs2_lock_res *lockres, ...@@ -693,6 +711,17 @@ void ocfs2_qinfo_lock_res_init(struct ocfs2_lock_res *lockres,
info); info);
} }
void ocfs2_refcount_lock_res_init(struct ocfs2_lock_res *lockres,
struct ocfs2_super *osb, u64 ref_blkno,
unsigned int generation)
{
ocfs2_lock_res_init_once(lockres);
ocfs2_build_lock_name(OCFS2_LOCK_TYPE_REFCOUNT, ref_blkno,
generation, lockres->l_name);
ocfs2_lock_res_init_common(osb, lockres, OCFS2_LOCK_TYPE_REFCOUNT,
&ocfs2_refcount_block_lops, osb);
}
void ocfs2_lock_res_free(struct ocfs2_lock_res *res) void ocfs2_lock_res_free(struct ocfs2_lock_res *res)
{ {
mlog_entry_void(); mlog_entry_void();
...@@ -1548,8 +1577,10 @@ int ocfs2_rw_lock(struct inode *inode, int write) ...@@ -1548,8 +1577,10 @@ int ocfs2_rw_lock(struct inode *inode, int write)
(unsigned long long)OCFS2_I(inode)->ip_blkno, (unsigned long long)OCFS2_I(inode)->ip_blkno,
write ? "EXMODE" : "PRMODE"); write ? "EXMODE" : "PRMODE");
if (ocfs2_mount_local(osb)) if (ocfs2_mount_local(osb)) {
mlog_exit(0);
return 0; return 0;
}
lockres = &OCFS2_I(inode)->ip_rw_lockres; lockres = &OCFS2_I(inode)->ip_rw_lockres;
...@@ -2127,7 +2158,7 @@ static int ocfs2_inode_lock_update(struct inode *inode, ...@@ -2127,7 +2158,7 @@ static int ocfs2_inode_lock_update(struct inode *inode,
/* This will discard any caching information we might have had /* This will discard any caching information we might have had
* for the inode metadata. */ * for the inode metadata. */
ocfs2_metadata_cache_purge(inode); ocfs2_metadata_cache_purge(INODE_CACHE(inode));
ocfs2_extent_map_trunc(inode, 0); ocfs2_extent_map_trunc(inode, 0);
...@@ -3009,6 +3040,7 @@ static void ocfs2_unlock_ast(void *opaque, int error) ...@@ -3009,6 +3040,7 @@ static void ocfs2_unlock_ast(void *opaque, int error)
"unlock_action %d\n", error, lockres->l_name, "unlock_action %d\n", error, lockres->l_name,
lockres->l_unlock_action); lockres->l_unlock_action);
spin_unlock_irqrestore(&lockres->l_lock, flags); spin_unlock_irqrestore(&lockres->l_lock, flags);
mlog_exit_void();
return; return;
} }
...@@ -3495,11 +3527,11 @@ static int ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres, ...@@ -3495,11 +3527,11 @@ static int ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres,
return UNBLOCK_CONTINUE; return UNBLOCK_CONTINUE;
} }
static int ocfs2_check_meta_downconvert(struct ocfs2_lock_res *lockres, static int ocfs2_ci_checkpointed(struct ocfs2_caching_info *ci,
int new_level) struct ocfs2_lock_res *lockres,
int new_level)
{ {
struct inode *inode = ocfs2_lock_res_inode(lockres); int checkpointed = ocfs2_ci_fully_checkpointed(ci);
int checkpointed = ocfs2_inode_fully_checkpointed(inode);
BUG_ON(new_level != DLM_LOCK_NL && new_level != DLM_LOCK_PR); BUG_ON(new_level != DLM_LOCK_NL && new_level != DLM_LOCK_PR);
BUG_ON(lockres->l_level != DLM_LOCK_EX && !checkpointed); BUG_ON(lockres->l_level != DLM_LOCK_EX && !checkpointed);
...@@ -3507,10 +3539,18 @@ static int ocfs2_check_meta_downconvert(struct ocfs2_lock_res *lockres, ...@@ -3507,10 +3539,18 @@ static int ocfs2_check_meta_downconvert(struct ocfs2_lock_res *lockres,
if (checkpointed) if (checkpointed)
return 1; return 1;
ocfs2_start_checkpoint(OCFS2_SB(inode->i_sb)); ocfs2_start_checkpoint(OCFS2_SB(ocfs2_metadata_cache_get_super(ci)));
return 0; return 0;
} }
static int ocfs2_check_meta_downconvert(struct ocfs2_lock_res *lockres,
int new_level)
{
struct inode *inode = ocfs2_lock_res_inode(lockres);
return ocfs2_ci_checkpointed(INODE_CACHE(inode), lockres, new_level);
}
static void ocfs2_set_meta_lvb(struct ocfs2_lock_res *lockres) static void ocfs2_set_meta_lvb(struct ocfs2_lock_res *lockres)
{ {
struct inode *inode = ocfs2_lock_res_inode(lockres); struct inode *inode = ocfs2_lock_res_inode(lockres);
...@@ -3640,6 +3680,26 @@ static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres, ...@@ -3640,6 +3680,26 @@ static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres,
return UNBLOCK_CONTINUE_POST; return UNBLOCK_CONTINUE_POST;
} }
static int ocfs2_check_refcount_downconvert(struct ocfs2_lock_res *lockres,
int new_level)
{
struct ocfs2_refcount_tree *tree =
ocfs2_lock_res_refcount_tree(lockres);
return ocfs2_ci_checkpointed(&tree->rf_ci, lockres, new_level);
}
static int ocfs2_refcount_convert_worker(struct ocfs2_lock_res *lockres,
int blocking)
{
struct ocfs2_refcount_tree *tree =
ocfs2_lock_res_refcount_tree(lockres);
ocfs2_metadata_cache_purge(&tree->rf_ci);
return UNBLOCK_CONTINUE;
}
static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres) static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres)
{ {
struct ocfs2_qinfo_lvb *lvb; struct ocfs2_qinfo_lvb *lvb;
...@@ -3752,6 +3812,37 @@ int ocfs2_qinfo_lock(struct ocfs2_mem_dqinfo *oinfo, int ex) ...@@ -3752,6 +3812,37 @@ int ocfs2_qinfo_lock(struct ocfs2_mem_dqinfo *oinfo, int ex)
return status; return status;
} }
int ocfs2_refcount_lock(struct ocfs2_refcount_tree *ref_tree, int ex)
{
int status;
int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
struct ocfs2_lock_res *lockres = &ref_tree->rf_lockres;
struct ocfs2_super *osb = lockres->l_priv;
if (ocfs2_is_hard_readonly(osb))
return -EROFS;
if (ocfs2_mount_local(osb))
return 0;
status = ocfs2_cluster_lock(osb, lockres, level, 0, 0);
if (status < 0)
mlog_errno(status);
return status;
}
void ocfs2_refcount_unlock(struct ocfs2_refcount_tree *ref_tree, int ex)
{
int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
struct ocfs2_lock_res *lockres = &ref_tree->rf_lockres;
struct ocfs2_super *osb = lockres->l_priv;
if (!ocfs2_mount_local(osb))
ocfs2_cluster_unlock(osb, lockres, level);
}
/* /*
* This is the filesystem locking protocol. It provides the lock handling * This is the filesystem locking protocol. It provides the lock handling
* hooks for the underlying DLM. It has a maximum version number. * hooks for the underlying DLM. It has a maximum version number.
......
...@@ -101,6 +101,9 @@ void ocfs2_file_lock_res_init(struct ocfs2_lock_res *lockres, ...@@ -101,6 +101,9 @@ void ocfs2_file_lock_res_init(struct ocfs2_lock_res *lockres,
struct ocfs2_mem_dqinfo; struct ocfs2_mem_dqinfo;
void ocfs2_qinfo_lock_res_init(struct ocfs2_lock_res *lockres, void ocfs2_qinfo_lock_res_init(struct ocfs2_lock_res *lockres,
struct ocfs2_mem_dqinfo *info); struct ocfs2_mem_dqinfo *info);
void ocfs2_refcount_lock_res_init(struct ocfs2_lock_res *lockres,
struct ocfs2_super *osb, u64 ref_blkno,
unsigned int generation);
void ocfs2_lock_res_free(struct ocfs2_lock_res *res); void ocfs2_lock_res_free(struct ocfs2_lock_res *res);
int ocfs2_create_new_inode_locks(struct inode *inode); int ocfs2_create_new_inode_locks(struct inode *inode);
int ocfs2_drop_inode_locks(struct inode *inode); int ocfs2_drop_inode_locks(struct inode *inode);
...@@ -148,6 +151,9 @@ int ocfs2_file_lock(struct file *file, int ex, int trylock); ...@@ -148,6 +151,9 @@ int ocfs2_file_lock(struct file *file, int ex, int trylock);
void ocfs2_file_unlock(struct file *file); void ocfs2_file_unlock(struct file *file);
int ocfs2_qinfo_lock(struct ocfs2_mem_dqinfo *oinfo, int ex); int ocfs2_qinfo_lock(struct ocfs2_mem_dqinfo *oinfo, int ex);
void ocfs2_qinfo_unlock(struct ocfs2_mem_dqinfo *oinfo, int ex); void ocfs2_qinfo_unlock(struct ocfs2_mem_dqinfo *oinfo, int ex);
struct ocfs2_refcount_tree;
int ocfs2_refcount_lock(struct ocfs2_refcount_tree *ref_tree, int ex);
void ocfs2_refcount_unlock(struct ocfs2_refcount_tree *ref_tree, int ex);
void ocfs2_mark_lockres_freeing(struct ocfs2_lock_res *lockres); void ocfs2_mark_lockres_freeing(struct ocfs2_lock_res *lockres);
......
...@@ -293,7 +293,7 @@ static int ocfs2_last_eb_is_empty(struct inode *inode, ...@@ -293,7 +293,7 @@ static int ocfs2_last_eb_is_empty(struct inode *inode,
struct ocfs2_extent_block *eb; struct ocfs2_extent_block *eb;
struct ocfs2_extent_list *el; struct ocfs2_extent_list *el;
ret = ocfs2_read_extent_block(inode, last_eb_blk, &eb_bh); ret = ocfs2_read_extent_block(INODE_CACHE(inode), last_eb_blk, &eb_bh);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
goto out; goto out;
...@@ -353,11 +353,11 @@ static int ocfs2_search_for_hole_index(struct ocfs2_extent_list *el, ...@@ -353,11 +353,11 @@ static int ocfs2_search_for_hole_index(struct ocfs2_extent_list *el,
* eb_bh is NULL. Otherwise, eb_bh should point to the extent block * eb_bh is NULL. Otherwise, eb_bh should point to the extent block
* containing el. * containing el.
*/ */
static int ocfs2_figure_hole_clusters(struct inode *inode, int ocfs2_figure_hole_clusters(struct ocfs2_caching_info *ci,
struct ocfs2_extent_list *el, struct ocfs2_extent_list *el,
struct buffer_head *eb_bh, struct buffer_head *eb_bh,
u32 v_cluster, u32 v_cluster,
u32 *num_clusters) u32 *num_clusters)
{ {
int ret, i; int ret, i;
struct buffer_head *next_eb_bh = NULL; struct buffer_head *next_eb_bh = NULL;
...@@ -375,7 +375,7 @@ static int ocfs2_figure_hole_clusters(struct inode *inode, ...@@ -375,7 +375,7 @@ static int ocfs2_figure_hole_clusters(struct inode *inode,
if (le64_to_cpu(eb->h_next_leaf_blk) == 0ULL) if (le64_to_cpu(eb->h_next_leaf_blk) == 0ULL)
goto no_more_extents; goto no_more_extents;
ret = ocfs2_read_extent_block(inode, ret = ocfs2_read_extent_block(ci,
le64_to_cpu(eb->h_next_leaf_blk), le64_to_cpu(eb->h_next_leaf_blk),
&next_eb_bh); &next_eb_bh);
if (ret) { if (ret) {
...@@ -428,7 +428,8 @@ static int ocfs2_get_clusters_nocache(struct inode *inode, ...@@ -428,7 +428,8 @@ static int ocfs2_get_clusters_nocache(struct inode *inode,
tree_height = le16_to_cpu(el->l_tree_depth); tree_height = le16_to_cpu(el->l_tree_depth);
if (tree_height > 0) { if (tree_height > 0) {
ret = ocfs2_find_leaf(inode, el, v_cluster, &eb_bh); ret = ocfs2_find_leaf(INODE_CACHE(inode), el, v_cluster,
&eb_bh);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
goto out; goto out;
...@@ -455,7 +456,8 @@ static int ocfs2_get_clusters_nocache(struct inode *inode, ...@@ -455,7 +456,8 @@ static int ocfs2_get_clusters_nocache(struct inode *inode,
* field. * field.
*/ */
if (hole_len) { if (hole_len) {
ret = ocfs2_figure_hole_clusters(inode, el, eb_bh, ret = ocfs2_figure_hole_clusters(INODE_CACHE(inode),
el, eb_bh,
v_cluster, &len); v_cluster, &len);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
...@@ -539,7 +541,8 @@ static void ocfs2_relative_extent_offsets(struct super_block *sb, ...@@ -539,7 +541,8 @@ static void ocfs2_relative_extent_offsets(struct super_block *sb,
int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster, int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster,
u32 *p_cluster, u32 *num_clusters, u32 *p_cluster, u32 *num_clusters,
struct ocfs2_extent_list *el) struct ocfs2_extent_list *el,
unsigned int *extent_flags)
{ {
int ret = 0, i; int ret = 0, i;
struct buffer_head *eb_bh = NULL; struct buffer_head *eb_bh = NULL;
...@@ -548,7 +551,8 @@ int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster, ...@@ -548,7 +551,8 @@ int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster,
u32 coff; u32 coff;
if (el->l_tree_depth) { if (el->l_tree_depth) {
ret = ocfs2_find_leaf(inode, el, v_cluster, &eb_bh); ret = ocfs2_find_leaf(INODE_CACHE(inode), el, v_cluster,
&eb_bh);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
goto out; goto out;
...@@ -590,6 +594,9 @@ int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster, ...@@ -590,6 +594,9 @@ int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster,
*p_cluster = *p_cluster + coff; *p_cluster = *p_cluster + coff;
if (num_clusters) if (num_clusters)
*num_clusters = ocfs2_rec_clusters(el, rec) - coff; *num_clusters = ocfs2_rec_clusters(el, rec) - coff;
if (extent_flags)
*extent_flags = rec->e_flags;
} }
out: out:
if (eb_bh) if (eb_bh)
...@@ -862,8 +869,8 @@ int ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr, ...@@ -862,8 +869,8 @@ int ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr,
BUG_ON(bhs[done + i]->b_blocknr != (p_block + i)); BUG_ON(bhs[done + i]->b_blocknr != (p_block + i));
} }
rc = ocfs2_read_blocks(inode, p_block, count, bhs + done, rc = ocfs2_read_blocks(INODE_CACHE(inode), p_block, count,
flags, validate); bhs + done, flags, validate);
if (rc) { if (rc) {
mlog_errno(rc); mlog_errno(rc);
break; break;
......
...@@ -55,12 +55,18 @@ int ocfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, ...@@ -55,12 +55,18 @@ int ocfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster, int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster,
u32 *p_cluster, u32 *num_clusters, u32 *p_cluster, u32 *num_clusters,
struct ocfs2_extent_list *el); struct ocfs2_extent_list *el,
unsigned int *extent_flags);
int ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr, int ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr,
struct buffer_head *bhs[], int flags, struct buffer_head *bhs[], int flags,
int (*validate)(struct super_block *sb, int (*validate)(struct super_block *sb,
struct buffer_head *bh)); struct buffer_head *bh));
int ocfs2_figure_hole_clusters(struct ocfs2_caching_info *ci,
struct ocfs2_extent_list *el,
struct buffer_head *eb_bh,
u32 v_cluster,
u32 *num_clusters);
static inline int ocfs2_read_virt_block(struct inode *inode, u64 v_block, static inline int ocfs2_read_virt_block(struct inode *inode, u64 v_block,
struct buffer_head **bh, struct buffer_head **bh,
int (*validate)(struct super_block *sb, int (*validate)(struct super_block *sb,
......
...@@ -59,6 +59,7 @@ ...@@ -59,6 +59,7 @@
#include "xattr.h" #include "xattr.h"
#include "acl.h" #include "acl.h"
#include "quota.h" #include "quota.h"
#include "refcounttree.h"
#include "buffer_head_io.h" #include "buffer_head_io.h"
...@@ -259,7 +260,7 @@ int ocfs2_update_inode_atime(struct inode *inode, ...@@ -259,7 +260,7 @@ int ocfs2_update_inode_atime(struct inode *inode,
goto out; goto out;
} }
ret = ocfs2_journal_access_di(handle, inode, bh, ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), bh,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
...@@ -334,6 +335,39 @@ int ocfs2_simple_size_update(struct inode *inode, ...@@ -334,6 +335,39 @@ int ocfs2_simple_size_update(struct inode *inode,
return ret; return ret;
} }
static int ocfs2_cow_file_pos(struct inode *inode,
struct buffer_head *fe_bh,
u64 offset)
{
int status;
u32 phys, cpos = offset >> OCFS2_SB(inode->i_sb)->s_clustersize_bits;
unsigned int num_clusters = 0;
unsigned int ext_flags = 0;
/*
* If the new offset is aligned to the range of the cluster, there is
* no space for ocfs2_zero_range_for_truncate to fill, so no need to
* CoW either.
*/
if ((offset & (OCFS2_SB(inode->i_sb)->s_clustersize - 1)) == 0)
return 0;
status = ocfs2_get_clusters(inode, cpos, &phys,
&num_clusters, &ext_flags);
if (status) {
mlog_errno(status);
goto out;
}
if (!(ext_flags & OCFS2_EXT_REFCOUNTED))
goto out;
return ocfs2_refcount_cow(inode, fe_bh, cpos, 1, cpos+1);
out:
return status;
}
static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb, static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb,
struct inode *inode, struct inode *inode,
struct buffer_head *fe_bh, struct buffer_head *fe_bh,
...@@ -346,6 +380,17 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb, ...@@ -346,6 +380,17 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb,
mlog_entry_void(); mlog_entry_void();
/*
* We need to CoW the cluster contains the offset if it is reflinked
* since we will call ocfs2_zero_range_for_truncate later which will
* write "0" from offset to the end of the cluster.
*/
status = ocfs2_cow_file_pos(inode, fe_bh, new_i_size);
if (status) {
mlog_errno(status);
return status;
}
/* TODO: This needs to actually orphan the inode in this /* TODO: This needs to actually orphan the inode in this
* transaction. */ * transaction. */
...@@ -356,7 +401,7 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb, ...@@ -356,7 +401,7 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb,
goto out; goto out;
} }
status = ocfs2_journal_access_di(handle, inode, fe_bh, status = ocfs2_journal_access_di(handle, INODE_CACHE(inode), fe_bh,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
if (status < 0) { if (status < 0) {
mlog_errno(status); mlog_errno(status);
...@@ -486,6 +531,8 @@ static int ocfs2_truncate_file(struct inode *inode, ...@@ -486,6 +531,8 @@ static int ocfs2_truncate_file(struct inode *inode,
up_write(&OCFS2_I(inode)->ip_alloc_sem); up_write(&OCFS2_I(inode)->ip_alloc_sem);
bail: bail:
if (!status && OCFS2_I(inode)->ip_clusters == 0)
status = ocfs2_try_remove_refcount_tree(inode, di_bh);
mlog_exit(status); mlog_exit(status);
return status; return status;
...@@ -515,11 +562,10 @@ int ocfs2_add_inode_data(struct ocfs2_super *osb, ...@@ -515,11 +562,10 @@ int ocfs2_add_inode_data(struct ocfs2_super *osb,
int ret; int ret;
struct ocfs2_extent_tree et; struct ocfs2_extent_tree et;
ocfs2_init_dinode_extent_tree(&et, inode, fe_bh); ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), fe_bh);
ret = ocfs2_add_clusters_in_btree(osb, inode, logical_offset, ret = ocfs2_add_clusters_in_btree(handle, &et, logical_offset,
clusters_to_add, mark_unwritten, clusters_to_add, mark_unwritten,
&et, handle, data_ac, meta_ac, reason_ret);
data_ac, meta_ac, reason_ret);
return ret; return ret;
} }
...@@ -564,7 +610,7 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start, ...@@ -564,7 +610,7 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
(unsigned long long)OCFS2_I(inode)->ip_blkno, (unsigned long long)OCFS2_I(inode)->ip_blkno,
(long long)i_size_read(inode), le32_to_cpu(fe->i_clusters), (long long)i_size_read(inode), le32_to_cpu(fe->i_clusters),
clusters_to_add); clusters_to_add);
ocfs2_init_dinode_extent_tree(&et, inode, bh); ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), bh);
status = ocfs2_lock_allocators(inode, &et, clusters_to_add, 0, status = ocfs2_lock_allocators(inode, &et, clusters_to_add, 0,
&data_ac, &meta_ac); &data_ac, &meta_ac);
if (status) { if (status) {
...@@ -593,7 +639,7 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start, ...@@ -593,7 +639,7 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
/* reserve a write to the file entry early on - that we if we /* reserve a write to the file entry early on - that we if we
* run out of credits in the allocation path, we can still * run out of credits in the allocation path, we can still
* update i_size. */ * update i_size. */
status = ocfs2_journal_access_di(handle, inode, bh, status = ocfs2_journal_access_di(handle, INODE_CACHE(inode), bh,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
if (status < 0) { if (status < 0) {
mlog_errno(status); mlog_errno(status);
...@@ -1131,7 +1177,7 @@ static int __ocfs2_write_remove_suid(struct inode *inode, ...@@ -1131,7 +1177,7 @@ static int __ocfs2_write_remove_suid(struct inode *inode,
goto out; goto out;
} }
ret = ocfs2_journal_access_di(handle, inode, bh, ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), bh,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
if (ret < 0) { if (ret < 0) {
mlog_errno(ret); mlog_errno(ret);
...@@ -1395,7 +1441,7 @@ static int ocfs2_remove_inode_range(struct inode *inode, ...@@ -1395,7 +1441,7 @@ static int ocfs2_remove_inode_range(struct inode *inode,
struct address_space *mapping = inode->i_mapping; struct address_space *mapping = inode->i_mapping;
struct ocfs2_extent_tree et; struct ocfs2_extent_tree et;
ocfs2_init_dinode_extent_tree(&et, inode, di_bh); ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), di_bh);
ocfs2_init_dealloc_ctxt(&dealloc); ocfs2_init_dealloc_ctxt(&dealloc);
if (byte_len == 0) if (byte_len == 0)
...@@ -1657,6 +1703,70 @@ static long ocfs2_fallocate(struct inode *inode, int mode, loff_t offset, ...@@ -1657,6 +1703,70 @@ static long ocfs2_fallocate(struct inode *inode, int mode, loff_t offset,
OCFS2_IOC_RESVSP64, &sr, change_size); OCFS2_IOC_RESVSP64, &sr, change_size);
} }
int ocfs2_check_range_for_refcount(struct inode *inode, loff_t pos,
size_t count)
{
int ret = 0;
unsigned int extent_flags;
u32 cpos, clusters, extent_len, phys_cpos;
struct super_block *sb = inode->i_sb;
if (!ocfs2_refcount_tree(OCFS2_SB(inode->i_sb)) ||
!(OCFS2_I(inode)->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL))
return 0;
cpos = pos >> OCFS2_SB(sb)->s_clustersize_bits;
clusters = ocfs2_clusters_for_bytes(sb, pos + count) - cpos;
while (clusters) {
ret = ocfs2_get_clusters(inode, cpos, &phys_cpos, &extent_len,
&extent_flags);
if (ret < 0) {
mlog_errno(ret);
goto out;
}
if (phys_cpos && (extent_flags & OCFS2_EXT_REFCOUNTED)) {
ret = 1;
break;
}
if (extent_len > clusters)
extent_len = clusters;
clusters -= extent_len;
cpos += extent_len;
}
out:
return ret;
}
static int ocfs2_prepare_inode_for_refcount(struct inode *inode,
loff_t pos, size_t count,
int *meta_level)
{
int ret;
struct buffer_head *di_bh = NULL;
u32 cpos = pos >> OCFS2_SB(inode->i_sb)->s_clustersize_bits;
u32 clusters =
ocfs2_clusters_for_bytes(inode->i_sb, pos + count) - cpos;
ret = ocfs2_inode_lock(inode, &di_bh, 1);
if (ret) {
mlog_errno(ret);
goto out;
}
*meta_level = 1;
ret = ocfs2_refcount_cow(inode, di_bh, cpos, clusters, UINT_MAX);
if (ret)
mlog_errno(ret);
out:
brelse(di_bh);
return ret;
}
static int ocfs2_prepare_inode_for_write(struct dentry *dentry, static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
loff_t *ppos, loff_t *ppos,
size_t count, size_t count,
...@@ -1713,6 +1823,22 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry, ...@@ -1713,6 +1823,22 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
end = saved_pos + count; end = saved_pos + count;
ret = ocfs2_check_range_for_refcount(inode, saved_pos, count);
if (ret == 1) {
ocfs2_inode_unlock(inode, meta_level);
meta_level = -1;
ret = ocfs2_prepare_inode_for_refcount(inode,
saved_pos,
count,
&meta_level);
}
if (ret < 0) {
mlog_errno(ret);
goto out_unlock;
}
/* /*
* Skip the O_DIRECT checks if we don't need * Skip the O_DIRECT checks if we don't need
* them. * them.
...@@ -1759,7 +1885,8 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry, ...@@ -1759,7 +1885,8 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
*ppos = saved_pos; *ppos = saved_pos;
out_unlock: out_unlock:
ocfs2_inode_unlock(inode, meta_level); if (meta_level >= 0)
ocfs2_inode_unlock(inode, meta_level);
out: out:
return ret; return ret;
......
...@@ -69,4 +69,6 @@ int ocfs2_update_inode_atime(struct inode *inode, ...@@ -69,4 +69,6 @@ int ocfs2_update_inode_atime(struct inode *inode,
int ocfs2_change_file_space(struct file *file, unsigned int cmd, int ocfs2_change_file_space(struct file *file, unsigned int cmd,
struct ocfs2_space_resv *sr); struct ocfs2_space_resv *sr);
int ocfs2_check_range_for_refcount(struct inode *inode, loff_t pos,
size_t count);
#endif /* OCFS2_FILE_H */ #endif /* OCFS2_FILE_H */
...@@ -53,6 +53,7 @@ ...@@ -53,6 +53,7 @@
#include "sysfile.h" #include "sysfile.h"
#include "uptodate.h" #include "uptodate.h"
#include "xattr.h" #include "xattr.h"
#include "refcounttree.h"
#include "buffer_head_io.h" #include "buffer_head_io.h"
...@@ -562,7 +563,8 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb, ...@@ -562,7 +563,8 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb,
goto out; goto out;
} }
status = ocfs2_journal_access_di(handle, inode, fe_bh, status = ocfs2_journal_access_di(handle, INODE_CACHE(inode),
fe_bh,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
if (status < 0) { if (status < 0) {
mlog_errno(status); mlog_errno(status);
...@@ -646,7 +648,7 @@ static int ocfs2_remove_inode(struct inode *inode, ...@@ -646,7 +648,7 @@ static int ocfs2_remove_inode(struct inode *inode,
} }
/* set the inodes dtime */ /* set the inodes dtime */
status = ocfs2_journal_access_di(handle, inode, di_bh, status = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
if (status < 0) { if (status < 0) {
mlog_errno(status); mlog_errno(status);
...@@ -662,7 +664,7 @@ static int ocfs2_remove_inode(struct inode *inode, ...@@ -662,7 +664,7 @@ static int ocfs2_remove_inode(struct inode *inode,
goto bail_commit; goto bail_commit;
} }
ocfs2_remove_from_cache(inode, di_bh); ocfs2_remove_from_cache(INODE_CACHE(inode), di_bh);
vfs_dq_free_inode(inode); vfs_dq_free_inode(inode);
status = ocfs2_free_dinode(handle, inode_alloc_inode, status = ocfs2_free_dinode(handle, inode_alloc_inode,
...@@ -781,6 +783,12 @@ static int ocfs2_wipe_inode(struct inode *inode, ...@@ -781,6 +783,12 @@ static int ocfs2_wipe_inode(struct inode *inode,
goto bail_unlock_dir; goto bail_unlock_dir;
} }
status = ocfs2_remove_refcount_tree(inode, di_bh);
if (status < 0) {
mlog_errno(status);
goto bail_unlock_dir;
}
status = ocfs2_remove_inode(inode, di_bh, orphan_dir_inode, status = ocfs2_remove_inode(inode, di_bh, orphan_dir_inode,
orphan_dir_bh); orphan_dir_bh);
if (status < 0) if (status < 0)
...@@ -1112,13 +1120,14 @@ void ocfs2_clear_inode(struct inode *inode) ...@@ -1112,13 +1120,14 @@ void ocfs2_clear_inode(struct inode *inode)
ocfs2_lock_res_free(&oi->ip_inode_lockres); ocfs2_lock_res_free(&oi->ip_inode_lockres);
ocfs2_lock_res_free(&oi->ip_open_lockres); ocfs2_lock_res_free(&oi->ip_open_lockres);
ocfs2_metadata_cache_purge(inode); ocfs2_metadata_cache_exit(INODE_CACHE(inode));
mlog_bug_on_msg(oi->ip_metadata_cache.ci_num_cached, mlog_bug_on_msg(INODE_CACHE(inode)->ci_num_cached,
"Clear inode of %llu, inode has %u cache items\n", "Clear inode of %llu, inode has %u cache items\n",
(unsigned long long)oi->ip_blkno, oi->ip_metadata_cache.ci_num_cached); (unsigned long long)oi->ip_blkno,
INODE_CACHE(inode)->ci_num_cached);
mlog_bug_on_msg(!(oi->ip_flags & OCFS2_INODE_CACHE_INLINE), mlog_bug_on_msg(!(INODE_CACHE(inode)->ci_flags & OCFS2_CACHE_FL_INLINE),
"Clear inode of %llu, inode has a bad flag\n", "Clear inode of %llu, inode has a bad flag\n",
(unsigned long long)oi->ip_blkno); (unsigned long long)oi->ip_blkno);
...@@ -1145,9 +1154,7 @@ void ocfs2_clear_inode(struct inode *inode) ...@@ -1145,9 +1154,7 @@ void ocfs2_clear_inode(struct inode *inode)
(unsigned long long)oi->ip_blkno, oi->ip_open_count); (unsigned long long)oi->ip_blkno, oi->ip_open_count);
/* Clear all other flags. */ /* Clear all other flags. */
oi->ip_flags = OCFS2_INODE_CACHE_INLINE; oi->ip_flags = 0;
oi->ip_created_trans = 0;
oi->ip_last_trans = 0;
oi->ip_dir_start_lookup = 0; oi->ip_dir_start_lookup = 0;
oi->ip_blkno = 0ULL; oi->ip_blkno = 0ULL;
...@@ -1239,7 +1246,7 @@ int ocfs2_mark_inode_dirty(handle_t *handle, ...@@ -1239,7 +1246,7 @@ int ocfs2_mark_inode_dirty(handle_t *handle,
mlog_entry("(inode %llu)\n", mlog_entry("(inode %llu)\n",
(unsigned long long)OCFS2_I(inode)->ip_blkno); (unsigned long long)OCFS2_I(inode)->ip_blkno);
status = ocfs2_journal_access_di(handle, inode, bh, status = ocfs2_journal_access_di(handle, INODE_CACHE(inode), bh,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
if (status < 0) { if (status < 0) {
mlog_errno(status); mlog_errno(status);
...@@ -1380,8 +1387,8 @@ int ocfs2_read_inode_block_full(struct inode *inode, struct buffer_head **bh, ...@@ -1380,8 +1387,8 @@ int ocfs2_read_inode_block_full(struct inode *inode, struct buffer_head **bh,
int rc; int rc;
struct buffer_head *tmp = *bh; struct buffer_head *tmp = *bh;
rc = ocfs2_read_blocks(inode, OCFS2_I(inode)->ip_blkno, 1, &tmp, rc = ocfs2_read_blocks(INODE_CACHE(inode), OCFS2_I(inode)->ip_blkno,
flags, ocfs2_validate_inode_block); 1, &tmp, flags, ocfs2_validate_inode_block);
/* If ocfs2_read_blocks() got us a new bh, pass it up. */ /* If ocfs2_read_blocks() got us a new bh, pass it up. */
if (!rc && !*bh) if (!rc && !*bh)
...@@ -1394,3 +1401,56 @@ int ocfs2_read_inode_block(struct inode *inode, struct buffer_head **bh) ...@@ -1394,3 +1401,56 @@ int ocfs2_read_inode_block(struct inode *inode, struct buffer_head **bh)
{ {
return ocfs2_read_inode_block_full(inode, bh, 0); return ocfs2_read_inode_block_full(inode, bh, 0);
} }
static u64 ocfs2_inode_cache_owner(struct ocfs2_caching_info *ci)
{
struct ocfs2_inode_info *oi = cache_info_to_inode(ci);
return oi->ip_blkno;
}
static struct super_block *ocfs2_inode_cache_get_super(struct ocfs2_caching_info *ci)
{
struct ocfs2_inode_info *oi = cache_info_to_inode(ci);
return oi->vfs_inode.i_sb;
}
static void ocfs2_inode_cache_lock(struct ocfs2_caching_info *ci)
{
struct ocfs2_inode_info *oi = cache_info_to_inode(ci);
spin_lock(&oi->ip_lock);
}
static void ocfs2_inode_cache_unlock(struct ocfs2_caching_info *ci)
{
struct ocfs2_inode_info *oi = cache_info_to_inode(ci);
spin_unlock(&oi->ip_lock);
}
static void ocfs2_inode_cache_io_lock(struct ocfs2_caching_info *ci)
{
struct ocfs2_inode_info *oi = cache_info_to_inode(ci);
mutex_lock(&oi->ip_io_mutex);
}
static void ocfs2_inode_cache_io_unlock(struct ocfs2_caching_info *ci)
{
struct ocfs2_inode_info *oi = cache_info_to_inode(ci);
mutex_unlock(&oi->ip_io_mutex);
}
const struct ocfs2_caching_operations ocfs2_inode_caching_ops = {
.co_owner = ocfs2_inode_cache_owner,
.co_get_super = ocfs2_inode_cache_get_super,
.co_cache_lock = ocfs2_inode_cache_lock,
.co_cache_unlock = ocfs2_inode_cache_unlock,
.co_io_lock = ocfs2_inode_cache_io_lock,
.co_io_unlock = ocfs2_inode_cache_io_unlock,
};
...@@ -60,12 +60,6 @@ struct ocfs2_inode_info ...@@ -60,12 +60,6 @@ struct ocfs2_inode_info
u32 ip_dir_start_lookup; u32 ip_dir_start_lookup;
/* next two are protected by trans_inc_lock */
/* which transaction were we created on? Zero if none. */
unsigned long ip_created_trans;
/* last transaction we were a part of. */
unsigned long ip_last_trans;
struct ocfs2_caching_info ip_metadata_cache; struct ocfs2_caching_info ip_metadata_cache;
struct ocfs2_extent_map ip_extent_map; struct ocfs2_extent_map ip_extent_map;
...@@ -106,8 +100,6 @@ struct ocfs2_inode_info ...@@ -106,8 +100,6 @@ struct ocfs2_inode_info
#define OCFS2_INODE_MAYBE_ORPHANED 0x00000020 #define OCFS2_INODE_MAYBE_ORPHANED 0x00000020
/* Does someone have the file open O_DIRECT */ /* Does someone have the file open O_DIRECT */
#define OCFS2_INODE_OPEN_DIRECT 0x00000040 #define OCFS2_INODE_OPEN_DIRECT 0x00000040
/* Indicates that the metadata cache should be used as an array. */
#define OCFS2_INODE_CACHE_INLINE 0x00000080
static inline struct ocfs2_inode_info *OCFS2_I(struct inode *inode) static inline struct ocfs2_inode_info *OCFS2_I(struct inode *inode)
{ {
...@@ -120,6 +112,12 @@ static inline struct ocfs2_inode_info *OCFS2_I(struct inode *inode) ...@@ -120,6 +112,12 @@ static inline struct ocfs2_inode_info *OCFS2_I(struct inode *inode)
extern struct kmem_cache *ocfs2_inode_cache; extern struct kmem_cache *ocfs2_inode_cache;
extern const struct address_space_operations ocfs2_aops; extern const struct address_space_operations ocfs2_aops;
extern const struct ocfs2_caching_operations ocfs2_inode_caching_ops;
static inline struct ocfs2_caching_info *INODE_CACHE(struct inode *inode)
{
return &OCFS2_I(inode)->ip_metadata_cache;
}
void ocfs2_clear_inode(struct inode *inode); void ocfs2_clear_inode(struct inode *inode);
void ocfs2_delete_inode(struct inode *inode); void ocfs2_delete_inode(struct inode *inode);
...@@ -172,4 +170,10 @@ int ocfs2_read_inode_block(struct inode *inode, struct buffer_head **bh); ...@@ -172,4 +170,10 @@ int ocfs2_read_inode_block(struct inode *inode, struct buffer_head **bh);
/* The same, but can be passed OCFS2_BH_* flags */ /* The same, but can be passed OCFS2_BH_* flags */
int ocfs2_read_inode_block_full(struct inode *inode, struct buffer_head **bh, int ocfs2_read_inode_block_full(struct inode *inode, struct buffer_head **bh,
int flags); int flags);
static inline struct ocfs2_inode_info *cache_info_to_inode(struct ocfs2_caching_info *ci)
{
return container_of(ci, struct ocfs2_inode_info, ip_metadata_cache);
}
#endif /* OCFS2_INODE_H */ #endif /* OCFS2_INODE_H */
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "ocfs2_fs.h" #include "ocfs2_fs.h"
#include "ioctl.h" #include "ioctl.h"
#include "resize.h" #include "resize.h"
#include "refcounttree.h"
#include <linux/ext2_fs.h> #include <linux/ext2_fs.h>
...@@ -115,6 +116,9 @@ long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -115,6 +116,9 @@ long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
int status; int status;
struct ocfs2_space_resv sr; struct ocfs2_space_resv sr;
struct ocfs2_new_group_input input; struct ocfs2_new_group_input input;
struct reflink_arguments args;
const char *old_path, *new_path;
bool preserve;
switch (cmd) { switch (cmd) {
case OCFS2_IOC_GETFLAGS: case OCFS2_IOC_GETFLAGS:
...@@ -160,6 +164,15 @@ long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -160,6 +164,15 @@ long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return -EFAULT; return -EFAULT;
return ocfs2_group_add(inode, &input); return ocfs2_group_add(inode, &input);
case OCFS2_IOC_REFLINK:
if (copy_from_user(&args, (struct reflink_arguments *)arg,
sizeof(args)))
return -EFAULT;
old_path = (const char *)(unsigned long)args.old_path;
new_path = (const char *)(unsigned long)args.new_path;
preserve = (args.preserve != 0);
return ocfs2_reflink_ioctl(inode, old_path, new_path, preserve);
default: default:
return -ENOTTY; return -ENOTTY;
} }
...@@ -182,6 +195,7 @@ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg) ...@@ -182,6 +195,7 @@ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
case OCFS2_IOC_GROUP_EXTEND: case OCFS2_IOC_GROUP_EXTEND:
case OCFS2_IOC_GROUP_ADD: case OCFS2_IOC_GROUP_ADD:
case OCFS2_IOC_GROUP_ADD64: case OCFS2_IOC_GROUP_ADD64:
case OCFS2_IOC_REFLINK:
break; break;
default: default:
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
......
此差异已折叠。
此差异已折叠。
...@@ -297,8 +297,8 @@ void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb) ...@@ -297,8 +297,8 @@ void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb)
} }
memcpy(alloc_copy, alloc, bh->b_size); memcpy(alloc_copy, alloc, bh->b_size);
status = ocfs2_journal_access_di(handle, local_alloc_inode, bh, status = ocfs2_journal_access_di(handle, INODE_CACHE(local_alloc_inode),
OCFS2_JOURNAL_ACCESS_WRITE); bh, OCFS2_JOURNAL_ACCESS_WRITE);
if (status < 0) { if (status < 0) {
mlog_errno(status); mlog_errno(status);
goto out_commit; goto out_commit;
...@@ -392,7 +392,7 @@ int ocfs2_begin_local_alloc_recovery(struct ocfs2_super *osb, ...@@ -392,7 +392,7 @@ int ocfs2_begin_local_alloc_recovery(struct ocfs2_super *osb,
ocfs2_clear_local_alloc(alloc); ocfs2_clear_local_alloc(alloc);
ocfs2_compute_meta_ecc(osb->sb, alloc_bh->b_data, &alloc->i_check); ocfs2_compute_meta_ecc(osb->sb, alloc_bh->b_data, &alloc->i_check);
status = ocfs2_write_block(osb, alloc_bh, inode); status = ocfs2_write_block(osb, alloc_bh, INODE_CACHE(inode));
if (status < 0) if (status < 0)
mlog_errno(status); mlog_errno(status);
...@@ -678,7 +678,8 @@ int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb, ...@@ -678,7 +678,8 @@ int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb,
* delete bits from it! */ * delete bits from it! */
*num_bits = bits_wanted; *num_bits = bits_wanted;
status = ocfs2_journal_access_di(handle, local_alloc_inode, status = ocfs2_journal_access_di(handle,
INODE_CACHE(local_alloc_inode),
osb->local_alloc_bh, osb->local_alloc_bh,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
if (status < 0) { if (status < 0) {
...@@ -1156,7 +1157,8 @@ static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb, ...@@ -1156,7 +1157,8 @@ static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb,
} }
memcpy(alloc_copy, alloc, osb->local_alloc_bh->b_size); memcpy(alloc_copy, alloc, osb->local_alloc_bh->b_size);
status = ocfs2_journal_access_di(handle, local_alloc_inode, status = ocfs2_journal_access_di(handle,
INODE_CACHE(local_alloc_inode),
osb->local_alloc_bh, osb->local_alloc_bh,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
if (status < 0) { if (status < 0) {
......
此差异已折叠。
...@@ -35,5 +35,11 @@ int ocfs2_orphan_del(struct ocfs2_super *osb, ...@@ -35,5 +35,11 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
struct inode *orphan_dir_inode, struct inode *orphan_dir_inode,
struct inode *inode, struct inode *inode,
struct buffer_head *orphan_dir_bh); struct buffer_head *orphan_dir_bh);
int ocfs2_create_inode_in_orphan(struct inode *dir,
int mode,
struct inode **new_inode);
int ocfs2_mv_orphaned_inode_to_new(struct inode *dir,
struct inode *new_inode,
struct dentry *new_dentry);
#endif /* OCFS2_NAMEI_H */ #endif /* OCFS2_NAMEI_H */
此差异已折叠。
此差异已折叠。
...@@ -49,6 +49,7 @@ enum ocfs2_lock_type { ...@@ -49,6 +49,7 @@ enum ocfs2_lock_type {
OCFS2_LOCK_TYPE_QINFO, OCFS2_LOCK_TYPE_QINFO,
OCFS2_LOCK_TYPE_NFS_SYNC, OCFS2_LOCK_TYPE_NFS_SYNC,
OCFS2_LOCK_TYPE_ORPHAN_SCAN, OCFS2_LOCK_TYPE_ORPHAN_SCAN,
OCFS2_LOCK_TYPE_REFCOUNT,
OCFS2_NUM_LOCK_TYPES OCFS2_NUM_LOCK_TYPES
}; };
...@@ -89,6 +90,9 @@ static inline char ocfs2_lock_type_char(enum ocfs2_lock_type type) ...@@ -89,6 +90,9 @@ static inline char ocfs2_lock_type_char(enum ocfs2_lock_type type)
case OCFS2_LOCK_TYPE_ORPHAN_SCAN: case OCFS2_LOCK_TYPE_ORPHAN_SCAN:
c = 'P'; c = 'P';
break; break;
case OCFS2_LOCK_TYPE_REFCOUNT:
c = 'T';
break;
default: default:
c = '\0'; c = '\0';
} }
...@@ -110,6 +114,7 @@ static char *ocfs2_lock_type_strings[] = { ...@@ -110,6 +114,7 @@ static char *ocfs2_lock_type_strings[] = {
[OCFS2_LOCK_TYPE_QINFO] = "Quota", [OCFS2_LOCK_TYPE_QINFO] = "Quota",
[OCFS2_LOCK_TYPE_NFS_SYNC] = "NFSSync", [OCFS2_LOCK_TYPE_NFS_SYNC] = "NFSSync",
[OCFS2_LOCK_TYPE_ORPHAN_SCAN] = "OrphanScan", [OCFS2_LOCK_TYPE_ORPHAN_SCAN] = "OrphanScan",
[OCFS2_LOCK_TYPE_REFCOUNT] = "Refcount",
}; };
static inline const char *ocfs2_lock_type_string(enum ocfs2_lock_type type) static inline const char *ocfs2_lock_type_string(enum ocfs2_lock_type type)
......
...@@ -253,8 +253,9 @@ ssize_t ocfs2_quota_write(struct super_block *sb, int type, ...@@ -253,8 +253,9 @@ ssize_t ocfs2_quota_write(struct super_block *sb, int type,
flush_dcache_page(bh->b_page); flush_dcache_page(bh->b_page);
set_buffer_uptodate(bh); set_buffer_uptodate(bh);
unlock_buffer(bh); unlock_buffer(bh);
ocfs2_set_buffer_uptodate(gqinode, bh); ocfs2_set_buffer_uptodate(INODE_CACHE(gqinode), bh);
err = ocfs2_journal_access_dq(handle, gqinode, bh, ja_type); err = ocfs2_journal_access_dq(handle, INODE_CACHE(gqinode), bh,
ja_type);
if (err < 0) { if (err < 0) {
brelse(bh); brelse(bh);
goto out; goto out;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
...@@ -150,8 +150,8 @@ int ocfs2_refresh_slot_info(struct ocfs2_super *osb) ...@@ -150,8 +150,8 @@ int ocfs2_refresh_slot_info(struct ocfs2_super *osb)
* be !NULL. Thus, ocfs2_read_blocks() will ignore blocknr. If * be !NULL. Thus, ocfs2_read_blocks() will ignore blocknr. If
* this is not true, the read of -1 (UINT64_MAX) will fail. * this is not true, the read of -1 (UINT64_MAX) will fail.
*/ */
ret = ocfs2_read_blocks(si->si_inode, -1, si->si_blocks, si->si_bh, ret = ocfs2_read_blocks(INODE_CACHE(si->si_inode), -1, si->si_blocks,
OCFS2_BH_IGNORE_CACHE, NULL); si->si_bh, OCFS2_BH_IGNORE_CACHE, NULL);
if (ret == 0) { if (ret == 0) {
spin_lock(&osb->osb_lock); spin_lock(&osb->osb_lock);
ocfs2_update_slot_info(si); ocfs2_update_slot_info(si);
...@@ -213,7 +213,7 @@ static int ocfs2_update_disk_slot(struct ocfs2_super *osb, ...@@ -213,7 +213,7 @@ static int ocfs2_update_disk_slot(struct ocfs2_super *osb,
ocfs2_update_disk_slot_old(si, slot_num, &bh); ocfs2_update_disk_slot_old(si, slot_num, &bh);
spin_unlock(&osb->osb_lock); spin_unlock(&osb->osb_lock);
status = ocfs2_write_block(osb, bh, si->si_inode); status = ocfs2_write_block(osb, bh, INODE_CACHE(si->si_inode));
if (status < 0) if (status < 0)
mlog_errno(status); mlog_errno(status);
...@@ -404,8 +404,8 @@ static int ocfs2_map_slot_buffers(struct ocfs2_super *osb, ...@@ -404,8 +404,8 @@ static int ocfs2_map_slot_buffers(struct ocfs2_super *osb,
(unsigned long long)blkno); (unsigned long long)blkno);
bh = NULL; /* Acquire a fresh bh */ bh = NULL; /* Acquire a fresh bh */
status = ocfs2_read_blocks(si->si_inode, blkno, 1, &bh, status = ocfs2_read_blocks(INODE_CACHE(si->si_inode), blkno,
OCFS2_BH_IGNORE_CACHE, NULL); 1, &bh, OCFS2_BH_IGNORE_CACHE, NULL);
if (status < 0) { if (status < 0) {
mlog_errno(status); mlog_errno(status);
goto bail; goto bail;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册