/** * Helper function to retrieve DMU object id from fid for accounting object */ uint64_t osd_quota_fid2dmu(const struct lu_fid *fid) { LASSERT(fid_is_acct(fid)); if (fid_oid(fid) == ACCT_GROUP_OID) return DMU_GROUPUSED_OBJECT; return DMU_USERUSED_OBJECT; }
int osd_oi_lookup(struct osd_thread_info *info, struct osd_device *osd, const struct lu_fid *fid, struct osd_inode_id *id, enum oi_check_flags flags) { if (unlikely(fid_is_last_id(fid))) return osd_obj_spec_lookup(info, osd, fid, id); if (fid_is_on_ost(info, osd, fid, flags) || fid_is_llog(fid)) return osd_obj_map_lookup(info, osd, fid, id); if (unlikely(fid_seq(fid) == FID_SEQ_LOCAL_FILE)) { int rc; if (fid_is_fs_root(fid)) { osd_id_gen(id, osd_sb(osd)->s_root->d_inode->i_ino, osd_sb(osd)->s_root->d_inode->i_generation); return 0; } if (unlikely(fid_is_acct(fid))) return osd_acct_obj_lookup(info, osd, fid, id); /* For other special FIDs, try OI first, then do spec lookup */ rc = __osd_oi_lookup(info, osd, fid, id); if (rc == -ENOENT) return osd_obj_spec_lookup(info, osd, fid, id); return rc; } if (!osd->od_igif_inoi && fid_is_igif(fid)) { osd_id_gen(id, lu_igif_ino(fid), lu_igif_gen(fid)); return 0; } return __osd_oi_lookup(info, osd, fid, id); }
int osd_oi_lookup(struct osd_thread_info *info, struct osd_device *osd, const struct lu_fid *fid, struct osd_inode_id *id, enum oi_check_flags flags) { if (unlikely(fid_is_last_id(fid))) return osd_obj_spec_lookup(info, osd, fid, id); if (fid_is_on_ost(info, osd, fid, flags) || fid_is_llog(fid)) return osd_obj_map_lookup(info, osd, fid, id); if (fid_is_fs_root(fid)) { osd_id_gen(id, osd_sb(osd)->s_root->d_inode->i_ino, osd_sb(osd)->s_root->d_inode->i_generation); return 0; } if (unlikely(fid_is_acct(fid))) return osd_acct_obj_lookup(info, osd, fid, id); if (!osd->od_igif_inoi && fid_is_igif(fid)) { osd_id_gen(id, lu_igif_ino(fid), lu_igif_gen(fid)); return 0; } return __osd_oi_lookup(info, osd, fid, id); }
/* * Concurrency: shouldn't matter. */ int osd_object_init0(const struct lu_env *env, struct osd_object *obj) { struct osd_device *osd = osd_obj2dev(obj); const struct lu_fid *fid = lu_object_fid(&obj->oo_dt.do_lu); int rc = 0; ENTRY; if (obj->oo_db == NULL) RETURN(0); /* object exist */ rc = osd_object_sa_init(obj, osd); if (rc) RETURN(rc); /* cache attrs in object */ rc = __osd_object_attr_get(env, osd, obj, &obj->oo_attr); if (rc) RETURN(rc); if (likely(!fid_is_acct(fid))) /* no body operations for accounting objects */ obj->oo_dt.do_body_ops = &osd_body_ops; /* * initialize object before marking it existing */ obj->oo_dt.do_lu.lo_header->loh_attr |= obj->oo_attr.la_mode & S_IFMT; smp_mb(); obj->oo_dt.do_lu.lo_header->loh_attr |= LOHA_EXISTS; RETURN(0); }
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_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); }
/* * Concurrency: @dt is write locked. */ static int osd_object_create(const struct lu_env *env, struct dt_object *dt, struct lu_attr *attr, struct dt_allocation_hint *hint, struct dt_object_format *dof, struct thandle *th) { struct osd_thread_info *info = osd_oti_get(env); struct lustre_mdt_attrs *lma = &info->oti_mdt_attrs; struct zpl_direntry *zde = &info->oti_zde.lzd_reg; 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); char *buf = info->oti_str; struct osd_thandle *oh; dmu_buf_t *db = NULL; uint64_t zapid, parent = 0; int rc; ENTRY; /* concurrent create declarations should not see * the object inconsistent (db, attr, etc). * in regular cases acquisition should be cheap */ down_write(&obj->oo_guard); if (unlikely(dt_object_exists(dt))) GOTO(out, rc = -EEXIST); LASSERT(osd_invariant(obj)); LASSERT(dof != NULL); LASSERT(th != NULL); oh = container_of0(th, struct osd_thandle, ot_super); /* * XXX missing: Quote handling. */ LASSERT(obj->oo_db == NULL); /* to follow ZFS on-disk format we need * to initialize parent dnode properly */ if (hint != NULL && hint->dah_parent != NULL && !dt_object_remote(hint->dah_parent)) parent = osd_dt_obj(hint->dah_parent)->oo_db->db_object; /* we may fix some attributes, better do not change the source */ obj->oo_attr = *attr; obj->oo_attr.la_valid |= LA_SIZE | LA_NLINK | LA_TYPE; db = osd_create_type_f(dof->dof_type)(env, obj, &obj->oo_attr, oh); if (IS_ERR(db)) { rc = PTR_ERR(db); db = NULL; GOTO(out, rc); } zde->zde_pad = 0; zde->zde_dnode = db->db_object; zde->zde_type = IFTODT(attr->la_mode & S_IFMT); zapid = osd_get_name_n_idx(env, osd, fid, buf, sizeof(info->oti_str)); rc = -zap_add(osd->od_os, zapid, buf, 8, 1, zde, oh->ot_tx); if (rc) GOTO(out, rc); /* Now add in all of the "SA" attributes */ rc = -sa_handle_get(osd->od_os, db->db_object, NULL, SA_HDL_PRIVATE, &obj->oo_sa_hdl); if (rc) GOTO(out, rc); /* configure new osd object */ obj->oo_db = db; parent = parent != 0 ? parent : zapid; rc = __osd_attr_init(env, osd, obj->oo_sa_hdl, oh->ot_tx, &obj->oo_attr, parent); if (rc) GOTO(out, rc); /* XXX: oo_lma_flags */ obj->oo_dt.do_lu.lo_header->loh_attr |= obj->oo_attr.la_mode & S_IFMT; smp_mb(); obj->oo_dt.do_lu.lo_header->loh_attr |= LOHA_EXISTS; if (likely(!fid_is_acct(lu_object_fid(&obj->oo_dt.do_lu)))) /* no body operations for accounting objects */ obj->oo_dt.do_body_ops = &osd_body_ops; rc = -nvlist_alloc(&obj->oo_sa_xattr, NV_UNIQUE_NAME, KM_SLEEP); if (rc) GOTO(out, rc); /* initialize LMA */ lustre_lma_init(lma, lu_object_fid(&obj->oo_dt.do_lu), 0, 0); lustre_lma_swab(lma); rc = -nvlist_add_byte_array(obj->oo_sa_xattr, XATTR_NAME_LMA, (uchar_t *)lma, sizeof(*lma)); if (rc) GOTO(out, rc); rc = __osd_sa_xattr_update(env, obj, oh); if (rc) GOTO(out, rc); /* Add new object to inode accounting. * Errors are not considered as fatal */ rc = -zap_increment_int(osd->od_os, osd->od_iusr_oid, (attr->la_valid & LA_UID) ? attr->la_uid : 0, 1, oh->ot_tx); if (rc) CERROR("%s: failed to add "DFID" to accounting ZAP for usr %d " "(%d)\n", osd->od_svname, PFID(fid), attr->la_uid, rc); rc = -zap_increment_int(osd->od_os, osd->od_igrp_oid, (attr->la_valid & LA_GID) ? attr->la_gid : 0, 1, oh->ot_tx); if (rc) CERROR("%s: failed to add "DFID" to accounting ZAP for grp %d " "(%d)\n", osd->od_svname, PFID(fid), attr->la_gid, rc); out: if (unlikely(rc && db)) { dmu_object_free(osd->od_os, db->db_object, oh->ot_tx); sa_buf_rele(db, osd_obj_tag); obj->oo_db = NULL; } up_write(&obj->oo_guard); RETURN(rc); }