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