/* * Concurrency: @dt is write locked. */ static int osd_object_ref_add(const struct lu_env *env, struct dt_object *dt, struct thandle *handle) { struct osd_object *obj = osd_dt_obj(dt); struct osd_thandle *oh; struct osd_device *osd = osd_obj2dev(obj); uint64_t nlink; int rc; ENTRY; LASSERT(osd_invariant(obj)); LASSERT(dt_object_exists(dt)); LASSERT(obj->oo_sa_hdl != NULL); oh = container_of0(handle, struct osd_thandle, ot_super); write_lock(&obj->oo_attr_lock); nlink = ++obj->oo_attr.la_nlink; write_unlock(&obj->oo_attr_lock); rc = osd_object_sa_update(obj, SA_ZPL_LINKS(osd), &nlink, 8, oh); return rc; }
static int osd_attr_get(const struct lu_env *env, struct dt_object *dt, struct lu_attr *attr, struct lustre_capa *capa) { struct osd_object *obj = osd_dt_obj(dt); uint64_t blocks; uint32_t blksize; LASSERT(dt_object_exists(dt)); LASSERT(osd_invariant(obj)); LASSERT(obj->oo_db); read_lock(&obj->oo_attr_lock); *attr = obj->oo_attr; read_unlock(&obj->oo_attr_lock); /* with ZFS_DEBUG zrl_add_debug() called by DB_DNODE_ENTER() * from within sa_object_size() can block on a mutex, so * we can't call sa_object_size() holding rwlock */ sa_object_size(obj->oo_sa_hdl, &blksize, &blocks); /* we do not control size of indices, so always calculate * it from number of blocks reported by DMU */ if (S_ISDIR(attr->la_mode)) attr->la_size = 512 * blocks; /* Block size may be not set; suggest maximal I/O transfers. */ if (blksize == 0) blksize = 1ULL << SPA_MAXBLOCKSHIFT; attr->la_blksize = blksize; attr->la_blocks = blocks; attr->la_valid |= LA_BLOCKS | LA_BLKSIZE; return 0; }
/** * 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); }
/* * Concurrency: @dt is write locked. */ static int osd_object_ref_del(const struct lu_env *env, struct dt_object *dt, struct thandle *handle) { struct osd_object *obj = osd_dt_obj(dt); struct osd_thandle *oh; struct osd_device *osd = osd_obj2dev(obj); uint64_t nlink; int rc; ENTRY; down_read(&obj->oo_guard); if (unlikely(!dt_object_exists(dt) || obj->oo_destroyed)) GOTO(out, rc = -ENOENT); LASSERT(osd_invariant(obj)); LASSERT(obj->oo_sa_hdl != NULL); oh = container_of0(handle, struct osd_thandle, ot_super); LASSERT(!lu_object_is_dying(dt->do_lu.lo_header)); write_lock(&obj->oo_attr_lock); nlink = --obj->oo_attr.la_nlink; write_unlock(&obj->oo_attr_lock); rc = osd_object_sa_update(obj, SA_ZPL_LINKS(osd), &nlink, 8, oh); out: up_read(&obj->oo_guard); RETURN(rc); }
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); }
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_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); }
int osd_xattr_get(const struct lu_env *env, struct dt_object *dt, struct lu_buf *buf, const char *name) { struct osd_object *obj = osd_dt_obj(dt); int rc, size = 0; ENTRY; LASSERT(obj->oo_db != NULL); LASSERT(osd_invariant(obj)); if (!osd_obj2dev(obj)->od_posix_acl && (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0 || strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0)) RETURN(-EOPNOTSUPP); down_read(&obj->oo_guard); rc = __osd_xattr_get(env, obj, buf, name, &size); up_read(&obj->oo_guard); if (rc == -ENOENT) rc = -ENODATA; else if (rc == 0) rc = size; RETURN(rc); }
int osd_xattr_set(const struct lu_env *env, struct dt_object *dt, const struct lu_buf *buf, const char *name, int fl, struct thandle *handle) { struct osd_object *obj = osd_dt_obj(dt); struct osd_thandle *oh; int rc = 0; ENTRY; LASSERT(handle != NULL); LASSERT(osd_invariant(obj)); if (!osd_obj2dev(obj)->od_posix_acl && (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0 || strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0)) RETURN(-EOPNOTSUPP); if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_LINKEA_OVERFLOW) && strcmp(name, XATTR_NAME_LINK) == 0) RETURN(-ENOSPC); oh = container_of0(handle, struct osd_thandle, ot_super); down_write(&obj->oo_guard); CDEBUG(D_INODE, "Setting xattr %s with size %d\n", name, (int)buf->lb_len); rc = osd_xattr_set_internal(env, obj, buf, name, fl, oh); up_write(&obj->oo_guard); RETURN(rc); }
static int osd_dir_delete(const struct lu_env *env, struct dt_object *dt, const struct dt_key *key, struct thandle *th, struct lustre_capa *capa) { struct osd_object *obj = osd_dt_obj(dt); struct osd_device *osd = osd_obj2dev(obj); struct osd_thandle *oh; dmu_buf_t *zap_db = obj->oo_db; int rc; ENTRY; LASSERT(obj->oo_db); LASSERT(udmu_object_is_zap(obj->oo_db)); LASSERT(th != NULL); oh = container_of0(th, struct osd_thandle, ot_super); /* Remove key from the ZAP */ rc = -zap_remove(osd->od_objset.os, zap_db->db_object, (char *) key, oh->ot_tx); if (rc && rc != -ENOENT) CERROR("%s: zap_remove failed: rc = %d\n", osd->od_svname, rc); RETURN(rc); }
int osd_xattr_del(const struct lu_env *env, struct dt_object *dt, const char *name, struct thandle *handle) { struct osd_object *obj = osd_dt_obj(dt); struct osd_thandle *oh; int rc; ENTRY; LASSERT(handle != NULL); LASSERT(obj->oo_db != NULL); LASSERT(osd_invariant(obj)); LASSERT(dt_object_exists(dt)); oh = container_of0(handle, struct osd_thandle, ot_super); LASSERT(oh->ot_tx != NULL); if (!osd_obj2dev(obj)->od_posix_acl && (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0 || strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0)) RETURN(-EOPNOTSUPP); down_write(&obj->oo_guard); rc = __osd_xattr_del(env, obj, name, oh); up_write(&obj->oo_guard); RETURN(rc); }
/* * Concurrency: @dt is write locked. */ static int osd_object_ref_del(const struct lu_env *env, struct dt_object *dt, struct thandle *handle) { struct osd_object *obj = osd_dt_obj(dt); struct osd_thandle *oh; struct osd_device *osd = osd_obj2dev(obj); udmu_objset_t *uos = &osd->od_objset; uint64_t nlink; int rc; ENTRY; LASSERT(osd_invariant(obj)); LASSERT(dt_object_exists(dt)); LASSERT(obj->oo_sa_hdl != NULL); oh = container_of0(handle, struct osd_thandle, ot_super); LASSERT(!lu_object_is_dying(dt->do_lu.lo_header)); write_lock(&obj->oo_attr_lock); nlink = --obj->oo_attr.la_nlink; write_unlock(&obj->oo_attr_lock); rc = osd_object_sa_update(obj, SA_ZPL_LINKS(uos), &nlink, 8, oh); return rc; }
int osd_xattr_set(const struct lu_env *env, struct dt_object *dt, const struct lu_buf *buf, const char *name, int fl, struct thandle *handle, struct lustre_capa *capa) { struct osd_object *obj = osd_dt_obj(dt); struct osd_thandle *oh; int rc = 0; ENTRY; LASSERT(handle != NULL); LASSERT(osd_invariant(obj)); LASSERT(dt_object_exists(dt)); LASSERT(obj->oo_db); if (!osd_obj2dev(obj)->od_posix_acl && (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0 || strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0)) RETURN(-EOPNOTSUPP); oh = container_of0(handle, struct osd_thandle, ot_super); down(&obj->oo_guard); CDEBUG(D_INODE, "Setting xattr %s with size %d\n", name, (int)buf->lb_len); rc = osd_xattr_set_internal(env, obj, buf, name, fl, oh, capa); up(&obj->oo_guard); RETURN(rc); }
int osd_index_try(const struct lu_env *env, struct dt_object *dt, const struct dt_index_features *feat) { struct osd_object *obj = osd_dt_obj(dt); ENTRY; LASSERT(dt_object_exists(dt)); /* * XXX: implement support for fixed-size keys sorted with natural * numerical way (not using internal hash value) */ if (feat->dif_flags & DT_IND_RANGE) RETURN(-ERANGE); if (unlikely(feat == &dt_otable_features)) /* do not support oi scrub yet. */ RETURN(-ENOTSUPP); LASSERT(obj->oo_db != NULL); if (likely(feat == &dt_directory_features)) { if (udmu_object_is_zap(obj->oo_db)) dt->do_index_ops = &osd_dir_ops; else RETURN(-ENOTDIR); } else if (unlikely(feat == &dt_acct_features)) { LASSERT(fid_is_acct(lu_object_fid(&dt->do_lu))); dt->do_index_ops = &osd_acct_index_ops; } else if (udmu_object_is_zap(obj->oo_db) && dt->do_index_ops == NULL) { /* For index file, we don't support variable key & record sizes * and the key has to be unique */ if ((feat->dif_flags & ~DT_IND_UPDATE) != 0) RETURN(-EINVAL); if (feat->dif_keysize_max > ZAP_MAXNAMELEN) RETURN(-E2BIG); if (feat->dif_keysize_max != feat->dif_keysize_min) RETURN(-EINVAL); /* As for the record size, it should be a multiple of 8 bytes * and smaller than the maximum value length supported by ZAP. */ if (feat->dif_recsize_max > ZAP_MAXVALUELEN) RETURN(-E2BIG); if (feat->dif_recsize_max != feat->dif_recsize_min) RETURN(-EINVAL); obj->oo_keysize = feat->dif_keysize_max; obj->oo_recsize = feat->dif_recsize_max; obj->oo_recusize = 1; /* ZFS prefers to work with array of 64bits */ if ((obj->oo_recsize & 7) == 0) { obj->oo_recsize >>= 3; obj->oo_recusize = 8; } dt->do_index_ops = &osd_index_ops; }
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_object_write_unlock(const struct lu_env *env, struct dt_object *dt) { struct osd_object *obj = osd_dt_obj(dt); LASSERT(osd_invariant(obj)); up_write(&obj->oo_sem); }
/** * 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 void osd_object_write_lock(const struct lu_env *env, struct dt_object *dt, unsigned role) { struct osd_object *obj = osd_dt_obj(dt); LASSERT(osd_invariant(obj)); down_write(&obj->oo_sem); }
int osd_index_try(const struct lu_env *env, struct dt_object *dt, const struct dt_index_features *feat) { struct osd_object *obj = osd_dt_obj(dt); ENTRY; LASSERT(dt_object_exists(dt)); /* * XXX: implement support for fixed-size keys sorted with natural * numerical way (not using internal hash value) */ if (feat->dif_flags & DT_IND_RANGE) RETURN(-ERANGE); if (unlikely(feat == &dt_otable_features)) /* do not support oi scrub yet. */ RETURN(-ENOTSUPP); LASSERT(obj->oo_db != NULL); if (likely(feat == &dt_directory_features)) { if (udmu_object_is_zap(obj->oo_db)) dt->do_index_ops = &osd_dir_ops; else RETURN(-ENOTDIR); } else if (unlikely(feat == &dt_acct_features)) { LASSERT(fid_is_acct(lu_object_fid(&dt->do_lu))); dt->do_index_ops = &osd_acct_index_ops; } else if (udmu_object_is_zap(obj->oo_db) && dt->do_index_ops == NULL) { /* For index file, we don't support variable key & record sizes * and the key has to be unique */ if ((feat->dif_flags & ~DT_IND_UPDATE) != 0) RETURN(-EINVAL); /* Although the zap_*_uint64() primitives support large keys, we * limit ourselves to 64-bit keys for now */ if (feat->dif_keysize_max != sizeof(__u64) || feat->dif_keysize_min != sizeof(__u64)) RETURN(-EINVAL); /* As for the record size, it should be a multiple of 8 bytes * and smaller than the maximum value length supported by ZAP. */ if (feat->dif_recsize_max > ZAP_MAXVALUELEN) RETURN(-E2BIG); if (feat->dif_recsize_max != feat->dif_recsize_min || (feat->dif_recsize_max & (sizeof(__u64) - 1))) RETURN(-EINVAL); obj->oo_recsize = feat->dif_recsize_max / sizeof(__u64); dt->do_index_ops = &osd_index_ops; } RETURN(0); }
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_object_sync(const struct lu_env *env, struct dt_object *dt) { struct osd_device *osd = osd_obj2dev(osd_dt_obj(dt)); ENTRY; /* XXX: no other option than syncing the whole filesystem until we * support ZIL */ txg_wait_synced(dmu_objset_pool(osd->od_objset.os), 0ULL); RETURN(0); }
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); }
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); int rc; ENTRY; rc = -zap_lookup_uint64(osd->od_objset.os, obj->oo_db->db_object, (const __u64 *)key, 1, 8, obj->oo_recsize, (void *)rec); RETURN(rc == 0 ? 1 : rc); }
static int osd_object_write_locked(const struct lu_env *env, struct dt_object *dt) { struct osd_object *obj = osd_dt_obj(dt); int rc = 1; LASSERT(osd_invariant(obj)); if (down_write_trylock(&obj->oo_sem)) { rc = 0; up_write(&obj->oo_sem); } return rc; }
static int osd_object_sync(const struct lu_env *env, struct dt_object *dt, __u64 start, __u64 end) { struct osd_device *osd = osd_obj2dev(osd_dt_obj(dt)); ENTRY; /* XXX: no other option than syncing the whole filesystem until we * support ZIL. If the object tracked the txg that it was last * modified in, it could pass that txg here instead of "0". Maybe * the changes are already committed, so no wait is needed at all? */ txg_wait_synced(dmu_objset_pool(osd->od_os), 0ULL); RETURN(0); }
static ssize_t osd_write(const struct lu_env *env, struct dt_object *dt, const struct lu_buf *buf, loff_t *pos, struct thandle *th, int ignore_quota) { struct osd_object *obj = osd_dt_obj(dt); struct osd_device *osd = osd_obj2dev(obj); struct osd_thandle *oh; uint64_t offset = *pos; int rc; ENTRY; LASSERT(dt_object_exists(dt)); LASSERT(obj->oo_db); LASSERT(th != NULL); oh = container_of0(th, struct osd_thandle, ot_super); record_start_io(osd, WRITE, 0); dmu_write(osd->od_os, obj->oo_db->db_object, offset, (uint64_t)buf->lb_len, buf->lb_buf, oh->ot_tx); write_lock(&obj->oo_attr_lock); if (obj->oo_attr.la_size < offset + buf->lb_len) { obj->oo_attr.la_size = offset + buf->lb_len; write_unlock(&obj->oo_attr_lock); /* osd_object_sa_update() will be copying directly from oo_attr * into dbuf. any update within a single txg will copy the * most actual */ rc = osd_object_sa_update(obj, SA_ZPL_SIZE(osd), &obj->oo_attr.la_size, 8, oh); if (unlikely(rc)) GOTO(out, rc); } else { write_unlock(&obj->oo_attr_lock); } *pos += buf->lb_len; rc = buf->lb_len; out: record_end_io(osd, WRITE, 0, buf->lb_len, buf->lb_len >> PAGE_CACHE_SHIFT); RETURN(rc); }
int osd_declare_xattr_set(const struct lu_env *env, struct dt_object *dt, const struct lu_buf *buf, const char *name, int fl, struct thandle *handle) { struct osd_object *obj = osd_dt_obj(dt); struct osd_thandle *oh; ENTRY; LASSERT(handle != NULL); oh = container_of0(handle, struct osd_thandle, ot_super); down_read(&obj->oo_guard); __osd_xattr_declare_set(env, obj, buf->lb_len, name, oh); up_read(&obj->oo_guard); RETURN(0); }
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); }
static ssize_t osd_declare_write(const struct lu_env *env, struct dt_object *dt, const struct lu_buf *buf, loff_t pos, struct thandle *th) { struct osd_object *obj = osd_dt_obj(dt); struct osd_device *osd = osd_obj2dev(obj); struct osd_thandle *oh; uint64_t oid; ENTRY; oh = container_of0(th, struct osd_thandle, ot_super); /* in some cases declare can race with creation (e.g. llog) * and we need to wait till object is initialized. notice * LOHA_EXISTs is supposed to be the last step in the * initialization */ /* declare possible size change. notice we can't check * current size here as another thread can change it */ if (dt_object_exists(dt)) { LASSERT(obj->oo_db); oid = obj->oo_db->db_object; dmu_tx_hold_sa(oh->ot_tx, obj->oo_sa_hdl, 0); } else { oid = DMU_NEW_OBJECT; dmu_tx_hold_sa_create(oh->ot_tx, ZFS_SA_BASE_ATTR_SIZE); } /* XXX: we still miss for append declaration support in ZFS * -1 means append which is used by llog mostly, llog * can grow upto LLOG_MIN_CHUNK_SIZE*8 records */ if (pos == -1) pos = max_t(loff_t, 256 * 8 * LLOG_MIN_CHUNK_SIZE, obj->oo_attr.la_size + (2 << 20)); dmu_tx_hold_write(oh->ot_tx, oid, pos, buf->lb_len); /* dt_declare_write() is usually called for system objects, such * as llog or last_rcvd files. We needn't enforce quota on those * objects, so always set the lqi_space as 0. */ RETURN(osd_declare_quota(env, osd, obj->oo_attr.la_uid, obj->oo_attr.la_gid, 0, oh, true, NULL, false)); }