/** * Initialize osd Iterator for given osd index object. * * \param dt - osd index object * \param attr - not used * \param capa - BYPASS_CAPA */ static struct dt_it *osd_it_acct_init(const struct lu_env *env, struct dt_object *dt, __u32 attr, struct lustre_capa *capa) { struct osd_thread_info *info = osd_oti_get(env); struct osd_it_quota *it; struct lu_object *lo = &dt->do_lu; struct osd_device *osd = osd_dev(lo->lo_dev); int rc; ENTRY; LASSERT(lu_object_exists(lo)); if (info == NULL) RETURN(ERR_PTR(-ENOMEM)); it = &info->oti_it_quota; memset(it, 0, sizeof(*it)); it->oiq_oid = osd_quota_fid2dmu(lu_object_fid(lo)); /* initialize zap cursor */ rc = -udmu_zap_cursor_init(&it->oiq_zc, &osd->od_objset, it->oiq_oid,0); if (rc) RETURN(ERR_PTR(rc)); /* take object reference */ lu_object_get(lo); it->oiq_obj = osd_dt_obj(dt); it->oiq_reset = 1; RETURN((struct dt_it *)it); }
/* * return status : * rc == 0 -> end of directory. * rc > 0 -> ok, proceed. * rc < 0 -> error. ( EOVERFLOW can be masked.) */ static int osd_dir_it_load(const struct lu_env *env, const struct dt_it *di, __u64 hash) { struct osd_zap_it *it = (struct osd_zap_it *)di; struct osd_object *obj = it->ozi_obj; struct osd_device *osd = osd_obj2dev(obj); zap_attribute_t *za = &osd_oti_get(env)->oti_za; int rc; ENTRY; udmu_zap_cursor_fini(it->ozi_zc); if (udmu_zap_cursor_init(&it->ozi_zc, &osd->od_objset, obj->oo_db->db_object, hash)) RETURN(-ENOMEM); if (hash <= 2) { it->ozi_pos = hash; rc = +1; } else { it->ozi_pos = 3; /* to return whether the end has been reached */ rc = osd_index_retrieve_skip_dots(it, za); if (rc == 0) rc = +1; else if (rc == -ENOENT) rc = 0; } RETURN(rc); }
static struct dt_it *osd_index_it_init(const struct lu_env *env, struct dt_object *dt, __u32 unused, struct lustre_capa *capa) { struct osd_thread_info *info = osd_oti_get(env); struct osd_zap_it *it; struct osd_object *obj = osd_dt_obj(dt); struct osd_device *osd = osd_obj2dev(obj); struct lu_object *lo = &dt->do_lu; ENTRY; /* XXX: check capa ? */ LASSERT(lu_object_exists(lo)); LASSERT(obj->oo_db); LASSERT(udmu_object_is_zap(obj->oo_db)); LASSERT(info); it = &info->oti_it_zap; if (udmu_zap_cursor_init(&it->ozi_zc, &osd->od_objset, obj->oo_db->db_object, 0)) RETURN(ERR_PTR(-ENOMEM)); it->ozi_obj = obj; it->ozi_capa = capa; it->ozi_reset = 1; lu_object_get(lo); RETURN((struct dt_it *)it); }
/* * return status : * rc == 0 -> ok, proceed. * rc > 0 -> end of directory. * rc < 0 -> error. ( EOVERFLOW can be masked.) */ static int osd_zap_it_load(const struct lu_env *env, const struct dt_it *di, __u64 hash) { struct osd_zap_it *it = (struct osd_zap_it *)di; struct osd_object *obj = it->ozi_obj; struct osd_device *osd = osd_obj2dev(obj); int rc; ENTRY; udmu_zap_cursor_fini(it->ozi_zc); if (udmu_zap_cursor_init(&it->ozi_zc, &osd->od_objset, obj->oo_db->db_object, hash)) RETURN(-ENOMEM); it->ozi_reset = 0; /* same as osd_zap_it_next()*/ rc = -udmu_zap_cursor_retrieve_key(env, it->ozi_zc, NULL, NAME_MAX + 1); if (rc == 0) RETURN(+1); else if (rc == -ENOENT) /* end of dir*/ RETURN(0); RETURN(rc); }
int osd_xattr_list(const struct lu_env *env, struct dt_object *dt, struct lu_buf *lb, struct lustre_capa *capa) { struct osd_thread_info *oti = osd_oti_get(env); struct osd_object *obj = osd_dt_obj(dt); struct osd_device *osd = osd_obj2dev(obj); udmu_objset_t *uos = &osd->od_objset; zap_cursor_t *zc; int rc, counted = 0, remain = lb->lb_len; ENTRY; LASSERT(obj->oo_db != NULL); LASSERT(osd_invariant(obj)); LASSERT(dt_object_exists(dt)); down(&obj->oo_guard); rc = osd_sa_xattr_list(env, obj, lb); if (rc < 0) GOTO(out, rc); counted = rc; remain -= counted; /* continue with dnode xattr if any */ if (obj->oo_xattr == ZFS_NO_OBJECT) GOTO(out, rc = counted); rc = -udmu_zap_cursor_init(&zc, uos, obj->oo_xattr, 0); if (rc) GOTO(out, rc); while ((rc = -udmu_zap_cursor_retrieve_key(env, zc, oti->oti_key, MAXNAMELEN)) == 0) { rc = strlen(oti->oti_key); if (lb->lb_buf != NULL) { if (rc + 1 > remain) RETURN(-ERANGE); memcpy(lb->lb_buf, oti->oti_key, rc); lb->lb_buf += rc; *((char *)lb->lb_buf) = '\0'; lb->lb_buf++; remain -= rc + 1; } counted += rc + 1; zap_cursor_advance(zc); } if (rc < 0) GOTO(out_fini, rc); rc = counted; out_fini: udmu_zap_cursor_fini(zc); out: up(&obj->oo_guard); RETURN(rc); }
static void __osd_declare_object_destroy(const struct lu_env *env, struct osd_object *obj, struct osd_thandle *oh) { struct osd_device *osd = osd_obj2dev(obj); udmu_objset_t *uos = &osd->od_objset; dmu_buf_t *db = obj->oo_db; zap_attribute_t *za = &osd_oti_get(env)->oti_za; uint64_t oid = db->db_object, xid; dmu_tx_t *tx = oh->ot_tx; zap_cursor_t *zc; int rc = 0; dmu_tx_hold_free(tx, oid, 0, DMU_OBJECT_END); /* zap holding xattrs */ if (obj->oo_xattr != ZFS_NO_OBJECT) { oid = obj->oo_xattr; dmu_tx_hold_free(tx, oid, 0, DMU_OBJECT_END); rc = -udmu_zap_cursor_init(&zc, uos, oid, 0); if (rc) goto out; while ((rc = -zap_cursor_retrieve(zc, za)) == 0) { BUG_ON(za->za_integer_length != sizeof(uint64_t)); BUG_ON(za->za_num_integers != 1); rc = -zap_lookup(uos->os, obj->oo_xattr, za->za_name, sizeof(uint64_t), 1, &xid); if (rc) { CERROR("%s: xattr lookup failed: rc = %d\n", osd->od_svname, rc); goto out_err; } dmu_tx_hold_free(tx, xid, 0, DMU_OBJECT_END); zap_cursor_advance(zc); } if (rc == -ENOENT) rc = 0; out_err: udmu_zap_cursor_fini(zc); } out: if (rc && tx->tx_err == 0) tx->tx_err = -rc; }
/* * Delete a DMU object * * The transaction passed to this routine must have * dmu_tx_hold_free(tx, oid, 0, DMU_OBJECT_END) called * and then assigned to a transaction group. * * This will release db and set it to NULL to prevent further dbuf releases. */ static int __osd_object_destroy(const struct lu_env *env, struct osd_object *obj, dmu_tx_t *tx, void *tag) { struct osd_device *osd = osd_obj2dev(obj); udmu_objset_t *uos = &osd->od_objset; uint64_t xid; zap_attribute_t *za = &osd_oti_get(env)->oti_za; zap_cursor_t *zc; int rc; /* Assert that the transaction has been assigned to a transaction group. */ LASSERT(tx->tx_txg != 0); /* zap holding xattrs */ if (obj->oo_xattr != ZFS_NO_OBJECT) { rc = -udmu_zap_cursor_init(&zc, uos, obj->oo_xattr, 0); if (rc) return rc; while ((rc = -zap_cursor_retrieve(zc, za)) == 0) { BUG_ON(za->za_integer_length != sizeof(uint64_t)); BUG_ON(za->za_num_integers != 1); rc = -zap_lookup(uos->os, obj->oo_xattr, za->za_name, sizeof(uint64_t), 1, &xid); if (rc) { CERROR("%s: lookup xattr %s failed: rc = %d\n", osd->od_svname, za->za_name, rc); continue; } rc = __osd_object_free(uos, xid, tx); if (rc) CERROR("%s: fetch xattr %s failed: rc = %d\n", osd->od_svname, za->za_name, rc); zap_cursor_advance(zc); } udmu_zap_cursor_fini(zc); rc = __osd_object_free(uos, obj->oo_xattr, tx); if (rc) CERROR("%s: freeing xattr failed: rc = %d\n", osd->od_svname, rc); } return __osd_object_free(uos, obj->oo_db->db_object, tx); }
/** * Move Iterator to record specified by \a key * * \param di osd iterator * \param key key for index * * \retval +ve di points to record with least key not larger than key * \retval 0 di points to exact matched key * \retval -ve failure */ static int osd_dir_it_get(const struct lu_env *env, struct dt_it *di, const struct dt_key *key) { struct osd_zap_it *it = (struct osd_zap_it *)di; struct osd_object *obj = it->ozi_obj; struct osd_device *osd = osd_obj2dev(obj); char *name = (char *)key; int rc; ENTRY; LASSERT(it); LASSERT(it->ozi_zc); udmu_zap_cursor_fini(it->ozi_zc); if (udmu_zap_cursor_init(&it->ozi_zc, &osd->od_objset, obj->oo_db->db_object, 0)) RETURN(-ENOMEM); /* XXX: implementation of the API is broken at the moment */ LASSERT(((const char *)key)[0] == 0); if (name[0] == 0) { it->ozi_pos = 0; RETURN(1); } if (name[0] == '.') { if (name[1] == 0) { it->ozi_pos = 1; GOTO(out, rc = 1); } else if (name[1] == '.' && name[2] == 0) { it->ozi_pos = 2; GOTO(out, rc = 1); } } /* neither . nor .. - some real record */ it->ozi_pos = 3; rc = +1; out: RETURN(rc); }
static int osd_zap_it_get(const struct lu_env *env, struct dt_it *di, const struct dt_key *key) { struct osd_zap_it *it = (struct osd_zap_it *)di; struct osd_object *obj = it->ozi_obj; struct osd_device *osd = osd_obj2dev(obj); ENTRY; LASSERT(it); LASSERT(it->ozi_zc); /* XXX: API is broken at the moment */ LASSERT(((const char *)key)[0] == '\0'); udmu_zap_cursor_fini(it->ozi_zc); if (udmu_zap_cursor_init(&it->ozi_zc, &osd->od_objset, obj->oo_db->db_object, 0)) RETURN(-ENOMEM); it->ozi_reset = 1; RETURN(+1); }
/** * Restore iterator from cookie. if the \a hash isn't found, * restore the first valid record. * * \param di - osd iterator * \param hash - iterator location cookie * * \retval +ve - di points to exact matched key * \retval 0 - di points to the first valid record * \retval -ve - failure */ static int osd_it_acct_load(const struct lu_env *env, const struct dt_it *di, __u64 hash) { struct osd_it_quota *it = (struct osd_it_quota *)di; struct osd_device *osd = osd_obj2dev(it->oiq_obj); zap_cursor_t *zc; int rc; ENTRY; /* create new cursor pointing to the new hash */ rc = -udmu_zap_cursor_init(&zc, &osd->od_objset, it->oiq_oid, hash); if (rc) RETURN(rc); udmu_zap_cursor_fini(it->oiq_zc); it->oiq_zc = zc; it->oiq_reset = 0; rc = -udmu_zap_cursor_retrieve_key(env, it->oiq_zc, NULL, 32); if (rc == 0) RETURN(+1); else if (rc == -ENOENT) RETURN(0); RETURN(rc); }