|
@@ -141,6 +141,13 @@ struct ocfs2_xattr_search {
|
|
|
/* Operations on struct ocfs2_xa_entry */
|
|
|
struct ocfs2_xa_loc;
|
|
|
struct ocfs2_xa_loc_operations {
|
|
|
+ /*
|
|
|
+ * Journal functions
|
|
|
+ */
|
|
|
+ int (*xlo_journal_access)(handle_t *handle, struct ocfs2_xa_loc *loc,
|
|
|
+ int type);
|
|
|
+ void (*xlo_journal_dirty)(handle_t *handle, struct ocfs2_xa_loc *loc);
|
|
|
+
|
|
|
/*
|
|
|
* Return a pointer to the appropriate buffer in loc->xl_storage
|
|
|
* at the given offset from loc->xl_header.
|
|
@@ -186,6 +193,9 @@ struct ocfs2_xa_loc_operations {
|
|
|
* tracking the on-disk structure.
|
|
|
*/
|
|
|
struct ocfs2_xa_loc {
|
|
|
+ /* This xattr belongs to this inode */
|
|
|
+ struct inode *xl_inode;
|
|
|
+
|
|
|
/* The ocfs2_xattr_header inside the on-disk storage. Not NULL. */
|
|
|
struct ocfs2_xattr_header *xl_header;
|
|
|
|
|
@@ -1540,6 +1550,17 @@ static int ocfs2_xa_check_space_helper(int needed_space, int free_start,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int ocfs2_xa_journal_access(handle_t *handle, struct ocfs2_xa_loc *loc,
|
|
|
+ int type)
|
|
|
+{
|
|
|
+ return loc->xl_ops->xlo_journal_access(handle, loc, type);
|
|
|
+}
|
|
|
+
|
|
|
+static void ocfs2_xa_journal_dirty(handle_t *handle, struct ocfs2_xa_loc *loc)
|
|
|
+{
|
|
|
+ loc->xl_ops->xlo_journal_dirty(handle, loc);
|
|
|
+}
|
|
|
+
|
|
|
/* Give a pointer into the storage for the given offset */
|
|
|
static void *ocfs2_xa_offset_pointer(struct ocfs2_xa_loc *loc, int offset)
|
|
|
{
|
|
@@ -1629,6 +1650,29 @@ static void ocfs2_xa_fill_value_buf(struct ocfs2_xa_loc *loc,
|
|
|
name_size);
|
|
|
}
|
|
|
|
|
|
+static int ocfs2_xa_block_journal_access(handle_t *handle,
|
|
|
+ struct ocfs2_xa_loc *loc, int type)
|
|
|
+{
|
|
|
+ struct buffer_head *bh = loc->xl_storage;
|
|
|
+ ocfs2_journal_access_func access;
|
|
|
+
|
|
|
+ if (loc->xl_size == (bh->b_size -
|
|
|
+ offsetof(struct ocfs2_xattr_block,
|
|
|
+ xb_attrs.xb_header)))
|
|
|
+ access = ocfs2_journal_access_xb;
|
|
|
+ else
|
|
|
+ access = ocfs2_journal_access_di;
|
|
|
+ return access(handle, INODE_CACHE(loc->xl_inode), bh, type);
|
|
|
+}
|
|
|
+
|
|
|
+static void ocfs2_xa_block_journal_dirty(handle_t *handle,
|
|
|
+ struct ocfs2_xa_loc *loc)
|
|
|
+{
|
|
|
+ struct buffer_head *bh = loc->xl_storage;
|
|
|
+
|
|
|
+ ocfs2_journal_dirty(handle, bh);
|
|
|
+}
|
|
|
+
|
|
|
static void *ocfs2_xa_block_offset_pointer(struct ocfs2_xa_loc *loc,
|
|
|
int offset)
|
|
|
{
|
|
@@ -1755,6 +1799,8 @@ static void ocfs2_xa_block_fill_value_buf(struct ocfs2_xa_loc *loc,
|
|
|
* storage and unindexed ocfs2_xattr_blocks.
|
|
|
*/
|
|
|
static const struct ocfs2_xa_loc_operations ocfs2_xa_block_loc_ops = {
|
|
|
+ .xlo_journal_access = ocfs2_xa_block_journal_access,
|
|
|
+ .xlo_journal_dirty = ocfs2_xa_block_journal_dirty,
|
|
|
.xlo_offset_pointer = ocfs2_xa_block_offset_pointer,
|
|
|
.xlo_check_space = ocfs2_xa_block_check_space,
|
|
|
.xlo_can_reuse = ocfs2_xa_block_can_reuse,
|
|
@@ -1765,6 +1811,22 @@ static const struct ocfs2_xa_loc_operations ocfs2_xa_block_loc_ops = {
|
|
|
.xlo_fill_value_buf = ocfs2_xa_block_fill_value_buf,
|
|
|
};
|
|
|
|
|
|
+static int ocfs2_xa_bucket_journal_access(handle_t *handle,
|
|
|
+ struct ocfs2_xa_loc *loc, int type)
|
|
|
+{
|
|
|
+ struct ocfs2_xattr_bucket *bucket = loc->xl_storage;
|
|
|
+
|
|
|
+ return ocfs2_xattr_bucket_journal_access(handle, bucket, type);
|
|
|
+}
|
|
|
+
|
|
|
+static void ocfs2_xa_bucket_journal_dirty(handle_t *handle,
|
|
|
+ struct ocfs2_xa_loc *loc)
|
|
|
+{
|
|
|
+ struct ocfs2_xattr_bucket *bucket = loc->xl_storage;
|
|
|
+
|
|
|
+ ocfs2_xattr_bucket_journal_dirty(handle, bucket);
|
|
|
+}
|
|
|
+
|
|
|
static void *ocfs2_xa_bucket_offset_pointer(struct ocfs2_xa_loc *loc,
|
|
|
int offset)
|
|
|
{
|
|
@@ -1772,8 +1834,8 @@ static void *ocfs2_xa_bucket_offset_pointer(struct ocfs2_xa_loc *loc,
|
|
|
int block, block_offset;
|
|
|
|
|
|
/* The header is at the front of the bucket */
|
|
|
- block = offset >> bucket->bu_inode->i_sb->s_blocksize_bits;
|
|
|
- block_offset = offset % bucket->bu_inode->i_sb->s_blocksize;
|
|
|
+ block = offset >> loc->xl_inode->i_sb->s_blocksize_bits;
|
|
|
+ block_offset = offset % loc->xl_inode->i_sb->s_blocksize;
|
|
|
|
|
|
return bucket_block(bucket, block) + block_offset;
|
|
|
}
|
|
@@ -1813,8 +1875,7 @@ static int ocfs2_xa_bucket_check_space(struct ocfs2_xa_loc *loc,
|
|
|
int free_start = ocfs2_xa_get_free_start(loc);
|
|
|
int needed_space = ocfs2_xi_entry_usage(xi);
|
|
|
int size = namevalue_size_xi(xi);
|
|
|
- struct ocfs2_xattr_bucket *bucket = loc->xl_storage;
|
|
|
- struct super_block *sb = bucket->bu_inode->i_sb;
|
|
|
+ struct super_block *sb = loc->xl_inode->i_sb;
|
|
|
|
|
|
/*
|
|
|
* Bucket storage does not reclaim name+value pairs it cannot
|
|
@@ -1896,8 +1957,7 @@ static void ocfs2_xa_bucket_add_namevalue(struct ocfs2_xa_loc *loc, int size)
|
|
|
{
|
|
|
int free_start = ocfs2_xa_get_free_start(loc);
|
|
|
struct ocfs2_xattr_header *xh = loc->xl_header;
|
|
|
- struct ocfs2_xattr_bucket *bucket = loc->xl_storage;
|
|
|
- struct super_block *sb = bucket->bu_inode->i_sb;
|
|
|
+ struct super_block *sb = loc->xl_inode->i_sb;
|
|
|
int nameval_offset;
|
|
|
|
|
|
free_start = ocfs2_bucket_align_free_start(sb, free_start, size);
|
|
@@ -1912,7 +1972,7 @@ static void ocfs2_xa_bucket_fill_value_buf(struct ocfs2_xa_loc *loc,
|
|
|
struct ocfs2_xattr_value_buf *vb)
|
|
|
{
|
|
|
struct ocfs2_xattr_bucket *bucket = loc->xl_storage;
|
|
|
- struct super_block *sb = bucket->bu_inode->i_sb;
|
|
|
+ struct super_block *sb = loc->xl_inode->i_sb;
|
|
|
int nameval_offset = le16_to_cpu(loc->xl_entry->xe_name_offset);
|
|
|
int size = namevalue_size_xe(loc->xl_entry);
|
|
|
int block_offset = nameval_offset >> sb->s_blocksize_bits;
|
|
@@ -1929,6 +1989,8 @@ static void ocfs2_xa_bucket_fill_value_buf(struct ocfs2_xa_loc *loc,
|
|
|
|
|
|
/* Operations for xattrs stored in buckets. */
|
|
|
static const struct ocfs2_xa_loc_operations ocfs2_xa_bucket_loc_ops = {
|
|
|
+ .xlo_journal_access = ocfs2_xa_bucket_journal_access,
|
|
|
+ .xlo_journal_dirty = ocfs2_xa_bucket_journal_dirty,
|
|
|
.xlo_offset_pointer = ocfs2_xa_bucket_offset_pointer,
|
|
|
.xlo_check_space = ocfs2_xa_bucket_check_space,
|
|
|
.xlo_can_reuse = ocfs2_xa_bucket_can_reuse,
|
|
@@ -2049,6 +2111,7 @@ static void ocfs2_init_dinode_xa_loc(struct ocfs2_xa_loc *loc,
|
|
|
{
|
|
|
struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data;
|
|
|
|
|
|
+ loc->xl_inode = inode;
|
|
|
loc->xl_ops = &ocfs2_xa_block_loc_ops;
|
|
|
loc->xl_storage = bh;
|
|
|
loc->xl_entry = entry;
|
|
@@ -2065,6 +2128,7 @@ static void ocfs2_init_dinode_xa_loc(struct ocfs2_xa_loc *loc,
|
|
|
}
|
|
|
|
|
|
static void ocfs2_init_xattr_block_xa_loc(struct ocfs2_xa_loc *loc,
|
|
|
+ struct inode *inode,
|
|
|
struct buffer_head *bh,
|
|
|
struct ocfs2_xattr_entry *entry)
|
|
|
{
|
|
@@ -2073,6 +2137,7 @@ static void ocfs2_init_xattr_block_xa_loc(struct ocfs2_xa_loc *loc,
|
|
|
|
|
|
BUG_ON(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED);
|
|
|
|
|
|
+ loc->xl_inode = inode;
|
|
|
loc->xl_ops = &ocfs2_xa_block_loc_ops;
|
|
|
loc->xl_storage = bh;
|
|
|
loc->xl_header = &(xb->xb_attrs.xb_header);
|
|
@@ -2085,6 +2150,7 @@ static void ocfs2_init_xattr_bucket_xa_loc(struct ocfs2_xa_loc *loc,
|
|
|
struct ocfs2_xattr_bucket *bucket,
|
|
|
struct ocfs2_xattr_entry *entry)
|
|
|
{
|
|
|
+ loc->xl_inode = bucket->bu_inode;
|
|
|
loc->xl_ops = &ocfs2_xa_bucket_loc_ops;
|
|
|
loc->xl_storage = bucket;
|
|
|
loc->xl_header = bucket_xh(bucket);
|
|
@@ -2226,21 +2292,18 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- if (!(flag & OCFS2_INLINE_XATTR_FL)) {
|
|
|
- ret = vb.vb_access(handle, INODE_CACHE(inode), vb.vb_bh,
|
|
|
- OCFS2_JOURNAL_ACCESS_WRITE);
|
|
|
- if (ret) {
|
|
|
- mlog_errno(ret);
|
|
|
- goto out;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
if (xs->xattr_bh == xs->inode_bh)
|
|
|
ocfs2_init_dinode_xa_loc(&loc, inode, xs->inode_bh,
|
|
|
xs->not_found ? NULL : xs->here);
|
|
|
else
|
|
|
- ocfs2_init_xattr_block_xa_loc(&loc, xs->xattr_bh,
|
|
|
+ ocfs2_init_xattr_block_xa_loc(&loc, inode, xs->xattr_bh,
|
|
|
xs->not_found ? NULL : xs->here);
|
|
|
+ ret = ocfs2_xa_journal_access(handle, &loc,
|
|
|
+ OCFS2_JOURNAL_ACCESS_WRITE);
|
|
|
+ if (ret) {
|
|
|
+ mlog_errno(ret);
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
|
|
|
/*
|
|
|
* Prepare our entry and insert the inline value. This will
|
|
@@ -2258,13 +2321,7 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
|
|
|
ocfs2_xa_store_inline_value(&loc, xi);
|
|
|
xs->here = loc.xl_entry;
|
|
|
|
|
|
- if (!(flag & OCFS2_INLINE_XATTR_FL)) {
|
|
|
- ret = ocfs2_journal_dirty(handle, xs->xattr_bh);
|
|
|
- if (ret < 0) {
|
|
|
- mlog_errno(ret);
|
|
|
- goto out;
|
|
|
- }
|
|
|
- }
|
|
|
+ ocfs2_xa_journal_dirty(handle, &loc);
|
|
|
|
|
|
if (!(oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL) &&
|
|
|
(flag & OCFS2_INLINE_XATTR_FL)) {
|
|
@@ -5325,15 +5382,15 @@ static int ocfs2_xattr_set_entry_in_bucket(struct inode *inode,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- ret = ocfs2_xattr_bucket_journal_access(handle, xs->bucket,
|
|
|
- OCFS2_JOURNAL_ACCESS_WRITE);
|
|
|
+ ocfs2_init_xattr_bucket_xa_loc(&loc, xs->bucket,
|
|
|
+ xs->not_found ? NULL : xs->here);
|
|
|
+ ret = ocfs2_xa_journal_access(handle, &loc,
|
|
|
+ OCFS2_JOURNAL_ACCESS_WRITE);
|
|
|
if (ret < 0) {
|
|
|
mlog_errno(ret);
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- ocfs2_init_xattr_bucket_xa_loc(&loc, xs->bucket,
|
|
|
- xs->not_found ? NULL : xs->here);
|
|
|
ret = ocfs2_xa_prepare_entry(&loc, xi, name_hash);
|
|
|
if (ret) {
|
|
|
if (ret != -ENOSPC)
|
|
@@ -5345,7 +5402,7 @@ static int ocfs2_xattr_set_entry_in_bucket(struct inode *inode,
|
|
|
ocfs2_xa_store_inline_value(&loc, xi);
|
|
|
xs->here = loc.xl_entry;
|
|
|
|
|
|
- ocfs2_xattr_bucket_journal_dirty(handle, xs->bucket);
|
|
|
+ ocfs2_xa_journal_dirty(handle, &loc);
|
|
|
|
|
|
out:
|
|
|
return ret;
|