aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2010-05-31 03:52:56 -0400
committerEric Van Hensbergen <ericvh@gmail.com>2010-08-02 15:28:35 -0400
commitebf46264a004818fe5b23f0ac18ac7336897d807 (patch)
tree0b8ea6810a8e665e3b7bb97f1e85ebde7d0d9ee0
parenteda25e46161527845572131b37706a458d9270ef (diff)
fs/9p: Add support user. xattr
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com> Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
-rw-r--r--fs/9p/Makefile4
-rw-r--r--fs/9p/vfs_inode.c15
-rw-r--r--fs/9p/vfs_super.c6
-rw-r--r--fs/9p/xattr.c160
-rw-r--r--fs/9p/xattr.h27
-rw-r--r--fs/9p/xattr_user.c80
6 files changed, 289 insertions, 3 deletions
diff --git a/fs/9p/Makefile b/fs/9p/Makefile
index 1a940ec7af61..91fba025fcbe 100644
--- a/fs/9p/Makefile
+++ b/fs/9p/Makefile
@@ -8,6 +8,8 @@ obj-$(CONFIG_9P_FS) := 9p.o
8 vfs_dir.o \ 8 vfs_dir.o \
9 vfs_dentry.o \ 9 vfs_dentry.o \
10 v9fs.o \ 10 v9fs.o \
11 fid.o 11 fid.o \
12 xattr.o \
13 xattr_user.o
12 14
139p-$(CONFIG_9P_FSCACHE) += cache.o 159p-$(CONFIG_9P_FSCACHE) += cache.o
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 2ac245902a4f..39352ef954dc 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -35,6 +35,7 @@
35#include <linux/idr.h> 35#include <linux/idr.h>
36#include <linux/sched.h> 36#include <linux/sched.h>
37#include <linux/slab.h> 37#include <linux/slab.h>
38#include <linux/xattr.h>
38#include <net/9p/9p.h> 39#include <net/9p/9p.h>
39#include <net/9p/client.h> 40#include <net/9p/client.h>
40 41
@@ -42,6 +43,7 @@
42#include "v9fs_vfs.h" 43#include "v9fs_vfs.h"
43#include "fid.h" 44#include "fid.h"
44#include "cache.h" 45#include "cache.h"
46#include "xattr.h"
45 47
46static const struct inode_operations v9fs_dir_inode_operations; 48static const struct inode_operations v9fs_dir_inode_operations;
47static const struct inode_operations v9fs_dir_inode_operations_dotu; 49static const struct inode_operations v9fs_dir_inode_operations_dotu;
@@ -1931,6 +1933,11 @@ static const struct inode_operations v9fs_dir_inode_operations_dotl = {
1931 .rename = v9fs_vfs_rename, 1933 .rename = v9fs_vfs_rename,
1932 .getattr = v9fs_vfs_getattr_dotl, 1934 .getattr = v9fs_vfs_getattr_dotl,
1933 .setattr = v9fs_vfs_setattr_dotl, 1935 .setattr = v9fs_vfs_setattr_dotl,
1936 .setxattr = generic_setxattr,
1937 .getxattr = generic_getxattr,
1938 .removexattr = generic_removexattr,
1939 .listxattr = v9fs_listxattr,
1940
1934}; 1941};
1935 1942
1936static const struct inode_operations v9fs_dir_inode_operations = { 1943static const struct inode_operations v9fs_dir_inode_operations = {
@@ -1953,6 +1960,10 @@ static const struct inode_operations v9fs_file_inode_operations = {
1953static const struct inode_operations v9fs_file_inode_operations_dotl = { 1960static const struct inode_operations v9fs_file_inode_operations_dotl = {
1954 .getattr = v9fs_vfs_getattr_dotl, 1961 .getattr = v9fs_vfs_getattr_dotl,
1955 .setattr = v9fs_vfs_setattr_dotl, 1962 .setattr = v9fs_vfs_setattr_dotl,
1963 .setxattr = generic_setxattr,
1964 .getxattr = generic_getxattr,
1965 .removexattr = generic_removexattr,
1966 .listxattr = v9fs_listxattr,
1956}; 1967};
1957 1968
1958static const struct inode_operations v9fs_symlink_inode_operations = { 1969static const struct inode_operations v9fs_symlink_inode_operations = {
@@ -1969,4 +1980,8 @@ static const struct inode_operations v9fs_symlink_inode_operations_dotl = {
1969 .put_link = v9fs_vfs_put_link, 1980 .put_link = v9fs_vfs_put_link,
1970 .getattr = v9fs_vfs_getattr_dotl, 1981 .getattr = v9fs_vfs_getattr_dotl,
1971 .setattr = v9fs_vfs_setattr_dotl, 1982 .setattr = v9fs_vfs_setattr_dotl,
1983 .setxattr = generic_setxattr,
1984 .getxattr = generic_getxattr,
1985 .removexattr = generic_removexattr,
1986 .listxattr = v9fs_listxattr,
1972}; 1987};
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index 3623f692b448..0a2e2030c844 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -45,6 +45,7 @@
45#include "v9fs.h" 45#include "v9fs.h"
46#include "v9fs_vfs.h" 46#include "v9fs_vfs.h"
47#include "fid.h" 47#include "fid.h"
48#include "xattr.h"
48 49
49static const struct super_operations v9fs_super_ops, v9fs_super_ops_dotl; 50static const struct super_operations v9fs_super_ops, v9fs_super_ops_dotl;
50 51
@@ -77,9 +78,10 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
77 sb->s_blocksize_bits = fls(v9ses->maxdata - 1); 78 sb->s_blocksize_bits = fls(v9ses->maxdata - 1);
78 sb->s_blocksize = 1 << sb->s_blocksize_bits; 79 sb->s_blocksize = 1 << sb->s_blocksize_bits;
79 sb->s_magic = V9FS_MAGIC; 80 sb->s_magic = V9FS_MAGIC;
80 if (v9fs_proto_dotl(v9ses)) 81 if (v9fs_proto_dotl(v9ses)) {
81 sb->s_op = &v9fs_super_ops_dotl; 82 sb->s_op = &v9fs_super_ops_dotl;
82 else 83 sb->s_xattr = v9fs_xattr_handlers;
84 } else
83 sb->s_op = &v9fs_super_ops; 85 sb->s_op = &v9fs_super_ops;
84 sb->s_bdi = &v9ses->bdi; 86 sb->s_bdi = &v9ses->bdi;
85 87
diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c
new file mode 100644
index 000000000000..c434424be869
--- /dev/null
+++ b/fs/9p/xattr.c
@@ -0,0 +1,160 @@
1/*
2 * Copyright IBM Corporation, 2010
3 * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2.1 of the GNU Lesser General Public License
7 * as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 *
13 */
14
15#include <linux/module.h>
16#include <linux/fs.h>
17#include <linux/sched.h>
18#include <net/9p/9p.h>
19#include <net/9p/client.h>
20
21#include "fid.h"
22#include "xattr.h"
23
24/*
25 * v9fs_xattr_get()
26 *
27 * Copy an extended attribute into the buffer
28 * provided, or compute the buffer size required.
29 * Buffer is NULL to compute the size of the buffer required.
30 *
31 * Returns a negative error number on failure, or the number of bytes
32 * used / required on success.
33 */
34ssize_t v9fs_xattr_get(struct dentry *dentry, const char *name,
35 void *buffer, size_t buffer_size)
36{
37 ssize_t retval;
38 int msize, read_count;
39 u64 offset = 0, attr_size;
40 struct p9_fid *fid, *attr_fid;
41
42 P9_DPRINTK(P9_DEBUG_VFS, "%s: name = %s value_len = %zu\n",
43 __func__, name, buffer_size);
44
45 fid = v9fs_fid_lookup(dentry);
46 if (IS_ERR(fid))
47 return PTR_ERR(fid);
48
49 attr_fid = p9_client_xattrwalk(fid, name, &attr_size);
50 if (IS_ERR(attr_fid)) {
51 retval = PTR_ERR(attr_fid);
52 P9_DPRINTK(P9_DEBUG_VFS,
53 "p9_client_attrwalk failed %zd\n", retval);
54 attr_fid = NULL;
55 goto error;
56 }
57 if (!buffer_size) {
58 /* request to get the attr_size */
59 retval = attr_size;
60 goto error;
61 }
62 if (attr_size > buffer_size) {
63 retval = -ERANGE;
64 goto error;
65 }
66 msize = attr_fid->clnt->msize;
67 while (attr_size) {
68 if (attr_size > (msize - P9_IOHDRSZ))
69 read_count = msize - P9_IOHDRSZ;
70 else
71 read_count = attr_size;
72 read_count = p9_client_read(attr_fid, ((char *)buffer)+offset,
73 0, offset, read_count);
74 if (read_count < 0) {
75 /* error in xattr read */
76 retval = read_count;
77 goto error;
78 }
79 offset += read_count;
80 attr_size -= read_count;
81 }
82 /* Total read xattr bytes */
83 retval = offset;
84error:
85 if (attr_fid)
86 p9_client_clunk(attr_fid);
87 return retval;
88
89}
90
91/*
92 * v9fs_xattr_set()
93 *
94 * Create, replace or remove an extended attribute for this inode. Buffer
95 * is NULL to remove an existing extended attribute, and non-NULL to
96 * either replace an existing extended attribute, or create a new extended
97 * attribute. The flags XATTR_REPLACE and XATTR_CREATE
98 * specify that an extended attribute must exist and must not exist
99 * previous to the call, respectively.
100 *
101 * Returns 0, or a negative error number on failure.
102 */
103int v9fs_xattr_set(struct dentry *dentry, const char *name,
104 const void *value, size_t value_len, int flags)
105{
106 u64 offset = 0;
107 int retval, msize, write_count;
108 struct p9_fid *fid = NULL;
109
110 P9_DPRINTK(P9_DEBUG_VFS, "%s: name = %s value_len = %zu flags = %d\n",
111 __func__, name, value_len, flags);
112
113 fid = v9fs_fid_clone(dentry);
114 if (IS_ERR(fid)) {
115 retval = PTR_ERR(fid);
116 fid = NULL;
117 goto error;
118 }
119 /*
120 * On success fid points to xattr
121 */
122 retval = p9_client_xattrcreate(fid, name, value_len, flags);
123 if (retval < 0) {
124 P9_DPRINTK(P9_DEBUG_VFS,
125 "p9_client_xattrcreate failed %d\n", retval);
126 goto error;
127 }
128 msize = fid->clnt->msize;;
129 while (value_len) {
130 if (value_len > (msize - P9_IOHDRSZ))
131 write_count = msize - P9_IOHDRSZ;
132 else
133 write_count = value_len;
134 write_count = p9_client_write(fid, ((char *)value)+offset,
135 0, offset, write_count);
136 if (write_count < 0) {
137 /* error in xattr write */
138 retval = write_count;
139 goto error;
140 }
141 offset += write_count;
142 value_len -= write_count;
143 }
144 /* Total read xattr bytes */
145 retval = offset;
146error:
147 if (fid)
148 retval = p9_client_clunk(fid);
149 return retval;
150}
151
152ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
153{
154 return v9fs_xattr_get(dentry, NULL, buffer, buffer_size);
155}
156
157const struct xattr_handler *v9fs_xattr_handlers[] = {
158 &v9fs_xattr_user_handler,
159 NULL
160};
diff --git a/fs/9p/xattr.h b/fs/9p/xattr.h
new file mode 100644
index 000000000000..9ddf672ae5c4
--- /dev/null
+++ b/fs/9p/xattr.h
@@ -0,0 +1,27 @@
1/*
2 * Copyright IBM Corporation, 2010
3 * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2.1 of the GNU Lesser General Public License
7 * as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 *
13 */
14#ifndef FS_9P_XATTR_H
15#define FS_9P_XATTR_H
16
17#include <linux/xattr.h>
18
19extern const struct xattr_handler *v9fs_xattr_handlers[];
20extern struct xattr_handler v9fs_xattr_user_handler;
21
22extern ssize_t v9fs_xattr_get(struct dentry *, const char *,
23 void *, size_t);
24extern int v9fs_xattr_set(struct dentry *, const char *,
25 const void *, size_t, int);
26extern ssize_t v9fs_listxattr(struct dentry *, char *, size_t);
27#endif /* FS_9P_XATTR_H */
diff --git a/fs/9p/xattr_user.c b/fs/9p/xattr_user.c
new file mode 100644
index 000000000000..d0b701b72080
--- /dev/null
+++ b/fs/9p/xattr_user.c
@@ -0,0 +1,80 @@
1/*
2 * Copyright IBM Corporation, 2010
3 * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2.1 of the GNU Lesser General Public License
7 * as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 *
13 */
14
15
16#include <linux/module.h>
17#include <linux/string.h>
18#include <linux/fs.h>
19#include <linux/slab.h>
20#include "xattr.h"
21
22static int v9fs_xattr_user_get(struct dentry *dentry, const char *name,
23 void *buffer, size_t size, int type)
24{
25 int retval;
26 char *full_name;
27 size_t name_len;
28 size_t prefix_len = XATTR_USER_PREFIX_LEN;
29
30 if (name == NULL)
31 return -EINVAL;
32
33 if (strcmp(name, "") == 0)
34 return -EINVAL;
35
36 name_len = strlen(name);
37 full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
38 if (!full_name)
39 return -ENOMEM;
40 memcpy(full_name, XATTR_USER_PREFIX, prefix_len);
41 memcpy(full_name+prefix_len, name, name_len);
42 full_name[prefix_len + name_len] = '\0';
43
44 retval = v9fs_xattr_get(dentry, full_name, buffer, size);
45 kfree(full_name);
46 return retval;
47}
48
49static int v9fs_xattr_user_set(struct dentry *dentry, const char *name,
50 const void *value, size_t size, int flags, int type)
51{
52 int retval;
53 char *full_name;
54 size_t name_len;
55 size_t prefix_len = XATTR_USER_PREFIX_LEN;
56
57 if (name == NULL)
58 return -EINVAL;
59
60 if (strcmp(name, "") == 0)
61 return -EINVAL;
62
63 name_len = strlen(name);
64 full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
65 if (!full_name)
66 return -ENOMEM;
67 memcpy(full_name, XATTR_USER_PREFIX, prefix_len);
68 memcpy(full_name + prefix_len, name, name_len);
69 full_name[prefix_len + name_len] = '\0';
70
71 retval = v9fs_xattr_set(dentry, full_name, value, size, flags);
72 kfree(full_name);
73 return retval;
74}
75
76struct xattr_handler v9fs_xattr_user_handler = {
77 .prefix = XATTR_USER_PREFIX,
78 .get = v9fs_xattr_user_get,
79 .set = v9fs_xattr_user_set,
80};