static int osd_sa_xattr_list(const struct lu_env *env, struct osd_object *obj, const struct lu_buf *lb) { nvpair_t *nvp = NULL; int len, counted = 0; int rc = 0; if (obj->oo_sa_xattr == NULL) { rc = __osd_xattr_cache(env, obj); if (rc) return rc; } LASSERT(obj->oo_sa_xattr); while ((nvp = nvlist_next_nvpair(obj->oo_sa_xattr, nvp)) != NULL) { const char *name = nvpair_name(nvp); if (!osd_obj2dev(obj)->od_posix_acl && (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0 || strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0)) continue; len = strlen(name); if (lb->lb_buf != NULL) { if (counted + len + 1 > lb->lb_len) return -ERANGE; memcpy(lb->lb_buf + counted, name, len + 1); } counted += len + 1; } return counted; }
static int __osd_sa_xattr_get(const struct lu_env *env, struct osd_object *obj, const struct lu_buf *buf, const char *name, int *sizep) { uchar_t *nv_value; int rc; LASSERT(obj->oo_sa_hdl); if (obj->oo_sa_xattr == NULL) { rc = __osd_xattr_cache(env, obj); if (rc) return rc; } LASSERT(obj->oo_sa_xattr); rc = -nvlist_lookup_byte_array(obj->oo_sa_xattr, name, &nv_value, sizep); if (rc) return rc; if (buf == NULL || buf->lb_buf == NULL) { /* return the required size by *sizep */ return 0; } if (*sizep > buf->lb_len) return -ERANGE; /* match ldiskfs error */ memcpy(buf->lb_buf, nv_value, *sizep); return 0; }
static int osd_sa_xattr_list(const struct lu_env *env, struct osd_object *obj, struct lu_buf *lb) { nvpair_t *nvp = NULL; int len, counted = 0, remain = lb->lb_len; int rc = 0; if (obj->oo_sa_xattr == NULL) { rc = __osd_xattr_cache(env, obj); if (rc) return rc; } LASSERT(obj->oo_sa_xattr); while ((nvp = nvlist_next_nvpair(obj->oo_sa_xattr, nvp)) != NULL) { len = strlen(nvpair_name(nvp)); if (lb->lb_buf != NULL) { if (len + 1 > remain) return -ERANGE; memcpy(lb->lb_buf, nvpair_name(nvp), len); lb->lb_buf += len; *((char *)lb->lb_buf) = '\0'; lb->lb_buf++; remain -= len + 1; } counted += len + 1; } return counted; }
static int __osd_sa_xattr_del(const struct lu_env *env, struct osd_object *obj, const char *name, struct osd_thandle *oh) { int rc; if (obj->oo_sa_xattr == NULL) { rc = __osd_xattr_cache(env, obj); if (rc) return rc; } rc = -nvlist_remove(obj->oo_sa_xattr, name, DATA_TYPE_BYTE_ARRAY); if (rc == 0) rc = __osd_sa_xattr_schedule_update(env, obj, oh); return rc; }
int __osd_sa_xattr_set(const struct lu_env *env, struct osd_object *obj, const struct lu_buf *buf, const char *name, int fl, struct osd_thandle *oh) { dmu_buf_impl_t *db; uchar_t *nv_value; size_t size; int nv_size; int rc; int too_big = 0; LASSERT(obj->oo_sa_hdl); if (obj->oo_sa_xattr == NULL) { rc = __osd_xattr_cache(env, obj); if (rc) return rc; } LASSERT(obj->oo_sa_xattr); /* Limited to 32k to keep nvpair memory allocations small */ if (buf->lb_len > DXATTR_MAX_ENTRY_SIZE) { too_big = 1; } else { /* Prevent the DXATTR SA from consuming the entire SA * region */ rc = -nvlist_size(obj->oo_sa_xattr, &size, NV_ENCODE_XDR); if (rc) return rc; if (size + buf->lb_len > DXATTR_MAX_SA_SIZE) too_big = 1; } /* even in case of -EFBIG we must lookup xattr and check can we * rewrite it then delete from SA */ rc = -nvlist_lookup_byte_array(obj->oo_sa_xattr, name, &nv_value, &nv_size); if (rc == 0) { if (fl & LU_XATTR_CREATE) { return -EEXIST; } else if (too_big) { rc = -nvlist_remove(obj->oo_sa_xattr, name, DATA_TYPE_BYTE_ARRAY); if (rc < 0) return rc; rc = __osd_sa_xattr_schedule_update(env, obj, oh); return rc == 0 ? -EFBIG : rc; } } else if (rc == -ENOENT) { if (fl & LU_XATTR_REPLACE) return -ENODATA; else if (too_big) return -EFBIG; } else { return rc; } /* Ensure xattr doesn't exist in ZAP */ if (obj->oo_xattr != ZFS_NO_OBJECT) { struct osd_device *osd = osd_obj2dev(obj); uint64_t objid; rc = -zap_lookup(osd->od_os, obj->oo_xattr, name, 8, 1, &objid); if (rc == 0) { rc = -dmu_object_free(osd->od_os, objid, oh->ot_tx); if (rc == 0) zap_remove(osd->od_os, obj->oo_xattr, name, oh->ot_tx); } } rc = -nvlist_add_byte_array(obj->oo_sa_xattr, name, (uchar_t *)buf->lb_buf, buf->lb_len); if (rc) return rc; /* batch updates only for just created dnodes where we * used to set number of EAs in a single transaction */ db = (dmu_buf_impl_t *)obj->oo_db; if (DB_DNODE(db)->dn_allocated_txg == oh->ot_tx->tx_txg) rc = __osd_sa_xattr_schedule_update(env, obj, oh); else rc = __osd_sa_xattr_update(env, obj, oh); return rc; }
int __osd_sa_xattr_set(const struct lu_env *env, struct osd_object *obj, const struct lu_buf *buf, const char *name, int fl, struct osd_thandle *oh) { uchar_t *nv_value; size_t size; int nv_size; int rc; int too_big = 0; LASSERT(obj->oo_sa_hdl); if (obj->oo_sa_xattr == NULL) { rc = __osd_xattr_cache(env, obj); if (rc) return rc; } LASSERT(obj->oo_sa_xattr); /* Limited to 32k to keep nvpair memory allocations small */ if (buf->lb_len > DXATTR_MAX_ENTRY_SIZE) { too_big = 1; } else { /* Prevent the DXATTR SA from consuming the entire SA * region */ rc = -nvlist_size(obj->oo_sa_xattr, &size, NV_ENCODE_XDR); if (rc) return rc; if (size + buf->lb_len > DXATTR_MAX_SA_SIZE) too_big = 1; } /* even in case of -EFBIG we must lookup xattr and check can we * rewrite it then delete from SA */ rc = -nvlist_lookup_byte_array(obj->oo_sa_xattr, name, &nv_value, &nv_size); if (rc == 0) { if (fl & LU_XATTR_CREATE) { return -EEXIST; } else if (too_big) { rc = -nvlist_remove(obj->oo_sa_xattr, name, DATA_TYPE_BYTE_ARRAY); if (rc < 0) return rc; rc = __osd_sa_xattr_update(env, obj, oh); return rc == 0 ? -EFBIG : rc; } } else if (rc == -ENOENT) { if (fl & LU_XATTR_REPLACE) return -ENODATA; else if (too_big) return -EFBIG; } else { return rc; } rc = -nvlist_add_byte_array(obj->oo_sa_xattr, name, (uchar_t *)buf->lb_buf, buf->lb_len); if (rc) return rc; rc = __osd_sa_xattr_update(env, obj, oh); return rc; }