Whamcloud - gitweb
cc6b0abc7a25423a9c09ed1deab52559c69ae3aa
[fs/lustre-release.git] / lustre / llite / xattr.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (c) 2004 - 2005 Cluster File Systems, Inc.
5  *
6  *   This file is part of Lustre, http://www.lustre.org.
7  *
8  *   Lustre is free software; you can redistribute it and/or
9  *   modify it under the terms of version 2 of the GNU General Public
10  *   License as published by the Free Software Foundation.
11  *
12  *   Lustre is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with Lustre; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 #include <linux/fs.h>
23 #include <linux/sched.h>
24 #include <linux/mm.h>
25 #include <linux/smp_lock.h>
26 #ifdef HAVE_LINUX_XATTR_ACL_H
27 #include <linux/xattr_acl.h>
28 #else
29 #define XATTR_NAME_ACL_ACCESS   "system.posix_acl_access"
30 #define XATTR_NAME_ACL_DEFAULT  "system.posix_acl_default"
31 #endif
32
33 #define DEBUG_SUBSYSTEM S_LLITE
34
35 #include <linux/obd_support.h>
36 #include <linux/lustre_lite.h>
37 #include <linux/lustre_dlm.h>
38 #include <linux/lustre_version.h>
39 #include <linux/lustre_mdc.h>
40
41 #include "llite_internal.h"
42
43 #define XATTR_USER_PREFIX       "user."
44 #define XATTR_TRUSTED_PREFIX    "trusted."
45 #define XATTR_SECURITY_PREFIX   "security."
46
47 #define XATTR_USER_T            (1)
48 #define XATTR_TRUSTED_T         (2)
49 #define XATTR_SECURITY_T        (3)
50 #define XATTR_ACL_T             (4)
51 #define XATTR_OTHER_T           (5)
52
53 static
54 int get_xattr_type(const char *name)
55 {
56         if (!strcmp(name, XATTR_NAME_ACL_ACCESS) ||
57             !strcmp(name, XATTR_NAME_ACL_DEFAULT))
58                 return XATTR_ACL_T;
59
60         if (!strncmp(name, XATTR_USER_PREFIX,
61                      sizeof(XATTR_USER_PREFIX) - 1))
62                 return XATTR_USER_T;
63
64         if (!strncmp(name, XATTR_TRUSTED_PREFIX,
65                      sizeof(XATTR_TRUSTED_PREFIX) - 1))
66                 return XATTR_TRUSTED_T;
67
68         if (!strncmp(name, XATTR_SECURITY_PREFIX,
69                      sizeof(XATTR_SECURITY_PREFIX) - 1))
70                 return XATTR_SECURITY_T;
71
72         return XATTR_OTHER_T;
73 }
74
75 static
76 int xattr_type_filter(struct ll_sb_info *sbi, int xattr_type)
77 {
78         if (xattr_type == XATTR_ACL_T && !(sbi->ll_flags & LL_SBI_ACL))
79                 return -EOPNOTSUPP;
80         if (xattr_type == XATTR_USER_T && !(sbi->ll_flags & LL_SBI_USER_XATTR))
81                 return -EOPNOTSUPP;
82         if (xattr_type == XATTR_TRUSTED_T && !capable(CAP_SYS_ADMIN))
83                 return -EPERM;
84         if (xattr_type == XATTR_OTHER_T)
85                 return -EOPNOTSUPP;
86
87         return 0;
88 }
89
90 static
91 int ll_setxattr_common(struct inode *inode, const char *name,
92                        const void *value, size_t size,
93                        int flags, __u64 valid)
94 {
95         struct ll_sb_info *sbi = ll_i2sbi(inode);
96         struct ptlrpc_request *req;
97         struct lu_fid fid;
98         int xattr_type, rc;
99         ENTRY;
100
101         lprocfs_counter_incr(sbi->ll_stats, LPROC_LL_SETXATTR);
102
103         xattr_type = get_xattr_type(name);
104         rc = xattr_type_filter(sbi, xattr_type);
105         if (rc)
106                 RETURN(rc);
107
108         ll_inode2fid(&fid, inode);
109         rc = mdc_setxattr(sbi->ll_mdc_exp, &fid, valid,
110                           name, value, size, 0, flags, &req);
111         if (rc) {
112                 if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) {
113                         LCONSOLE_INFO("Disabling user_xattr feature because "
114                                       "it is not supported on the server\n"); 
115                         sbi->ll_flags &= ~LL_SBI_USER_XATTR;
116                 }
117                 RETURN(rc);
118         }
119
120         ptlrpc_req_finished(req);
121         RETURN(0);
122 }
123
124 int ll_setxattr(struct dentry *dentry, const char *name,
125                 const void *value, size_t size, int flags)
126 {
127         struct inode *inode = dentry->d_inode;
128
129         LASSERT(inode);
130         LASSERT(name);
131
132         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), xattr %s\n",
133                inode->i_ino, inode->i_generation, inode, name);
134
135         return ll_setxattr_common(inode, name, value, size, flags,
136                                   OBD_MD_FLXATTR);
137 }
138
139 int ll_removexattr(struct dentry *dentry, const char *name)
140 {
141         struct inode *inode = dentry->d_inode;
142
143         LASSERT(inode);
144         LASSERT(name);
145
146         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), xattr %s\n",
147                inode->i_ino, inode->i_generation, inode, name);
148
149         return ll_setxattr_common(inode, name, NULL, 0, 0,
150                                   OBD_MD_FLXATTRRM);
151 }
152
153 static
154 int ll_getxattr_common(struct inode *inode, const char *name,
155                        void *buffer, size_t size, __u64 valid)
156 {
157         struct ll_sb_info *sbi = ll_i2sbi(inode);
158         struct ptlrpc_request *req = NULL;
159         struct mdt_body *body;
160         struct lu_fid fid;
161         void *xdata;
162         int xattr_type, rc;
163         ENTRY;
164
165         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n",
166                inode->i_ino, inode->i_generation, inode);
167
168         lprocfs_counter_incr(sbi->ll_stats, LPROC_LL_GETXATTR);
169
170         /* listxattr have slightly different behavior from of ext3:
171          * without 'user_xattr' ext3 will list all xattr names but
172          * filtered out "^user..*"; we list them all for simplicity.
173          */
174         if (!name) {
175                 xattr_type = XATTR_OTHER_T;
176                 goto do_getxattr;
177         }
178
179         xattr_type = get_xattr_type(name);
180         rc = xattr_type_filter(sbi, xattr_type);
181         if (rc)
182                 RETURN(rc);
183
184 do_getxattr:
185         ll_inode2fid(&fid, inode);
186         rc = mdc_getxattr(sbi->ll_mdc_exp, &fid, valid, name, NULL, 0,
187                           size, &req);
188         if (rc) {
189                 if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) {
190                         LCONSOLE_INFO("Disabling user_xattr feature because "
191                                       "it is not supported on the server\n"); 
192                         sbi->ll_flags &= ~LL_SBI_USER_XATTR;
193                 }
194                 RETURN(rc);
195         }
196
197         body = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*body));
198         LASSERT(body);
199         LASSERT_REPSWABBED(req, 0);
200
201         /* only detect the xattr size */
202         if (size == 0)
203                 GOTO(out, rc = body->eadatasize);
204
205         if (size < body->eadatasize) {
206                 CERROR("server bug: replied size %u > %u\n",
207                        body->eadatasize, (int)size);
208                 GOTO(out, rc = -ERANGE);
209         }
210
211         if (req->rq_repmsg->bufcount < 2) {
212                 CERROR("reply bufcount %u\n", req->rq_repmsg->bufcount);
213                 GOTO(out, rc = -EFAULT);
214         }
215
216         /* do not need swab xattr data */
217         LASSERT_REPSWAB(req, 1);
218         xdata = lustre_msg_buf(req->rq_repmsg, 1, body->eadatasize);
219         if (!xdata) {
220                 CERROR("can't extract: %u : %u\n", body->eadatasize,
221                        lustre_msg_buflen(req->rq_repmsg, 1));
222                 GOTO(out, rc = -EFAULT);
223         }
224
225         LASSERT(buffer);
226         memcpy(buffer, xdata, body->eadatasize);
227         rc = body->eadatasize;
228 out:
229         ptlrpc_req_finished(req);
230         RETURN(rc);
231 }
232
233 ssize_t ll_getxattr(struct dentry *dentry, const char *name,
234                     void *buffer, size_t size)
235 {
236         struct inode *inode = dentry->d_inode;
237
238         LASSERT(inode);
239         LASSERT(name);
240
241         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), xattr %s\n",
242                inode->i_ino, inode->i_generation, inode, name);
243
244         return ll_getxattr_common(inode, name, buffer, size, OBD_MD_FLXATTR);
245 }
246
247 ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size)
248 {
249         struct inode *inode = dentry->d_inode;
250
251         LASSERT(inode);
252
253         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n",
254                inode->i_ino, inode->i_generation, inode);
255
256         return ll_getxattr_common(inode, NULL, buffer, size, OBD_MD_FLXATTRLS);
257 }
258