Release 4.10 fs/ocfs2/xattr.c
/* -*- mode: c; c-basic-offset: 8; -*-
* vim: noexpandtab sw=8 ts=8 sts=0:
*
* xattr.c
*
* Copyright (C) 2004, 2008 Oracle. All rights reserved.
*
* CREDITS:
* Lots of code in this file is copy from linux/fs/ext3/xattr.c.
* Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
#include <linux/capability.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/highmem.h>
#include <linux/pagemap.h>
#include <linux/uio.h>
#include <linux/sched.h>
#include <linux/splice.h>
#include <linux/mount.h>
#include <linux/writeback.h>
#include <linux/falloc.h>
#include <linux/sort.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/security.h>
#include <cluster/masklog.h>
#include "ocfs2.h"
#include "alloc.h"
#include "blockcheck.h"
#include "dlmglue.h"
#include "file.h"
#include "symlink.h"
#include "sysfile.h"
#include "inode.h"
#include "journal.h"
#include "ocfs2_fs.h"
#include "suballoc.h"
#include "uptodate.h"
#include "buffer_head_io.h"
#include "super.h"
#include "xattr.h"
#include "refcounttree.h"
#include "acl.h"
#include "ocfs2_trace.h"
struct ocfs2_xattr_def_value_root {
struct ocfs2_xattr_value_root xv;
struct ocfs2_extent_rec er;
};
struct ocfs2_xattr_bucket {
/* The inode these xattrs are associated with */
struct inode *bu_inode;
/* The actual buffers that make up the bucket */
struct buffer_head *bu_bhs[OCFS2_XATTR_MAX_BLOCKS_PER_BUCKET];
/* How many blocks make up one bucket for this filesystem */
int bu_blocks;
};
struct ocfs2_xattr_set_ctxt {
handle_t *handle;
struct ocfs2_alloc_context *meta_ac;
struct ocfs2_alloc_context *data_ac;
struct ocfs2_cached_dealloc_ctxt dealloc;
int set_abort;
};
#define OCFS2_XATTR_ROOT_SIZE (sizeof(struct ocfs2_xattr_def_value_root))
#define OCFS2_XATTR_INLINE_SIZE 80
#define OCFS2_XATTR_HEADER_GAP 4
#define OCFS2_XATTR_FREE_IN_IBODY (OCFS2_MIN_XATTR_INLINE_SIZE \
- sizeof(struct ocfs2_xattr_header) \
- OCFS2_XATTR_HEADER_GAP)
#define OCFS2_XATTR_FREE_IN_BLOCK(ptr) ((ptr)->i_sb->s_blocksize \
- sizeof(struct ocfs2_xattr_block) \
- sizeof(struct ocfs2_xattr_header) \
- OCFS2_XATTR_HEADER_GAP)
static struct ocfs2_xattr_def_value_root def_xv = {
.xv.xr_list.l_count = cpu_to_le16(1),
};
const struct xattr_handler *ocfs2_xattr_handlers[] = {
&ocfs2_xattr_user_handler,
&posix_acl_access_xattr_handler,
&posix_acl_default_xattr_handler,
&ocfs2_xattr_trusted_handler,
&ocfs2_xattr_security_handler,
NULL
};
static const struct xattr_handler *ocfs2_xattr_handler_map[OCFS2_XATTR_MAX] = {
[OCFS2_XATTR_INDEX_USER] = &ocfs2_xattr_user_handler,
[OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS]
= &posix_acl_access_xattr_handler,
[OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT]
= &posix_acl_default_xattr_handler,
[OCFS2_XATTR_INDEX_TRUSTED] = &ocfs2_xattr_trusted_handler,
[OCFS2_XATTR_INDEX_SECURITY] = &ocfs2_xattr_security_handler,
};
struct ocfs2_xattr_info {
int xi_name_index;
const char *xi_name;
int xi_name_len;
const void *xi_value;
size_t xi_value_len;
};
struct ocfs2_xattr_search {
struct buffer_head *inode_bh;
/*
* xattr_bh point to the block buffer head which has extended attribute
* when extended attribute in inode, xattr_bh is equal to inode_bh.
*/
struct buffer_head *xattr_bh;
struct ocfs2_xattr_header *header;
struct ocfs2_xattr_bucket *bucket;
void *base;
void *end;
struct ocfs2_xattr_entry *here;
int not_found;
};
/* 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.
*/
void *(*xlo_offset_pointer)(struct ocfs2_xa_loc *loc, int offset);
/* Can we reuse the existing entry for the new value? */
int (*xlo_can_reuse)(struct ocfs2_xa_loc *loc,
struct ocfs2_xattr_info *xi);
/* How much space is needed for the new value? */
int (*xlo_check_space)(struct ocfs2_xa_loc *loc,
struct ocfs2_xattr_info *xi);
/*
* Return the offset of the first name+value pair. This is
* the start of our downward-filling free space.
*/
int (*xlo_get_free_start)(struct ocfs2_xa_loc *loc);
/*
* Remove the name+value at this location. Do whatever is
* appropriate with the remaining name+value pairs.
*/
void (*xlo_wipe_namevalue)(struct ocfs2_xa_loc *loc);
/* Fill xl_entry with a new entry */
void (*xlo_add_entry)(struct ocfs2_xa_loc *loc, u32 name_hash);
/* Add name+value storage to an entry */
void (*xlo_add_namevalue)(struct ocfs2_xa_loc *loc, int size);
/*
* Initialize the value buf's access and bh fields for this entry.
* ocfs2_xa_fill_value_buf() will handle the xv pointer.
*/
void (*xlo_fill_value_buf)(struct ocfs2_xa_loc *loc,
struct ocfs2_xattr_value_buf *vb);
};
/*
* Describes an xattr entry location. This is a memory structure
* 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;
/* Bytes from xl_header to the end of the storage */
int xl_size;
/*
* The ocfs2_xattr_entry this location describes. If this is
* NULL, this location describes the on-disk structure where it
* would have been.
*/
struct ocfs2_xattr_entry *xl_entry;
/*
* Internal housekeeping
*/
/* Buffer(s) containing this entry */
void *xl_storage;
/* Operations on the storage backing this location */
const struct ocfs2_xa_loc_operations *xl_ops;
};
/*
* Convenience functions to calculate how much space is needed for a
* given name+value pair
*/
static int namevalue_size(int name_len, uint64_t value_len)
{
if (value_len > OCFS2_XATTR_INLINE_SIZE)
return OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_ROOT_SIZE;
else
return OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_SIZE(value_len);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
joel becker | joel becker | 38 | 100.00% | 1 | 100.00% |
| Total | 38 | 100.00% | 1 | 100.00% |
static int namevalue_size_xi(struct ocfs2_xattr_info *xi)
{
return namevalue_size(xi->xi_name_len, xi->xi_value_len);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
joel becker | joel becker | 23 | 100.00% | 1 | 100.00% |
| Total | 23 | 100.00% | 1 | 100.00% |
static int namevalue_size_xe(struct ocfs2_xattr_entry *xe)
{
u64 value_len = le64_to_cpu(xe->xe_value_size);
BUG_ON((value_len > OCFS2_XATTR_INLINE_SIZE) &&
ocfs2_xattr_is_local(xe));
return namevalue_size(xe->xe_name_len, value_len);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
joel becker | joel becker | 45 | 100.00% | 1 | 100.00% |
| Total | 45 | 100.00% | 1 | 100.00% |
static int ocfs2_xattr_bucket_get_name_value(struct super_block *sb,
struct ocfs2_xattr_header *xh,
int index,
int *block_off,
int *new_offset);
static int ocfs2_xattr_block_find(struct inode *inode,
int name_index,
const char *name,
struct ocfs2_xattr_search *xs);
static int ocfs2_xattr_index_block_find(struct inode *inode,
struct buffer_head *root_bh,
int name_index,
const char *name,
struct ocfs2_xattr_search *xs);
static int ocfs2_xattr_tree_list_index_block(struct inode *inode,
struct buffer_head *blk_bh,
char *buffer,
size_t buffer_size);
static int ocfs2_xattr_create_index_block(struct inode *inode,
struct ocfs2_xattr_search *xs,
struct ocfs2_xattr_set_ctxt *ctxt);
static int ocfs2_xattr_set_entry_index_block(struct inode *inode,
struct ocfs2_xattr_info *xi,
struct ocfs2_xattr_search *xs,
struct ocfs2_xattr_set_ctxt *ctxt);
typedef int (xattr_tree_rec_func)(struct inode *inode,
struct buffer_head *root_bh,
u64 blkno, u32 cpos, u32 len, void *para);
static int ocfs2_iterate_xattr_index_block(struct inode *inode,
struct buffer_head *root_bh,
xattr_tree_rec_func *rec_func,
void *para);
static int ocfs2_delete_xattr_in_bucket(struct inode *inode,
struct ocfs2_xattr_bucket *bucket,
void *para);
static int ocfs2_rm_xattr_cluster(struct inode *inode,
struct buffer_head *root_bh,
u64 blkno,
u32 cpos,
u32 len,
void *para);
static int ocfs2_mv_xattr_buckets(struct inode *inode, handle_t *handle,
u64 src_blk, u64 last_blk, u64 to_blk,
unsigned int start_bucket,
u32 *first_hash);
static int ocfs2_prepare_refcount_xattr(struct inode *inode,
struct ocfs2_dinode *di,
struct ocfs2_xattr_info *xi,
struct ocfs2_xattr_search *xis,
struct ocfs2_xattr_search *xbs,
struct ocfs2_refcount_tree **ref_tree,
int *meta_need,
int *credits);
static int ocfs2_get_xattr_tree_value_root(struct super_block *sb,
struct ocfs2_xattr_bucket *bucket,
int offset,
struct ocfs2_xattr_value_root **xv,
struct buffer_head **bh);
static inline u16 ocfs2_xattr_buckets_per_cluster(struct ocfs2_super *osb)
{
return (1 << osb->s_clustersize_bits) / OCFS2_XATTR_BUCKET_SIZE;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tiger yang | tiger yang | 23 | 100.00% | 1 | 100.00% |
| Total | 23 | 100.00% | 1 | 100.00% |
static inline u16 ocfs2_blocks_per_xattr_bucket(struct super_block *sb)
{
return OCFS2_XATTR_BUCKET_SIZE / (1 << sb->s_blocksize_bits);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tiger yang | tiger yang | 23 | 100.00% | 1 | 100.00% |
| Total | 23 | 100.00% | 1 | 100.00% |
#define bucket_blkno(_b) ((_b)->bu_bhs[0]->b_blocknr)
#define bucket_block(_b, _n) ((_b)->bu_bhs[(_n)]->b_data)
#define bucket_xh(_b) ((struct ocfs2_xattr_header *)bucket_block((_b), 0))
static struct ocfs2_xattr_bucket *ocfs2_xattr_bucket_new(struct inode *inode)
{
struct ocfs2_xattr_bucket *bucket;
int blks = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
BUG_ON(blks > OCFS2_XATTR_MAX_BLOCKS_PER_BUCKET);
bucket = kzalloc(sizeof(struct ocfs2_xattr_bucket), GFP_NOFS);
if (bucket) {
bucket->bu_inode = inode;
bucket->bu_blocks = blks;
}
return bucket;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
joel becker | joel becker | 69 | 100.00% | 2 | 100.00% |
| Total | 69 | 100.00% | 2 | 100.00% |
static void ocfs2_xattr_bucket_relse(struct ocfs2_xattr_bucket *bucket)
{
int i;
for (i = 0; i < bucket->bu_blocks; i++) {
brelse(bucket->bu_bhs[i]);
bucket->bu_bhs[i] = NULL;
}
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
joel becker | joel becker | 50 | 100.00% | 2 | 100.00% |
| Total | 50 | 100.00% | 2 | 100.00% |
static void ocfs2_xattr_bucket_free(struct ocfs2_xattr_bucket *bucket)
{
if (bucket) {
ocfs2_xattr_bucket_relse(bucket);
bucket->bu_inode = NULL;
kfree(bucket);
}
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
joel becker | joel becker | 33 | 100.00% | 1 | 100.00% |
| Total | 33 | 100.00% | 1 | 100.00% |
/*
* A bucket that has never been written to disk doesn't need to be
* read. We just need the buffer_heads. Don't call this for
* buckets that are already on disk. ocfs2_read_xattr_bucket() initializes
* them fully.
*/
static int ocfs2_init_xattr_bucket(struct ocfs2_xattr_bucket *bucket,
u64 xb_blkno, int new)
{
int i, rc = 0;
for (i = 0; i < bucket->bu_blocks; i++) {
bucket->bu_bhs[i] = sb_getblk(bucket->bu_inode->i_sb,
xb_blkno + i);
if (!bucket->bu_bhs[i]) {
rc = -ENOMEM;
mlog_errno(rc);
break;
}
if (!ocfs2_buffer_uptodate(INODE_CACHE(bucket->bu_inode),
bucket->bu_bhs[i])) {
if (new)
ocfs2_set_new_buffer_uptodate(INODE_CACHE(bucket->bu_inode),
bucket->bu_bhs[i]);
else {
set_buffer_uptodate(bucket->bu_bhs[i]);
ocfs2_set_buffer_uptodate(INODE_CACHE(bucket->bu_inode),
bucket->bu_bhs[i]);
}
}
}
if (rc)
ocfs2_xattr_bucket_relse(bucket);
return rc;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
joel becker | joel becker | 112 | 66.27% | 3 | 50.00% |
wengang wang | wengang wang | 39 | 23.08% | 1 | 16.67% |
tao ma | tao ma | 17 | 10.06% | 1 | 16.67% |
rui xiang | rui xiang | 1 | 0.59% | 1 | 16.67% |
| Total | 169 | 100.00% | 6 | 100.00% |
/* Read the xattr bucket at xb_blkno */
static int ocfs2_read_xattr_bucket(struct ocfs2_xattr_bucket *bucket,
u64 xb_blkno)
{
int rc;
rc = ocfs2_read_blocks(INODE_CACHE(bucket->bu_inode), xb_blkno,
bucket->bu_blocks, bucket->bu_bhs, 0,
NULL);
if (!rc) {
spin_lock(&OCFS2_SB(bucket->bu_inode->i_sb)->osb_xattr_lock);
rc = ocfs2_validate_meta_ecc_bhs(bucket->bu_inode->i_sb,
bucket->bu_bhs,
bucket->bu_blocks,
&bucket_xh(bucket)->xh_check);
spin_unlock(&OCFS2_SB(bucket->bu_inode->i_sb)->osb_xattr_lock);
if (rc)
mlog_errno(rc);
}
if (rc)
ocfs2_xattr_bucket_relse(bucket);
return rc;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
joel becker | joel becker | 98 | 76.56% | 5 | 83.33% |
tao ma | tao ma | 30 | 23.44% | 1 | 16.67% |
| Total | 128 | 100.00% | 6 | 100.00% |
static int ocfs2_xattr_bucket_journal_access(handle_t *handle,
struct ocfs2_xattr_bucket *bucket,
int type)
{
int i, rc = 0;
for (i = 0; i < bucket->bu_blocks; i++) {
rc = ocfs2_journal_access(handle,
INODE_CACHE(bucket->bu_inode),
bucket->bu_bhs[i], type);
if (rc) {
mlog_errno(rc);
break;
}
}
return rc;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
joel becker | joel becker | 80 | 100.00% | 3 | 100.00% |
| Total | 80 | 100.00% | 3 | 100.00% |
static void ocfs2_xattr_bucket_journal_dirty(handle_t *handle,
struct ocfs2_xattr_bucket *bucket)
{
int i;
spin_lock(&OCFS2_SB(bucket->bu_inode->i_sb)->osb_xattr_lock);
ocfs2_compute_meta_ecc_bhs(bucket->bu_inode->i_sb,
bucket->bu_bhs, bucket->bu_blocks,
&bucket_xh(bucket)->xh_check);
spin_unlock(&OCFS2_SB(bucket->bu_inode->i_sb)->osb_xattr_lock);
for (i = 0; i < bucket->bu_blocks; i++)
ocfs2_journal_dirty(handle, bucket->bu_bhs[i]);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
joel becker | joel becker | 70 | 70.00% | 3 | 75.00% |
tao ma | tao ma | 30 | 30.00% | 1 | 25.00% |
| Total | 100 | 100.00% | 4 | 100.00% |
static void ocfs2_xattr_bucket_copy_data(struct ocfs2_xattr_bucket *dest,
struct ocfs2_xattr_bucket *src)
{
int i;
int blocksize = src->bu_inode->i_sb->s_blocksize;
BUG_ON(dest->bu_blocks != src->bu_blocks);
BUG_ON(dest->bu_inode != src->bu_inode);
for (i = 0; i < src->bu_blocks; i++) {
memcpy(bucket_block(dest, i), bucket_block(src, i),
blocksize);
}
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
joel becker | joel becker | 88 | 100.00% | 2 | 100.00% |
| Total | 88 | 100.00% | 2 | 100.00% |
static int ocfs2_validate_xattr_block(struct super_block *sb,
struct buffer_head *bh)
{
int rc;
struct ocfs2_xattr_block *xb =
(struct ocfs2_xattr_block *)bh->b_data;
trace_ocfs2_validate_xattr_block((unsigned long long)bh->b_blocknr);
BUG_ON(!buffer_uptodate(bh));
/*
* If the ecc fails, we return the error but otherwise
* leave the filesystem running. We know any error is
* local to this block.
*/
rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &xb->xb_check);
if (rc)
return rc;
/*
* Errors after here are fatal
*/
if (!OCFS2_IS_VALID_XATTR_BLOCK(xb)) {
return ocfs2_error(sb,
"Extended attribute block #%llu has bad signature %.*s\n",
(unsigned long long)bh->b_blocknr, 7,
xb->xb_signature);
}
if (le64_to_cpu(xb->xb_blkno) != bh->b_blocknr) {
return ocfs2_error(sb,
"Extended attribute block #%llu has an invalid xb_blkno of %llu\n",
(unsigned long long)bh->b_blocknr,
(unsigned long long)le64_to_cpu(xb->xb_blkno));
}
if (le32_to_cpu(xb->xb_fs_generation) != OCFS2_SB(sb)->fs_generation) {
return ocfs2_error(sb,
"Extended attribute block #%llu has an invalid xb_fs_generation of #%u\n",
(unsigned long long)bh->b_blocknr,
le32_to_cpu(xb->xb_fs_generation));
}
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
joel becker | joel becker | 194 | 96.52% | 2 | 40.00% |
joe perches | joe perches | 3 | 1.49% | 1 | 20.00% |
goldwyn rodrigues | goldwyn rodrigues | 3 | 1.49% | 1 | 20.00% |
tao ma | tao ma | 1 | 0.50% | 1 | 20.00% |
| Total | 201 | 100.00% | 5 | 100.00% |
static int ocfs2_read_xattr_block(struct inode *inode, u64 xb_blkno,
struct buffer_head **bh)
{
int rc;
struct buffer_head *tmp = *bh;
rc = ocfs2_read_block(INODE_CACHE(inode), xb_blkno, &tmp,
ocfs2_validate_xattr_block);
/* If ocfs2_read_block() got us a new bh, pass it up. */
if (!rc && !*bh)
*bh = tmp;
return rc;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
joel becker | joel becker | 66 | 100.00% | 3 | 100.00% |
| Total | 66 | 100.00% | 3 | 100.00% |
static inline const char *ocfs2_xattr_prefix(int name_index)
{
const struct xattr_handler *handler = NULL;
if (name_index > 0 && name_index < OCFS2_XATTR_MAX)
handler = ocfs2_xattr_handler_map[name_index];
return handler ? xattr_prefix(handler) : NULL;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tiger yang | tiger yang | 32 | 68.09% | 1 | 20.00% |
tao ma | tao ma | 11 | 23.40% | 2 | 40.00% |
andreas gruenbacher | andreas gruenbacher | 3 | 6.38% | 1 | 20.00% |
stephen hemminger | stephen hemminger | 1 | 2.13% | 1 | 20.00% |
| Total | 47 | 100.00% | 5 | 100.00% |
static u32 ocfs2_xattr_name_hash(struct inode *inode,
const char *name,
int name_len)
{
/* Get hash value of uuid from super block */
u32 hash = OCFS2_SB(inode->i_sb)->uuid_hash;
int i;
/* hash extended attribute name */
for (i = 0; i < name_len; i++) {
hash = (hash << OCFS2_HASH_SHIFT) ^
(hash >> (8*sizeof(hash) - OCFS2_HASH_SHIFT)) ^
*name++;
}
return hash;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tiger yang | tiger yang | 67 | 82.72% | 1 | 33.33% |
tao ma | tao ma | 14 | 17.28% | 2 | 66.67% |
| Total | 81 | 100.00% | 3 | 100.00% |
static int ocfs2_xattr_entry_real_size(int name_len, size_t value_len)
{
return namevalue_size(name_len, value_len) +
sizeof(struct ocfs2_xattr_entry);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tiger yang | tiger yang | 17 | 65.38% | 1 | 50.00% |
joel becker | joel becker | 9 | 34.62% | 1 | 50.00% |
| Total | 26 | 100.00% | 2 | 100.00% |
static int ocfs2_xi_entry_usage(struct ocfs2_xattr_info *xi)
{
return namevalue_size_xi(xi) +
sizeof(struct ocfs2_xattr_entry);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
joel becker | joel becker | 15 | 65.22% | 1 | 50.00% |
tiger yang | tiger yang | 8 | 34.78% | 1 | 50.00% |
| Total | 23 | 100.00% | 2 | 100.00% |
static int ocfs2_xe_entry_usage(struct ocfs2_xattr_entry *xe)
{
return namevalue_size_xe(xe) +
sizeof(struct ocfs2_xattr_entry);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
joel becker | joel becker | 20 | 86.96% | 1 | 50.00% |
tiger yang | tiger yang | 3 | 13.04% | 1 | 50.00% |
| Total | 23 | 100.00% | 2 | 100.00% |
int ocfs2_calc_security_init(struct inode *dir,
struct ocfs2_security_xattr_info *si,
int *want_clusters,
int *xattr_credits,
struct ocfs2_alloc_context **xattr_ac)
{
int ret = 0;
struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
int s_size = ocfs2_xattr_entry_real_size(strlen(si->name),
si->value_len);
/*
* The max space of security xattr taken inline is
* 256(name) + 80(value) + 16(entry) = 352 bytes,
* So reserve one metadata block for it is ok.
*/
if (dir->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE ||
s_size > OCFS2_XATTR_FREE_IN_IBODY) {
ret = ocfs2_reserve_new_metadata_blocks(osb, 1, xattr_ac);
if (ret) {
mlog_errno(ret);
return ret;
}
*xattr_credits += OCFS2_XATTR_BLOCK_CREATE_CREDITS;
}
/* reserve clusters for xattr value which will be set in B tree*/
if (si->value_len > OCFS2_XATTR_INLINE_SIZE) {
int new_clusters = ocfs2_clusters_for_bytes(dir->i_sb,
si->value_len);
*xattr_credits += ocfs2_clusters_to_blocks(dir->i_sb,
new_clusters);
*want_clusters += new_clusters;
}
return ret;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tiger yang | tiger yang | 155 | 100.00% | 2 | 100.00% |
| Total | 155 | 100.00% | 2 | 100.00% |
int ocfs2_calc_xattr_init(struct inode *dir,
struct buffer_head *dir_bh,
umode_t mode,
struct ocfs2_security_xattr_info *si,
int *want_clusters,
int *xattr_credits,
int *want_meta)
{
int ret = 0;
struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
int s_size = 0, a_size = 0, acl_len = 0, new_clusters;
if (si->enable)
s_size = ocfs2_xattr_entry_real_size(strlen(si->name),
si->value_len);
if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) {
acl_len = ocfs2_xattr_get_nolock(dir, dir_bh,
OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT,
"", NULL, 0);
if (acl_len > 0) {
a_size = ocfs2_xattr_entry_real_size(0, acl_len);
if (S_ISDIR(mode))
a_size <<= 1;
} else if (acl_len != 0 && acl_len != -ENODATA) {
mlog_errno(ret);
return ret;
}
}
if (!(s_size + a_size))
return ret;
/*
* The max space of security xattr taken inline is
* 256(name) + 80(value) + 16(entry) = 352 bytes,
* The max space of acl xattr taken inline is
* 80(value) + 16(entry) * 2(if directory) = 192 bytes,
* when blocksize = 512, may reserve one more cluser for
* xattr bucket, otherwise reserve one metadata block
* for them is ok.
* If this is a new directory with inline data,
* we choose to reserve the entire inline area for
* directory contents and force an external xattr block.
*/
if (dir->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE ||
(S_ISDIR(mode) && ocfs2_supports_inline_data(osb)) ||
(s_size + a_size) > OCFS2_XATTR_FREE_IN_IBODY) {
*want_meta = *want_meta + 1;
*xattr_credits += OCFS2_XATTR_BLOCK_CREATE_CREDITS;
}
if (dir->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE &&
(s_size + a_size) > OCFS2_XATTR_FREE_IN_BLOCK(dir)) {
*want_clusters += 1;
*xattr_credits += ocfs2_blocks_per_xattr_bucket(dir->i_sb);
}
/*
* reserve credits and clusters for xattrs which has large value
* and have to be set outside
*/
if (si->enable && si->value_len > OCFS2_XATTR_INLINE_SIZE) {
new_clusters = ocfs2_clusters_for_bytes(dir->i_sb,
si->value_len);
*xattr_credits += ocfs2_clusters_to_blocks(dir->i_sb,
new_clusters);
*want_clusters += new_clusters;
}
if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL &&
acl_len > OCFS2_XATTR_INLINE_SIZE) {
/* for directory, it has DEFAULT and ACCESS two types of acls */
new_clusters = (S_ISDIR(mode) ? 2 : 1) *
ocfs2_clusters_for_bytes(dir->i_sb, acl_len);
*xattr_credits += ocfs2_clusters_to_blocks(dir->i_sb,
new_clusters);
*want_clusters += new_clusters;
}
return ret;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
tiger yang | tiger yang | 356 | 97.80% | 3 | 60.00% |
mark fasheh | mark fasheh | 7 | 1.92% | 1 | 20.00% |
al viro | al viro | 1 | 0.27% | 1 | 20.00% |
| Total | 364 | 100.00% | 5 | 100.00% |
static int ocfs2_xattr_extend_allocation(struct inode *inode,
u32 clusters_to_add,
struct ocfs2_xattr_value_buf *vb,
struct ocfs2_xattr_set_ctxt *ctxt)
{
int status = 0, credits;
handle_t *handle = ctxt->handle;
enum ocfs2_alloc_restarted why;
u32 prev_clusters, logical_start = le32_to_cpu(vb->vb_xv->xr_clusters);
struct ocfs2_extent_tree et;
ocfs2_init_xattr_value_extent_tree(&et, INODE_CACHE(inode), vb);
while (clusters_to_add) {
trace_ocfs2_xattr_extend_allocation(clusters_to_add);
status = vb