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