Whamcloud - gitweb
cleanup usage obd_set_info_async, obd_get_info.
[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
27 #define DEBUG_SUBSYSTEM S_LLITE
28
29 #include <obd_support.h>
30 #include <lustre_lite.h>
31 #include <lustre_dlm.h>
32 #include <linux/lustre_version.h>
33
34 #ifndef POSIX_ACL_XATTR_ACCESS
35 #ifndef XATTR_NAME_ACL_ACCESS
36 #define XATTR_NAME_ACL_ACCESS   "system.posix_acl_access"
37 #endif
38 #define POSIX_ACL_XATTR_ACCESS XATTR_NAME_ACL_ACCESS
39 #endif
40 #ifndef POSIX_ACL_XATTR_DEFAULT
41 #ifndef XATTR_NAME_ACL_DEFAULT
42 #define XATTR_NAME_ACL_DEFAULT  "system.posix_acl_default"
43 #endif
44 #define POSIX_ACL_XATTR_DEFAULT XATTR_NAME_ACL_DEFAULT
45 #endif
46
47 #include "llite_internal.h"
48
49 #define XATTR_USER_PREFIX       "user."
50 #define XATTR_TRUSTED_PREFIX    "trusted."
51 #define XATTR_SECURITY_PREFIX   "security."
52 #define XATTR_LUSTRE_PREFIX     "lustre."
53
54 #define XATTR_USER_T            (1)
55 #define XATTR_TRUSTED_T         (2)
56 #define XATTR_SECURITY_T        (3)
57 #define XATTR_ACL_ACCESS_T      (4)
58 #define XATTR_ACL_DEFAULT_T     (5)
59 #define XATTR_LUSTRE_T          (6)
60 #define XATTR_OTHER_T           (7)
61
62 static
63 int get_xattr_type(const char *name)
64 {
65         if (!strcmp(name, POSIX_ACL_XATTR_ACCESS))
66                 return XATTR_ACL_ACCESS_T;
67
68         if (!strcmp(name, POSIX_ACL_XATTR_DEFAULT))
69                 return XATTR_ACL_DEFAULT_T;
70
71         if (!strncmp(name, XATTR_USER_PREFIX,
72                      sizeof(XATTR_USER_PREFIX) - 1))
73                 return XATTR_USER_T;
74
75         if (!strncmp(name, XATTR_TRUSTED_PREFIX,
76                      sizeof(XATTR_TRUSTED_PREFIX) - 1))
77                 return XATTR_TRUSTED_T;
78
79         if (!strncmp(name, XATTR_SECURITY_PREFIX,
80                      sizeof(XATTR_SECURITY_PREFIX) - 1))
81                 return XATTR_SECURITY_T;
82
83         if (!strncmp(name, XATTR_LUSTRE_PREFIX,
84                      sizeof(XATTR_LUSTRE_PREFIX) - 1))
85                 return XATTR_LUSTRE_T;
86
87         return XATTR_OTHER_T;
88 }
89
90 static
91 int xattr_type_filter(struct ll_sb_info *sbi, int xattr_type)
92 {
93         if ((xattr_type == XATTR_ACL_ACCESS_T ||
94              xattr_type == XATTR_ACL_DEFAULT_T) &&
95             !(sbi->ll_flags & LL_SBI_ACL))
96                 return -EOPNOTSUPP;
97
98         if (xattr_type == XATTR_USER_T && !(sbi->ll_flags & LL_SBI_USER_XATTR))
99                 return -EOPNOTSUPP;
100         if (xattr_type == XATTR_TRUSTED_T && !capable(CAP_SYS_ADMIN))
101                 return -EPERM;
102         if (xattr_type == XATTR_OTHER_T)
103                 return -EOPNOTSUPP;
104
105         return 0;
106 }
107
108 static
109 int ll_setxattr_common(struct inode *inode, const char *name,
110                        const void *value, size_t size,
111                        int flags, __u64 valid)
112 {
113         struct ll_sb_info *sbi = ll_i2sbi(inode);
114         struct ptlrpc_request *req;
115         struct ll_fid fid;
116         int xattr_type, rc;
117         ENTRY;
118
119
120         xattr_type = get_xattr_type(name);
121         rc = xattr_type_filter(sbi, xattr_type);
122         if (rc)
123                 RETURN(rc);
124
125         /* b10667: ignore lustre special xattr for now */
126         if ((xattr_type == XATTR_TRUSTED_T && strcmp(name, "trusted.lov") == 0) ||
127             (xattr_type == XATTR_LUSTRE_T && strcmp(name, "lustre.lov") == 0))
128                 RETURN(0);
129
130         ll_inode2fid(&fid, inode);
131         rc = mdc_setxattr(sbi->ll_mdc_exp, &fid, valid,
132                           name, value, size, 0, flags, &req);
133         if (rc) {
134                 if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) {
135                         LCONSOLE_INFO("Disabling user_xattr feature because "
136                                       "it is not supported on the server\n"); 
137                         sbi->ll_flags &= ~LL_SBI_USER_XATTR;
138                 }
139                 RETURN(rc);
140         }
141
142         ptlrpc_req_finished(req);
143         RETURN(0);
144 }
145
146 int ll_setxattr(struct dentry *dentry, const char *name,
147                 const void *value, size_t size, int flags)
148 {
149         struct inode *inode = dentry->d_inode;
150
151         LASSERT(inode);
152         LASSERT(name);
153
154         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), xattr %s\n",
155                inode->i_ino, inode->i_generation, inode, name);
156
157         ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_SETXATTR, 1);
158
159         if ((strncmp(name, XATTR_TRUSTED_PREFIX, 
160                     sizeof(XATTR_TRUSTED_PREFIX) - 1) == 0 &&
161              strcmp(name + sizeof(XATTR_TRUSTED_PREFIX) - 1, "lov") == 0) ||
162             (strncmp(name, XATTR_LUSTRE_PREFIX, 
163                     sizeof(XATTR_LUSTRE_PREFIX) - 1) == 0 &&
164              strcmp(name + sizeof(XATTR_LUSTRE_PREFIX) - 1, "lov") == 0)) {
165                 struct lov_user_md *lump = (struct lov_user_md *)value;
166                 int rc = 0;
167
168                 if (S_ISREG(inode->i_mode)) {
169                         struct file f;
170                         int flags = FMODE_WRITE;
171                         
172                         f.f_dentry = dentry;
173                         rc = ll_lov_setstripe_ea_info(inode, &f, flags, 
174                                                       lump, sizeof(*lump));
175                         /* b10667: rc always be 0 here for now */
176                         rc = 0;
177                 } else if (S_ISDIR(inode->i_mode)) {
178                         rc = ll_dir_setstripe(inode, lump, 0);
179                 }
180                 
181                 return rc;
182         }
183
184         return ll_setxattr_common(inode, name, value, size, flags,
185                                   OBD_MD_FLXATTR);
186 }
187
188 int ll_removexattr(struct dentry *dentry, const char *name)
189 {
190         struct inode *inode = dentry->d_inode;
191
192         LASSERT(inode);
193         LASSERT(name);
194
195         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), xattr %s\n",
196                inode->i_ino, inode->i_generation, inode, name);
197
198         ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_REMOVEXATTR, 1);
199         return ll_setxattr_common(inode, name, NULL, 0, 0,
200                                   OBD_MD_FLXATTRRM);
201 }
202
203 static
204 int ll_getxattr_common(struct inode *inode, const char *name,
205                        void *buffer, size_t size, __u64 valid)
206 {
207         struct ll_sb_info *sbi = ll_i2sbi(inode);
208         struct ptlrpc_request *req = NULL;
209         struct mds_body *body;
210         struct ll_fid fid;
211         void *xdata;
212         int xattr_type, rc;
213         ENTRY;
214
215         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n",
216                inode->i_ino, inode->i_generation, inode);
217
218
219         /* listxattr have slightly different behavior from of ext3:
220          * without 'user_xattr' ext3 will list all xattr names but
221          * filtered out "^user..*"; we list them all for simplicity.
222          */
223         if (!name) {
224                 xattr_type = XATTR_OTHER_T;
225                 goto do_getxattr;
226         }
227
228         xattr_type = get_xattr_type(name);
229         rc = xattr_type_filter(sbi, xattr_type);
230         if (rc)
231                 RETURN(rc);
232
233         /* posix acl is under protection of LOOKUP lock. when calling to this,
234          * we just have path resolution to the target inode, so we have great
235          * chance that cached ACL is uptodate.
236          */
237 #ifdef CONFIG_FS_POSIX_ACL
238         if (xattr_type == XATTR_ACL_ACCESS_T) {
239                 struct ll_inode_info *lli = ll_i2info(inode);
240                 struct posix_acl *acl;
241
242                 spin_lock(&lli->lli_lock);
243                 acl = posix_acl_dup(lli->lli_posix_acl);
244                 spin_unlock(&lli->lli_lock);
245
246                 if (!acl)
247                         RETURN(-ENODATA);
248
249                 rc = posix_acl_to_xattr(acl, buffer, size);
250                 posix_acl_release(acl);
251                 RETURN(rc);
252         }
253         if (xattr_type == XATTR_ACL_DEFAULT_T && !S_ISDIR(inode->i_mode))
254                 RETURN(-ENODATA);
255 #endif
256
257 do_getxattr:
258         ll_inode2fid(&fid, inode);
259         rc = mdc_getxattr(sbi->ll_mdc_exp, &fid, valid, name, NULL, 0, size,
260                           &req);
261         if (rc) {
262                 if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) {
263                         LCONSOLE_INFO("Disabling user_xattr feature because "
264                                       "it is not supported on the server\n"); 
265                         sbi->ll_flags &= ~LL_SBI_USER_XATTR;
266                 }
267                 RETURN(rc);
268         }
269
270         body = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, sizeof(*body));
271         LASSERT(body);
272         LASSERT(lustre_rep_swabbed(req, REPLY_REC_OFF));
273
274         /* only detect the xattr size */
275         if (size == 0)
276                 GOTO(out, rc = body->eadatasize);
277
278         if (size < body->eadatasize) {
279                 CERROR("server bug: replied size %u > %u\n",
280                        body->eadatasize, (int)size);
281                 GOTO(out, rc = -ERANGE);
282         }
283
284         if (lustre_msg_bufcount(req->rq_repmsg) < 3) {
285                 CERROR("reply bufcount %u\n",
286                        lustre_msg_bufcount(req->rq_repmsg));
287                 GOTO(out, rc = -EFAULT);
288         }
289
290         /* do not need swab xattr data */
291         lustre_set_rep_swabbed(req, REPLY_REC_OFF + 1);
292         xdata = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF + 1,
293                                body->eadatasize);
294         if (!xdata) {
295                 CERROR("can't extract: %u : %u\n", body->eadatasize,
296                        lustre_msg_buflen(req->rq_repmsg, REPLY_REC_OFF + 1));
297                 GOTO(out, rc = -EFAULT);
298         }
299
300         LASSERT(buffer);
301         memcpy(buffer, xdata, body->eadatasize);
302         rc = body->eadatasize;
303 out:
304         ptlrpc_req_finished(req);
305         RETURN(rc);
306 }
307
308 ssize_t ll_getxattr(struct dentry *dentry, const char *name,
309                     void *buffer, size_t size)
310 {
311         struct inode *inode = dentry->d_inode;
312
313         LASSERT(inode);
314         LASSERT(name);
315
316         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), xattr %s\n",
317                inode->i_ino, inode->i_generation, inode, name);
318
319         ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_GETXATTR, 1);
320
321         if ((strncmp(name, XATTR_TRUSTED_PREFIX, 
322                     sizeof(XATTR_TRUSTED_PREFIX) - 1) == 0 &&
323              strcmp(name + sizeof(XATTR_TRUSTED_PREFIX) - 1, "lov") == 0) ||
324             (strncmp(name, XATTR_LUSTRE_PREFIX, 
325                     sizeof(XATTR_LUSTRE_PREFIX) - 1) == 0 &&
326              strcmp(name + sizeof(XATTR_LUSTRE_PREFIX) - 1, "lov") == 0)) {
327                 struct lov_user_md *lump;
328                 struct lov_mds_md *lmm = NULL;
329                 struct ptlrpc_request *request = NULL;
330                 int rc = 0, lmmsize;
331
332                 if (S_ISREG(inode->i_mode)) {
333                         rc = ll_lov_getstripe_ea_info(dentry->d_parent->d_inode, 
334                                                       dentry->d_name.name, &lmm, 
335                                                       &lmmsize, &request);
336                 } else if (S_ISDIR(inode->i_mode)) {
337                         rc = ll_dir_getstripe(inode, &lmm, &lmmsize, &request);
338                 }
339
340                 if (rc < 0)
341                        GOTO(out, rc);
342                 if (size == 0)
343                        GOTO(out, rc = lmmsize);
344
345                 if (size < lmmsize) {
346                         CERROR("server bug: replied size %u > %u\n",
347                                lmmsize, (int)size);
348                         GOTO(out, rc = -ERANGE);
349                 }
350
351                 lump = (struct lov_user_md *)buffer;
352                 memcpy(lump, lmm, lmmsize);
353
354                 rc = lmmsize;
355 out:
356                 ptlrpc_req_finished(request);
357                 return(rc);
358         }
359
360         return ll_getxattr_common(inode, name, buffer, size, OBD_MD_FLXATTR);
361 }
362
363 ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size)
364 {
365         struct inode *inode = dentry->d_inode;
366         int rc = 0, rc2 = 0;
367         struct lov_mds_md *lmm = NULL;
368         struct ptlrpc_request *request = NULL;
369         int lmmsize;
370
371         LASSERT(inode);
372
373         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n",
374                inode->i_ino, inode->i_generation, inode);
375
376         ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_LISTXATTR, 1);
377
378         rc = ll_getxattr_common(inode, NULL, buffer, size, OBD_MD_FLXATTRLS);
379
380         if (S_ISREG(inode->i_mode)) {
381                 struct ll_inode_info *lli = ll_i2info(inode);
382                 struct lov_stripe_md *lsm = NULL;
383                 lsm = lli->lli_smd;
384                 if (lsm == NULL)
385                         rc2 = -1; 
386         } else if (S_ISDIR(inode->i_mode)) {
387                 rc2 = ll_dir_getstripe(inode, &lmm, &lmmsize, &request);
388         }
389
390         if (rc2 < 0) {
391                 GOTO(out, rc2 = 0);
392         } else {
393                 const int prefix_len = sizeof(XATTR_LUSTRE_PREFIX) - 1;
394                 const size_t name_len   = sizeof("lov") - 1;
395                 const size_t total_len  = prefix_len + name_len + 1;
396
397                 if (buffer && (rc + total_len) <= size) {
398                         buffer += rc;
399                         memcpy(buffer,XATTR_LUSTRE_PREFIX, prefix_len);
400                         memcpy(buffer+prefix_len, "lov", name_len);
401                         buffer[prefix_len + name_len] = '\0';
402                 }
403                 rc2 = total_len;
404         }
405 out:
406         ptlrpc_req_finished(request);
407         rc = rc + rc2;
408         
409         return rc;
410 }
411