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