Whamcloud - gitweb
LU-5458: libcfs: protect kkuc_groups from write access
[fs/lustre-release.git] / lustre / osd-zfs / osd_xattr.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  */
30 /*
31  * Copyright (c) 2012, 2013, Intel Corporation.
32  * Use is subject to license terms.
33  */
34 /*
35  * This file is part of Lustre, http://www.lustre.org/
36  * Lustre is a trademark of Sun Microsystems, Inc.
37  *
38  * lustre/osd-zfs/osd_xattr.c
39  * functions to manipulate extended attributes and system attributes
40  *
41  * Author: Alex Zhuravlev <bzzz@whamcloud.com>
42  * Author: Mike Pershin <tappro@whamcloud.com>
43  */
44
45 #define DEBUG_SUBSYSTEM S_OSD
46
47 #include <lustre_ver.h>
48 #include <libcfs/libcfs.h>
49 #include <obd_support.h>
50 #include <lustre_net.h>
51 #include <obd.h>
52 #include <obd_class.h>
53 #include <lustre_disk.h>
54 #include <lustre_fid.h>
55
56 #include "osd_internal.h"
57
58 #include <sys/dnode.h>
59 #include <sys/dbuf.h>
60 #include <sys/spa.h>
61 #include <sys/stat.h>
62 #include <sys/zap.h>
63 #include <sys/spa_impl.h>
64 #include <sys/zfs_znode.h>
65 #include <sys/dmu_tx.h>
66 #include <sys/dmu_objset.h>
67 #include <sys/dsl_prop.h>
68 #include <sys/sa_impl.h>
69 #include <sys/txg.h>
70
71 #include <linux/posix_acl_xattr.h>
72
73 /*
74  * Copy an extended attribute into the buffer provided, or compute the
75  * required buffer size.
76  *
77  * If buf is NULL, it computes the required buffer size.
78  *
79  * Returns 0 on success or a negative error number on failure.
80  * On success, the number of bytes used / required is stored in 'size'.
81  *
82  * No locking is done here.
83  */
84 int __osd_xattr_load(struct osd_device *osd, uint64_t dnode, nvlist_t **sa)
85 {
86         sa_handle_t *sa_hdl;
87         char        *buf;
88         int          rc, size;
89
90         if (unlikely(dnode == ZFS_NO_OBJECT))
91                 return -ENOENT;
92
93         rc = -sa_handle_get(osd->od_os, dnode, NULL, SA_HDL_PRIVATE, &sa_hdl);
94         if (rc)
95                 return rc;
96
97         rc = -sa_size(sa_hdl, SA_ZPL_DXATTR(osd), &size);
98         if (rc) {
99                 if (rc == -ENOENT)
100                         rc = -nvlist_alloc(sa, NV_UNIQUE_NAME, KM_SLEEP);
101                 goto out_sa;
102         }
103
104         buf = sa_spill_alloc(KM_SLEEP);
105         if (buf == NULL) {
106                 rc = -ENOMEM;
107                 goto out_sa;
108         }
109         rc = -sa_lookup(sa_hdl, SA_ZPL_DXATTR(osd), buf, size);
110         if (rc == 0)
111                 rc = -nvlist_unpack(buf, size, sa, KM_SLEEP);
112         sa_spill_free(buf);
113 out_sa:
114         sa_handle_destroy(sa_hdl);
115
116         return rc;
117 }
118
119 static inline int __osd_xattr_cache(const struct lu_env *env,
120                                     struct osd_object *obj)
121 {
122         LASSERT(obj->oo_sa_xattr == NULL);
123         LASSERT(obj->oo_db != NULL);
124
125         return __osd_xattr_load(osd_obj2dev(obj), obj->oo_db->db_object,
126                                 &obj->oo_sa_xattr);
127 }
128
129 int __osd_sa_xattr_get(const struct lu_env *env, struct osd_object *obj,
130                        const struct lu_buf *buf, const char *name, int *sizep)
131 {
132         uchar_t *nv_value;
133         int      rc;
134
135         LASSERT(obj->oo_sa_hdl);
136
137         if (obj->oo_sa_xattr == NULL) {
138                 rc = __osd_xattr_cache(env, obj);
139                 if (rc)
140                         return rc;
141         }
142
143         LASSERT(obj->oo_sa_xattr);
144         rc = -nvlist_lookup_byte_array(obj->oo_sa_xattr, name, &nv_value,
145                         sizep);
146         if (rc)
147                 return rc;
148
149         if (buf == NULL || buf->lb_buf == NULL) {
150                 /* return the required size by *sizep */
151                 return 0;
152         }
153
154         if (*sizep > buf->lb_len)
155                 return -ERANGE; /* match ldiskfs error */
156
157         memcpy(buf->lb_buf, nv_value, *sizep);
158         return 0;
159 }
160
161 int __osd_xattr_get_large(const struct lu_env *env, struct osd_device *osd,
162                           uint64_t xattr, struct lu_buf *buf,
163                           const char *name, int *sizep)
164 {
165         dmu_buf_t       *xa_data_db;
166         sa_handle_t     *sa_hdl = NULL;
167         uint64_t         xa_data_obj, size;
168         int              rc;
169
170         /* are there any extended attributes? */
171         if (xattr == ZFS_NO_OBJECT)
172                 return -ENOENT;
173
174         /* Lookup the object number containing the xattr data */
175         rc = -zap_lookup(osd->od_os, xattr, name, sizeof(uint64_t), 1,
176                         &xa_data_obj);
177         if (rc)
178                 return rc;
179
180         rc = __osd_obj2dbuf(env, osd->od_os, xa_data_obj, &xa_data_db);
181         if (rc)
182                 return rc;
183
184         rc = -sa_handle_get(osd->od_os, xa_data_obj, NULL, SA_HDL_PRIVATE,
185                         &sa_hdl);
186         if (rc)
187                 goto out_rele;
188
189         /* Get the xattr value length / object size */
190         rc = -sa_lookup(sa_hdl, SA_ZPL_SIZE(osd), &size, 8);
191         if (rc)
192                 goto out;
193
194         if (size > INT_MAX) {
195                 rc = -EOVERFLOW;
196                 goto out;
197         }
198
199         *sizep = (int)size;
200
201         if (buf == NULL || buf->lb_buf == NULL) {
202                 /* We only need to return the required size */
203                 goto out;
204         }
205         if (*sizep > buf->lb_len) {
206                 rc = -ERANGE; /* match ldiskfs error */
207                 goto out;
208         }
209
210         rc = -dmu_read(osd->od_os, xa_data_db->db_object, 0,
211                         size, buf->lb_buf, DMU_READ_PREFETCH);
212
213 out:
214         sa_handle_destroy(sa_hdl);
215 out_rele:
216         dmu_buf_rele(xa_data_db, FTAG);
217
218         return rc;
219 }
220
221 int __osd_xattr_get(const struct lu_env *env, struct osd_object *obj,
222                     struct lu_buf *buf, const char *name, int *sizep)
223 {
224         int rc;
225
226         /* check SA_ZPL_DXATTR first then fallback to directory xattr */
227         rc = __osd_sa_xattr_get(env, obj, buf, name, sizep);
228         if (rc != -ENOENT)
229                 return rc;
230
231         rc = __osd_xattr_get_large(env, osd_obj2dev(obj), obj->oo_xattr,
232                                    buf, name, sizep);
233
234         return rc;
235 }
236
237 int osd_xattr_get(const struct lu_env *env, struct dt_object *dt,
238                   struct lu_buf *buf, const char *name,
239                   struct lustre_capa *capa)
240 {
241         struct osd_object  *obj  = osd_dt_obj(dt);
242         int                 rc, size = 0;
243         ENTRY;
244
245         LASSERT(obj->oo_db != NULL);
246         LASSERT(osd_invariant(obj));
247         LASSERT(dt_object_exists(dt));
248
249         if (!osd_obj2dev(obj)->od_posix_acl &&
250             (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0 ||
251              strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0))
252                 RETURN(-EOPNOTSUPP);
253
254         down(&obj->oo_guard);
255         rc = __osd_xattr_get(env, obj, buf, name, &size);
256         up(&obj->oo_guard);
257
258         if (rc == -ENOENT)
259                 rc = -ENODATA;
260         else if (rc == 0)
261                 rc = size;
262         RETURN(rc);
263 }
264
265 void __osd_xattr_declare_set(const struct lu_env *env, struct osd_object *obj,
266                              int vallen, const char *name,
267                              struct osd_thandle *oh)
268 {
269         struct osd_device *osd = osd_obj2dev(obj);
270         dmu_buf_t         *db = obj->oo_db;
271         dmu_tx_t          *tx = oh->ot_tx;
272         uint64_t           xa_data_obj;
273         int                rc = 0;
274         int                here;
275
276         here = dt_object_exists(&obj->oo_dt);
277
278         /* object may be not yet created */
279         if (here) {
280                 LASSERT(db);
281                 LASSERT(obj->oo_sa_hdl);
282                 /* we might just update SA_ZPL_DXATTR */
283                 dmu_tx_hold_sa(tx, obj->oo_sa_hdl, 1);
284
285                 if (obj->oo_xattr == ZFS_NO_OBJECT)
286                         rc = -ENOENT;
287         }
288
289         if (!here || rc == -ENOENT) {
290                 /* we'll be updating SA_ZPL_XATTR */
291                 if (here) {
292                         LASSERT(obj->oo_sa_hdl);
293                         dmu_tx_hold_sa(tx, obj->oo_sa_hdl, 1);
294                 }
295                 /* xattr zap + entry */
296                 dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, TRUE, (char *) name);
297                 /* xattr value obj */
298                 dmu_tx_hold_sa_create(tx, ZFS_SA_BASE_ATTR_SIZE);
299                 dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, vallen);
300                 return;
301         }
302
303         rc = -zap_lookup(osd->od_os, obj->oo_xattr, name, sizeof(uint64_t), 1,
304                         &xa_data_obj);
305         if (rc == 0) {
306                 /*
307                  * Entry already exists.
308                  * We'll truncate the existing object.
309                  */
310                 dmu_tx_hold_bonus(tx, xa_data_obj);
311                 dmu_tx_hold_free(tx, xa_data_obj, vallen, DMU_OBJECT_END);
312                 dmu_tx_hold_write(tx, xa_data_obj, 0, vallen);
313                 return;
314         } else if (rc == -ENOENT) {
315                 /*
316                  * Entry doesn't exist, we need to create a new one and a new
317                  * object to store the value.
318                  */
319                 dmu_tx_hold_bonus(tx, obj->oo_xattr);
320                 dmu_tx_hold_zap(tx, obj->oo_xattr, TRUE, (char *) name);
321                 dmu_tx_hold_sa_create(tx, ZFS_SA_BASE_ATTR_SIZE);
322                 dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, vallen);
323                 return;
324         }
325
326         /* An error happened */
327         tx->tx_err = -rc;
328 }
329
330 int osd_declare_xattr_set(const struct lu_env *env, struct dt_object *dt,
331                           const struct lu_buf *buf, const char *name,
332                           int fl, struct thandle *handle)
333 {
334         struct osd_object  *obj = osd_dt_obj(dt);
335         struct osd_thandle *oh;
336         ENTRY;
337
338         LASSERT(handle != NULL);
339         oh = container_of0(handle, struct osd_thandle, ot_super);
340
341         down(&obj->oo_guard);
342         __osd_xattr_declare_set(env, obj, buf->lb_len, name, oh);
343         up(&obj->oo_guard);
344
345         RETURN(0);
346 }
347
348 /*
349  * Set an extended attribute.
350  * This transaction must have called udmu_xattr_declare_set() first.
351  *
352  * Returns 0 on success or a negative error number on failure.
353  *
354  * No locking is done here.
355  */
356 static int
357 __osd_sa_xattr_update(const struct lu_env *env, struct osd_object *obj,
358                       struct osd_thandle *oh)
359 {
360         struct osd_device *osd = osd_obj2dev(obj);
361         char              *dxattr;
362         size_t             sa_size;
363         int                rc;
364
365         ENTRY;
366         LASSERT(obj->oo_sa_hdl);
367         LASSERT(obj->oo_sa_xattr);
368
369         /* Update the SA for additions, modifications, and removals. */
370         rc = -nvlist_size(obj->oo_sa_xattr, &sa_size, NV_ENCODE_XDR);
371         if (rc)
372                 return rc;
373
374         dxattr = sa_spill_alloc(KM_SLEEP);
375         if (dxattr == NULL)
376                 RETURN(-ENOMEM);
377
378         rc = -nvlist_pack(obj->oo_sa_xattr, &dxattr, &sa_size,
379                                 NV_ENCODE_XDR, KM_SLEEP);
380         if (rc)
381                 GOTO(out_free, rc);
382
383         rc = osd_object_sa_update(obj, SA_ZPL_DXATTR(osd), dxattr, sa_size, oh);
384 out_free:
385         sa_spill_free(dxattr);
386         RETURN(rc);
387 }
388
389 int __osd_sa_xattr_set(const struct lu_env *env, struct osd_object *obj,
390                        const struct lu_buf *buf, const char *name, int fl,
391                        struct osd_thandle *oh)
392 {
393         uchar_t *nv_value;
394         size_t  size;
395         int     nv_size;
396         int     rc;
397         int     too_big = 0;
398
399         LASSERT(obj->oo_sa_hdl);
400         if (obj->oo_sa_xattr == NULL) {
401                 rc = __osd_xattr_cache(env, obj);
402                 if (rc)
403                         return rc;
404         }
405
406         LASSERT(obj->oo_sa_xattr);
407         /* Limited to 32k to keep nvpair memory allocations small */
408         if (buf->lb_len > DXATTR_MAX_ENTRY_SIZE) {
409                 too_big = 1;
410         } else {
411                 /* Prevent the DXATTR SA from consuming the entire SA
412                  * region */
413                 rc = -nvlist_size(obj->oo_sa_xattr, &size, NV_ENCODE_XDR);
414                 if (rc)
415                         return rc;
416
417                 if (size + buf->lb_len > DXATTR_MAX_SA_SIZE)
418                         too_big = 1;
419         }
420
421         /* even in case of -EFBIG we must lookup xattr and check can we
422          * rewrite it then delete from SA */
423         rc = -nvlist_lookup_byte_array(obj->oo_sa_xattr, name, &nv_value,
424                                         &nv_size);
425         if (rc == 0) {
426                 if (fl & LU_XATTR_CREATE) {
427                         return -EEXIST;
428                 } else if (too_big) {
429                         rc = -nvlist_remove(obj->oo_sa_xattr, name,
430                                                 DATA_TYPE_BYTE_ARRAY);
431                         if (rc < 0)
432                                 return rc;
433                         rc = __osd_sa_xattr_update(env, obj, oh);
434                         return rc == 0 ? -EFBIG : rc;
435                 }
436         } else if (rc == -ENOENT) {
437                 if (fl & LU_XATTR_REPLACE)
438                         return -ENODATA;
439                 else if (too_big)
440                         return -EFBIG;
441         } else {
442                 return rc;
443         }
444
445         /* Ensure xattr doesn't exist in ZAP */
446         if (obj->oo_xattr != ZFS_NO_OBJECT) {
447                 struct osd_device *osd = osd_obj2dev(obj);
448                 uint64_t           objid;
449                 rc = -zap_lookup(osd->od_os, obj->oo_xattr,
450                                  name, 8, 1, &objid);
451                 if (rc == 0) {
452                         rc = -dmu_object_free(osd->od_os, objid, oh->ot_tx);
453                         if (rc == 0)
454                                 zap_remove(osd->od_os, obj->oo_xattr,
455                                            name, oh->ot_tx);
456                 }
457         }
458
459         rc = -nvlist_add_byte_array(obj->oo_sa_xattr, name,
460                                     (uchar_t *)buf->lb_buf, buf->lb_len);
461         if (rc)
462                 return rc;
463
464         rc = __osd_sa_xattr_update(env, obj, oh);
465         return rc;
466 }
467
468 int
469 __osd_xattr_set(const struct lu_env *env, struct osd_object *obj,
470                 const struct lu_buf *buf, const char *name, int fl,
471                 struct osd_thandle *oh)
472 {
473         struct osd_device *osd = osd_obj2dev(obj);
474         dmu_buf_t         *xa_zap_db = NULL;
475         dmu_buf_t         *xa_data_db = NULL;
476         uint64_t           xa_data_obj;
477         sa_handle_t       *sa_hdl = NULL;
478         dmu_tx_t          *tx = oh->ot_tx;
479         uint64_t           size;
480         int                rc;
481
482         LASSERT(obj->oo_sa_hdl);
483
484         if (obj->oo_xattr == ZFS_NO_OBJECT) {
485                 struct lu_attr *la = &osd_oti_get(env)->oti_la;
486
487                 la->la_valid = LA_MODE;
488                 la->la_mode = S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO;
489                 rc = __osd_zap_create(env, osd, &xa_zap_db, tx, la,
490                                       obj->oo_db->db_object, 0);
491                 if (rc)
492                         return rc;
493
494                 obj->oo_xattr = xa_zap_db->db_object;
495                 rc = osd_object_sa_update(obj, SA_ZPL_XATTR(osd),
496                                 &obj->oo_xattr, 8, oh);
497                 if (rc)
498                         goto out;
499         }
500
501         rc = -zap_lookup(osd->od_os, obj->oo_xattr, name, sizeof(uint64_t), 1,
502                          &xa_data_obj);
503         if (rc == 0) {
504                 if (fl & LU_XATTR_CREATE) {
505                         rc = -EEXIST;
506                         goto out;
507                 }
508                 /*
509                  * Entry already exists.
510                  * We'll truncate the existing object.
511                  */
512                 rc = __osd_obj2dbuf(env, osd->od_os, xa_data_obj,
513                                         &xa_data_db);
514                 if (rc)
515                         goto out;
516
517                 rc = -sa_handle_get(osd->od_os, xa_data_obj, NULL,
518                                         SA_HDL_PRIVATE, &sa_hdl);
519                 if (rc)
520                         goto out;
521
522                 rc = -sa_lookup(sa_hdl, SA_ZPL_SIZE(osd), &size, 8);
523                 if (rc)
524                         goto out_sa;
525
526                 rc = -dmu_free_range(osd->od_os, xa_data_db->db_object,
527                                         0, DMU_OBJECT_END, tx);
528                 if (rc)
529                         goto out_sa;
530         } else if (rc == -ENOENT) {
531                 struct lu_attr *la = &osd_oti_get(env)->oti_la;
532                 /*
533                  * Entry doesn't exist, we need to create a new one and a new
534                  * object to store the value.
535                  */
536                 if (fl & LU_XATTR_REPLACE) {
537                         /* should be ENOATTR according to the
538                          * man, but that is undefined here */
539                         rc = -ENODATA;
540                         goto out;
541                 }
542
543                 la->la_valid = LA_MODE;
544                 la->la_mode = S_IFREG | S_IRUGO | S_IWUSR;
545                 rc = __osd_object_create(env, osd, &xa_data_db, tx, la,
546                                          obj->oo_xattr);
547                 if (rc)
548                         goto out;
549                 xa_data_obj = xa_data_db->db_object;
550
551                 rc = -sa_handle_get(osd->od_os, xa_data_obj, NULL,
552                                         SA_HDL_PRIVATE, &sa_hdl);
553                 if (rc)
554                         goto out;
555
556                 rc = -zap_add(osd->od_os, obj->oo_xattr, name, sizeof(uint64_t),
557                                 1, &xa_data_obj, tx);
558                 if (rc)
559                         goto out_sa;
560         } else {
561                 /* There was an error looking up the xattr name */
562                 goto out;
563         }
564
565         /* Finally write the xattr value */
566         dmu_write(osd->od_os, xa_data_obj, 0, buf->lb_len, buf->lb_buf, tx);
567
568         size = buf->lb_len;
569         rc = -sa_update(sa_hdl, SA_ZPL_SIZE(osd), &size, 8, tx);
570
571 out_sa:
572         sa_handle_destroy(sa_hdl);
573 out:
574         if (xa_data_db != NULL)
575                 dmu_buf_rele(xa_data_db, FTAG);
576         if (xa_zap_db != NULL)
577                 dmu_buf_rele(xa_zap_db, FTAG);
578
579         return rc;
580 }
581
582 int osd_xattr_set(const struct lu_env *env, struct dt_object *dt,
583                   const struct lu_buf *buf, const char *name, int fl,
584                   struct thandle *handle, struct lustre_capa *capa)
585 {
586         struct osd_object  *obj = osd_dt_obj(dt);
587         struct osd_thandle *oh;
588         int rc = 0;
589         ENTRY;
590
591         LASSERT(handle != NULL);
592         LASSERT(osd_invariant(obj));
593         LASSERT(dt_object_exists(dt));
594         LASSERT(obj->oo_db);
595
596         if (!osd_obj2dev(obj)->od_posix_acl &&
597             (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0 ||
598              strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0))
599                 RETURN(-EOPNOTSUPP);
600
601         oh = container_of0(handle, struct osd_thandle, ot_super);
602
603         down(&obj->oo_guard);
604         CDEBUG(D_INODE, "Setting xattr %s with size %d\n",
605                 name, (int)buf->lb_len);
606         rc = osd_xattr_set_internal(env, obj, buf, name, fl, oh, capa);
607         up(&obj->oo_guard);
608
609         RETURN(rc);
610 }
611
612 static void
613 __osd_xattr_declare_del(const struct lu_env *env, struct osd_object *obj,
614                         const char *name, struct osd_thandle *oh)
615 {
616         struct osd_device *osd = osd_obj2dev(obj);
617         dmu_tx_t          *tx = oh->ot_tx;
618         uint64_t           xa_data_obj;
619         int                rc;
620
621         /* update SA_ZPL_DXATTR if xattr was in SA */
622         dmu_tx_hold_sa(tx, obj->oo_sa_hdl, 0);
623
624         if (obj->oo_xattr == ZFS_NO_OBJECT)
625                 return;
626
627         rc = -zap_lookup(osd->od_os, obj->oo_xattr, name, 8, 1, &xa_data_obj);
628         if (rc == 0) {
629                 /*
630                  * Entry exists.
631                  * We'll delete the existing object and ZAP entry.
632                  */
633                 dmu_tx_hold_bonus(tx, xa_data_obj);
634                 dmu_tx_hold_free(tx, xa_data_obj, 0, DMU_OBJECT_END);
635                 dmu_tx_hold_zap(tx, obj->oo_xattr, FALSE, (char *) name);
636                 return;
637         } else if (rc == -ENOENT) {
638                 /*
639                  * Entry doesn't exist, nothing to be changed.
640                  */
641                 return;
642         }
643
644         /* An error happened */
645         tx->tx_err = -rc;
646 }
647
648 int osd_declare_xattr_del(const struct lu_env *env, struct dt_object *dt,
649                           const char *name, struct thandle *handle)
650 {
651         struct osd_object  *obj = osd_dt_obj(dt);
652         struct osd_thandle *oh;
653         ENTRY;
654
655         LASSERT(handle != NULL);
656         LASSERT(dt_object_exists(dt));
657         LASSERT(osd_invariant(obj));
658
659         oh = container_of0(handle, struct osd_thandle, ot_super);
660         LASSERT(oh->ot_tx != NULL);
661         LASSERT(obj->oo_db != NULL);
662
663         down(&obj->oo_guard);
664         __osd_xattr_declare_del(env, obj, name, oh);
665         up(&obj->oo_guard);
666
667         RETURN(0);
668 }
669
670 int __osd_sa_xattr_del(const struct lu_env *env, struct osd_object *obj,
671                        const char *name, struct osd_thandle *oh)
672 {
673         int rc;
674
675         if (obj->oo_sa_xattr == NULL) {
676                 rc = __osd_xattr_cache(env, obj);
677                 if (rc)
678                         return rc;
679         }
680
681         rc = -nvlist_remove(obj->oo_sa_xattr, name, DATA_TYPE_BYTE_ARRAY);
682         if (rc == 0)
683                 rc = __osd_sa_xattr_update(env, obj, oh);
684         return rc;
685 }
686
687 int __osd_xattr_del(const struct lu_env *env, struct osd_object *obj,
688                     const char *name, struct osd_thandle *oh)
689 {
690         struct osd_device *osd = osd_obj2dev(obj);
691         uint64_t           xa_data_obj;
692         int                rc;
693
694         /* try remove xattr from SA at first */
695         rc = __osd_sa_xattr_del(env, obj, name, oh);
696         if (rc != -ENOENT)
697                 return rc;
698
699         if (obj->oo_xattr == ZFS_NO_OBJECT)
700                 return 0;
701
702         rc = -zap_lookup(osd->od_os, obj->oo_xattr, name, sizeof(uint64_t), 1,
703                         &xa_data_obj);
704         if (rc == -ENOENT) {
705                 rc = 0;
706         } else if (rc == 0) {
707                 /*
708                  * Entry exists.
709                  * We'll delete the existing object and ZAP entry.
710                  */
711                 rc = -dmu_object_free(osd->od_os, xa_data_obj, oh->ot_tx);
712                 if (rc)
713                         return rc;
714
715                 rc = -zap_remove(osd->od_os, obj->oo_xattr, name, oh->ot_tx);
716         }
717
718         return rc;
719 }
720
721 int osd_xattr_del(const struct lu_env *env, struct dt_object *dt,
722                   const char *name, struct thandle *handle,
723                   struct lustre_capa *capa)
724 {
725         struct osd_object  *obj = osd_dt_obj(dt);
726         struct osd_thandle *oh;
727         int                 rc;
728         ENTRY;
729
730         LASSERT(handle != NULL);
731         LASSERT(obj->oo_db != NULL);
732         LASSERT(osd_invariant(obj));
733         LASSERT(dt_object_exists(dt));
734         oh = container_of0(handle, struct osd_thandle, ot_super);
735         LASSERT(oh->ot_tx != NULL);
736
737         if (!osd_obj2dev(obj)->od_posix_acl &&
738             (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0 ||
739              strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0))
740                 RETURN(-EOPNOTSUPP);
741
742         down(&obj->oo_guard);
743         rc = __osd_xattr_del(env, obj, name, oh);
744         up(&obj->oo_guard);
745
746         RETURN(rc);
747 }
748
749 static int
750 osd_sa_xattr_list(const struct lu_env *env, struct osd_object *obj,
751                   struct lu_buf *lb)
752 {
753         nvpair_t *nvp = NULL;
754         int       len, counted = 0, remain = lb->lb_len;
755         int       rc = 0;
756
757         if (obj->oo_sa_xattr == NULL) {
758                 rc = __osd_xattr_cache(env, obj);
759                 if (rc)
760                         return rc;
761         }
762
763         LASSERT(obj->oo_sa_xattr);
764
765         while ((nvp = nvlist_next_nvpair(obj->oo_sa_xattr, nvp)) != NULL) {
766                 const char *name = nvpair_name(nvp);
767
768                 if (!osd_obj2dev(obj)->od_posix_acl &&
769                     (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0 ||
770                      strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0))
771                         continue;
772
773                 len = strlen(nvpair_name(nvp));
774                 if (lb->lb_buf != NULL) {
775                         if (len + 1 > remain)
776                                 return -ERANGE;
777
778                         memcpy(lb->lb_buf, name, len);
779                         lb->lb_buf += len;
780                         *((char *)lb->lb_buf) = '\0';
781                         lb->lb_buf++;
782                         remain -= len + 1;
783                 }
784                 counted += len + 1;
785         }
786         return counted;
787 }
788
789 int osd_xattr_list(const struct lu_env *env, struct dt_object *dt,
790                    struct lu_buf *lb, struct lustre_capa *capa)
791 {
792         struct osd_object      *obj = osd_dt_obj(dt);
793         struct osd_device      *osd = osd_obj2dev(obj);
794         zap_attribute_t        *za = &osd_oti_get(env)->oti_za;
795         zap_cursor_t           *zc;
796         int                    rc, counted = 0, remain = lb->lb_len;
797         ENTRY;
798
799         LASSERT(obj->oo_db != NULL);
800         LASSERT(osd_invariant(obj));
801         LASSERT(dt_object_exists(dt));
802
803         down(&obj->oo_guard);
804
805         rc = osd_sa_xattr_list(env, obj, lb);
806         if (rc < 0)
807                 GOTO(out, rc);
808         counted = rc;
809         remain -= counted;
810
811         /* continue with dnode xattr if any */
812         if (obj->oo_xattr == ZFS_NO_OBJECT)
813                 GOTO(out, rc = counted);
814
815         rc = osd_zap_cursor_init(&zc, osd->od_os, obj->oo_xattr, 0);
816         if (rc)
817                 GOTO(out, rc);
818
819         while ((rc = -zap_cursor_retrieve(zc, za)) == 0) {
820                 if (!osd_obj2dev(obj)->od_posix_acl &&
821                     (strcmp(za->za_name, POSIX_ACL_XATTR_ACCESS) == 0 ||
822                      strcmp(za->za_name, POSIX_ACL_XATTR_DEFAULT) == 0)) {
823                         zap_cursor_advance(zc);
824                         continue;
825                 }
826
827                 rc = strlen(za->za_name);
828                 if (lb->lb_buf != NULL) {
829                         if (rc + 1 > remain)
830                                 RETURN(-ERANGE);
831
832                         memcpy(lb->lb_buf, za->za_name, rc);
833                         lb->lb_buf += rc;
834                         *((char *)lb->lb_buf) = '\0';
835                         lb->lb_buf++;
836                         remain -= rc + 1;
837                 }
838                 counted += rc + 1;
839
840                 zap_cursor_advance(zc);
841         }
842         if (rc == -ENOENT) /* no more kes in the index */
843                 rc = 0;
844         else if (unlikely(rc < 0))
845                 GOTO(out_fini, rc);
846         rc = counted;
847
848 out_fini:
849         osd_zap_cursor_fini(zc);
850 out:
851         up(&obj->oo_guard);
852         RETURN(rc);
853
854 }
855
856