X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fosd-ldiskfs%2Fosd_quota.c;h=174fe371df3eb1768706d06f4ac8ec628b4d9f47;hb=f4b93dff9a8f4a59976ea864c4e3c2c42faa5770;hp=c53d6f8e4e5b497f9630e02c847d9902425c0801;hpb=0209add4a5099817111c8576afe930d1e2daef03;p=fs%2Flustre-release.git diff --git a/lustre/osd-ldiskfs/osd_quota.c b/lustre/osd-ldiskfs/osd_quota.c index c53d6f8..174fe37 100644 --- a/lustre/osd-ldiskfs/osd_quota.c +++ b/lustre/osd-ldiskfs/osd_quota.c @@ -21,7 +21,7 @@ * GPL HEADER END */ /* - * Copyright (c) 2012, 2013, Intel Corporation. + * Copyright (c) 2012, 2014, Intel Corporation. * Use is subject to license terms. * * Author: Johann Lombardi @@ -92,7 +92,6 @@ int osd_acct_obj_lookup(struct osd_thread_info *info, struct osd_device *osd, * \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 @@ -100,8 +99,7 @@ int osd_acct_obj_lookup(struct osd_thread_info *info, struct osd_device *osd, 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) + const struct dt_key *dtkey) { struct osd_thread_info *info = osd_oti_get(env); #ifdef HAVE_DQUOT_FS_DISK_QUOTA @@ -148,13 +146,11 @@ static int osd_acct_index_lookup(const struct lu_env *env, * * \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) + __u32 attr) { - struct osd_thread_info *info = osd_oti_get(env); struct osd_it_quota *it; struct lu_object *lo = &dt->do_lu; struct osd_object *obj = osd_dt_obj(dt); @@ -163,14 +159,13 @@ static struct dt_it *osd_it_acct_init(const struct lu_env *env, LASSERT(lu_object_exists(lo)); - if (info == NULL) + OBD_ALLOC_PTR(it); + if (it == NULL) RETURN(ERR_PTR(-ENOMEM)); - it = &info->oti_it_quota; - memset(it, 0, sizeof(*it)); lu_object_get(lo); it->oiq_obj = obj; - CFS_INIT_LIST_HEAD(&it->oiq_list); + INIT_LIST_HEAD(&it->oiq_list); /* LUSTRE_DQTREEOFF is the initial offset where the tree can be found */ it->oiq_blk[0] = LUSTRE_DQTREEOFF; @@ -194,10 +189,13 @@ static void osd_it_acct_fini(const struct lu_env *env, struct dt_it *di) lu_object_put(env, &it->oiq_obj->oo_dt.do_lu); - cfs_list_for_each_entry_safe(leaf, tmp, &it->oiq_list, oql_link) { - cfs_list_del_init(&leaf->oql_link); + list_for_each_entry_safe(leaf, tmp, &it->oiq_list, oql_link) { + list_del_init(&leaf->oql_link); OBD_FREE_PTR(leaf); } + + OBD_FREE_PTR(it); + EXIT; } @@ -262,9 +260,9 @@ static int osd_it_add_processed(struct osd_it_quota *it, int depth) OBD_ALLOC_PTR(leaf); if (leaf == NULL) RETURN(-ENOMEM); - CFS_INIT_LIST_HEAD(&leaf->oql_link); + INIT_LIST_HEAD(&leaf->oql_link); leaf->oql_blk = it->oiq_blk[depth]; - cfs_list_add_tail(&leaf->oql_link, &it->oiq_list); + list_add_tail(&leaf->oql_link, &it->oiq_list); RETURN(0); } @@ -379,8 +377,7 @@ static int osd_it_acct_rec(const struct lu_env *env, ENTRY; - rc = osd_acct_index_lookup(env, &it->oiq_obj->oo_dt, dtrec, key, - BYPASS_CAPA); + rc = osd_acct_index_lookup(env, &it->oiq_obj->oo_dt, dtrec, key); RETURN(rc > 0 ? 0 : rc); } @@ -493,23 +490,25 @@ static inline void osd_qid_set_type(struct osd_thandle *oh, int i, int type) * Reserve journal credits for quota files update first, then call * ->op_begin() to perform quota enforcement. * - * \param env - the environment passed by the caller - * \param oh - osd transaction handle - * \param qi - quota id & space required for this operation - * \param allocated - dquot entry in quota accounting file has been allocated - * \param flags - if the operation is write, return no user quota, no - * group quota, or sync commit flags to the caller + * \param env - the environment passed by the caller + * \param oh - osd transaction handle + * \param qi - quota id & space required for this operation + * \param obj - osd object, could be NULL when it's under create + * \param enforce - whether to perform quota enforcement + * \param flags - if the operation is write, return no user quota, no + * group quota, or sync commit flags to the caller * - * \retval 0 - success - * \retval -ve - failure + * \retval 0 - success + * \retval -ve - failure */ int osd_declare_qid(const struct lu_env *env, struct osd_thandle *oh, - struct lquota_id_info *qi, bool allocated, int *flags) + struct lquota_id_info *qi, struct osd_object *obj, + bool enforce, int *flags) { - struct osd_thread_info *info = osd_oti_get(env); - struct osd_device *dev = info->oti_dev; + struct osd_device *dev = osd_dt_dev(oh->ot_super.th_dev); struct qsd_instance *qsd = dev->od_quota_slave; - int i, rc; + struct inode *inode = NULL; + int i, rc = 0, crd; bool found = false; ENTRY; @@ -532,9 +531,28 @@ int osd_declare_qid(const struct lu_env *env, struct osd_thandle *oh, RETURN(-EOVERFLOW); } - osd_trans_declare_op(env, oh, OSD_OT_QUOTA, - (allocated || qi->lqi_id.qid_uid == 0) ? - 1: LDISKFS_QUOTA_INIT_BLOCKS(osd_sb(dev))); + if (obj != NULL) + inode = obj->oo_inode; + + /* root ID entry should be always present in the quota file */ + if (qi->lqi_id.qid_uid == 0) { + crd = 1; + } else { + /* used space for this ID could be dropped to zero, + * reserve extra credits for removing ID entry from + * the quota file */ + if (qi->lqi_space < 0) + crd = LDISKFS_QUOTA_DEL_BLOCKS(osd_sb(dev)); + /* reserve credits for adding ID entry to the quota + * file if the i_dquot isn't initialized yet. */ + else if (inode == NULL || + inode->i_dquot[qi->lqi_type] == NULL) + crd = LDISKFS_QUOTA_INIT_BLOCKS(osd_sb(dev)); + else + crd = 1; + } + + osd_trans_declare_op(env, oh, OSD_OT_QUOTA, crd); oh->ot_id_array[i] = qi->lqi_id.qid_uid; osd_qid_set_type(oh, i, qi->lqi_type); @@ -546,7 +564,8 @@ int osd_declare_qid(const struct lu_env *env, struct osd_thandle *oh, RETURN(0); /* check quota */ - rc = qsd_op_begin(env, qsd, oh->ot_quota_trans, qi, flags); + if (enforce) + rc = qsd_op_begin(env, qsd, oh->ot_quota_trans, qi, flags); RETURN(rc); } @@ -558,8 +577,8 @@ int osd_declare_qid(const struct lu_env *env, struct osd_thandle *oh, * \param gid - group id of the inode * \param space - how many blocks/inodes will be consumed/released * \param oh - osd transaction handle + * \param obj - osd object, could be NULL when it's under create * \param is_blk - block quota or inode quota? - * \param allocated - dquot entry in quota accounting file has been allocated * \param flags - if the operation is write, return no user quota, no * group quota, or sync commit flags to the caller * \param force - set to 1 when changes are performed by root user and thus @@ -570,7 +589,8 @@ int osd_declare_qid(const struct lu_env *env, struct osd_thandle *oh, */ int osd_declare_inode_qid(const struct lu_env *env, qid_t uid, qid_t gid, long long space, struct osd_thandle *oh, - bool is_blk, bool allocated, int *flags, bool force) + struct osd_object *obj, bool is_blk, int *flags, + bool force) { struct osd_thread_info *info = osd_oti_get(env); struct lquota_id_info *qi = &info->oti_qi; @@ -582,7 +602,7 @@ int osd_declare_inode_qid(const struct lu_env *env, qid_t uid, qid_t gid, qi->lqi_type = USRQUOTA; qi->lqi_space = space; qi->lqi_is_blk = is_blk; - rcu = osd_declare_qid(env, oh, qi, allocated, flags); + rcu = osd_declare_qid(env, oh, qi, obj, true, flags); if (force && (rcu == -EDQUOT || rcu == -EINPROGRESS)) /* ignore EDQUOT & EINPROGRESS when changes are done by root */ @@ -598,7 +618,7 @@ int osd_declare_inode_qid(const struct lu_env *env, qid_t uid, qid_t gid, /* and now group quota */ qi->lqi_id.qid_gid = gid; qi->lqi_type = GRPQUOTA; - rcg = osd_declare_qid(env, oh, qi, allocated, flags); + rcg = osd_declare_qid(env, oh, qi, obj, true, flags); if (force && (rcg == -EDQUOT || rcg == -EINPROGRESS)) /* as before, ignore EDQUOT & EINPROGRESS for root */ @@ -607,11 +627,10 @@ int osd_declare_inode_qid(const struct lu_env *env, qid_t uid, qid_t gid, RETURN(rcu ? rcu : rcg); } +#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 7, 53, 0) /* Following code is used to migrate old admin quota files (in Linux quota * file v2 format) into the new quota global indexes (in IAM format). */ -#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2,7,50,0) - /* copied from osd_it_acct_get(), only changed the 'type' to -1 */ static int osd_it_admin_get(const struct lu_env *env, struct dt_it *di, const struct dt_key *key) @@ -728,7 +747,7 @@ static int osd_it_admin_next(const struct lu_env *env, struct dt_it *di) RETURN(rc); } -const struct dt_index_operations osd_admin_index_ops = { +static const struct dt_index_operations osd_admin_index_ops = { .dio_lookup = osd_acct_index_lookup, .dio_it = { .init = osd_it_acct_init, @@ -801,7 +820,7 @@ static int convert_quota_file(const struct lu_env *env, /* iterate the old admin file, insert each record into the * new index file. */ - it = iops->init(env, old, 0, BYPASS_CAPA); + it = iops->init(env, old, 0); if (IS_ERR(it)) GOTO(out, rc = PTR_ERR(it)); @@ -866,6 +885,7 @@ static int truncate_quota_index(const struct lu_env *env, struct dt_object *dt, struct inode *inode; int rc; struct iam_container *bag = &(osd_dt_obj(dt))->oo_dir->od_container; + struct lu_buf *lb = &osd_oti_get(env)->oti_buf; ENTRY; LASSERT(bag->ic_root_bh != NULL); @@ -897,7 +917,9 @@ static int truncate_quota_index(const struct lu_env *env, struct dt_object *dt, inode = osd_dt_obj(dt)->oo_inode; LASSERT(inode); - rc = dt_declare_record_write(env, dt, NULL, 0, th); + /* iam_lfix_create() writes two blocks at the beginning */ + lb->lb_len = osd_sb(osd)->s_blocksize * 2; + rc = dt_declare_record_write(env, dt, lb, 0, th); if (rc) GOTO(out, rc); @@ -906,11 +928,11 @@ static int truncate_quota_index(const struct lu_env *env, struct dt_object *dt, GOTO(out, rc); dt_write_lock(env, dt, 0); - rc = dt_punch(env, dt, 0, OBD_OBJECT_EOF, th, BYPASS_CAPA); + rc = dt_punch(env, dt, 0, OBD_OBJECT_EOF, th); if (rc) GOTO(out_lock, rc); - rc = dt_attr_set(env, dt, attr, th, BYPASS_CAPA); + rc = dt_attr_set(env, dt, attr, th); if (rc) GOTO(out_lock, rc); @@ -1114,6 +1136,4 @@ out: RETURN(rc); } -#else -#warning "remove old quota compatibility code" -#endif +#endif /* LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 7, 53, 0) */