X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fquota%2Flquota_disk.c;h=bc7183364634ab57d4d7b27591ade372a9df5a1e;hb=210803a2475862464045b609eee43237d74e853b;hp=777b2ab68afac26411a70db2d9268b84c5875569;hpb=294aa9cb666c48e02da1057c222fe5f206ce38fc;p=fs%2Flustre-release.git diff --git a/lustre/quota/lquota_disk.c b/lustre/quota/lquota_disk.c index 777b2ab..bc71833 100644 --- a/lustre/quota/lquota_disk.c +++ b/lustre/quota/lquota_disk.c @@ -21,7 +21,7 @@ * GPL HEADER END */ /* - * Copyright (c) 2012 Intel, Inc. + * Copyright (c) 2012, 2017, Intel Corporation. * Use is subject to license terms. * * Author: Johann Lombardi @@ -41,19 +41,16 @@ * required and create the index file on disk if * it does not exist. * - lquota_disk_for_each_slv: iterate over all existing slave index files - * - lquota_disk_read: read quota settings from a index file + * - lquota_disk_read: read quota settings from an index file * - lquota_disk_declare_write: reserve credits to update a record in an index * file * - lquota_disk_write: update a record in an index file * - lquota_disk_update_ver: update version of an index file */ -#ifndef EXPORT_SYMTAB -# define EXPORT_SYMTAB -#endif - #define DEBUG_SUBSYSTEM S_LQUOTA +#include #include "lquota_internal.h" #define LQUOTA_MODE (S_IFREG | S_IRUGO | S_IWUSR) @@ -68,10 +65,10 @@ lquota_disk_find_create(const struct lu_env *env, struct dt_device *dev, const struct dt_index_features *idx_feat, char *name) { - struct lquota_thread_info *qti = lquota_info(env); - struct dt_object *obj; - struct local_oid_storage *los; - int rc; + struct lquota_thread_info *qti = lquota_info(env); + struct dt_object *obj; + struct local_oid_storage *los; + int rc; ENTRY; /* Set up local storage */ @@ -88,7 +85,7 @@ lquota_disk_find_create(const struct lu_env *env, struct dt_device *dev, /* local_oid_storage_fini() will finalize the local storage device, * we have to open the object in another device stack */ qti->qti_fid = obj->do_lu.lo_header->loh_fid; - lu_object_put_nocache(env, &obj->do_lu); + dt_object_put_nocache(env, obj); obj = dt_locate(env, dev, &qti->qti_fid); if (IS_ERR(obj)) GOTO(out, obj); @@ -100,7 +97,7 @@ out: /* * helper function to generate the filename associated with a slave index file */ -static inline int lquota_disk_slv_filename(struct lu_fid *glb_fid, +static inline int lquota_disk_slv_filename(const struct lu_fid *glb_fid, struct obd_uuid *uuid, char *filename) { @@ -132,7 +129,7 @@ static inline int lquota_disk_slv_filename(struct lu_fid *glb_fid, name++; /* the filename is composed of the most signicant bits of the global - * FID, that's to say the oid which encodes the pool id, pool type and + * FID, that's to say the oid which encodes the pool type and * quota type, followed by the export UUID */ sprintf(filename, "0x%x-%s", glb_fid->f_oid, name); @@ -184,7 +181,7 @@ struct dt_object *lquota_disk_dir_find_create(const struct lu_env *env, GOTO(out, rc); parent = dt_locate_at(env, dev, &qti->qti_fid, - dev->dd_lu_dev.ld_site->ls_top_dev); + dev->dd_lu_dev.ld_site->ls_top_dev, NULL); if (IS_ERR(parent)) GOTO(out, rc = PTR_ERR(parent)); } else { @@ -200,7 +197,7 @@ struct dt_object *lquota_disk_dir_find_create(const struct lu_env *env, /* local_oid_storage_fini() will finalize the local storage device, * we have to open the object in another device stack */ qti->qti_fid = qt_dir->do_lu.lo_header->loh_fid; - lu_object_put_nocache(env, &qt_dir->do_lu); + dt_object_put_nocache(env, qt_dir); qt_dir = dt_locate(env, dev, &qti->qti_fid); if (IS_ERR(qt_dir)) GOTO(out, rc = PTR_ERR(qt_dir)); @@ -210,12 +207,12 @@ struct dt_object *lquota_disk_dir_find_create(const struct lu_env *env, EXIT; out: if (parent != NULL && !IS_ERR(parent)) - lu_object_put(env, &parent->do_lu); + dt_object_put(env, parent); if (los != NULL) local_oid_storage_fini(env, los); if (rc) { if (qt_dir != NULL && !IS_ERR(qt_dir)) - lu_object_put(env, &qt_dir->do_lu); + dt_object_put(env, qt_dir); qt_dir = ERR_PTR(rc); } return qt_dir; @@ -248,20 +245,10 @@ struct dt_object *lquota_disk_glb_find_create(const struct lu_env *env, CDEBUG(D_QUOTA, "look-up/create %sglobal idx file ("DFID")\n", local ? "local " : "", PFID(fid)); -#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2,7,50,0) - /* we use different index feature for each quota type and target type - * for the time being. This is done for on-disk conversion from the old - * quota format. Once this is no longer required, we should just be - * using dt_quota_glb_features for all global index file */ - idx_feat = glb_idx_feature(fid); -#else -#warning "remove old quota compatibility code" idx_feat = &dt_quota_glb_features; -#endif /* the filename is composed of the most signicant bits of the FID, - * that's to say the oid which encodes the pool id, pool type and quota - * type */ + * that's to say the oid which encodes the pool type and quota type */ sprintf(qti->qti_buf, "0x%x", fid->f_oid); if (local) { @@ -295,7 +282,7 @@ struct dt_object *lquota_disk_glb_find_create(const struct lu_env *env, CERROR("%s: failed to setup index operations for "DFID " rc:%d\n", dev->dd_lu_dev.ld_obd->obd_name, PFID(lu_object_fid(&glb_idx->do_lu)), rc); - lu_object_put(env, &glb_idx->do_lu); + dt_object_put(env, glb_idx); glb_idx = ERR_PTR(rc); } } @@ -320,7 +307,7 @@ struct dt_object *lquota_disk_glb_find_create(const struct lu_env *env, struct dt_object *lquota_disk_slv_find(const struct lu_env *env, struct dt_device *dev, struct dt_object *parent, - struct lu_fid *glb_fid, + const struct lu_fid *glb_fid, struct obd_uuid *uuid) { struct lquota_thread_info *qti = lquota_info(env); @@ -355,7 +342,7 @@ struct dt_object *lquota_disk_slv_find(const struct lu_env *env, CERROR("%s: failed to setup slave index operations for " "%s, rc:%d\n", dev->dd_lu_dev.ld_obd->obd_name, obd_uuid2str(uuid), rc); - lu_object_put(env, &slv_idx->do_lu); + dt_object_put(env, slv_idx); slv_idx = ERR_PTR(rc); } } @@ -394,7 +381,7 @@ struct dt_object *lquota_disk_slv_find_create(const struct lu_env *env, { struct lquota_thread_info *qti = lquota_info(env); struct dt_object *slv_idx; - int rc; + int rc, type; ENTRY; LASSERT(uuid != NULL); @@ -407,20 +394,29 @@ struct dt_object *lquota_disk_slv_find_create(const struct lu_env *env, if (rc) RETURN(ERR_PTR(rc)); + if (lu_device_is_md(dev->dd_lu_dev.ld_site->ls_top_dev)) + type = LDD_F_SV_TYPE_MDT; + else + type = LDD_F_SV_TYPE_OST; + /* Slave indexes uses the FID_SEQ_QUOTA sequence since they can be read * through the network */ qti->qti_fid.f_seq = FID_SEQ_QUOTA; qti->qti_fid.f_ver = 0; if (local) { - int type; + int pool_type, qtype; - rc = lquota_extract_fid(glb_fid, NULL, NULL, &type); + rc = lquota_extract_fid(glb_fid, &pool_type, &qtype); if (rc) RETURN(ERR_PTR(rc)); /* use predefined fid in the reserved oid list */ - qti->qti_fid.f_oid = (type == USRQUOTA) ? LQUOTA_USR_OID - : LQUOTA_GRP_OID; + if ((type == LDD_F_SV_TYPE_MDT && pool_type == LQUOTA_RES_MD) || + (type == LDD_F_SV_TYPE_OST && pool_type == LQUOTA_RES_DT)) + qti->qti_fid.f_oid = qtype2slv_oid(qtype); + else + qti->qti_fid.f_oid = pool_type << 16 | + qtype2slv_oid(qtype); slv_idx = local_index_find_or_create_with_fid(env, dev, &qti->qti_fid, @@ -450,7 +446,7 @@ struct dt_object *lquota_disk_slv_find_create(const struct lu_env *env, CERROR("%s: failed to setup index operations for "DFID " rc:%d\n", dev->dd_lu_dev.ld_obd->obd_name, PFID(lu_object_fid(&slv_idx->do_lu)), rc); - lu_object_put(env, &slv_idx->do_lu); + dt_object_put(env, slv_idx); slv_idx = ERR_PTR(rc); } } @@ -482,7 +478,7 @@ int lquota_disk_for_each_slv(const struct lu_env *env, struct dt_object *parent, int rc; ENTRY; - OBD_ALLOC(name, sizeof("0x00000000-")); + OBD_ALLOC(name, LQUOTA_NAME_MAX); if (name == NULL) RETURN(-ENOMEM); @@ -491,9 +487,9 @@ int lquota_disk_for_each_slv(const struct lu_env *env, struct dt_object *parent, sprintf(name, "0x%x-", glb_fid->f_oid); iops = &parent->do_index_ops->dio_it; - it = iops->init(env, parent, 0, BYPASS_CAPA); + it = iops->init(env, parent, 0); if (IS_ERR(it)) { - OBD_FREE(name, sizeof("0x00000000-")); + OBD_FREE(name, LQUOTA_NAME_MAX); RETURN(PTR_ERR(it)); } @@ -545,7 +541,7 @@ int lquota_disk_for_each_slv(const struct lu_env *env, struct dt_object *parent, if (qti->qti_fid.f_seq != FID_SEQ_QUOTA) goto next; - rc = func(env, glb_fid, (char *)key, &qti->qti_fid, arg); + rc = func(env, glb_fid, qti->qti_buf, &qti->qti_fid, arg); if (rc) break; next: @@ -556,7 +552,7 @@ next: iops->put(env, it); iops->fini(env, it); - OBD_FREE(name, sizeof("0x00000000-")); + OBD_FREE(name, LQUOTA_NAME_MAX); if (rc > 0) rc = 0; RETURN(rc); @@ -583,8 +579,7 @@ int lquota_disk_read(const struct lu_env *env, struct dt_object *obj, /* lookup on-disk record from index file */ dt_read_lock(env, obj, 0); - rc = dt_lookup(env, obj, rec, (struct dt_key *)&id->qid_uid, - BYPASS_CAPA); + rc = dt_lookup(env, obj, rec, (struct dt_key *)&id->qid_uid); dt_read_unlock(env, obj); RETURN(rc); @@ -660,11 +655,10 @@ int lquota_disk_write(const struct lu_env *env, struct thandle *th, dt_write_lock(env, obj, 0); /* check whether there is already an existing record for this ID */ - rc = dt_lookup(env, obj, (struct dt_rec *)&qti->qti_rec, key, - BYPASS_CAPA); + rc = dt_lookup(env, obj, (struct dt_rec *)&qti->qti_rec, key); if (rc == 0) { /* delete existing record in order to replace it */ - rc = dt_delete(env, obj, key, th, BYPASS_CAPA); + rc = dt_delete(env, obj, key, th); if (rc) GOTO(out, rc); } else if (rc == -ENOENT) { @@ -676,13 +670,13 @@ int lquota_disk_write(const struct lu_env *env, struct thandle *th, if (rec != NULL) { /* insert record with updated quota settings */ - rc = dt_insert(env, obj, rec, key, th, BYPASS_CAPA, 1); + rc = dt_insert(env, obj, rec, key, th); if (rc) { /* try to insert the old one */ rc = dt_insert(env, obj, (struct dt_rec *)&qti->qti_rec, - key, th, BYPASS_CAPA, 1); + key, th); LASSERTF(rc == 0, "failed to insert record in quota " - "index "DFID, + "index "DFID"\n", PFID(lu_object_fid(&obj->do_lu))); GOTO(out, rc); } @@ -707,6 +701,36 @@ out: return rc; } +int lquota_disk_delete(const struct lu_env *env, struct thandle *th, + struct dt_object *obj, __u64 qid, __u64 *ver) +{ + struct lquota_thread_info *qti = lquota_info(env); + struct dt_key *key = (struct dt_key *)&qid; + int rc; + + ENTRY; + + LASSERT(dt_object_exists(obj)); + LASSERT(obj->do_index_ops != NULL); + + /* lock index */ + dt_write_lock(env, obj, 0); + + /* check whether there is already an existing record for this ID */ + rc = dt_lookup(env, obj, (struct dt_rec *)&qti->qti_rec, key); + if (rc == 0) { + rc = dt_delete(env, obj, key, th); + if (rc == 0 && ver != NULL) { + *ver = dt_version_get(env, obj); + (*ver)++; + dt_version_set(env, obj, *ver, th); + } + } + + dt_write_unlock(env, obj); + RETURN(rc); +} + /* * Update version of an index file * @@ -741,3 +765,67 @@ out: dt_trans_stop(env, dev, th); return rc; } + +/* + * Write a global record + * + * \param env - is the environment passed by the caller + * \param obj - is the on-disk global index to be updated + * \param id - index to be updated + * \param rec - record to be written + */ +int lquota_disk_write_glb(const struct lu_env *env, struct dt_object *obj, + __u64 id, struct lquota_glb_rec *rec) +{ + struct dt_device *dev = lu2dt_dev(obj->do_lu.lo_dev); + struct thandle *th; + struct dt_key *key = (struct dt_key *)&id; + int rc; + ENTRY; + + th = dt_trans_create(env, dev); + if (IS_ERR(th)) + RETURN(PTR_ERR(th)); + + /* the entry with 0 key can always be found in IAM file. */ + if (id == 0) { + rc = dt_declare_delete(env, obj, key, th); + if (rc) + GOTO(out, rc); + } + + rc = dt_declare_insert(env, obj, (struct dt_rec *)rec, key, th); + if (rc) + GOTO(out, rc); + + rc = dt_trans_start_local(env, dev, th); + if (rc) + GOTO(out, rc); + + dt_write_lock(env, obj, 0); + + if (id == 0) { + struct lquota_glb_rec *tmp; + + OBD_ALLOC_PTR(tmp); + if (tmp == NULL) + GOTO(out_lock, rc = -ENOMEM); + + rc = dt_lookup(env, obj, (struct dt_rec *)tmp, key); + + OBD_FREE_PTR(tmp); + if (rc == 0) { + rc = dt_delete(env, obj, key, th); + if (rc) + GOTO(out_lock, rc); + } + rc = 0; + } + + rc = dt_insert(env, obj, (struct dt_rec *)rec, key, th); +out_lock: + dt_write_unlock(env, obj); +out: + dt_trans_stop(env, dev, th); + RETURN(rc); +}