mirror of
https://github.com/torvalds/linux.git
synced 2024-11-17 01:22:07 +00:00
012255961c
Where the previous patches added the ability of list/get xattr in buckets for ocfs2, this patch enables ocfs2 to store large numbers of EAs. The original design doc is written by Mark Fasheh, and it can be found in http://oss.oracle.com/osswiki/OCFS2/DesignDocs/IndexedEATrees. I only had to make small modifications to it. First, because the bucket size is 4K, a new field named xh_free_start is added in ocfs2_xattr_header to indicate the next valid name/value offset in a bucket. It is used when we store new EA name/value. With this field, we can find the place more quickly and what's more, we don't need to sort the name/value every time to let the last entry indicate the next unused space. This makes the insert operation more efficient for blocksizes smaller than 4k. Because of the new xh_free_start, another field named as xh_name_value_len is also added in ocfs2_xattr_header. It records the total length of all the name/values in the bucket. We need this so that we can check it and defragment the bucket if there is not enough contiguous free space. An xattr insertion looks like this: 1. xattr_index_block_find: find the right bucket by the name_hash, say bucketA. 2. check whether there is enough space in bucketA. If yes, insert it directly and modify xh_free_start and xh_name_value_len accordingly. If not, check xh_name_value_len to see whether we can store this by defragment the bucket. If yes, defragment it and go on insertion. 3. If defragement doesn't work, check whether there is new empty bucket in the clusters within this extent record. If yes, init the new bucket and move all the buckets after bucketA one by one to the next bucket. Move half of the entries in bucketA to the next bucket and go on insertion. 4. If there is no new bucket, grow the extent tree. As for xattr deletion, we will delete an xattr bucket when all it's xattrs are removed and move all the buckets after it to the previous one. When all the xattr buckets in an extend record are freed, free this extend records from ocfs2_xattr_tree. Signed-off-by: Tao Ma <tao.ma@oracle.com> Signed-off-by: Mark Fasheh <mfasheh@suse.com>
69 lines
2.1 KiB
C
69 lines
2.1 KiB
C
/* -*- mode: c; c-basic-offset: 8; -*-
|
|
* vim: noexpandtab sw=8 ts=8 sts=0:
|
|
*
|
|
* xattr.h
|
|
*
|
|
* Function prototypes
|
|
*
|
|
* Copyright (C) 2008 Oracle. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* 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.
|
|
*
|
|
* You should have received a copy of the GNU General Public
|
|
* License along with this program; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 021110-1307, USA.
|
|
*/
|
|
|
|
#ifndef OCFS2_XATTR_H
|
|
#define OCFS2_XATTR_H
|
|
|
|
#include <linux/init.h>
|
|
#include <linux/xattr.h>
|
|
|
|
enum ocfs2_xattr_type {
|
|
OCFS2_XATTR_INDEX_USER = 1,
|
|
OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS,
|
|
OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT,
|
|
OCFS2_XATTR_INDEX_TRUSTED,
|
|
OCFS2_XATTR_INDEX_SECURITY,
|
|
OCFS2_XATTR_MAX
|
|
};
|
|
|
|
extern struct xattr_handler ocfs2_xattr_user_handler;
|
|
extern struct xattr_handler ocfs2_xattr_trusted_handler;
|
|
|
|
extern ssize_t ocfs2_listxattr(struct dentry *, char *, size_t);
|
|
extern int ocfs2_xattr_get(struct inode *, int, const char *, void *, size_t);
|
|
extern int ocfs2_xattr_set(struct inode *, int, const char *, const void *,
|
|
size_t, int);
|
|
extern int ocfs2_xattr_remove(struct inode *inode, struct buffer_head *di_bh);
|
|
extern struct xattr_handler *ocfs2_xattr_handlers[];
|
|
|
|
static inline u16 ocfs2_xattr_buckets_per_cluster(struct ocfs2_super *osb)
|
|
{
|
|
return (1 << osb->s_clustersize_bits) / OCFS2_XATTR_BUCKET_SIZE;
|
|
}
|
|
|
|
static inline u16 ocfs2_blocks_per_xattr_bucket(struct super_block *sb)
|
|
{
|
|
return OCFS2_XATTR_BUCKET_SIZE / (1 << sb->s_blocksize_bits);
|
|
}
|
|
|
|
static inline u16 ocfs2_xattr_max_xe_in_bucket(struct super_block *sb)
|
|
{
|
|
u16 len = sb->s_blocksize -
|
|
offsetof(struct ocfs2_xattr_header, xh_entries);
|
|
|
|
return len / sizeof(struct ocfs2_xattr_entry);
|
|
}
|
|
#endif /* OCFS2_XATTR_H */
|