Whamcloud - gitweb
land b_colibri_devel on HEAD:
[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 <lustre_ver.h>
33 //#include <lustre_mdc.h>
34 #include <linux/lustre_acl.h>
35
36 #include "llite_internal.h"
37
38 #define XATTR_USER_PREFIX       "user."
39 #define XATTR_TRUSTED_PREFIX    "trusted."
40 #define XATTR_SECURITY_PREFIX   "security."
41 #define XATTR_LUSTRE_PREFIX     "lustre."
42
43 #define XATTR_USER_T            (1)
44 #define XATTR_TRUSTED_T         (2)
45 #define XATTR_SECURITY_T        (3)
46 #define XATTR_ACL_ACCESS_T      (4)
47 #define XATTR_ACL_DEFAULT_T     (5)
48 #define XATTR_LUSTRE_T          (6)
49 #define XATTR_OTHER_T           (7)
50
51 static
52 int get_xattr_type(const char *name)
53 {
54         if (!strcmp(name, POSIX_ACL_XATTR_ACCESS))
55                 return XATTR_ACL_ACCESS_T;
56
57         if (!strcmp(name, POSIX_ACL_XATTR_DEFAULT))
58                 return XATTR_ACL_DEFAULT_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         if (!strncmp(name, XATTR_LUSTRE_PREFIX,
73                      sizeof(XATTR_LUSTRE_PREFIX) - 1))
74                 return XATTR_LUSTRE_T;
75
76         return XATTR_OTHER_T;
77 }
78
79 static
80 int xattr_type_filter(struct ll_sb_info *sbi, int xattr_type)
81 {
82         if ((xattr_type == XATTR_ACL_ACCESS_T ||
83              xattr_type == XATTR_ACL_DEFAULT_T) &&
84            !(sbi->ll_flags & LL_SBI_ACL))
85                 return -EOPNOTSUPP;
86
87         if (xattr_type == XATTR_USER_T && !(sbi->ll_flags & LL_SBI_USER_XATTR))
88                 return -EOPNOTSUPP;
89         if (xattr_type == XATTR_TRUSTED_T && !capable(CAP_SYS_ADMIN))
90                 return -EPERM;
91         if (xattr_type == XATTR_OTHER_T)
92                 return -EOPNOTSUPP;
93
94         return 0;
95 }
96
97 static
98 int ll_setxattr_common(struct inode *inode, const char *name,
99                        const void *value, size_t size,
100                        int flags, __u64 valid)
101 {
102         struct ll_sb_info *sbi = ll_i2sbi(inode);
103         struct ptlrpc_request *req;
104         int xattr_type, rc;
105         struct obd_capa *oc;
106         posix_acl_xattr_header *new_value = NULL;
107         struct rmtacl_ctl_entry *rce = NULL;
108         ext_acl_xattr_header *acl = NULL;
109         const char *pv = value;
110         ENTRY;
111
112         xattr_type = get_xattr_type(name);
113         rc = xattr_type_filter(sbi, xattr_type);
114         if (rc)
115                 RETURN(rc);
116
117         /* b10667: ignore lustre special xattr for now */
118         if ((xattr_type == XATTR_TRUSTED_T && strcmp(name, "trusted.lov") == 0) ||
119             (xattr_type == XATTR_LUSTRE_T && strcmp(name, "lustre.lov") == 0))
120                 RETURN(0);
121
122 #ifdef CONFIG_FS_POSIX_ACL
123         if (sbi->ll_flags & LL_SBI_RMT_CLIENT &&
124             (xattr_type == XATTR_ACL_ACCESS_T ||
125             xattr_type == XATTR_ACL_DEFAULT_T)) {
126                 rce = rct_search(&sbi->ll_rct, cfs_curproc_pid());
127                 if (rce == NULL ||
128                     (rce->rce_ops != RMT_LSETFACL &&
129                     rce->rce_ops != RMT_RSETFACL))
130                         RETURN(-EOPNOTSUPP);
131
132                 if (rce->rce_ops == RMT_LSETFACL) {
133                         struct eacl_entry *ee;
134
135                         ee = et_search_del(&sbi->ll_et, cfs_curproc_pid(),
136                                            ll_inode2fid(inode), xattr_type);
137                         LASSERT(ee != NULL);
138                         if (valid & OBD_MD_FLXATTR) {
139                                 acl = lustre_acl_xattr_merge2ext(
140                                                 (posix_acl_xattr_header *)value,
141                                                 size, ee->ee_acl);
142                                 if (IS_ERR(acl)) {
143                                         ee_free(ee);
144                                         RETURN(PTR_ERR(acl));
145                                 }
146                                 size =  CFS_ACL_XATTR_SIZE(\
147                                                 le32_to_cpu(acl->a_count), \
148                                                 ext_acl_xattr);
149                                 pv = (const char *)acl;
150                         }
151                         ee_free(ee);
152                 } else if (rce->rce_ops == RMT_RSETFACL) {
153                         size = lustre_posix_acl_xattr_filter(
154                                                 (posix_acl_xattr_header *)value,
155                                                 size, &new_value);
156                         if (unlikely(size < 0))
157                                 RETURN(size);
158
159                         pv = (const char *)new_value;
160                 } else
161                         RETURN(-EOPNOTSUPP);
162
163                 valid |= rce_ops2valid(rce->rce_ops);
164         }
165 #endif
166         oc = ll_mdscapa_get(inode);
167         rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc,
168                          valid, name, pv, size, 0, flags, ll_i2suppgid(inode),
169                          &req);
170         capa_put(oc);
171 #ifdef CONFIG_FS_POSIX_ACL
172         if (new_value != NULL)
173                 lustre_posix_acl_xattr_free(new_value, size);
174         if (acl != NULL)
175                 lustre_ext_acl_xattr_free(acl);
176 #endif
177         if (rc) {
178                 if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) {
179                         LCONSOLE_INFO("Disabling user_xattr feature because "
180                                       "it is not supported on the server\n"); 
181                         sbi->ll_flags &= ~LL_SBI_USER_XATTR;
182                 }
183                 RETURN(rc);
184         }
185
186         ptlrpc_req_finished(req);
187         RETURN(0);
188 }
189
190 int ll_setxattr(struct dentry *dentry, const char *name,
191                 const void *value, size_t size, int flags)
192 {
193         struct inode *inode = dentry->d_inode;
194
195         LASSERT(inode);
196         LASSERT(name);
197
198         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), xattr %s\n",
199                inode->i_ino, inode->i_generation, inode, name);
200
201         ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_SETXATTR, 1);
202
203         if ((strncmp(name, XATTR_TRUSTED_PREFIX, 
204                      sizeof(XATTR_TRUSTED_PREFIX) - 1) == 0 &&
205              strcmp(name + sizeof(XATTR_TRUSTED_PREFIX) - 1, "lov") == 0) ||
206             (strncmp(name, XATTR_LUSTRE_PREFIX, 
207                      sizeof(XATTR_LUSTRE_PREFIX) - 1) == 0 &&
208              strcmp(name + sizeof(XATTR_LUSTRE_PREFIX) - 1, "lov") == 0)) {
209                 struct lov_user_md *lump = (struct lov_user_md *)value;
210                 int rc = 0;
211
212                 if (S_ISREG(inode->i_mode)) {
213                         struct file f;
214                         int flags = FMODE_WRITE;
215                         
216                         f.f_dentry = dentry;
217                         rc = ll_lov_setstripe_ea_info(inode, &f, flags, 
218                                                       lump, sizeof(*lump));
219                         /* b10667: rc always be 0 here for now */
220                         rc = 0;
221                 } else if (S_ISDIR(inode->i_mode)) {
222                         rc = ll_dir_setstripe(inode, lump, 0);
223                 }
224                 
225                 return rc;
226         }
227
228         return ll_setxattr_common(inode, name, value, size, flags,
229                                   OBD_MD_FLXATTR);
230 }
231
232 int ll_removexattr(struct dentry *dentry, const char *name)
233 {
234         struct inode *inode = dentry->d_inode;
235
236         LASSERT(inode);
237         LASSERT(name);
238
239         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), xattr %s\n",
240                inode->i_ino, inode->i_generation, inode, name);
241
242         ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_REMOVEXATTR, 1);
243         return ll_setxattr_common(inode, name, NULL, 0, 0,
244                                   OBD_MD_FLXATTRRM);
245 }
246
247 static
248 int ll_getxattr_common(struct inode *inode, const char *name,
249                        void *buffer, size_t size, __u64 valid)
250 {
251         struct ll_sb_info *sbi = ll_i2sbi(inode);
252         struct ptlrpc_request *req = NULL;
253         struct mdt_body *body;
254         int xattr_type, rc;
255         void *xdata;
256         struct obd_capa *oc;
257         struct rmtacl_ctl_entry *rce = NULL;
258         ENTRY;
259
260         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n",
261                inode->i_ino, inode->i_generation, inode);
262
263         /* listxattr have slightly different behavior from of ext3:
264          * without 'user_xattr' ext3 will list all xattr names but
265          * filtered out "^user..*"; we list them all for simplicity.
266          */
267         if (!name) {
268                 xattr_type = XATTR_OTHER_T;
269                 goto do_getxattr;
270         }
271
272         xattr_type = get_xattr_type(name);
273         rc = xattr_type_filter(sbi, xattr_type);
274         if (rc)
275                 RETURN(rc);
276
277 #ifdef CONFIG_FS_POSIX_ACL
278         if (sbi->ll_flags & LL_SBI_RMT_CLIENT &&
279             (xattr_type == XATTR_ACL_ACCESS_T ||
280             xattr_type == XATTR_ACL_DEFAULT_T)) {
281                 rce = rct_search(&sbi->ll_rct, cfs_curproc_pid());
282                 if (rce == NULL ||
283                     (rce->rce_ops != RMT_LSETFACL &&
284                     rce->rce_ops != RMT_LGETFACL &&
285                     rce->rce_ops != RMT_RSETFACL &&
286                     rce->rce_ops != RMT_RGETFACL))
287                         RETURN(-EOPNOTSUPP);
288         }
289 #endif
290
291         /* posix acl is under protection of LOOKUP lock. when calling to this,
292          * we just have path resolution to the target inode, so we have great
293          * chance that cached ACL is uptodate.
294          */
295 #ifdef CONFIG_FS_POSIX_ACL
296         if (xattr_type == XATTR_ACL_ACCESS_T &&
297             !(sbi->ll_flags & LL_SBI_RMT_CLIENT)) {
298                 struct ll_inode_info *lli = ll_i2info(inode);
299                 struct posix_acl *acl;
300
301                 spin_lock(&lli->lli_lock);
302                 acl = posix_acl_dup(lli->lli_posix_acl);
303                 spin_unlock(&lli->lli_lock);
304
305                 if (!acl)
306                         RETURN(-ENODATA);
307
308                 rc = posix_acl_to_xattr(acl, buffer, size);
309                 posix_acl_release(acl);
310                 RETURN(rc);
311         }
312 #endif
313
314 do_getxattr:
315         oc = ll_mdscapa_get(inode);
316         rc = md_getxattr(sbi->ll_md_exp, ll_inode2fid(inode), oc,
317                          valid | (rce ? rce_ops2valid(rce->rce_ops) : 0),
318                          name, NULL, 0, size, 0, &req);
319         capa_put(oc);
320         if (rc) {
321                 if (rc == -EOPNOTSUPP && xattr_type == XATTR_USER_T) {
322                         LCONSOLE_INFO("Disabling user_xattr feature because "
323                                       "it is not supported on the server\n"); 
324                         sbi->ll_flags &= ~LL_SBI_USER_XATTR;
325                 }
326                 RETURN(rc);
327         }
328
329         body = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, sizeof(*body));
330         LASSERT(body);
331         LASSERT(lustre_rep_swabbed(req, REPLY_REC_OFF));
332
333         /* only detect the xattr size */
334         if (size == 0)
335                 GOTO(out, rc = body->eadatasize);
336
337         if (size < body->eadatasize) {
338                 CERROR("server bug: replied size %u > %u\n",
339                        body->eadatasize, (int)size);
340                 GOTO(out, rc = -ERANGE);
341         }
342
343         if (lustre_msg_bufcount(req->rq_repmsg) < 3) {
344                 CERROR("reply bufcount %u\n",
345                        lustre_msg_bufcount(req->rq_repmsg));
346                 GOTO(out, rc = -EFAULT);
347         }
348
349         /* do not need swab xattr data */
350         lustre_set_rep_swabbed(req, REPLY_REC_OFF + 1);
351         xdata = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF + 1,
352                                body->eadatasize);
353         if (!xdata) {
354                 CERROR("can't extract: %u : %u\n", body->eadatasize,
355                        lustre_msg_buflen(req->rq_repmsg, REPLY_REC_OFF + 1));
356                 GOTO(out, rc = -EFAULT);
357         }
358
359 #ifdef CONFIG_FS_POSIX_ACL
360         if (body->eadatasize >= 0 && rce && rce->rce_ops == RMT_LSETFACL) {
361                 ext_acl_xattr_header *acl;
362
363                 acl = lustre_posix_acl_xattr_2ext((posix_acl_xattr_header *)xdata,
364                                                   body->eadatasize);
365                 if (IS_ERR(acl))
366                         GOTO(out, rc = PTR_ERR(acl));
367
368                 rc = ee_add(&sbi->ll_et, cfs_curproc_pid(), ll_inode2fid(inode),
369                             xattr_type, acl);
370                 if (unlikely(rc < 0)) {
371                         lustre_ext_acl_xattr_free(acl);
372                         GOTO(out, rc);
373                 }
374         }
375
376         if (xattr_type == XATTR_ACL_ACCESS_T && !body->eadatasize)
377                 GOTO(out, rc = -ENODATA);
378 #endif
379         LASSERT(buffer);
380         memcpy(buffer, xdata, body->eadatasize);
381         rc = body->eadatasize;
382         EXIT;
383 out:
384         ptlrpc_req_finished(req);
385         return rc;
386 }
387
388 ssize_t ll_getxattr(struct dentry *dentry, const char *name,
389                     void *buffer, size_t size)
390 {
391         struct inode *inode = dentry->d_inode;
392
393         LASSERT(inode);
394         LASSERT(name);
395
396         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), xattr %s\n",
397                inode->i_ino, inode->i_generation, inode, name);
398
399         ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_GETXATTR, 1);
400
401         if ((strncmp(name, XATTR_TRUSTED_PREFIX, 
402                      sizeof(XATTR_TRUSTED_PREFIX) - 1) == 0 &&
403              strcmp(name + sizeof(XATTR_TRUSTED_PREFIX) - 1, "lov") == 0) ||
404             (strncmp(name, XATTR_LUSTRE_PREFIX, 
405                      sizeof(XATTR_LUSTRE_PREFIX) - 1) == 0 &&
406              strcmp(name + sizeof(XATTR_LUSTRE_PREFIX) - 1, "lov") == 0)) {
407                 struct lov_user_md *lump;
408                 struct lov_mds_md *lmm = NULL;
409                 struct ptlrpc_request *request = NULL;
410                 int rc = 0, lmmsize;
411
412                 if (S_ISREG(inode->i_mode)) {
413                         rc = ll_lov_getstripe_ea_info(dentry->d_parent->d_inode, 
414                                                       dentry->d_name.name, &lmm, 
415                                                       &lmmsize, &request);
416                 } else if (S_ISDIR(inode->i_mode)) {
417                         rc = ll_dir_getstripe(inode, &lmm, &lmmsize, &request);
418                 }
419
420                 if (rc < 0)
421                        GOTO(out, rc);
422                 if (size == 0)
423                        GOTO(out, rc = lmmsize);
424
425                 if (size < lmmsize) {
426                         CERROR("server bug: replied size %u > %u\n",
427                                lmmsize, (int)size);
428                         GOTO(out, rc = -ERANGE);
429                 }
430
431                 lump = (struct lov_user_md *)buffer;
432                 memcpy(lump, lmm, lmmsize);
433
434                 rc = lmmsize;
435 out:
436                 ptlrpc_req_finished(request);
437                 return(rc);
438         }
439
440         return ll_getxattr_common(inode, name, buffer, size, OBD_MD_FLXATTR);
441 }
442
443 ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size)
444 {
445         struct inode *inode = dentry->d_inode;
446         int rc = 0, rc2 = 0;
447         struct lov_mds_md *lmm = NULL;
448         struct ptlrpc_request *request = NULL;
449         int lmmsize;
450
451         LASSERT(inode);
452
453         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n",
454                inode->i_ino, inode->i_generation, inode);
455
456         ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_LISTXATTR, 1);
457
458         rc = ll_getxattr_common(inode, NULL, buffer, size, OBD_MD_FLXATTRLS);
459
460         if (S_ISREG(inode->i_mode)) {
461                 struct ll_inode_info *lli = ll_i2info(inode);
462                 struct lov_stripe_md *lsm = NULL;
463                 lsm = lli->lli_smd;
464                 if (lsm == NULL)
465                         rc2 = -1; 
466         } else if (S_ISDIR(inode->i_mode)) {
467                 rc2 = ll_dir_getstripe(inode, &lmm, &lmmsize, &request);
468         }
469
470         if (rc2 < 0) {
471                 GOTO(out, rc2 = 0);
472         } else {
473                 const int prefix_len = sizeof(XATTR_LUSTRE_PREFIX) - 1;
474                 const size_t name_len   = sizeof("lov") - 1;
475                 const size_t total_len  = prefix_len + name_len + 1;
476
477                 if (buffer && (rc + total_len) <= size) {
478                         buffer += rc;
479                         memcpy(buffer,XATTR_LUSTRE_PREFIX, prefix_len);
480                         memcpy(buffer+prefix_len, "lov", name_len);
481                         buffer[prefix_len + name_len] = '\0';
482                 }
483                 rc2 = total_len;
484         }
485 out:
486         ptlrpc_req_finished(request);
487         rc = rc + rc2;
488         
489         return rc;
490 }
491