Whamcloud - gitweb
b=14149
[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 = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
330         LASSERT(body);
331
332         /* only detect the xattr size */
333         if (size == 0)
334                 GOTO(out, rc = body->eadatasize);
335
336         if (size < body->eadatasize) {
337                 CERROR("server bug: replied size %u > %u\n",
338                        body->eadatasize, (int)size);
339                 GOTO(out, rc = -ERANGE);
340         }
341
342         /* do not need swab xattr data */
343         xdata = req_capsule_server_sized_get(&req->rq_pill, &RMF_EADATA,
344                                              body->eadatasize);
345         if (!xdata)
346                 GOTO(out, rc = -EFAULT);
347
348 #ifdef CONFIG_FS_POSIX_ACL
349         if (body->eadatasize >= 0 && rce && rce->rce_ops == RMT_LSETFACL) {
350                 ext_acl_xattr_header *acl;
351
352                 acl = lustre_posix_acl_xattr_2ext((posix_acl_xattr_header *)xdata,
353                                                   body->eadatasize);
354                 if (IS_ERR(acl))
355                         GOTO(out, rc = PTR_ERR(acl));
356
357                 rc = ee_add(&sbi->ll_et, cfs_curproc_pid(), ll_inode2fid(inode),
358                             xattr_type, acl);
359                 if (unlikely(rc < 0)) {
360                         lustre_ext_acl_xattr_free(acl);
361                         GOTO(out, rc);
362                 }
363         }
364
365         if (xattr_type == XATTR_ACL_ACCESS_T && !body->eadatasize)
366                 GOTO(out, rc = -ENODATA);
367 #endif
368         LASSERT(buffer);
369         memcpy(buffer, xdata, body->eadatasize);
370         rc = body->eadatasize;
371         EXIT;
372 out:
373         ptlrpc_req_finished(req);
374         return rc;
375 }
376
377 ssize_t ll_getxattr(struct dentry *dentry, const char *name,
378                     void *buffer, size_t size)
379 {
380         struct inode *inode = dentry->d_inode;
381
382         LASSERT(inode);
383         LASSERT(name);
384
385         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), xattr %s\n",
386                inode->i_ino, inode->i_generation, inode, name);
387
388         ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_GETXATTR, 1);
389
390         if ((strncmp(name, XATTR_TRUSTED_PREFIX, 
391                      sizeof(XATTR_TRUSTED_PREFIX) - 1) == 0 &&
392              strcmp(name + sizeof(XATTR_TRUSTED_PREFIX) - 1, "lov") == 0) ||
393             (strncmp(name, XATTR_LUSTRE_PREFIX, 
394                      sizeof(XATTR_LUSTRE_PREFIX) - 1) == 0 &&
395              strcmp(name + sizeof(XATTR_LUSTRE_PREFIX) - 1, "lov") == 0)) {
396                 struct lov_user_md *lump;
397                 struct lov_mds_md *lmm = NULL;
398                 struct ptlrpc_request *request = NULL;
399                 int rc = 0, lmmsize;
400
401                 if (S_ISREG(inode->i_mode)) {
402                         rc = ll_lov_getstripe_ea_info(dentry->d_parent->d_inode, 
403                                                       dentry->d_name.name, &lmm, 
404                                                       &lmmsize, &request);
405                 } else if (S_ISDIR(inode->i_mode)) {
406                         rc = ll_dir_getstripe(inode, &lmm, &lmmsize, &request);
407                 }
408
409                 if (rc < 0)
410                        GOTO(out, rc);
411                 if (size == 0)
412                        GOTO(out, rc = lmmsize);
413
414                 if (size < lmmsize) {
415                         CERROR("server bug: replied size %u > %u\n",
416                                lmmsize, (int)size);
417                         GOTO(out, rc = -ERANGE);
418                 }
419
420                 lump = (struct lov_user_md *)buffer;
421                 memcpy(lump, lmm, lmmsize);
422
423                 rc = lmmsize;
424 out:
425                 ptlrpc_req_finished(request);
426                 return(rc);
427         }
428
429         return ll_getxattr_common(inode, name, buffer, size, OBD_MD_FLXATTR);
430 }
431
432 ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size)
433 {
434         struct inode *inode = dentry->d_inode;
435         int rc = 0, rc2 = 0;
436         struct lov_mds_md *lmm = NULL;
437         struct ptlrpc_request *request = NULL;
438         int lmmsize;
439
440         LASSERT(inode);
441
442         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n",
443                inode->i_ino, inode->i_generation, inode);
444
445         ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_LISTXATTR, 1);
446
447         rc = ll_getxattr_common(inode, NULL, buffer, size, OBD_MD_FLXATTRLS);
448
449         if (S_ISREG(inode->i_mode)) {
450                 struct ll_inode_info *lli = ll_i2info(inode);
451                 struct lov_stripe_md *lsm = NULL;
452                 lsm = lli->lli_smd;
453                 if (lsm == NULL)
454                         rc2 = -1; 
455         } else if (S_ISDIR(inode->i_mode)) {
456                 rc2 = ll_dir_getstripe(inode, &lmm, &lmmsize, &request);
457         }
458
459         if (rc2 < 0) {
460                 GOTO(out, rc2 = 0);
461         } else {
462                 const int prefix_len = sizeof(XATTR_LUSTRE_PREFIX) - 1;
463                 const size_t name_len   = sizeof("lov") - 1;
464                 const size_t total_len  = prefix_len + name_len + 1;
465
466                 if (buffer && (rc + total_len) <= size) {
467                         buffer += rc;
468                         memcpy(buffer,XATTR_LUSTRE_PREFIX, prefix_len);
469                         memcpy(buffer+prefix_len, "lov", name_len);
470                         buffer[prefix_len + name_len] = '\0';
471                 }
472                 rc2 = total_len;
473         }
474 out:
475         ptlrpc_req_finished(request);
476         rc = rc + rc2;
477         
478         return rc;
479 }
480