You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/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. ...
This commit is contained in:
@@ -28,6 +28,7 @@ ocfs2-objs := \
|
||||
locks.o \
|
||||
mmap.o \
|
||||
namei.o \
|
||||
refcounttree.o \
|
||||
resize.o \
|
||||
slot_map.o \
|
||||
suballoc.o \
|
||||
|
||||
+778
-580
File diff suppressed because it is too large
Load Diff
+82
-19
@@ -45,7 +45,8 @@
|
||||
*
|
||||
* ocfs2_extent_tree contains info for the root of the b-tree, it must have a
|
||||
* root ocfs2_extent_list and a root_bh so that they can be used in the b-tree
|
||||
* functions. 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
|
||||
* root_journal_access function.
|
||||
* ocfs2_extent_tree_operations abstract the normal operations we do for
|
||||
@@ -56,6 +57,7 @@ struct ocfs2_extent_tree {
|
||||
struct ocfs2_extent_tree_operations *et_ops;
|
||||
struct buffer_head *et_root_bh;
|
||||
struct ocfs2_extent_list *et_root_el;
|
||||
struct ocfs2_caching_info *et_ci;
|
||||
ocfs2_journal_access_func et_root_journal_access;
|
||||
void *et_object;
|
||||
unsigned int et_max_leaf_clusters;
|
||||
@@ -66,31 +68,32 @@ struct ocfs2_extent_tree {
|
||||
* specified object buffer.
|
||||
*/
|
||||
void ocfs2_init_dinode_extent_tree(struct ocfs2_extent_tree *et,
|
||||
struct inode *inode,
|
||||
struct ocfs2_caching_info *ci,
|
||||
struct buffer_head *bh);
|
||||
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 ocfs2_xattr_value_buf;
|
||||
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);
|
||||
void ocfs2_init_dx_root_extent_tree(struct ocfs2_extent_tree *et,
|
||||
struct inode *inode,
|
||||
struct ocfs2_caching_info *ci,
|
||||
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
|
||||
* allocated. This is a cached read. The extent block will be validated
|
||||
* 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 ocfs2_alloc_context;
|
||||
int ocfs2_insert_extent(struct ocfs2_super *osb,
|
||||
handle_t *handle,
|
||||
struct inode *inode,
|
||||
int ocfs2_insert_extent(handle_t *handle,
|
||||
struct ocfs2_extent_tree *et,
|
||||
u32 cpos,
|
||||
u64 start_blk,
|
||||
@@ -103,25 +106,36 @@ enum ocfs2_alloc_restarted {
|
||||
RESTART_TRANS,
|
||||
RESTART_META
|
||||
};
|
||||
int ocfs2_add_clusters_in_btree(struct ocfs2_super *osb,
|
||||
struct inode *inode,
|
||||
int ocfs2_add_clusters_in_btree(handle_t *handle,
|
||||
struct ocfs2_extent_tree *et,
|
||||
u32 *logical_offset,
|
||||
u32 clusters_to_add,
|
||||
int mark_unwritten,
|
||||
struct ocfs2_extent_tree *et,
|
||||
handle_t *handle,
|
||||
struct ocfs2_alloc_context *data_ac,
|
||||
struct ocfs2_alloc_context *meta_ac,
|
||||
enum ocfs2_alloc_restarted *reason_ret);
|
||||
struct ocfs2_cached_dealloc_ctxt;
|
||||
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,
|
||||
struct ocfs2_extent_tree *et,
|
||||
handle_t *handle, u32 cpos, u32 len, u32 phys,
|
||||
struct ocfs2_alloc_context *meta_ac,
|
||||
struct ocfs2_cached_dealloc_ctxt *dealloc);
|
||||
int ocfs2_remove_extent(struct inode *inode,
|
||||
struct ocfs2_extent_tree *et,
|
||||
u32 cpos, u32 len, handle_t *handle,
|
||||
int ocfs2_change_extent_flag(handle_t *handle,
|
||||
struct ocfs2_extent_tree *et,
|
||||
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_cached_dealloc_ctxt *dealloc);
|
||||
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);
|
||||
|
||||
int ocfs2_num_free_extents(struct ocfs2_super *osb,
|
||||
struct inode *inode,
|
||||
struct ocfs2_extent_tree *et);
|
||||
|
||||
/*
|
||||
@@ -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,
|
||||
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)
|
||||
{
|
||||
return c->c_global_allocator != NULL;
|
||||
@@ -222,8 +238,9 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
|
||||
int ocfs2_truncate_inline(struct inode *inode, struct buffer_head *di_bh,
|
||||
unsigned int start, unsigned int end, int trunc);
|
||||
|
||||
int ocfs2_find_leaf(struct inode *inode, struct ocfs2_extent_list *root_el,
|
||||
u32 cpos, struct buffer_head **leaf_bh);
|
||||
int ocfs2_find_leaf(struct ocfs2_caching_info *ci,
|
||||
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);
|
||||
|
||||
/*
|
||||
@@ -254,4 +271,50 @@ static inline int ocfs2_is_empty_extent(struct ocfs2_extent_rec *rec)
|
||||
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 */
|
||||
|
||||
+31
-6
@@ -44,6 +44,7 @@
|
||||
#include "suballoc.h"
|
||||
#include "super.h"
|
||||
#include "symlink.h"
|
||||
#include "refcounttree.h"
|
||||
|
||||
#include "buffer_head_io.h"
|
||||
|
||||
@@ -126,8 +127,8 @@ bail:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ocfs2_get_block(struct inode *inode, sector_t iblock,
|
||||
struct buffer_head *bh_result, int create)
|
||||
int ocfs2_get_block(struct inode *inode, sector_t iblock,
|
||||
struct buffer_head *bh_result, int create)
|
||||
{
|
||||
int err = 0;
|
||||
unsigned int ext_flags;
|
||||
@@ -590,6 +591,8 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock,
|
||||
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
|
||||
* the mapped bit on bh_result().
|
||||
@@ -687,6 +690,10 @@ static ssize_t ocfs2_direct_IO(int rw,
|
||||
if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
|
||||
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,
|
||||
inode->i_sb->s_bdev, iov, offset,
|
||||
nr_segs,
|
||||
@@ -1259,7 +1266,8 @@ static int ocfs2_write_cluster(struct address_space *mapping,
|
||||
goto out;
|
||||
}
|
||||
} 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,
|
||||
wc->w_handle, cpos, 1, phys,
|
||||
meta_ac, &wc->w_dealloc);
|
||||
@@ -1448,6 +1456,9 @@ static int ocfs2_populate_write_desc(struct inode *inode,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* We should already CoW the refcountd extent. */
|
||||
BUG_ON(ext_flags & OCFS2_EXT_REFCOUNTED);
|
||||
|
||||
/*
|
||||
* Assume worst case - that we're writing in
|
||||
* the middle of the extent.
|
||||
@@ -1528,7 +1539,7 @@ static int ocfs2_write_begin_inline(struct address_space *mapping,
|
||||
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);
|
||||
if (ret) {
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
@@ -1699,6 +1710,19 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
|
||||
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,
|
||||
&extents_to_split);
|
||||
if (ret) {
|
||||
@@ -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),
|
||||
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,
|
||||
clusters_to_alloc, extents_to_split,
|
||||
&data_ac, &meta_ac);
|
||||
@@ -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
|
||||
* 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);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
|
||||
@@ -57,6 +57,8 @@ int ocfs2_read_inline_data(struct inode *inode, struct page *page,
|
||||
struct buffer_head *di_bh);
|
||||
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 */
|
||||
#define ocfs2_iocb_is_rw_locked(iocb) \
|
||||
test_bit(0, (unsigned long *)&iocb->private)
|
||||
|
||||
+24
-23
@@ -52,12 +52,12 @@ enum ocfs2_state_bits {
|
||||
BUFFER_FNS(NeedsValidate, needs_validate);
|
||||
|
||||
int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh,
|
||||
struct inode *inode)
|
||||
struct ocfs2_caching_info *ci)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
mlog_entry("(bh->b_blocknr = %llu, inode=%p)\n",
|
||||
(unsigned long long)bh->b_blocknr, inode);
|
||||
mlog_entry("(bh->b_blocknr = %llu, ci=%p)\n",
|
||||
(unsigned long long)bh->b_blocknr, ci);
|
||||
|
||||
BUG_ON(bh->b_blocknr < OCFS2_SUPER_BLOCK_BLKNO);
|
||||
BUG_ON(buffer_jbd(bh));
|
||||
@@ -70,7 +70,7 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh,
|
||||
goto out;
|
||||
}
|
||||
|
||||
mutex_lock(&OCFS2_I(inode)->ip_io_mutex);
|
||||
ocfs2_metadata_cache_io_lock(ci);
|
||||
|
||||
lock_buffer(bh);
|
||||
set_buffer_uptodate(bh);
|
||||
@@ -85,7 +85,7 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh,
|
||||
wait_on_buffer(bh);
|
||||
|
||||
if (buffer_uptodate(bh)) {
|
||||
ocfs2_set_buffer_uptodate(inode, bh);
|
||||
ocfs2_set_buffer_uptodate(ci, bh);
|
||||
} else {
|
||||
/* We don't need to remove the clustered uptodate
|
||||
* 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,
|
||||
put_bh(bh);
|
||||
}
|
||||
|
||||
mutex_unlock(&OCFS2_I(inode)->ip_io_mutex);
|
||||
ocfs2_metadata_cache_io_unlock(ci);
|
||||
out:
|
||||
mlog_exit(ret);
|
||||
return ret;
|
||||
@@ -177,7 +177,7 @@ bail:
|
||||
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,
|
||||
int (*validate)(struct super_block *sb,
|
||||
struct buffer_head *bh))
|
||||
@@ -185,11 +185,12 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
|
||||
int status = 0;
|
||||
int i, ignore_cache = 0;
|
||||
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",
|
||||
inode, (unsigned long long)block, nr, flags);
|
||||
mlog_entry("(ci=%p, block=(%llu), nr=(%d), flags=%d)\n",
|
||||
ci, (unsigned long long)block, nr, flags);
|
||||
|
||||
BUG_ON(!inode);
|
||||
BUG_ON(!ci);
|
||||
BUG_ON((flags & OCFS2_BH_READAHEAD) &&
|
||||
(flags & OCFS2_BH_IGNORE_CACHE));
|
||||
|
||||
@@ -212,12 +213,12 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
|
||||
goto bail;
|
||||
}
|
||||
|
||||
mutex_lock(&OCFS2_I(inode)->ip_io_mutex);
|
||||
ocfs2_metadata_cache_io_lock(ci);
|
||||
for (i = 0 ; i < nr ; i++) {
|
||||
if (bhs[i] == NULL) {
|
||||
bhs[i] = sb_getblk(inode->i_sb, block++);
|
||||
bhs[i] = sb_getblk(sb, block++);
|
||||
if (bhs[i] == NULL) {
|
||||
mutex_unlock(&OCFS2_I(inode)->ip_io_mutex);
|
||||
ocfs2_metadata_cache_io_unlock(ci);
|
||||
status = -EIO;
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
@@ -250,11 +251,11 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
|
||||
* 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,
|
||||
"bh (%llu), inode %llu not uptodate\n",
|
||||
"bh (%llu), owner %llu not uptodate\n",
|
||||
(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
|
||||
* "go to disk" */
|
||||
ignore_cache = 1;
|
||||
@@ -283,7 +284,7 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
|
||||
* previously submitted request than we are
|
||||
* done here. */
|
||||
if ((flags & OCFS2_BH_READAHEAD)
|
||||
&& ocfs2_buffer_read_ahead(inode, bh))
|
||||
&& ocfs2_buffer_read_ahead(ci, bh))
|
||||
continue;
|
||||
|
||||
lock_buffer(bh);
|
||||
@@ -305,7 +306,7 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
|
||||
* buffer lock. */
|
||||
if (!(flags & OCFS2_BH_IGNORE_CACHE)
|
||||
&& !(flags & OCFS2_BH_READAHEAD)
|
||||
&& ocfs2_buffer_uptodate(inode, bh)) {
|
||||
&& ocfs2_buffer_uptodate(ci, bh)) {
|
||||
unlock_buffer(bh);
|
||||
continue;
|
||||
}
|
||||
@@ -327,7 +328,7 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
|
||||
|
||||
if (!(flags & OCFS2_BH_READAHEAD)) {
|
||||
/* 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. */
|
||||
if (!buffer_jbd(bh))
|
||||
wait_on_buffer(bh);
|
||||
@@ -351,7 +352,7 @@ int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
|
||||
* that better not have changed */
|
||||
BUG_ON(buffer_jbd(bh));
|
||||
clear_buffer_needs_validate(bh);
|
||||
status = validate(inode->i_sb, bh);
|
||||
status = validate(sb, bh);
|
||||
if (status) {
|
||||
put_bh(bh);
|
||||
bhs[i] = NULL;
|
||||
@@ -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
|
||||
* a forced read, or read-ahead which hasn't yet
|
||||
* 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",
|
||||
(unsigned long long)block, nr,
|
||||
@@ -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,
|
||||
* 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.
|
||||
*/
|
||||
int ocfs2_write_super_or_backup(struct ocfs2_super *osb,
|
||||
|
||||
@@ -33,7 +33,7 @@ void ocfs2_end_buffer_io_sync(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 ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block,
|
||||
unsigned int nr, struct buffer_head *bhs[]);
|
||||
|
||||
@@ -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
|
||||
* 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,
|
||||
int (*validate)(struct super_block *sb,
|
||||
struct buffer_head *bh));
|
||||
@@ -55,7 +55,7 @@ int ocfs2_write_super_or_backup(struct ocfs2_super *osb,
|
||||
#define OCFS2_BH_IGNORE_CACHE 1
|
||||
#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,
|
||||
int (*validate)(struct super_block *sb,
|
||||
struct buffer_head *bh))
|
||||
@@ -68,7 +68,7 @@ static inline int ocfs2_read_block(struct inode *inode, u64 off,
|
||||
goto bail;
|
||||
}
|
||||
|
||||
status = ocfs2_read_blocks(inode, off, 1, bh, 0, validate);
|
||||
status = ocfs2_read_blocks(ci, off, 1, bh, 0, validate);
|
||||
|
||||
bail:
|
||||
return status;
|
||||
|
||||
@@ -111,6 +111,7 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = {
|
||||
define_mask(EXPORT),
|
||||
define_mask(XATTR),
|
||||
define_mask(QUOTA),
|
||||
define_mask(REFCOUNT),
|
||||
define_mask(ERROR),
|
||||
define_mask(NOTICE),
|
||||
define_mask(KTHREAD),
|
||||
|
||||
@@ -113,6 +113,7 @@
|
||||
#define ML_EXPORT 0x0000000010000000ULL /* ocfs2 export operations */
|
||||
#define ML_XATTR 0x0000000020000000ULL /* ocfs2 extended attributes */
|
||||
#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 */
|
||||
#define ML_ERROR 0x0000000100000000ULL /* sent to KERN_ERR */
|
||||
#define ML_NOTICE 0x0000000200000000ULL /* setn to KERN_NOTICE */
|
||||
|
||||
+59
-48
@@ -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_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);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
@@ -564,7 +564,8 @@ static int ocfs2_read_dir_block_direct(struct inode *dir, u64 phys,
|
||||
int ret;
|
||||
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) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
@@ -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);
|
||||
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 (!ret && !*dx_root_bh)
|
||||
@@ -662,7 +664,8 @@ static int ocfs2_read_dx_leaf(struct inode *dir, u64 blkno,
|
||||
int ret;
|
||||
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 (!ret && !*dx_leaf_bh)
|
||||
@@ -680,7 +683,7 @@ static int ocfs2_read_dx_leaves(struct inode *dir, u64 start, int num,
|
||||
{
|
||||
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);
|
||||
if (ret)
|
||||
mlog_errno(ret);
|
||||
@@ -802,7 +805,8 @@ static int ocfs2_dx_dir_lookup_rec(struct inode *inode,
|
||||
struct ocfs2_extent_rec *rec = NULL;
|
||||
|
||||
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) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
@@ -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)
|
||||
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) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
@@ -1176,7 +1181,7 @@ static int __ocfs2_delete_entry(handle_t *handle, struct inode *dir,
|
||||
goto bail;
|
||||
}
|
||||
if (de == de_del) {
|
||||
status = access(handle, dir, bh,
|
||||
status = access(handle, INODE_CACHE(dir), bh,
|
||||
OCFS2_JOURNAL_ACCESS_WRITE);
|
||||
if (status < 0) {
|
||||
status = -EIO;
|
||||
@@ -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
|
||||
* 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);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
@@ -1334,7 +1339,7 @@ static int ocfs2_delete_entry_dx(handle_t *handle, struct inode *dir,
|
||||
}
|
||||
|
||||
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,
|
||||
OCFS2_JOURNAL_ACCESS_WRITE);
|
||||
if (ret) {
|
||||
@@ -1493,7 +1498,7 @@ static int __ocfs2_dx_dir_leaf_insert(struct inode *dir, handle_t *handle,
|
||||
int ret;
|
||||
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);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
@@ -1523,7 +1528,7 @@ static int ocfs2_dx_dir_insert(struct inode *dir, handle_t *handle,
|
||||
struct ocfs2_dx_root_block *dx_root;
|
||||
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);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
@@ -1645,11 +1650,13 @@ int __ocfs2_add_entry(handle_t *handle,
|
||||
*/
|
||||
if (ocfs2_free_list_at_root(lookup)) {
|
||||
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);
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
if (retval) {
|
||||
@@ -1700,11 +1707,13 @@ int __ocfs2_add_entry(handle_t *handle,
|
||||
}
|
||||
|
||||
if (insert_bh == parent_fe_bh)
|
||||
status = ocfs2_journal_access_di(handle, dir,
|
||||
status = ocfs2_journal_access_di(handle,
|
||||
INODE_CACHE(dir),
|
||||
insert_bh,
|
||||
OCFS2_JOURNAL_ACCESS_WRITE);
|
||||
else {
|
||||
status = ocfs2_journal_access_db(handle, dir,
|
||||
status = ocfs2_journal_access_db(handle,
|
||||
INODE_CACHE(dir),
|
||||
insert_bh,
|
||||
OCFS2_JOURNAL_ACCESS_WRITE);
|
||||
|
||||
@@ -2280,7 +2289,7 @@ static int ocfs2_fill_new_dir_id(struct ocfs2_super *osb,
|
||||
struct ocfs2_inline_data *data = &di->id2.i_data;
|
||||
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);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
@@ -2332,9 +2341,9 @@ static int ocfs2_fill_new_dir_el(struct ocfs2_super *osb,
|
||||
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);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
@@ -2418,9 +2427,9 @@ static int ocfs2_dx_dir_attach_index(struct ocfs2_super *osb,
|
||||
ret = -EIO;
|
||||
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);
|
||||
if (ret < 0) {
|
||||
mlog_errno(ret);
|
||||
@@ -2454,7 +2463,7 @@ static int ocfs2_dx_dir_attach_index(struct ocfs2_super *osb,
|
||||
if (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);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
@@ -2495,9 +2504,9 @@ static int ocfs2_dx_dir_format_cluster(struct ocfs2_super *osb,
|
||||
}
|
||||
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);
|
||||
if (ret < 0) {
|
||||
mlog_errno(ret);
|
||||
@@ -2582,7 +2591,6 @@ static int ocfs2_dx_dir_new_cluster(struct inode *dir,
|
||||
{
|
||||
int ret;
|
||||
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,
|
||||
num_dx_leaves, &phys_blkno);
|
||||
@@ -2591,7 +2599,7 @@ static int ocfs2_dx_dir_new_cluster(struct inode *dir,
|
||||
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);
|
||||
if (ret)
|
||||
mlog_errno(ret);
|
||||
@@ -2895,7 +2903,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
|
||||
struct ocfs2_extent_tree dx_et;
|
||||
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);
|
||||
dx_alloc = 0;
|
||||
@@ -3005,9 +3013,9 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
|
||||
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);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
@@ -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
|
||||
* 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);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
@@ -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
|
||||
* 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);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
@@ -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,
|
||||
dirdata_bh);
|
||||
} else {
|
||||
ocfs2_init_dx_root_extent_tree(&dx_et, dir, dx_root_bh);
|
||||
ret = ocfs2_insert_extent(osb, handle, dir, &dx_et, 0,
|
||||
ocfs2_init_dx_root_extent_tree(&dx_et,
|
||||
INODE_CACHE(dir),
|
||||
dx_root_bh);
|
||||
ret = ocfs2_insert_extent(handle, &dx_et, 0,
|
||||
dx_insert_blkno, 1, 0, NULL);
|
||||
if (ret)
|
||||
mlog_errno(ret);
|
||||
@@ -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);
|
||||
|
||||
ret = ocfs2_insert_extent(osb, handle, dir, &et, 1,
|
||||
ret = ocfs2_insert_extent(handle, &et, 1,
|
||||
blkno, len, 0, NULL);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
@@ -3337,8 +3347,9 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
|
||||
spin_lock(&OCFS2_I(dir)->ip_lock);
|
||||
if (dir_i_size == ocfs2_clusters_to_bytes(sb, OCFS2_I(dir)->ip_clusters)) {
|
||||
spin_unlock(&OCFS2_I(dir)->ip_lock);
|
||||
ocfs2_init_dinode_extent_tree(&et, dir, parent_fe_bh);
|
||||
num_free_extents = ocfs2_num_free_extents(osb, dir, &et);
|
||||
ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(dir),
|
||||
parent_fe_bh);
|
||||
num_free_extents = ocfs2_num_free_extents(osb, &et);
|
||||
if (num_free_extents < 0) {
|
||||
status = num_free_extents;
|
||||
mlog_errno(status);
|
||||
@@ -3387,9 +3398,9 @@ do_extend:
|
||||
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);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
@@ -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)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;
|
||||
/*
|
||||
@@ -3885,7 +3896,7 @@ static int ocfs2_dx_dir_rebalance(struct ocfs2_super *osb, struct inode *dir,
|
||||
}
|
||||
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);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
@@ -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++) {
|
||||
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);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
@@ -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
|
||||
* 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);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
@@ -4207,9 +4219,8 @@ static int ocfs2_expand_inline_dx_root(struct inode *dir,
|
||||
|
||||
/* This should never fail considering we start with an empty
|
||||
* dx_root. */
|
||||
ocfs2_init_dx_root_extent_tree(&et, dir, dx_root_bh);
|
||||
ret = ocfs2_insert_extent(osb, handle, dir, &et, 0,
|
||||
insert_blkno, 1, 0, NULL);
|
||||
ocfs2_init_dx_root_extent_tree(&et, INODE_CACHE(dir), dx_root_bh);
|
||||
ret = ocfs2_insert_extent(handle, &et, 0, insert_blkno, 1, 0, NULL);
|
||||
if (ret)
|
||||
mlog_errno(ret);
|
||||
did_quota = 0;
|
||||
@@ -4469,7 +4480,7 @@ static int ocfs2_dx_dir_remove_index(struct inode *dir,
|
||||
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);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
@@ -4532,7 +4543,7 @@ int ocfs2_dx_dir_truncate(struct inode *dir, struct buffer_head *di_bh)
|
||||
if (ocfs2_dx_root_inline(dx_root))
|
||||
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? */
|
||||
while (le32_to_cpu(dx_root->dr_clusters)) {
|
||||
@@ -4565,7 +4576,7 @@ remove_index:
|
||||
goto out;
|
||||
}
|
||||
|
||||
ocfs2_remove_from_cache(dir, dx_root_bh);
|
||||
ocfs2_remove_from_cache(INODE_CACHE(dir), dx_root_bh);
|
||||
out:
|
||||
ocfs2_schedule_truncate_log_flush(osb, 1);
|
||||
ocfs2_run_deallocs(osb, &dealloc);
|
||||
|
||||
@@ -212,14 +212,18 @@ static int dlm_purge_lockres(struct dlm_ctxt *dlm,
|
||||
spin_lock(&dlm->spinlock);
|
||||
}
|
||||
|
||||
spin_lock(&res->spinlock);
|
||||
if (!list_empty(&res->purge)) {
|
||||
mlog(0, "removing lockres %.*s:%p from purgelist, "
|
||||
"master = %d\n", res->lockname.len, res->lockname.name,
|
||||
res, master);
|
||||
list_del_init(&res->purge);
|
||||
spin_unlock(&res->spinlock);
|
||||
dlm_lockres_put(res);
|
||||
dlm->purge_count--;
|
||||
}
|
||||
} else
|
||||
spin_unlock(&res->spinlock);
|
||||
|
||||
__dlm_unhash_lockres(res);
|
||||
|
||||
/* lockres is not in the hash now. drop the flag and wake up
|
||||
|
||||
+98
-7
@@ -53,6 +53,7 @@
|
||||
#include "super.h"
|
||||
#include "uptodate.h"
|
||||
#include "quota.h"
|
||||
#include "refcounttree.h"
|
||||
|
||||
#include "buffer_head_io.h"
|
||||
|
||||
@@ -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 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)
|
||||
|
||||
/* 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 = {
|
||||
.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)
|
||||
{
|
||||
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
|
||||
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)
|
||||
{
|
||||
if (lockres->l_ops->get_osb)
|
||||
@@ -693,6 +711,17 @@ void ocfs2_qinfo_lock_res_init(struct ocfs2_lock_res *lockres,
|
||||
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)
|
||||
{
|
||||
mlog_entry_void();
|
||||
@@ -1548,8 +1577,10 @@ int ocfs2_rw_lock(struct inode *inode, int write)
|
||||
(unsigned long long)OCFS2_I(inode)->ip_blkno,
|
||||
write ? "EXMODE" : "PRMODE");
|
||||
|
||||
if (ocfs2_mount_local(osb))
|
||||
if (ocfs2_mount_local(osb)) {
|
||||
mlog_exit(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
lockres = &OCFS2_I(inode)->ip_rw_lockres;
|
||||
|
||||
@@ -2127,7 +2158,7 @@ static int ocfs2_inode_lock_update(struct inode *inode,
|
||||
|
||||
/* This will discard any caching information we might have had
|
||||
* for the inode metadata. */
|
||||
ocfs2_metadata_cache_purge(inode);
|
||||
ocfs2_metadata_cache_purge(INODE_CACHE(inode));
|
||||
|
||||
ocfs2_extent_map_trunc(inode, 0);
|
||||
|
||||
@@ -3009,6 +3040,7 @@ static void ocfs2_unlock_ast(void *opaque, int error)
|
||||
"unlock_action %d\n", error, lockres->l_name,
|
||||
lockres->l_unlock_action);
|
||||
spin_unlock_irqrestore(&lockres->l_lock, flags);
|
||||
mlog_exit_void();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3495,11 +3527,11 @@ out:
|
||||
return UNBLOCK_CONTINUE;
|
||||
}
|
||||
|
||||
static int ocfs2_check_meta_downconvert(struct ocfs2_lock_res *lockres,
|
||||
int new_level)
|
||||
static int ocfs2_ci_checkpointed(struct ocfs2_caching_info *ci,
|
||||
struct ocfs2_lock_res *lockres,
|
||||
int new_level)
|
||||
{
|
||||
struct inode *inode = ocfs2_lock_res_inode(lockres);
|
||||
int checkpointed = ocfs2_inode_fully_checkpointed(inode);
|
||||
int checkpointed = ocfs2_ci_fully_checkpointed(ci);
|
||||
|
||||
BUG_ON(new_level != DLM_LOCK_NL && new_level != DLM_LOCK_PR);
|
||||
BUG_ON(lockres->l_level != DLM_LOCK_EX && !checkpointed);
|
||||
@@ -3507,10 +3539,18 @@ static int ocfs2_check_meta_downconvert(struct ocfs2_lock_res *lockres,
|
||||
if (checkpointed)
|
||||
return 1;
|
||||
|
||||
ocfs2_start_checkpoint(OCFS2_SB(inode->i_sb));
|
||||
ocfs2_start_checkpoint(OCFS2_SB(ocfs2_metadata_cache_get_super(ci)));
|
||||
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)
|
||||
{
|
||||
struct inode *inode = ocfs2_lock_res_inode(lockres);
|
||||
@@ -3640,6 +3680,26 @@ static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres,
|
||||
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)
|
||||
{
|
||||
struct ocfs2_qinfo_lvb *lvb;
|
||||
@@ -3752,6 +3812,37 @@ bail:
|
||||
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
|
||||
* 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,
|
||||
struct ocfs2_mem_dqinfo;
|
||||
void ocfs2_qinfo_lock_res_init(struct ocfs2_lock_res *lockres,
|
||||
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);
|
||||
int ocfs2_create_new_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);
|
||||
void ocfs2_file_unlock(struct file *file);
|
||||
int ocfs2_qinfo_lock(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);
|
||||
|
||||
+20
-13
@@ -293,7 +293,7 @@ static int ocfs2_last_eb_is_empty(struct inode *inode,
|
||||
struct ocfs2_extent_block *eb;
|
||||
struct ocfs2_extent_list *el;
|
||||
|
||||
ret = ocfs2_read_extent_block(inode, last_eb_blk, &eb_bh);
|
||||
ret = ocfs2_read_extent_block(INODE_CACHE(inode), last_eb_blk, &eb_bh);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
@@ -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
|
||||
* containing el.
|
||||
*/
|
||||
static int ocfs2_figure_hole_clusters(struct inode *inode,
|
||||
struct ocfs2_extent_list *el,
|
||||
struct buffer_head *eb_bh,
|
||||
u32 v_cluster,
|
||||
u32 *num_clusters)
|
||||
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)
|
||||
{
|
||||
int ret, i;
|
||||
struct buffer_head *next_eb_bh = NULL;
|
||||
@@ -375,7 +375,7 @@ static int ocfs2_figure_hole_clusters(struct inode *inode,
|
||||
if (le64_to_cpu(eb->h_next_leaf_blk) == 0ULL)
|
||||
goto no_more_extents;
|
||||
|
||||
ret = ocfs2_read_extent_block(inode,
|
||||
ret = ocfs2_read_extent_block(ci,
|
||||
le64_to_cpu(eb->h_next_leaf_blk),
|
||||
&next_eb_bh);
|
||||
if (ret) {
|
||||
@@ -428,7 +428,8 @@ static int ocfs2_get_clusters_nocache(struct inode *inode,
|
||||
tree_height = le16_to_cpu(el->l_tree_depth);
|
||||
|
||||
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) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
@@ -455,7 +456,8 @@ static int ocfs2_get_clusters_nocache(struct inode *inode,
|
||||
* field.
|
||||
*/
|
||||
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);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
@@ -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,
|
||||
u32 *p_cluster, u32 *num_clusters,
|
||||
struct ocfs2_extent_list *el)
|
||||
struct ocfs2_extent_list *el,
|
||||
unsigned int *extent_flags)
|
||||
{
|
||||
int ret = 0, i;
|
||||
struct buffer_head *eb_bh = NULL;
|
||||
@@ -548,7 +551,8 @@ int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster,
|
||||
u32 coff;
|
||||
|
||||
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) {
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
@@ -590,6 +594,9 @@ int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster,
|
||||
*p_cluster = *p_cluster + coff;
|
||||
if (num_clusters)
|
||||
*num_clusters = ocfs2_rec_clusters(el, rec) - coff;
|
||||
|
||||
if (extent_flags)
|
||||
*extent_flags = rec->e_flags;
|
||||
}
|
||||
out:
|
||||
if (eb_bh)
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
rc = ocfs2_read_blocks(inode, p_block, count, bhs + done,
|
||||
flags, validate);
|
||||
rc = ocfs2_read_blocks(INODE_CACHE(inode), p_block, count,
|
||||
bhs + done, flags, validate);
|
||||
if (rc) {
|
||||
mlog_errno(rc);
|
||||
break;
|
||||
|
||||
@@ -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,
|
||||
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,
|
||||
struct buffer_head *bhs[], int flags,
|
||||
int (*validate)(struct super_block *sb,
|
||||
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,
|
||||
struct buffer_head **bh,
|
||||
int (*validate)(struct super_block *sb,
|
||||
|
||||
+139
-12
@@ -59,6 +59,7 @@
|
||||
#include "xattr.h"
|
||||
#include "acl.h"
|
||||
#include "quota.h"
|
||||
#include "refcounttree.h"
|
||||
|
||||
#include "buffer_head_io.h"
|
||||
|
||||
@@ -259,7 +260,7 @@ int ocfs2_update_inode_atime(struct inode *inode,
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = ocfs2_journal_access_di(handle, inode, bh,
|
||||
ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), bh,
|
||||
OCFS2_JOURNAL_ACCESS_WRITE);
|
||||
if (ret) {
|
||||
mlog_errno(ret);
|
||||
@@ -334,6 +335,39 @@ out:
|
||||
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,
|
||||
struct inode *inode,
|
||||
struct buffer_head *fe_bh,
|
||||
@@ -346,6 +380,17 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb,
|
||||
|
||||
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
|
||||
* transaction. */
|
||||
|
||||
@@ -356,7 +401,7 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb,
|
||||
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);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
@@ -486,6 +531,8 @@ bail_unlock_sem:
|
||||
up_write(&OCFS2_I(inode)->ip_alloc_sem);
|
||||
|
||||
bail:
|
||||
if (!status && OCFS2_I(inode)->ip_clusters == 0)
|
||||
status = ocfs2_try_remove_refcount_tree(inode, di_bh);
|
||||
|
||||
mlog_exit(status);
|
||||
return status;
|
||||
@@ -515,11 +562,10 @@ int ocfs2_add_inode_data(struct ocfs2_super *osb,
|
||||
int ret;
|
||||
struct ocfs2_extent_tree et;
|
||||
|
||||
ocfs2_init_dinode_extent_tree(&et, inode, fe_bh);
|
||||
ret = ocfs2_add_clusters_in_btree(osb, inode, logical_offset,
|
||||
clusters_to_add, mark_unwritten,
|
||||
&et, handle,
|
||||
data_ac, meta_ac, reason_ret);
|
||||
ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), fe_bh);
|
||||
ret = ocfs2_add_clusters_in_btree(handle, &et, logical_offset,
|
||||
clusters_to_add, mark_unwritten,
|
||||
data_ac, meta_ac, reason_ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -564,7 +610,7 @@ restart_all:
|
||||
(unsigned long long)OCFS2_I(inode)->ip_blkno,
|
||||
(long long)i_size_read(inode), le32_to_cpu(fe->i_clusters),
|
||||
clusters_to_add);
|
||||
ocfs2_init_dinode_extent_tree(&et, inode, bh);
|
||||
ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), bh);
|
||||
status = ocfs2_lock_allocators(inode, &et, clusters_to_add, 0,
|
||||
&data_ac, &meta_ac);
|
||||
if (status) {
|
||||
@@ -593,7 +639,7 @@ restarted_transaction:
|
||||
/* reserve a write to the file entry early on - that we if we
|
||||
* run out of credits in the allocation path, we can still
|
||||
* 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);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
@@ -1131,7 +1177,7 @@ static int __ocfs2_write_remove_suid(struct inode *inode,
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = ocfs2_journal_access_di(handle, inode, bh,
|
||||
ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), bh,
|
||||
OCFS2_JOURNAL_ACCESS_WRITE);
|
||||
if (ret < 0) {
|
||||
mlog_errno(ret);
|
||||
@@ -1395,7 +1441,7 @@ static int ocfs2_remove_inode_range(struct inode *inode,
|
||||
struct address_space *mapping = inode->i_mapping;
|
||||
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);
|
||||
|
||||
if (byte_len == 0)
|
||||
@@ -1657,6 +1703,70 @@ static long ocfs2_fallocate(struct inode *inode, int mode, loff_t offset,
|
||||
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,
|
||||
loff_t *ppos,
|
||||
size_t count,
|
||||
@@ -1713,6 +1823,22 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
|
||||
|
||||
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
|
||||
* them.
|
||||
@@ -1759,7 +1885,8 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
|
||||
*ppos = saved_pos;
|
||||
|
||||
out_unlock:
|
||||
ocfs2_inode_unlock(inode, meta_level);
|
||||
if (meta_level >= 0)
|
||||
ocfs2_inode_unlock(inode, meta_level);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
|
||||
@@ -69,4 +69,6 @@ int ocfs2_update_inode_atime(struct inode *inode,
|
||||
int ocfs2_change_file_space(struct file *file, unsigned int cmd,
|
||||
struct ocfs2_space_resv *sr);
|
||||
|
||||
int ocfs2_check_range_for_refcount(struct inode *inode, loff_t pos,
|
||||
size_t count);
|
||||
#endif /* OCFS2_FILE_H */
|
||||
|
||||
+73
-13
@@ -53,6 +53,7 @@
|
||||
#include "sysfile.h"
|
||||
#include "uptodate.h"
|
||||
#include "xattr.h"
|
||||
#include "refcounttree.h"
|
||||
|
||||
#include "buffer_head_io.h"
|
||||
|
||||
@@ -562,7 +563,8 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb,
|
||||
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);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
@@ -646,7 +648,7 @@ static int ocfs2_remove_inode(struct inode *inode,
|
||||
}
|
||||
|
||||
/* 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);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
@@ -662,7 +664,7 @@ static int ocfs2_remove_inode(struct inode *inode,
|
||||
goto bail_commit;
|
||||
}
|
||||
|
||||
ocfs2_remove_from_cache(inode, di_bh);
|
||||
ocfs2_remove_from_cache(INODE_CACHE(inode), di_bh);
|
||||
vfs_dq_free_inode(inode);
|
||||
|
||||
status = ocfs2_free_dinode(handle, inode_alloc_inode,
|
||||
@@ -781,6 +783,12 @@ static int ocfs2_wipe_inode(struct inode *inode,
|
||||
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,
|
||||
orphan_dir_bh);
|
||||
if (status < 0)
|
||||
@@ -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_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",
|
||||
(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",
|
||||
(unsigned long long)oi->ip_blkno);
|
||||
|
||||
@@ -1145,9 +1154,7 @@ void ocfs2_clear_inode(struct inode *inode)
|
||||
(unsigned long long)oi->ip_blkno, oi->ip_open_count);
|
||||
|
||||
/* Clear all other flags. */
|
||||
oi->ip_flags = OCFS2_INODE_CACHE_INLINE;
|
||||
oi->ip_created_trans = 0;
|
||||
oi->ip_last_trans = 0;
|
||||
oi->ip_flags = 0;
|
||||
oi->ip_dir_start_lookup = 0;
|
||||
oi->ip_blkno = 0ULL;
|
||||
|
||||
@@ -1239,7 +1246,7 @@ int ocfs2_mark_inode_dirty(handle_t *handle,
|
||||
mlog_entry("(inode %llu)\n",
|
||||
(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);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
@@ -1380,8 +1387,8 @@ int ocfs2_read_inode_block_full(struct inode *inode, struct buffer_head **bh,
|
||||
int rc;
|
||||
struct buffer_head *tmp = *bh;
|
||||
|
||||
rc = ocfs2_read_blocks(inode, OCFS2_I(inode)->ip_blkno, 1, &tmp,
|
||||
flags, ocfs2_validate_inode_block);
|
||||
rc = ocfs2_read_blocks(INODE_CACHE(inode), OCFS2_I(inode)->ip_blkno,
|
||||
1, &tmp, flags, ocfs2_validate_inode_block);
|
||||
|
||||
/* If ocfs2_read_blocks() got us a new bh, pass it up. */
|
||||
if (!rc && !*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);
|
||||
}
|
||||
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
|
||||
+12
-8
@@ -60,12 +60,6 @@ struct ocfs2_inode_info
|
||||
|
||||
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_extent_map ip_extent_map;
|
||||
@@ -106,8 +100,6 @@ struct ocfs2_inode_info
|
||||
#define OCFS2_INODE_MAYBE_ORPHANED 0x00000020
|
||||
/* Does someone have the file open O_DIRECT */
|
||||
#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)
|
||||
{
|
||||
@@ -120,6 +112,12 @@ static inline struct ocfs2_inode_info *OCFS2_I(struct inode *inode)
|
||||
extern struct kmem_cache *ocfs2_inode_cache;
|
||||
|
||||
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_delete_inode(struct inode *inode);
|
||||
@@ -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 */
|
||||
int ocfs2_read_inode_block_full(struct inode *inode, struct buffer_head **bh,
|
||||
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 */
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "ocfs2_fs.h"
|
||||
#include "ioctl.h"
|
||||
#include "resize.h"
|
||||
#include "refcounttree.h"
|
||||
|
||||
#include <linux/ext2_fs.h>
|
||||
|
||||
@@ -115,6 +116,9 @@ long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
int status;
|
||||
struct ocfs2_space_resv sr;
|
||||
struct ocfs2_new_group_input input;
|
||||
struct reflink_arguments args;
|
||||
const char *old_path, *new_path;
|
||||
bool preserve;
|
||||
|
||||
switch (cmd) {
|
||||
case OCFS2_IOC_GETFLAGS:
|
||||
@@ -160,6 +164,15 @@ long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
return -EFAULT;
|
||||
|
||||
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:
|
||||
return -ENOTTY;
|
||||
}
|
||||
@@ -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_ADD:
|
||||
case OCFS2_IOC_GROUP_ADD64:
|
||||
case OCFS2_IOC_REFLINK:
|
||||
break;
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user