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