Whamcloud - gitweb
LU-3105 osd: remove capa related stuff from servers
[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 = osd_zio_buf_alloc(size);
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         osd_zio_buf_free(buf, size);
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 {
244         struct osd_object  *obj  = osd_dt_obj(dt);
245         int                 rc, size = 0;
246         ENTRY;
247
248         LASSERT(obj->oo_db != NULL);
249         LASSERT(osd_invariant(obj));
250         LASSERT(dt_object_exists(dt));
251
252         if (!osd_obj2dev(obj)->od_posix_acl &&
253             (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0 ||
254              strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0))
255                 RETURN(-EOPNOTSUPP);
256
257         down(&obj->oo_guard);
258         rc = __osd_xattr_get(env, obj, buf, name, &size);
259         up(&obj->oo_guard);
260
261         if (rc == -ENOENT)
262                 rc = -ENODATA;
263         else if (rc == 0)
264                 rc = size;
265         RETURN(rc);
266 }
267
268 void __osd_xattr_declare_set(const struct lu_env *env, struct osd_object *obj,
269                              int vallen, const char *name,
270                              struct osd_thandle *oh)
271 {
272         struct osd_device *osd = osd_obj2dev(obj);
273         dmu_buf_t         *db = obj->oo_db;
274         dmu_tx_t          *tx = oh->ot_tx;
275         uint64_t           xa_data_obj;
276         int                rc = 0;
277         int                here;
278
279         here = dt_object_exists(&obj->oo_dt);
280
281         /* object may be not yet created */
282         if (here) {
283                 LASSERT(db);
284                 LASSERT(obj->oo_sa_hdl);
285                 /* we might just update SA_ZPL_DXATTR */
286                 dmu_tx_hold_sa(tx, obj->oo_sa_hdl, 1);
287
288                 if (obj->oo_xattr == ZFS_NO_OBJECT)
289                         rc = -ENOENT;
290         }
291
292         if (!here || rc == -ENOENT) {
293                 /* we'll be updating SA_ZPL_XATTR */
294                 if (here) {
295                         LASSERT(obj->oo_sa_hdl);
296                         dmu_tx_hold_sa(tx, obj->oo_sa_hdl, 1);
297                 }
298                 /* xattr zap + entry */
299                 dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, TRUE, (char *) name);
300                 /* xattr value obj */
301                 dmu_tx_hold_sa_create(tx, ZFS_SA_BASE_ATTR_SIZE);
302                 dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, vallen);
303                 return;
304         }
305
306         rc = -zap_lookup(osd->od_os, obj->oo_xattr, name, sizeof(uint64_t), 1,
307                         &xa_data_obj);
308         if (rc == 0) {
309                 /*
310                  * Entry already exists.
311                  * We'll truncate the existing object.
312                  */
313                 dmu_tx_hold_bonus(tx, xa_data_obj);
314                 dmu_tx_hold_free(tx, xa_data_obj, vallen, DMU_OBJECT_END);
315                 dmu_tx_hold_write(tx, xa_data_obj, 0, vallen);
316                 return;
317         } else if (rc == -ENOENT) {
318                 /*
319                  * Entry doesn't exist, we need to create a new one and a new
320                  * object to store the value.
321                  */
322                 dmu_tx_hold_bonus(tx, obj->oo_xattr);
323                 dmu_tx_hold_zap(tx, obj->oo_xattr, TRUE, (char *) name);
324                 dmu_tx_hold_sa_create(tx, ZFS_SA_BASE_ATTR_SIZE);
325                 dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, vallen);
326                 return;
327         }
328
329         /* An error happened */
330         tx->tx_err = -rc;
331 }
332
333 int osd_declare_xattr_set(const struct lu_env *env, struct dt_object *dt,
334                           const struct lu_buf *buf, const char *name,
335                           int fl, struct thandle *handle)
336 {
337         struct osd_object  *obj = osd_dt_obj(dt);
338         struct osd_thandle *oh;
339         ENTRY;
340
341         LASSERT(handle != NULL);
342         oh = container_of0(handle, struct osd_thandle, ot_super);
343
344         down(&obj->oo_guard);
345         __osd_xattr_declare_set(env, obj, buf->lb_len, name, oh);
346         up(&obj->oo_guard);
347
348         RETURN(0);
349 }
350
351 /*
352  * Set an extended attribute.
353  * This transaction must have called udmu_xattr_declare_set() first.
354  *
355  * Returns 0 on success or a negative error number on failure.
356  *
357  * No locking is done here.
358  */
359 static int
360 __osd_sa_xattr_update(const struct lu_env *env, struct osd_object *obj,
361                       struct osd_thandle *oh)
362 {
363         struct osd_device *osd = osd_obj2dev(obj);
364         char              *dxattr;
365         size_t             sa_size;
366         int                rc;
367
368         ENTRY;
369         LASSERT(obj->oo_sa_hdl);
370         LASSERT(obj->oo_sa_xattr);
371
372         /* Update the SA for additions, modifications, and removals. */
373         rc = -nvlist_size(obj->oo_sa_xattr, &sa_size, NV_ENCODE_XDR);
374         if (rc)
375                 return rc;
376
377         dxattr = osd_zio_buf_alloc(sa_size);
378         if (dxattr == NULL)
379                 RETURN(-ENOMEM);
380
381         rc = -nvlist_pack(obj->oo_sa_xattr, &dxattr, &sa_size,
382                                 NV_ENCODE_XDR, KM_SLEEP);
383         if (rc)
384                 GOTO(out_free, rc);
385
386         rc = osd_object_sa_update(obj, SA_ZPL_DXATTR(osd), dxattr, sa_size, oh);
387 out_free:
388         osd_zio_buf_free(dxattr, sa_size);
389         RETURN(rc);
390 }
391
392 int __osd_sa_xattr_set(const struct lu_env *env, struct osd_object *obj,
393                        const struct lu_buf *buf, const char *name, int fl,
394                        struct osd_thandle *oh)
395 {
396         uchar_t *nv_value;
397         size_t  size;
398         int     nv_size;
399         int     rc;
400         int     too_big = 0;
401
402         LASSERT(obj->oo_sa_hdl);
403         if (obj->oo_sa_xattr == NULL) {
404                 rc = __osd_xattr_cache(env, obj);
405                 if (rc)
406                         return rc;
407         }
408
409         LASSERT(obj->oo_sa_xattr);
410         /* Limited to 32k to keep nvpair memory allocations small */
411         if (buf->lb_len > DXATTR_MAX_ENTRY_SIZE) {
412                 too_big = 1;
413         } else {
414                 /* Prevent the DXATTR SA from consuming the entire SA
415                  * region */
416                 rc = -nvlist_size(obj->oo_sa_xattr, &size, NV_ENCODE_XDR);
417                 if (rc)
418                         return rc;
419
420                 if (size + buf->lb_len > DXATTR_MAX_SA_SIZE)
421                         too_big = 1;
422         }
423
424         /* even in case of -EFBIG we must lookup xattr and check can we
425          * rewrite it then delete from SA */
426         rc = -nvlist_lookup_byte_array(obj->oo_sa_xattr, name, &nv_value,
427                                         &nv_size);
428         if (rc == 0) {
429                 if (fl & LU_XATTR_CREATE) {
430                         return -EEXIST;
431                 } else if (too_big) {
432                         rc = -nvlist_remove(obj->oo_sa_xattr, name,
433                                                 DATA_TYPE_BYTE_ARRAY);
434                         if (rc < 0)
435                                 return rc;
436                         rc = __osd_sa_xattr_update(env, obj, oh);
437                         return rc == 0 ? -EFBIG : rc;
438                 }
439         } else if (rc == -ENOENT) {
440                 if (fl & LU_XATTR_REPLACE)
441                         return -ENODATA;
442                 else if (too_big)
443                         return -EFBIG;
444         } else {
445                 return rc;
446         }
447
448         /* Ensure xattr doesn't exist in ZAP */
449         if (obj->oo_xattr != ZFS_NO_OBJECT) {
450                 struct osd_device *osd = osd_obj2dev(obj);
451                 uint64_t           objid;
452                 rc = -zap_lookup(osd->od_os, obj->oo_xattr,
453                                  name, 8, 1, &objid);
454                 if (rc == 0) {
455                         rc = -dmu_object_free(osd->od_os, objid, oh->ot_tx);
456                         if (rc == 0)
457                                 zap_remove(osd->od_os, obj->oo_xattr,
458                                            name, oh->ot_tx);
459                 }
460         }
461
462         rc = -nvlist_add_byte_array(obj->oo_sa_xattr, name,
463                                     (uchar_t *)buf->lb_buf, buf->lb_len);
464         if (rc)
465                 return rc;
466
467         rc = __osd_sa_xattr_update(env, obj, oh);
468         return rc;
469 }
470
471 int
472 __osd_xattr_set(const struct lu_env *env, struct osd_object *obj,
473                 const struct lu_buf *buf, const char *name, int fl,
474                 struct osd_thandle *oh)
475 {
476         struct osd_device *osd = osd_obj2dev(obj);
477         dmu_buf_t         *xa_zap_db = NULL;
478         dmu_buf_t         *xa_data_db = NULL;
479         uint64_t           xa_data_obj;
480         sa_handle_t       *sa_hdl = NULL;
481         dmu_tx_t          *tx = oh->ot_tx;
482         uint64_t           size;
483         int                rc;
484
485         LASSERT(obj->oo_sa_hdl);
486
487         if (obj->oo_xattr == ZFS_NO_OBJECT) {
488                 struct lu_attr *la = &osd_oti_get(env)->oti_la;
489
490                 la->la_valid = LA_MODE;
491                 la->la_mode = S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO;
492                 rc = __osd_zap_create(env, osd, &xa_zap_db, tx, la,
493                                       obj->oo_db->db_object, 0);
494                 if (rc)
495                         return rc;
496
497                 obj->oo_xattr = xa_zap_db->db_object;
498                 rc = osd_object_sa_update(obj, SA_ZPL_XATTR(osd),
499                                 &obj->oo_xattr, 8, oh);
500                 if (rc)
501                         goto out;
502         }
503
504         rc = -zap_lookup(osd->od_os, obj->oo_xattr, name, sizeof(uint64_t), 1,
505                          &xa_data_obj);
506         if (rc == 0) {
507                 if (fl & LU_XATTR_CREATE) {
508                         rc = -EEXIST;
509                         goto out;
510                 }
511                 /*
512                  * Entry already exists.
513                  * We'll truncate the existing object.
514                  */
515                 rc = __osd_obj2dbuf(env, osd->od_os, xa_data_obj,
516                                         &xa_data_db);
517                 if (rc)
518                         goto out;
519
520                 rc = -sa_handle_get(osd->od_os, xa_data_obj, NULL,
521                                         SA_HDL_PRIVATE, &sa_hdl);
522                 if (rc)
523                         goto out;
524
525                 rc = -sa_lookup(sa_hdl, SA_ZPL_SIZE(osd), &size, 8);
526                 if (rc)
527                         goto out_sa;
528
529                 rc = -dmu_free_range(osd->od_os, xa_data_db->db_object,
530                                      0, DMU_OBJECT_END, tx);
531                 if (rc)
532                         goto out_sa;
533         } else if (rc == -ENOENT) {
534                 struct lu_attr *la = &osd_oti_get(env)->oti_la;
535                 /*
536                  * Entry doesn't exist, we need to create a new one and a new
537                  * object to store the value.
538                  */
539                 if (fl & LU_XATTR_REPLACE) {
540                         /* should be ENOATTR according to the
541                          * man, but that is undefined here */
542                         rc = -ENODATA;
543                         goto out;
544                 }
545
546                 la->la_valid = LA_MODE;
547                 la->la_mode = S_IFREG | S_IRUGO | S_IWUSR;
548                 rc = __osd_object_create(env, obj, &xa_data_db, tx, la,
549                                          obj->oo_xattr);
550                 if (rc)
551                         goto out;
552                 xa_data_obj = xa_data_db->db_object;
553
554                 rc = -sa_handle_get(osd->od_os, xa_data_obj, NULL,
555                                         SA_HDL_PRIVATE, &sa_hdl);
556                 if (rc)
557                         goto out;
558
559                 rc = -zap_add(osd->od_os, obj->oo_xattr, name, sizeof(uint64_t),
560                                 1, &xa_data_obj, tx);
561                 if (rc)
562                         goto out_sa;
563         } else {
564                 /* There was an error looking up the xattr name */
565                 goto out;
566         }
567
568         /* Finally write the xattr value */
569         dmu_write(osd->od_os, xa_data_obj, 0, buf->lb_len, buf->lb_buf, tx);
570
571         size = buf->lb_len;
572         rc = -sa_update(sa_hdl, SA_ZPL_SIZE(osd), &size, 8, tx);
573
574 out_sa:
575         sa_handle_destroy(sa_hdl);
576 out:
577         if (xa_data_db != NULL)
578                 dmu_buf_rele(xa_data_db, FTAG);
579         if (xa_zap_db != NULL)
580                 dmu_buf_rele(xa_zap_db, FTAG);
581
582         return rc;
583 }
584
585 int osd_xattr_set(const struct lu_env *env, struct dt_object *dt,
586                   const struct lu_buf *buf, const char *name, int fl,
587                   struct thandle *handle)
588 {
589         struct osd_object  *obj = osd_dt_obj(dt);
590         struct osd_thandle *oh;
591         int rc = 0;
592         ENTRY;
593
594         LASSERT(handle != NULL);
595         LASSERT(osd_invariant(obj));
596         LASSERT(dt_object_exists(dt));
597         LASSERT(obj->oo_db);
598
599         if (!osd_obj2dev(obj)->od_posix_acl &&
600             (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0 ||
601              strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0))
602                 RETURN(-EOPNOTSUPP);
603
604         if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_LINKEA_OVERFLOW) &&
605             strcmp(name, XATTR_NAME_LINK) == 0)
606                 RETURN(-ENOSPC);
607
608         oh = container_of0(handle, struct osd_thandle, ot_super);
609
610         down(&obj->oo_guard);
611         CDEBUG(D_INODE, "Setting xattr %s with size %d\n",
612                 name, (int)buf->lb_len);
613         rc = osd_xattr_set_internal(env, obj, buf, name, fl, oh);
614         up(&obj->oo_guard);
615
616         RETURN(rc);
617 }
618
619 static void
620 __osd_xattr_declare_del(const struct lu_env *env, struct osd_object *obj,
621                         const char *name, struct osd_thandle *oh)
622 {
623         struct osd_device *osd = osd_obj2dev(obj);
624         dmu_tx_t          *tx = oh->ot_tx;
625         uint64_t           xa_data_obj;
626         int                rc;
627
628         /* update SA_ZPL_DXATTR if xattr was in SA */
629         dmu_tx_hold_sa(tx, obj->oo_sa_hdl, 0);
630
631         if (obj->oo_xattr == ZFS_NO_OBJECT)
632                 return;
633
634         rc = -zap_lookup(osd->od_os, obj->oo_xattr, name, 8, 1, &xa_data_obj);
635         if (rc == 0) {
636                 /*
637                  * Entry exists.
638                  * We'll delete the existing object and ZAP entry.
639                  */
640                 dmu_tx_hold_bonus(tx, xa_data_obj);
641                 dmu_tx_hold_free(tx, xa_data_obj, 0, DMU_OBJECT_END);
642                 dmu_tx_hold_zap(tx, obj->oo_xattr, FALSE, (char *) name);
643                 return;
644         } else if (rc == -ENOENT) {
645                 /*
646                  * Entry doesn't exist, nothing to be changed.
647                  */
648                 return;
649         }
650
651         /* An error happened */
652         tx->tx_err = -rc;
653 }
654
655 int osd_declare_xattr_del(const struct lu_env *env, struct dt_object *dt,
656                           const char *name, struct thandle *handle)
657 {
658         struct osd_object  *obj = osd_dt_obj(dt);
659         struct osd_thandle *oh;
660         ENTRY;
661
662         LASSERT(handle != NULL);
663         LASSERT(dt_object_exists(dt));
664         LASSERT(osd_invariant(obj));
665
666         oh = container_of0(handle, struct osd_thandle, ot_super);
667         LASSERT(oh->ot_tx != NULL);
668         LASSERT(obj->oo_db != NULL);
669
670         down(&obj->oo_guard);
671         __osd_xattr_declare_del(env, obj, name, oh);
672         up(&obj->oo_guard);
673
674         RETURN(0);
675 }
676
677 int __osd_sa_xattr_del(const struct lu_env *env, struct osd_object *obj,
678                        const char *name, struct osd_thandle *oh)
679 {
680         int rc;
681
682         if (obj->oo_sa_xattr == NULL) {
683                 rc = __osd_xattr_cache(env, obj);
684                 if (rc)
685                         return rc;
686         }
687
688         rc = -nvlist_remove(obj->oo_sa_xattr, name, DATA_TYPE_BYTE_ARRAY);
689         if (rc == 0)
690                 rc = __osd_sa_xattr_update(env, obj, oh);
691         return rc;
692 }
693
694 int __osd_xattr_del(const struct lu_env *env, struct osd_object *obj,
695                     const char *name, struct osd_thandle *oh)
696 {
697         struct osd_device *osd = osd_obj2dev(obj);
698         uint64_t           xa_data_obj;
699         int                rc;
700
701         /* try remove xattr from SA at first */
702         rc = __osd_sa_xattr_del(env, obj, name, oh);
703         if (rc != -ENOENT)
704                 return rc;
705
706         if (obj->oo_xattr == ZFS_NO_OBJECT)
707                 return 0;
708
709         rc = -zap_lookup(osd->od_os, obj->oo_xattr, name, sizeof(uint64_t), 1,
710                         &xa_data_obj);
711         if (rc == -ENOENT) {
712                 rc = 0;
713         } else if (rc == 0) {
714                 /*
715                  * Entry exists.
716                  * We'll delete the existing object and ZAP entry.
717                  */
718                 rc = -dmu_object_free(osd->od_os, xa_data_obj, oh->ot_tx);
719                 if (rc)
720                         return rc;
721
722                 rc = -zap_remove(osd->od_os, obj->oo_xattr, name, oh->ot_tx);
723         }
724
725         return rc;
726 }
727
728 int osd_xattr_del(const struct lu_env *env, struct dt_object *dt,
729                   const char *name, struct thandle *handle)
730 {
731         struct osd_object  *obj = osd_dt_obj(dt);
732         struct osd_thandle *oh;
733         int                 rc;
734         ENTRY;
735
736         LASSERT(handle != NULL);
737         LASSERT(obj->oo_db != NULL);
738         LASSERT(osd_invariant(obj));
739         LASSERT(dt_object_exists(dt));
740         oh = container_of0(handle, struct osd_thandle, ot_super);
741         LASSERT(oh->ot_tx != NULL);
742
743         if (!osd_obj2dev(obj)->od_posix_acl &&
744             (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0 ||
745              strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0))
746                 RETURN(-EOPNOTSUPP);
747
748         down(&obj->oo_guard);
749         rc = __osd_xattr_del(env, obj, name, oh);
750         up(&obj->oo_guard);
751
752         RETURN(rc);
753 }
754
755 static int
756 osd_sa_xattr_list(const struct lu_env *env, struct osd_object *obj,
757                   const struct lu_buf *lb)
758 {
759         nvpair_t *nvp = NULL;
760         int       len, counted = 0;
761         int       rc = 0;
762
763         if (obj->oo_sa_xattr == NULL) {
764                 rc = __osd_xattr_cache(env, obj);
765                 if (rc)
766                         return rc;
767         }
768
769         LASSERT(obj->oo_sa_xattr);
770
771         while ((nvp = nvlist_next_nvpair(obj->oo_sa_xattr, nvp)) != NULL) {
772                 const char *name = nvpair_name(nvp);
773
774                 if (!osd_obj2dev(obj)->od_posix_acl &&
775                     (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0 ||
776                      strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0))
777                         continue;
778
779                 len = strlen(name);
780                 if (lb->lb_buf != NULL) {
781                         if (counted + len + 1 > lb->lb_len)
782                                 return -ERANGE;
783
784                         memcpy(lb->lb_buf + counted, name, len + 1);
785                 }
786                 counted += len + 1;
787         }
788         return counted;
789 }
790
791 int osd_xattr_list(const struct lu_env *env, struct dt_object *dt,
792                    const struct lu_buf *lb)
793 {
794         struct osd_object      *obj = osd_dt_obj(dt);
795         struct osd_device      *osd = osd_obj2dev(obj);
796         zap_attribute_t        *za = &osd_oti_get(env)->oti_za;
797         zap_cursor_t           *zc;
798         int                    rc, counted;
799         ENTRY;
800
801         LASSERT(obj->oo_db != NULL);
802         LASSERT(osd_invariant(obj));
803         LASSERT(dt_object_exists(dt));
804
805         down(&obj->oo_guard);
806
807         rc = osd_sa_xattr_list(env, obj, lb);
808         if (rc < 0)
809                 GOTO(out, rc);
810
811         counted = rc;
812
813         /* continue with dnode xattr if any */
814         if (obj->oo_xattr == ZFS_NO_OBJECT)
815                 GOTO(out, rc = counted);
816
817         rc = osd_zap_cursor_init(&zc, osd->od_os, obj->oo_xattr, 0);
818         if (rc)
819                 GOTO(out, rc);
820
821         while ((rc = -zap_cursor_retrieve(zc, za)) == 0) {
822                 if (!osd_obj2dev(obj)->od_posix_acl &&
823                     (strcmp(za->za_name, POSIX_ACL_XATTR_ACCESS) == 0 ||
824                      strcmp(za->za_name, POSIX_ACL_XATTR_DEFAULT) == 0)) {
825                         zap_cursor_advance(zc);
826                         continue;
827                 }
828
829                 rc = strlen(za->za_name);
830                 if (lb->lb_buf != NULL) {
831                         if (counted + rc + 1 > lb->lb_len)
832                                 RETURN(-ERANGE);
833
834                         memcpy(lb->lb_buf + counted, za->za_name, rc + 1);
835                 }
836                 counted += rc + 1;
837
838                 zap_cursor_advance(zc);
839         }
840         if (rc == -ENOENT) /* no more kes in the index */
841                 rc = 0;
842         else if (unlikely(rc < 0))
843                 GOTO(out_fini, rc);
844         rc = counted;
845
846 out_fini:
847         osd_zap_cursor_fini(zc);
848 out:
849         up(&obj->oo_guard);
850         RETURN(rc);
851
852 }