X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fosd-zfs%2Fosd_quota.c;h=45b68ff556443e6b5593d8ca505948053952c61e;hb=refs%2Fchanges%2F93%2F27093%2F40;hp=b3d45af56713ed0521f469c2d16efd2cf6765bc6;hpb=9fdbfed4ce20aaf7ac0e6b5001f323428d9d3893;p=fs%2Flustre-release.git diff --git a/lustre/osd-zfs/osd_quota.c b/lustre/osd-zfs/osd_quota.c index b3d45af..45b68ff 100644 --- a/lustre/osd-zfs/osd_quota.c +++ b/lustre/osd-zfs/osd_quota.c @@ -33,7 +33,7 @@ /** * Helper function to estimate the number of inodes in use for the given - * uid/gid from the block usage + * uid/gid/projid from the block usage */ static uint64_t osd_objset_user_iused(struct osd_device *osd, uint64_t uidbytes) { @@ -60,7 +60,7 @@ static uint64_t osd_objset_user_iused(struct osd_device *osd, uint64_t uidbytes) */ /** - * Return space usage consumed by a given uid or gid. + * Return space usage consumed by a given uid or gid or projid. * 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. @@ -91,7 +91,7 @@ static int osd_acct_index_lookup(const struct lu_env *env, rec->bspace = rec->ispace = 0; - /* convert the 64-bit uid/gid into a string */ + /* convert the 64-bit uid/gid/projid into a string */ snprintf(buf, buflen, "%llx", *((__u64 *)dtkey)); if (unlikely(!dn)) { CDEBUG(D_QUOTA, "%s: miss accounting obj for %s\n", @@ -106,7 +106,7 @@ static int osd_acct_index_lookup(const struct lu_env *env, rc = osd_zap_lookup(osd, dn->dn_object, dn, buf, sizeof(uint64_t), 1, &rec->bspace); if (rc == -ENOENT) { - /* user/group has not created anything yet */ + /* user/group/project has not created anything yet */ CDEBUG(D_QUOTA, "%s: id %s not found in DMU accounting ZAP\n", osd->od_svname, buf); /* -ENOENT is normal case, convert it as 1. */ @@ -207,6 +207,29 @@ static void osd_it_acct_fini(const struct lu_env *env, struct dt_it *di) } /** + * Locate the first entry that is for space accounting. + */ +static int osd_zap_locate(struct osd_it_quota *it, zap_attribute_t *za) +{ + int rc; + ENTRY; + + while (1) { + rc = -zap_cursor_retrieve(it->oiq_zc, za); + if (rc) + break; + + if (strncmp(za->za_name, OSD_DMU_USEROBJ_PREFIX, + OSD_DMU_USEROBJ_PREFIX_LEN)) + break; + + zap_cursor_advance(it->oiq_zc); + } + + RETURN(rc); +} + +/** * Move on to the next valid entry. * * \param di - osd iterator @@ -225,10 +248,9 @@ static int osd_it_acct_next(const struct lu_env *env, struct dt_it *di) 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); + + rc = osd_zap_locate(it, za); + RETURN(rc == -ENOENT ? 1 : rc); } /** @@ -245,10 +267,13 @@ static struct dt_key *osd_it_acct_key(const struct lu_env *env, ENTRY; it->oiq_reset = 0; - rc = -zap_cursor_retrieve(it->oiq_zc, za); + rc = osd_zap_locate(it, za); if (rc) RETURN(ERR_PTR(rc)); + rc = kstrtoull(za->za_name, 16, &it->oiq_id); + if (rc) + CERROR("couldn't parse name %s\n", za->za_name); RETURN((struct dt_key *) &it->oiq_id); } @@ -347,15 +372,18 @@ static int osd_it_acct_rec(const struct lu_env *env, if (unlikely(rc != 0)) RETURN(rc); - /* inode accounting is not maintained by DMU, so we use our own ZAP to - * track inode usage */ + /* inode accounting is maintained by DMU since 0.7.0 */ + strncpy(info->oti_buf, OSD_DMU_USEROBJ_PREFIX, + OSD_DMU_USEROBJ_PREFIX_LEN); + strlcpy(info->oti_buf + OSD_DMU_USEROBJ_PREFIX_LEN, za->za_name, + sizeof(info->oti_buf) - OSD_DMU_USEROBJ_PREFIX_LEN); rc = osd_zap_lookup(osd, it->oiq_obj->oo_dn->dn_object, - it->oiq_obj->oo_dn, za->za_name, sizeof(uint64_t), + it->oiq_obj->oo_dn, info->oti_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, za->za_name); + osd->od_svname, info->oti_buf); else if (rc) RETURN(rc); @@ -405,12 +433,11 @@ static int osd_it_acct_load(const struct lu_env *env, it->oiq_zc = zc; it->oiq_reset = 0; - rc = -zap_cursor_retrieve(it->oiq_zc, za); + rc = osd_zap_locate(it, za); if (rc == 0) rc = 1; else if (rc == -ENOENT) rc = 0; - RETURN(rc); } @@ -419,7 +446,7 @@ static int osd_it_acct_load(const struct lu_env *env, * move to the first valid record. * * \param di - osd iterator - * \param key - uid or gid + * \param key - uid or gid or projid * * \retval +ve - di points to exact matched key * \retval 0 - di points to the first valid record @@ -475,26 +502,27 @@ const struct dt_index_operations osd_acct_index_ops = { * \param osd - is the osd_device * \param uid - user id of the inode * \param gid - group id of the inode + * \param projid - project id of the inode * \param space - how many blocks/inodes will be consumed/released * \param oh - osd transaction handle - * \param is_blk - block quota or inode quota? * \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 - * can't failed with EDQUOT + * \param osd_qid_declare_flags - indicate this is a inode/block accounting + * and whether changes are performed by root user * * \retval 0 - success * \retval -ve - failure */ int osd_declare_quota(const struct lu_env *env, struct osd_device *osd, - qid_t uid, qid_t gid, long long space, - struct osd_thandle *oh, bool is_blk, int *flags, - bool force) + qid_t uid, qid_t gid, qid_t projid, long long space, + struct osd_thandle *oh, int *flags, + enum osd_qid_declare_flags osd_qid_declare_flags) { - struct osd_thread_info *info = osd_oti_get(env); - struct lquota_id_info *qi = &info->oti_qi; - struct qsd_instance *qsd = osd->od_quota_slave; - int rcu, rcg; /* user & group rc */ + struct osd_thread_info *info = osd_oti_get(env); + struct lquota_id_info *qi = &info->oti_qi; + struct qsd_instance *qsd = osd->od_quota_slave; + int rcu, rcg, rcp = 0; /* user & group & project rc */ + bool force = !!(osd_qid_declare_flags & OSD_QID_FORCE); ENTRY; if (unlikely(qsd == NULL)) @@ -505,9 +533,8 @@ int osd_declare_quota(const struct lu_env *env, struct osd_device *osd, qi->lqi_id.qid_uid = uid; qi->lqi_type = USRQUOTA; qi->lqi_space = space; - qi->lqi_is_blk = is_blk; + qi->lqi_is_blk = !!(osd_qid_declare_flags & OSD_QID_BLK); rcu = qsd_op_begin(env, qsd, &oh->ot_quota_trans, qi, flags); - if (force && (rcu == -EDQUOT || rcu == -EINPROGRESS)) /* ignore EDQUOT & EINPROGRESS when changes are done by root */ rcu = 0; @@ -523,10 +550,23 @@ int osd_declare_quota(const struct lu_env *env, struct osd_device *osd, qi->lqi_id.qid_gid = gid; qi->lqi_type = GRPQUOTA; rcg = qsd_op_begin(env, qsd, &oh->ot_quota_trans, qi, flags); - if (force && (rcg == -EDQUOT || rcg == -EINPROGRESS)) /* as before, ignore EDQUOT & EINPROGRESS for root */ rcg = 0; - RETURN(rcu ? rcu : rcg); +#ifdef ZFS_PROJINHERIT + if (rcg && (rcg != -EDQUOT || flags == NULL)) + RETURN(rcg); + + /* for project quota */ + if (osd->od_projectused_dn) { + qi->lqi_id.qid_projid = projid; + qi->lqi_type = PRJQUOTA; + rcp = qsd_op_begin(env, qsd, &oh->ot_quota_trans, qi, flags); + if (force && (rcp == -EDQUOT || rcp == -EINPROGRESS)) + rcp = 0; + } +#endif + + RETURN(rcu ? rcu : (rcg ? rcg : rcp)); }