[RFC][STEP 1][PATCH v2 09/17] nilfs2: implement listxattr and getxattr functionality

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Vyacheslav Dubeyko <slava@xxxxxxxxxxx>
Subject: [RFC][STEP 1][PATCH v2 09/17] nilfs2: implement listxattr and getxattr functionality

This patch adds functionality listxattr and getxattr operations.

Signed-off-by: Vyacheslav Dubeyko <slava@xxxxxxxxxxx>
CC: Ryusuke Konishi <konishi.ryusuke@xxxxxxxxxxxxx>
---
 fs/nilfs2/xafile.c |  167 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/nilfs2/xafile.h |   20 +++++++
 fs/nilfs2/xattr.c  |   64 ++++++++++++++++++++
 fs/nilfs2/xattr.h  |   44 ++++++++++++++
 4 files changed, 295 insertions(+)
 create mode 100644 fs/nilfs2/xattr.c
 create mode 100644 fs/nilfs2/xattr.h

diff --git a/fs/nilfs2/xafile.c b/fs/nilfs2/xafile.c
index 73904c1..e21900a 100644
--- a/fs/nilfs2/xafile.c
+++ b/fs/nilfs2/xafile.c
@@ -220,6 +220,19 @@ struct nilfs_xattr_search {
 	(!IS_SEARCH_KEY_EMPTY(data) && \
 	 IS_SEARCH_RESULT_EMPTY(data))
 
+/* Map of xattr handlers */
+static const struct xattr_handler *nilfs_xattr_handler_map[] = {
+	[NILFS_USER_XATTR_ID] = &nilfs_xattr_user_handler,
+#ifdef CONFIG_NILFS2_FS_POSIX_ACL
+	[NILFS_POSIX_ACL_ACCESS_XATTR_ID] = &nilfs_xattr_acl_access_handler,
+	[NILFS_POSIX_ACL_DEFAULT_XATTR_ID] = &nilfs_xattr_acl_default_handler,
+#endif
+	[NILFS_TRUSTED_XATTR_ID] = &nilfs_xattr_trusted_handler,
+#ifdef CONFIG_NILFS2_FS_SECURITY
+	[NILFS_SECURITY_XATTR_ID] = &nilfs_xattr_security_handler,
+#endif
+};
+
 /*
  * NILFS_XAFILE_I - convert inode info into xafile inode info
  */
@@ -230,6 +243,19 @@ struct nilfs_xafile_info *NILFS_XAFILE_I(struct inode *xafile)
 }
 
 /*
+ * nilfs_xattr_handler - get xattr handler by name index
+ */
+static inline
+const struct xattr_handler *nilfs_xattr_handler(int name_index)
+{
+	const struct xattr_handler *handler = NULL;
+
+	if (name_index > 0 && name_index < ARRAY_SIZE(nilfs_xattr_handler_map))
+		handler = nilfs_xattr_handler_map[name_index];
+	return handler;
+}
+
+/*
  * nilfs_xafile_get_node - get xafile node
  * @xafile: xafile inode
  * @node_id: node number
@@ -1298,3 +1324,144 @@ void nilfs_xafile_abort_new_node(struct inode *inode,
 	nilfs_xafile_abort_node_creation(xafile, &data->node.req);
 	nilfs_xafile_abort_node_change(data);
 }
+
+/*
+ * nilfs_xattr_list_entries - list inode's xattrs from one xanode
+ * @dentry: dentry object
+ * @bh: xanode's buffer
+ * @buf: buffer for getting xattrs' list [out]
+ * @size: buffer size
+ */
+static
+int nilfs_xattr_list_entries(struct dentry *dentry, struct buffer_head *bh,
+				char *buf, size_t buf_size)
+{
+	union nilfs_xanode_header *hdr = NILFS_XANODE_HDR(BH_DATA(bh));
+	union nilfs_xattr_key *key;
+	size_t rest = buf_size;
+
+	key = NILFS_XANODE_FIRST_NOT_INDEX_KEY(hdr);
+
+	for (; !IS_END_KEY(key); key = NEXT_KEY(key, 1)) {
+		u8 name_index = NILFS_XANODE_NAME_HASH(key)->name_index;
+		const struct nilfs_xanode_entry *entry =
+					NILFS_XANODE_ENTRY(key, BH_DATA(bh));
+		const struct xattr_handler *handler =
+				nilfs_xattr_handler(name_index);
+		__u8 name_len = NILFS_XANODE_NAME_HASH(key)->name_len;
+
+		if (handler) {
+			size_t size = handler->list(dentry, buf, rest,
+						    entry->name, name_len,
+						    handler->flags);
+			if (buf) {
+				if (size > rest)
+					return -ERANGE;
+				buf += size;
+			}
+			rest -= size;
+		}
+	}
+
+	return buf_size - rest;
+}
+
+/*
+ * nilfs_xafile_listxattr - list all inode's xattrs
+ * @dentry: dentry object
+ * @buffer: buffer for getting xattrs' list [out]
+ * @size: buffer size
+ */
+ssize_t nilfs_xafile_listxattr(struct dentry *dentry, char *buffer, size_t size)
+{
+	ssize_t ret = 0, err = 0;
+	struct inode *inode = dentry->d_inode;
+	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
+	struct buffer_head *bh = NULL;
+	__u64 node = NILFS_I(inode)->i_xattr;
+
+	if (!nilfs_has_xafile(nilfs))
+		return -EOPNOTSUPP;
+
+	if (node == NILFS_INVALID_XANODE)
+		return 0;
+
+	err = nilfs_xafile_get_checked_node(inode, node, &bh);
+	if (unlikely(err))
+		goto failed_xafile_listxattr;
+
+	err = nilfs_xattr_list_entries(dentry, bh, buffer, size);
+	if (unlikely(err < 0))
+		goto cleanup_after_failure;
+	else
+		ret += err;
+
+	brelse(bh);
+	return ret;
+
+cleanup_after_failure:
+	brelse(bh);
+
+failed_xafile_listxattr:
+	return err;
+}
+
+/*
+ * nilfs_xafile_getxattr - get xattr
+ * @inode: inode pointer
+ * @name: xattr's name
+ * @value: buffer for xattr's value [out]
+ * @size: buffer size
+ */
+ssize_t nilfs_xafile_getxattr(struct inode *inode,
+				int name_index, const char *name,
+				void *value, size_t size)
+{
+	ssize_t ret, err;
+	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
+	struct nilfs_xattr_search data;
+
+	if (!nilfs_has_xafile(nilfs))
+		return -EOPNOTSUPP;
+
+	if (NILFS_I(inode)->i_xattr == NILFS_INVALID_XANODE)
+		return -ENODATA;
+
+	err = nilfs_xattr_search_init(inode, name_index, (char *)name, &data);
+	if (unlikely(err))
+		return err;
+
+	err = nilfs_xafile_find_node(inode, &data);
+	if (unlikely(err)) {
+		ret = err;
+		goto failed_xafile_getxattr;
+	}
+
+	if (!data.result.found) {
+		ret = -ENODATA;
+		goto cleanup_after_failure;
+	}
+
+	ret = NILFS_XANODE_ENTRY_SIZE(data.result.key) -
+		NILFS_XANODE_NAME_HASH(data.result.key)->name_len;
+
+	if (value) {
+		char *xattr_value;
+
+		if (ret > size) {
+			ret = -ERANGE;
+			goto cleanup_after_failure;
+		}
+
+		xattr_value = NILFS_XATTR_VALUE(data.result.entry,
+						data.result.key);
+		memcpy(value, xattr_value, ret);
+	}
+
+cleanup_after_failure:
+	brelse(NODE_BH(&data.node));
+
+failed_xafile_getxattr:
+	nilfs_xattr_search_release(&data);
+	return ret;
+}
diff --git a/fs/nilfs2/xafile.h b/fs/nilfs2/xafile.h
index 846ea3a..50c4735 100644
--- a/fs/nilfs2/xafile.h
+++ b/fs/nilfs2/xafile.h
@@ -29,6 +29,20 @@
 /* Magic number of xafile node */
 #define NILFS_XANODE_MAGIC		0x5841 /* XA */
 
+/* Name indexes */
+#define NILFS_USER_XATTR_ID			1
+#define NILFS_POSIX_ACL_ACCESS_XATTR_ID		2
+#define NILFS_POSIX_ACL_DEFAULT_XATTR_ID	3
+#define NILFS_TRUSTED_XATTR_ID			4
+#define NILFS_SECURITY_XATTR_ID			5
+#define NILFS_SYSTEM_XATTR_ID			6
+#define NILFS_RICHACL_XATTR_ID			7
+#define NILFS_XATTR_MAX_ID			255
+
+#define IS_NAME_ID_VALID(name_index) \
+	(name_index < NILFS_USER_XATTR_ID || \
+	 name_index > NILFS_RICHACL_XATTR_ID)
+
 /* Xanode types */
 #define NILFS_UNKNOWN_XANODE_TYPE		0
 /* Temporary, numbers from 1 till 6 are simply reserved */
@@ -417,6 +431,12 @@ NILFS_XANODE_LAST_ENTRY(union nilfs_xanode_header *hdr)
 #define NILFS_XATTR_VALUE(entry, key) \
 	((char *)(entry) + NILFS_XANODE_NAME_HASH(key)->name_len)
 
+extern const struct xattr_handler nilfs_xattr_user_handler;
+extern const struct xattr_handler nilfs_xattr_trusted_handler;
+extern const struct xattr_handler nilfs_xattr_acl_access_handler;
+extern const struct xattr_handler nilfs_xattr_acl_default_handler;
+extern const struct xattr_handler nilfs_xattr_security_handler;
+
 /* Xafile API */
 ssize_t nilfs_xafile_listxattr(struct dentry *dentry, char *buf, size_t size);
 ssize_t nilfs_xafile_getxattr(struct inode *inode,
diff --git a/fs/nilfs2/xattr.c b/fs/nilfs2/xattr.c
new file mode 100644
index 0000000..7be523a
--- /dev/null
+++ b/fs/nilfs2/xattr.c
@@ -0,0 +1,64 @@
+/*
+ * xattr.c - NILFS extended attributes support implementation.
+ *
+ * Copyright (C) 2005-2013 Nippon Telegraph and Telephone Corporation.
+ * Copyright (C) 2013 Vyacheslav Dubeyko <slava@xxxxxxxxxxx>
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Written by Vyacheslav Dubeyko <slava@xxxxxxxxxxx>
+ */
+
+#include "nilfs.h"
+#include "xafile.h"
+#include "xattr.h"
+
+const struct xattr_handler *nilfs_xattr_handlers[] = {
+	&nilfs_xattr_user_handler,
+	&nilfs_xattr_trusted_handler,
+#ifdef CONFIG_NILFS2_FS_POSIX_ACL
+	&nilfs_xattr_acl_access_handler,
+	&nilfs_xattr_acl_default_handler,
+#endif
+#ifdef CONFIG_NILFS2_FS_SECURITY
+	&nilfs_xattr_security_handler,
+#endif
+	NULL
+};
+
+ssize_t nilfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
+{
+	ssize_t ret;
+	struct inode *inode = dentry->d_inode;
+
+	down_read(&NILFS_I(inode)->xattr_sem);
+	ret = nilfs_xafile_listxattr(dentry, buffer, size);
+	up_read(&NILFS_I(inode)->xattr_sem);
+
+	return ret;
+}
+
+ssize_t __nilfs_getxattr(struct inode *inode,
+				int name_index, const char *name,
+				void *value, size_t size)
+{
+	ssize_t ret;
+
+	down_read(&NILFS_I(inode)->xattr_sem);
+	ret = nilfs_xafile_getxattr(inode, name_index, name, value, size);
+	up_read(&NILFS_I(inode)->xattr_sem);
+
+	return ret;
+}
diff --git a/fs/nilfs2/xattr.h b/fs/nilfs2/xattr.h
new file mode 100644
index 0000000..0736086
--- /dev/null
+++ b/fs/nilfs2/xattr.h
@@ -0,0 +1,44 @@
+/*
+ * xattr.h - NILFS extended attributes declarations.
+ *
+ * Copyright (C) 2005-2013 Nippon Telegraph and Telephone Corporation.
+ * Copyright (C) 2013 Vyacheslav Dubeyko <slava@xxxxxxxxxxx>
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Written by Vyacheslav Dubeyko <slava@xxxxxxxxxxx>
+ */
+
+#ifndef _NILFS_XATTR_H
+#define _NILFS_XATTR_H
+
+#include <linux/xattr.h>
+
+extern const struct xattr_handler *nilfs_xattr_handlers[];
+
+ssize_t __nilfs_getxattr(struct inode *inode,
+				int name_index, const char *name,
+				void *value, size_t size);
+
+static inline ssize_t nilfs_getxattr(struct dentry *dentry,
+					int name_index, const char *name,
+					void *value, size_t size)
+{
+	return __nilfs_getxattr(dentry->d_inode, name_index, name, value, size);
+}
+
+ssize_t nilfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
+
+#endif /* _NILFS_XATTR_H */
-- 
1.7.9.5



--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Filesystem Development]     [Linux BTRFS]     [Linux CIFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux