/* * zap_cursor_retrieve read from current record. * to read bytes we need to call zap_lookup explicitly. */ int udmu_zap_cursor_retrieve_value(const struct lu_env *env, zap_cursor_t *zc, char *buf, int buf_size, int *bytes_read) { zap_attribute_t *za = &osd_oti_get(env)->oti_za; int err, actual_size; if ((err = zap_cursor_retrieve(zc, za))) return err; if (za->za_integer_length <= 0) return (ERANGE); actual_size = za->za_integer_length * za->za_num_integers; if (actual_size > buf_size) { actual_size = buf_size; buf_size = actual_size / za->za_integer_length; } else { buf_size = za->za_num_integers; } err = -zap_lookup(zc->zc_objset, zc->zc_zapobj, za->za_name, za->za_integer_length, buf_size, buf); if (!err) *bytes_read = actual_size; return err; }
/** * to load a directory entry at a time and stored it in * iterator's in-memory data structure. * * \param di, struct osd_it_ea, iterator's in memory structure * * \retval +ve, iterator reached to end * \retval 0, iterator not reached to end * \retval -ve, on error */ static int osd_dir_it_next(const struct lu_env *env, struct dt_it *di) { struct osd_zap_it *it = (struct osd_zap_it *)di; zap_attribute_t *za = &osd_oti_get(env)->oti_za; int rc; /* temp. storage should be enough for any key supported by ZFS */ CLASSERT(sizeof(za->za_name) <= sizeof(it->ozi_name)); /* * the first ->next() moves the cursor to . * the second ->next() moves the cursor to .. * then we get to the real records and have to verify any exist */ if (it->ozi_pos <= 2) { it->ozi_pos++; if (it->ozi_pos <=2) RETURN(0); } zap_cursor_advance(it->ozi_zc); /* * According to current API we need to return error if its last entry. * zap_cursor_advance() does not return any value. So we need to call * retrieve to check if there is any record. We should make * changes to Iterator API to not return status for this API */ rc = osd_index_retrieve_skip_dots(it, za); if (rc == -ENOENT) /* end of dir */ RETURN(+1); RETURN(rc); }
static int osd_index_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; /* close the current cursor */ zap_cursor_fini(it->ozi_zc); /* create a new one starting at hash */ memset(it->ozi_zc, 0, sizeof(*it->ozi_zc)); zap_cursor_init_serialized(it->ozi_zc, osd->od_objset.os, obj->oo_db->db_object, hash); it->ozi_reset = 0; rc = -zap_cursor_retrieve(it->ozi_zc, za); if (rc == 0) RETURN(+1); else if (rc == -ENOENT) RETURN(0); RETURN(rc); }
static int osd_dir_it_key_size(const struct lu_env *env, const struct dt_it *di) { struct osd_zap_it *it = (struct osd_zap_it *)di; zap_attribute_t *za = &osd_oti_get(env)->oti_za; int rc; ENTRY; if (it->ozi_pos <= 1) { it->ozi_pos = 1; RETURN(2); } else if (it->ozi_pos == 2) { RETURN(3); } if ((rc = -zap_cursor_retrieve(it->ozi_zc, za)) == 0) rc = strlen(za->za_name); #if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 3, 90, 0) if (rc == 0 && za->za_name[0] == '.') { if (za->za_name[1] == 0 || (za->za_name[1] == '.' && za->za_name[2] == 0)) { /* we should not get onto . and .. * stored in the directory. ->next() and * other methods should prevent this */ LBUG(); } } #endif RETURN(rc); }
int __osd_obj2dbuf(const struct lu_env *env, objset_t *os, uint64_t oid, dmu_buf_t **dbp) { dmu_object_info_t *doi = &osd_oti_get(env)->oti_doi; int rc; rc = -sa_buf_hold(os, oid, osd_obj_tag, dbp); if (rc) return rc; dmu_object_info_from_db(*dbp, doi); if (unlikely (oid != DMU_USERUSED_OBJECT && oid != DMU_GROUPUSED_OBJECT && doi->doi_bonus_type != DMU_OT_SA)) { sa_buf_rele(*dbp, osd_obj_tag); *dbp = NULL; return -EINVAL; } LASSERT(*dbp); LASSERT((*dbp)->db_object == oid); LASSERT((*dbp)->db_offset == -1); LASSERT((*dbp)->db_data != NULL); return 0; }
/* * 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 int osd_check_lma(const struct lu_env *env, struct osd_object *obj) { struct osd_thread_info *info = osd_oti_get(env); struct lu_buf buf; int rc; struct lustre_mdt_attrs *lma; ENTRY; CLASSERT(sizeof(info->oti_buf) >= sizeof(*lma)); lma = (struct lustre_mdt_attrs *)info->oti_buf; buf.lb_buf = lma; buf.lb_len = sizeof(info->oti_buf); rc = osd_xattr_get(env, &obj->oo_dt, &buf, XATTR_NAME_LMA); if (rc > 0) { rc = 0; lustre_lma_swab(lma); if (unlikely((lma->lma_incompat & ~LMA_INCOMPAT_SUPP) || CFS_FAIL_CHECK(OBD_FAIL_OSD_LMA_INCOMPAT))) { CWARN("%s: unsupported incompat LMA feature(s) %#x for " "fid = "DFID"\n", osd_obj2dev(obj)->od_svname, lma->lma_incompat & ~LMA_INCOMPAT_SUPP, PFID(lu_object_fid(&obj->oo_dt.do_lu))); rc = -EOPNOTSUPP; } } else if (rc == -ENODATA) { /* haven't initialize LMA xattr */ rc = 0; } RETURN(rc); }
static int osd_index_insert(const struct lu_env *env, struct dt_object *dt, const struct dt_rec *rec, const struct dt_key *key, struct thandle *th, struct lustre_capa *capa, int ignore_quota) { struct osd_object *obj = osd_dt_obj(dt); struct osd_device *osd = osd_obj2dev(obj); struct osd_thandle *oh; __u64 *k = osd_oti_get(env)->oti_key64; int rc; ENTRY; LASSERT(obj->oo_db); LASSERT(dt_object_exists(dt)); LASSERT(osd_invariant(obj)); LASSERT(th != NULL); oh = container_of0(th, struct osd_thandle, ot_super); rc = osd_prepare_key_uint64(obj, k, key); /* Insert (key,oid) into ZAP */ rc = -zap_add_uint64(osd->od_objset.os, obj->oo_db->db_object, k, rc, obj->oo_recusize, obj->oo_recsize, (void *)rec, oh->ot_tx); RETURN(rc); }
/** * 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_attribute_t *za = &osd_oti_get(env)->oti_za; zap_cursor_t *zc; int rc; ENTRY; /* create new cursor pointing to the new hash */ rc = osd_zap_cursor_init(&zc, osd->od_os, it->oiq_oid, hash); if (rc) RETURN(rc); osd_zap_cursor_fini(it->oiq_zc); it->oiq_zc = zc; it->oiq_reset = 0; rc = -zap_cursor_retrieve(it->oiq_zc, za); if (rc == 0) rc = 1; else if (rc == -ENOENT) rc = 0; RETURN(rc); }
/* * zap_cursor_retrieve read from current record. * to read bytes we need to call zap_lookup explicitly. */ static int osd_zap_cursor_retrieve_value(const struct lu_env *env, zap_cursor_t *zc, char *buf, int buf_size, int *bytes_read) { zap_attribute_t *za = &osd_oti_get(env)->oti_za; int rc, actual_size; rc = -zap_cursor_retrieve(zc, za); if (unlikely(rc != 0)) return -rc; if (unlikely(za->za_integer_length <= 0)) return -ERANGE; actual_size = za->za_integer_length * za->za_num_integers; if (actual_size > buf_size) { actual_size = buf_size; buf_size = actual_size / za->za_integer_length; } else { buf_size = za->za_num_integers; } rc = -zap_lookup(zc->zc_objset, zc->zc_zapobj, za->za_name, za->za_integer_length, buf_size, buf); if (likely(rc == 0)) *bytes_read = actual_size; 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); }
static int osd_dir_lookup(const struct lu_env *env, struct dt_object *dt, struct dt_rec *rec, const struct dt_key *key, 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); char *name = (char *)key; int rc; ENTRY; LASSERT(udmu_object_is_zap(obj->oo_db)); if (name[0] == '.') { if (name[1] == 0) { const struct lu_fid *f = lu_object_fid(&dt->do_lu); memcpy(rec, f, sizeof(*f)); RETURN(1); } else if (name[1] == '.' && name[2] == 0) { rc = osd_find_parent_fid(env, dt, (struct lu_fid *)rec); RETURN(rc == 0 ? 1 : rc); } } rc = -zap_lookup(osd->od_objset.os, obj->oo_db->db_object, (char *)key, 8, sizeof(oti->oti_zde) / 8, (void *)&oti->oti_zde); memcpy(rec, &oti->oti_zde.lzd_fid, sizeof(struct lu_fid)); RETURN(rc == 0 ? 1 : 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); }
/** * Return space usage consumed by a given uid or gid. * Block usage is accurrate since it is maintained by DMU itself. * However, DMU does not provide inode accounting, so the #inodes in use * is estimated from the block usage and statfs information. * * \param env - is the environment passed by the caller * \param dtobj - is the accounting object * \param dtrec - is the record to fill with space usage information * \param dtkey - is the id the of the user or group for which we would * like to access disk usage. * \param capa - is the capability, not used. * * \retval +ve - success : exact match * \retval -ve - failure */ static int osd_acct_index_lookup(const struct lu_env *env, struct dt_object *dtobj, struct dt_rec *dtrec, const struct dt_key *dtkey, struct lustre_capa *capa) { struct osd_thread_info *info = osd_oti_get(env); char *buf = info->oti_buf; struct lquota_acct_rec *rec = (struct lquota_acct_rec *)dtrec; struct osd_object *obj = osd_dt_obj(dtobj); struct osd_device *osd = osd_obj2dev(obj); int rc; uint64_t oid; ENTRY; rec->bspace = rec->ispace = 0; /* convert the 64-bit uid/gid into a string */ sprintf(buf, "%llx", *((__u64 *)dtkey)); /* fetch DMU object ID (DMU_USERUSED_OBJECT/DMU_GROUPUSED_OBJECT) to be * used */ oid = osd_quota_fid2dmu(lu_object_fid(&dtobj->do_lu)); /* disk usage (in bytes) is maintained by DMU. * DMU_USERUSED_OBJECT/DMU_GROUPUSED_OBJECT are special objects which * not associated with any dmu_but_t (see dnode_special_open()). * As a consequence, we cannot use udmu_zap_lookup() here since it * requires a valid oo_db. */ rc = -zap_lookup(osd->od_objset.os, oid, buf, sizeof(uint64_t), 1, &rec->bspace); if (rc == -ENOENT) /* user/group has not created anything yet */ CDEBUG(D_QUOTA, "%s: id %s not found in DMU accounting ZAP\n", osd->od_svname, buf); else if (rc) RETURN(rc); if (osd->od_quota_iused_est) { if (rec->bspace != 0) /* estimate #inodes in use */ rec->ispace = udmu_objset_user_iused(&osd->od_objset, rec->bspace); RETURN(+1); } /* as for inode accounting, it is not maintained by DMU, so we just * use our own ZAP to track inode usage */ rc = -zap_lookup(osd->od_objset.os, obj->oo_db->db_object, buf, sizeof(uint64_t), 1, &rec->ispace); if (rc == -ENOENT) /* user/group has not created any file yet */ CDEBUG(D_QUOTA, "%s: id %s not found in accounting ZAP\n", osd->od_svname, buf); else if (rc) RETURN(rc); RETURN(+1); }
static struct obd_capa *osd_capa_get(const struct lu_env *env, struct dt_object *dt, struct lustre_capa *old, __u64 opc) { struct osd_thread_info *info = osd_oti_get(env); const struct lu_fid *fid = lu_object_fid(&dt->do_lu); struct osd_object *obj = osd_dt_obj(dt); struct osd_device *dev = osd_obj2dev(obj); struct lustre_capa_key *key = &info->oti_capa_key; struct lustre_capa *capa = &info->oti_capa; struct obd_capa *oc; int rc; ENTRY; if (!dev->od_fl_capa) RETURN(ERR_PTR(-ENOENT)); LASSERT(dt_object_exists(dt)); LASSERT(osd_invariant(obj)); /* renewal sanity check */ if (old && osd_object_auth(env, dt, old, opc)) RETURN(ERR_PTR(-EACCES)); capa->lc_fid = *fid; capa->lc_opc = opc; capa->lc_uid = 0; capa->lc_flags = dev->od_capa_alg << 24; capa->lc_timeout = dev->od_capa_timeout; capa->lc_expiry = 0; oc = capa_lookup(dev->od_capa_hash, capa, 1); if (oc) { LASSERT(!capa_is_expired(oc)); RETURN(oc); } spin_lock(&capa_lock); *key = dev->od_capa_keys[1]; spin_unlock(&capa_lock); capa->lc_keyid = key->lk_keyid; capa->lc_expiry = cfs_time_current_sec() + dev->od_capa_timeout; rc = capa_hmac(capa->lc_hmac, capa, key->lk_key); if (rc) { DEBUG_CAPA(D_ERROR, capa, "HMAC failed: %d for", rc); LBUG(); RETURN(ERR_PTR(rc)); } oc = capa_add(dev->od_capa_hash, capa); RETURN(oc); }
/** * Inserts (key, value) pair in \a directory object. * * \param dt osd index object * \param key key for index * \param rec record reference * \param th transaction handler * \param capa capability descriptor * \param ignore_quota update should not affect quota * * \retval 0 success * \retval -ve failure */ static int osd_dir_insert(const struct lu_env *env, struct dt_object *dt, const struct dt_rec *rec, const struct dt_key *key, struct thandle *th, struct lustre_capa *capa, int ignore_quota) { struct osd_thread_info *oti = osd_oti_get(env); struct osd_object *parent = osd_dt_obj(dt); struct osd_device *osd = osd_obj2dev(parent); struct lu_fid *fid = (struct lu_fid *)rec; struct osd_thandle *oh; struct osd_object *child; __u32 attr; int rc; ENTRY; LASSERT(parent->oo_db); LASSERT(udmu_object_is_zap(parent->oo_db)); LASSERT(dt_object_exists(dt)); LASSERT(osd_invariant(parent)); /* * zfs_readdir() generates ./.. on fly, but * we want own entries (.. at least) with a fid */ #if LUSTRE_VERSION_CODE >= OBD_OCD_VERSION(2, 3, 61, 0) #warning "fix '.' and '..' handling" #endif LASSERT(th != NULL); oh = container_of0(th, struct osd_thandle, ot_super); child = osd_object_find(env, dt, fid); if (IS_ERR(child)) RETURN(PTR_ERR(child)); LASSERT(child->oo_db); CLASSERT(sizeof(oti->oti_zde.lzd_reg) == 8); CLASSERT(sizeof(oti->oti_zde) % 8 == 0); attr = child->oo_dt.do_lu.lo_header ->loh_attr; oti->oti_zde.lzd_reg.zde_type = IFTODT(attr & S_IFMT); oti->oti_zde.lzd_reg.zde_dnode = child->oo_db->db_object; oti->oti_zde.lzd_fid = *fid; /* Insert (key,oid) into ZAP */ rc = -zap_add(osd->od_objset.os, parent->oo_db->db_object, (char *)key, 8, sizeof(oti->oti_zde) / 8, (void *)&oti->oti_zde, oh->ot_tx); osd_object_put(env, child); RETURN(rc); }
static int osd_declare_object_destroy(const struct lu_env *env, struct dt_object *dt, struct thandle *th) { char *buf = osd_oti_get(env)->oti_str; const struct lu_fid *fid = lu_object_fid(&dt->do_lu); struct osd_object *obj = osd_dt_obj(dt); struct osd_device *osd = osd_obj2dev(obj); struct osd_thandle *oh; int rc; uint64_t zapid; ENTRY; LASSERT(th != NULL); LASSERT(dt_object_exists(dt)); oh = container_of0(th, struct osd_thandle, ot_super); LASSERT(oh->ot_tx != NULL); /* declare that we'll remove object from fid-dnode mapping */ zapid = osd_get_name_n_idx(env, osd, fid, buf); dmu_tx_hold_bonus(oh->ot_tx, zapid); dmu_tx_hold_zap(oh->ot_tx, zapid, FALSE, buf); osd_declare_xattrs_destroy(env, obj, oh); /* declare that we'll remove object from inode accounting ZAPs */ dmu_tx_hold_bonus(oh->ot_tx, osd->od_iusr_oid); dmu_tx_hold_zap(oh->ot_tx, osd->od_iusr_oid, FALSE, buf); dmu_tx_hold_bonus(oh->ot_tx, osd->od_igrp_oid); dmu_tx_hold_zap(oh->ot_tx, osd->od_igrp_oid, FALSE, buf); /* one less inode */ rc = osd_declare_quota(env, osd, obj->oo_attr.la_uid, obj->oo_attr.la_gid, -1, oh, false, NULL, false); if (rc) RETURN(rc); /* data to be truncated */ rc = osd_declare_quota(env, osd, obj->oo_attr.la_uid, obj->oo_attr.la_gid, 0, oh, true, NULL, false); if (rc) RETURN(rc); osd_object_set_destroy_type(obj); if (obj->oo_destroy == OSD_DESTROY_SYNC) dmu_tx_hold_free(oh->ot_tx, obj->oo_db->db_object, 0, DMU_OBJECT_END); else dmu_tx_hold_zap(oh->ot_tx, osd->od_unlinkedid, TRUE, NULL); RETURN(0); }
/** * Return pointer to the record under iterator. * * \param di - osd iterator * \param attr - not used */ static int osd_it_acct_rec(const struct lu_env *env, const struct dt_it *di, struct dt_rec *dtrec, __u32 attr) { struct osd_thread_info *info = osd_oti_get(env); char *buf = info->oti_buf; struct osd_it_quota *it = (struct osd_it_quota *)di; struct lquota_acct_rec *rec = (struct lquota_acct_rec *)dtrec; struct osd_object *obj = it->oiq_obj; struct osd_device *osd = osd_obj2dev(obj); int bytes_read; int rc; ENTRY; it->oiq_reset = 0; rec->ispace = rec->bspace = 0; /* retrieve block usage from the DMU accounting object */ rc = -udmu_zap_cursor_retrieve_value(env, it->oiq_zc, (char *)&rec->bspace, sizeof(uint64_t), &bytes_read); if (rc) RETURN(rc); if (osd->od_quota_iused_est) { if (rec->bspace != 0) /* estimate #inodes in use */ rec->ispace = udmu_objset_user_iused(&osd->od_objset, rec->bspace); RETURN(0); } /* retrieve key associated with the current cursor */ rc = -udmu_zap_cursor_retrieve_key(env, it->oiq_zc, buf, 32); if (rc) RETURN(rc); /* inode accounting is not maintained by DMU, so we use our own ZAP to * track inode usage */ rc = -zap_lookup(osd->od_objset.os, it->oiq_obj->oo_db->db_object, buf, sizeof(uint64_t), 1, &rec->ispace); if (rc == -ENOENT) /* user/group has not created any file yet */ CDEBUG(D_QUOTA, "%s: id %s not found in accounting ZAP\n", osd->od_svname, buf); else if (rc) RETURN(rc); RETURN(0); }
static int osd_index_it_rec(const struct lu_env *env, const struct dt_it *di, struct dt_rec *rec, __u32 attr) { zap_attribute_t *za = &osd_oti_get(env)->oti_za; struct osd_zap_it *it = (struct osd_zap_it *)di; struct osd_object *obj = it->ozi_obj; struct osd_device *osd = osd_obj2dev(obj); __u64 *k = osd_oti_get(env)->oti_key64; int rc; ENTRY; it->ozi_reset = 0; rc = -zap_cursor_retrieve(it->ozi_zc, za); if (rc) RETURN(rc); rc = osd_prepare_key_uint64(obj, k, (const struct dt_key *)za->za_name); rc = -zap_lookup_uint64(osd->od_objset.os, obj->oo_db->db_object, k, rc, obj->oo_recusize, obj->oo_recsize, (void *)rec); RETURN(rc); }
int udmu_zap_cursor_retrieve_key(const struct lu_env *env, zap_cursor_t *zc, char *key, int max) { zap_attribute_t *za = &osd_oti_get(env)->oti_za; int err; if ((err = zap_cursor_retrieve(zc, za))) return err; if (key) strcpy(key, za->za_name); return 0; }
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; }
/** * Move on to the next valid entry. * * \param di - osd iterator * * \retval +ve - iterator reached the end * \retval 0 - iterator has not reached the end yet * \retval -ve - unexpected failure */ static int osd_it_acct_next(const struct lu_env *env, struct dt_it *di) { struct osd_it_quota *it = (struct osd_it_quota *)di; zap_attribute_t *za = &osd_oti_get(env)->oti_za; int rc; ENTRY; if (it->oiq_reset == 0) zap_cursor_advance(it->oiq_zc); it->oiq_reset = 0; rc = -zap_cursor_retrieve(it->oiq_zc, za); if (rc == -ENOENT) /* reached the end */ rc = 1; RETURN(rc); }
/** * Free given iterator. * * \param di - osd iterator */ static void osd_it_acct_fini(const struct lu_env *env, struct dt_it *di) { struct osd_thread_info *info = osd_oti_get(env); struct osd_it_quota *it = (struct osd_it_quota *)di; ENTRY; osd_zap_cursor_fini(it->oiq_zc); lu_object_put(env, &it->oiq_obj->oo_dt.do_lu); if (it != &info->oti_it_quota) OBD_FREE_PTR(it); else info->oti_it_inline = 0; EXIT; }
/** * Return pointer to the key under iterator. * * \param di - osd iterator */ static struct dt_key *osd_it_acct_key(const struct lu_env *env, const struct dt_it *di) { struct osd_it_quota *it = (struct osd_it_quota *)di; zap_attribute_t *za = &osd_oti_get(env)->oti_za; int rc; ENTRY; it->oiq_reset = 0; rc = -zap_cursor_retrieve(it->oiq_zc, za); if (rc) RETURN(ERR_PTR(rc)); rc = kstrtoull(za->za_name, 16, &it->oiq_id); RETURN((struct dt_key *) &it->oiq_id); }
int osd_xattrs_destroy(const struct lu_env *env, struct osd_object *obj, struct osd_thandle *oh) { struct osd_device *osd = osd_obj2dev(obj); dmu_tx_t *tx = oh->ot_tx; zap_attribute_t *za = &osd_oti_get(env)->oti_za; zap_cursor_t *zc; uint64_t xid; int rc; /* The transaction must have been assigned to a transaction group. */ LASSERT(tx->tx_txg != 0); if (obj->oo_xattr == ZFS_NO_OBJECT) return 0; /* Nothing to do for SA xattrs */ /* Free the ZAP holding the xattrs */ rc = osd_zap_cursor_init(&zc, osd->od_os, obj->oo_xattr, 0); if (rc) return rc; while (zap_cursor_retrieve(zc, za) == 0) { LASSERT(za->za_num_integers == 1); LASSERT(za->za_integer_length == sizeof(uint64_t)); rc = -zap_lookup(osd->od_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); } else { rc = -dmu_object_free(osd->od_os, xid, tx); if (rc) CERROR("%s: free xattr %s failed: rc = %d\n", osd->od_svname, za->za_name, rc); } zap_cursor_advance(zc); } osd_zap_cursor_fini(zc); rc = -dmu_object_free(osd->od_os, obj->oo_xattr, tx); if (rc) CERROR("%s: free xattr "LPU64" failed: rc = %d\n", osd->od_svname, obj->oo_xattr, rc); return rc; }
/** * 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)); if (info->oti_it_inline) { OBD_ALLOC_PTR(it); if (it == NULL) RETURN(ERR_PTR(-ENOMEM)); } else { it = &info->oti_it_quota; info->oti_it_inline = 1; } memset(it, 0, sizeof(*it)); it->oiq_oid = osd_quota_fid2dmu(lu_object_fid(lo)); /* initialize zap cursor */ rc = osd_zap_cursor_init(&it->oiq_zc, osd->od_os, it->oiq_oid, 0); if (rc != 0) { if (it != &info->oti_it_quota) OBD_FREE_PTR(it); else info->oti_it_inline = 0; 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); }
/* * 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); }
static int osd_index_lookup(const struct lu_env *env, struct dt_object *dt, struct dt_rec *rec, const struct dt_key *key, struct lustre_capa *capa) { struct osd_object *obj = osd_dt_obj(dt); struct osd_device *osd = osd_obj2dev(obj); __u64 *k = osd_oti_get(env)->oti_key64; int rc; ENTRY; rc = osd_prepare_key_uint64(obj, k, key); rc = -zap_lookup_uint64(osd->od_objset.os, obj->oo_db->db_object, k, rc, obj->oo_recusize, obj->oo_recsize, (void *)rec); RETURN(rc == 0 ? 1 : rc); }
/** * Return pointer to the key under iterator. * * \param di - osd iterator */ static struct dt_key *osd_it_acct_key(const struct lu_env *env, const struct dt_it *di) { struct osd_it_quota *it = (struct osd_it_quota *)di; struct osd_thread_info *info = osd_oti_get(env); char *buf = info->oti_buf; char *p; int rc; ENTRY; it->oiq_reset = 0; rc = -udmu_zap_cursor_retrieve_key(env, it->oiq_zc, buf, 32); if (rc) RETURN(ERR_PTR(rc)); it->oiq_id = simple_strtoull(buf, &p, 16); RETURN((struct dt_key *) &it->oiq_id); }
static int capa_is_sane(const struct lu_env *env, struct osd_device *dev, struct lustre_capa *capa, struct lustre_capa_key *keys) { struct osd_thread_info *oti = osd_oti_get(env); struct obd_capa *oc; int i, rc = 0; ENTRY; oc = capa_lookup(dev->od_capa_hash, capa, 0); if (oc) { if (capa_is_expired(oc)) { DEBUG_CAPA(D_ERROR, capa, "expired"); rc = -ESTALE; } capa_put(oc); RETURN(rc); } spin_lock(&capa_lock); for (i = 0; i < 2; i++) { if (keys[i].lk_keyid == capa->lc_keyid) { oti->oti_capa_key = keys[i]; break; } } spin_unlock(&capa_lock); if (i == 2) { DEBUG_CAPA(D_ERROR, capa, "no matched capa key"); RETURN(-ESTALE); } rc = capa_hmac(oti->oti_capa.lc_hmac, capa, oti->oti_capa_key.lk_key); if (rc) RETURN(rc); if (memcmp(oti->oti_capa.lc_hmac, capa->lc_hmac, sizeof(capa->lc_hmac))) { DEBUG_CAPA(D_ERROR, capa, "HMAC mismatch"); RETURN(-EACCES); } oc = capa_add(dev->od_capa_hash, capa); capa_put(oc); RETURN(0); }