summaryrefslogtreecommitdiff
path: root/fs/ext4/xattr.h
diff options
context:
space:
mode:
authorTahsin Erdogan <tahsin@google.com>2017-06-22 18:44:55 +0300
committerTheodore Ts'o <tytso@mit.edu>2017-06-22 18:44:55 +0300
commitdec214d00e0d78a08b947d7dccdfdb84407a9f4d (patch)
treed0912312aa9d0deb0b6544445859e09090c1d404 /fs/ext4/xattr.h
parent30a7eb970c3aae6f1b74b2edea896fdca1cbea38 (diff)
downloadlinux-dec214d00e0d78a08b947d7dccdfdb84407a9f4d.tar.xz
ext4: xattr inode deduplication
Ext4 now supports xattr values that are up to 64k in size (vfs limit). Large xattr values are stored in external inodes each one holding a single value. Once written the data blocks of these inodes are immutable. The real world use cases are expected to have a lot of value duplication such as inherited acls etc. To reduce data duplication on disk, this patch implements a deduplicator that allows sharing of xattr inodes. The deduplication is based on an in-memory hash lookup that is a best effort sharing scheme. When a xattr inode is read from disk (i.e. getxattr() call), its crc32c hash is added to a hash table. Before creating a new xattr inode for a value being set, the hash table is checked to see if an existing inode holds an identical value. If such an inode is found, the ref count on that inode is incremented. On value removal the ref count is decremented and if it reaches zero the inode is deleted. The quota charging for such inodes is manually managed. Every reference holder is charged the full size as if there was no sharing happening. This is consistent with how xattr blocks are also charged. [ Fixed up journal credits calculation to handle inline data and the rare case where an shared xattr block can get freed when two thread race on breaking the xattr block sharing. --tytso ] Signed-off-by: Tahsin Erdogan <tahsin@google.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/xattr.h')
-rw-r--r--fs/ext4/xattr.h17
1 files changed, 2 insertions, 15 deletions
diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
index b2005a2716d9..67616cb9a059 100644
--- a/fs/ext4/xattr.h
+++ b/fs/ext4/xattr.h
@@ -70,19 +70,6 @@ struct ext4_xattr_entry {
#define IFIRST(hdr) ((struct ext4_xattr_entry *)((hdr)+1))
/*
- * Link EA inode back to parent one using i_mtime field.
- * Extra integer type conversion added to ignore higher
- * bits in i_mtime.tv_sec which might be set by ext4_get()
- */
-#define EXT4_XATTR_INODE_SET_PARENT(inode, inum) \
-do { \
- (inode)->i_mtime.tv_sec = inum; \
-} while(0)
-
-#define EXT4_XATTR_INODE_GET_PARENT(inode) \
-((__u32)(inode)->i_mtime.tv_sec)
-
-/*
* The minimum size of EA value when you start storing it in an external inode
* size of block - size of header - size of 1 entry - 4 null bytes
*/
@@ -165,9 +152,9 @@ extern ssize_t ext4_listxattr(struct dentry *, char *, size_t);
extern int ext4_xattr_get(struct inode *, int, const char *, void *, size_t);
extern int ext4_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
extern int ext4_xattr_set_handle(handle_t *, struct inode *, int, const char *, const void *, size_t, int);
-extern int ext4_xattr_set_credits(struct inode *inode, size_t value_len);
+extern int ext4_xattr_set_credits(struct inode *inode, size_t value_len,
+ int *credits);
-extern int ext4_xattr_inode_unlink(struct inode *inode, unsigned long ea_ino);
extern int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode,
struct ext4_xattr_inode_array **array,
int extra_credits);