Whamcloud - gitweb
LU-13124 scrub: check for multiple linked file
[fs/lustre-release.git] / lustre / osd-ldiskfs / osd_quota.c
index 5c4ce09..b3dc66a 100644 (file)
@@ -47,7 +47,7 @@ static inline int fid2type(const struct lu_fid *fid)
                return PRJQUOTA;
        }
 
-       LASSERTF(0, "invalid fid for quota type: %u", fid_oid(fid));
+       LASSERTF(0, "invalid fid for quota type: %u\n", fid_oid(fid));
        return USRQUOTA;
 }
 
@@ -97,8 +97,12 @@ int osd_acct_obj_lookup(struct osd_thread_info *info, struct osd_device *osd,
                        RETURN(-ENOENT);
                break;
        }
-       if (!ldiskfs_valid_inum(sb, id->oii_ino))
+
+       if (!ldiskfs_valid_inum(sb, id->oii_ino) &&
+           id->oii_ino != LDISKFS_USR_QUOTA_INO &&
+           id->oii_ino != LDISKFS_GRP_QUOTA_INO)
                RETURN(-ENOENT);
+
        RETURN(0);
 }
 
@@ -122,41 +126,30 @@ static int osd_acct_index_lookup(const struct lu_env *env,
        struct osd_thread_info *info = osd_oti_get(env);
 #if defined(HAVE_DQUOT_QC_DQBLK)
        struct qc_dqblk *dqblk = &info->oti_qdq;
-#elif defined(HAVE_DQUOT_FS_DISK_QUOTA)
-       struct fs_disk_quota *dqblk = &info->oti_fdq;
 #else
-       struct if_dqblk *dqblk = &info->oti_dqblk;
+       struct fs_disk_quota *dqblk = &info->oti_fdq;
 #endif
        struct super_block *sb = osd_sb(osd_obj2dev(osd_dt_obj(dtobj)));
        struct lquota_acct_rec *rec = (struct lquota_acct_rec *)dtrec;
        __u64 id = *((__u64 *)dtkey);
        int rc;
-#ifdef HAVE_DQUOT_KQID
        struct kqid qid;
-#endif
        int type;
 
        ENTRY;
 
        type = fid2type(lu_object_fid(&dtobj->do_lu));
        memset(dqblk, 0, sizeof(*dqblk));
-#ifdef HAVE_DQUOT_KQID
        qid = make_kqid(&init_user_ns, type, id);
        rc = sb->s_qcop->get_dqblk(sb, qid, dqblk);
-#else
-       rc = sb->s_qcop->get_dqblk(sb, type, (qid_t) id, dqblk);
-#endif
        if (rc)
                RETURN(rc);
 #if defined(HAVE_DQUOT_QC_DQBLK)
        rec->bspace = dqblk->d_space;
        rec->ispace = dqblk->d_ino_count;
-#elif defined(HAVE_DQUOT_FS_DISK_QUOTA)
+#else
        rec->bspace = dqblk->d_bcount;
        rec->ispace = dqblk->d_icount;
-#else
-       rec->bspace = dqblk->dqb_curspace;
-       rec->ispace = dqblk->dqb_curinodes;
 #endif
        RETURN(+1);
 }
@@ -518,8 +511,6 @@ void osd_quota_unpack(struct osd_object *obj, const struct dt_rec *rec)
        descr = obj->oo_dir->od_container.ic_descr;
 
        osd_quota_swab((char *)rec, descr->id_rec_size);
-#else
-       return;
 #endif
 }
 
@@ -545,12 +536,13 @@ static inline int osd_qid_type(struct osd_thandle *oh, int i)
  */
 int osd_declare_qid(const struct lu_env *env, struct osd_thandle *oh,
                    struct lquota_id_info *qi, struct osd_object *obj,
-                   bool enforce, int *flags)
+                   bool enforce, enum osd_quota_local_flags *local_flags)
 {
        struct osd_device *dev;
        struct qsd_instance *qsd;
        struct inode *inode = NULL;
        int i, rc = 0, crd;
+       __u8 res = qi->lqi_is_blk ? LQUOTA_RES_DT : LQUOTA_RES_MD;
        bool found = false;
 
        ENTRY;
@@ -562,10 +554,14 @@ int osd_declare_qid(const struct lu_env *env, struct osd_thandle *oh,
        dev = osd_dt_dev(oh->ot_super.th_dev);
        LASSERT(dev != NULL);
 
-       qsd = dev->od_quota_slave;
+       if (res == LQUOTA_RES_DT)
+               qsd = dev->od_quota_slave_dt;
+       else
+               qsd = dev->od_quota_slave_md;
 
        for (i = 0; i < oh->ot_id_cnt; i++) {
                if (oh->ot_id_array[i] == qi->lqi_id.qid_uid &&
+                   oh->ot_id_res[i] == res &&
                    oh->ot_id_types[i] == qi->lqi_type) {
                        found = true;
                        break;
@@ -582,37 +578,27 @@ int osd_declare_qid(const struct lu_env *env, struct osd_thandle *oh,
                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) {
+                       /* root ID should be always present in the quota file */
                        crd = 1;
                } else {
-                       /*
-                        * used space for this ID could be dropped to zero,
+                       /* can't rely on the current state as it can change
+                        * by the execution.
+                        * if 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 ||
-#ifdef HAVE_EXT4_INFO_DQUOT
-                                LDISKFS_I(inode)->i_dquot[qi->lqi_type] ==
-                                       NULL)
-#else
-                                inode->i_dquot[qi->lqi_type] == NULL)
-#endif
-                               crd = LDISKFS_QUOTA_INIT_BLOCKS(osd_sb(dev));
                        else
-                               crd = 1;
+                               crd = LDISKFS_QUOTA_INIT_BLOCKS(osd_sb(dev));
                }
 
                osd_trans_declare_op(env, oh, OSD_OT_QUOTA, crd);
 
                oh->ot_id_array[i] = qi->lqi_id.qid_uid;
                oh->ot_id_types[i] = qi->lqi_type;
+               oh->ot_id_res[i] = res;
                oh->ot_id_cnt++;
        }
 
@@ -622,7 +608,8 @@ int osd_declare_qid(const struct lu_env *env, struct osd_thandle *oh,
 
        /* check quota */
        if (enforce)
-               rc = qsd_op_begin(env, qsd, oh->ot_quota_trans, qi, flags);
+               rc = qsd_op_begin(env, qsd, oh->ot_quota_trans, qi,
+                                 local_flags);
        RETURN(rc);
 }
 
@@ -645,7 +632,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,
                          __u32 projid, long long space, struct osd_thandle *oh,
-                         struct osd_object *obj, int *flags,
+                         struct osd_object *obj,
+                         enum osd_quota_local_flags *local_flags,
                          enum osd_qid_declare_flags osd_qid_declare_flags)
 {
        struct osd_thread_info *info = osd_oti_get(env);
@@ -661,7 +649,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 = !!(osd_qid_declare_flags & OSD_QID_BLK);
-       rcu = osd_declare_qid(env, oh, qi, obj, true, flags);
+       rcu = osd_declare_qid(env, oh, qi, obj, true, local_flags);
 
        if (force && (rcu == -EDQUOT || rcu == -EINPROGRESS))
                /* ignore EDQUOT & EINPROGRESS when changes are done by root */
@@ -673,30 +661,33 @@ int osd_declare_inode_qid(const struct lu_env *env, qid_t uid, qid_t gid,
         * in. See osd_declare_write_commit().
         * When force is set to true, we also want to proceed with the gid
         */
-       if (rcu && (rcu != -EDQUOT || flags == NULL))
+       if (rcu && (rcu != -EDQUOT || local_flags == NULL))
                RETURN(rcu);
 
        /* and now group quota */
        qi->lqi_id.qid_gid = gid;
        qi->lqi_type = GRPQUOTA;
-       rcg = osd_declare_qid(env, oh, qi, obj, true, flags);
+       rcg = osd_declare_qid(env, oh, qi, obj, true, local_flags);
 
        if (force && (rcg == -EDQUOT || rcg == -EINPROGRESS))
                /* as before, ignore EDQUOT & EINPROGRESS for root */
                rcg = 0;
 
 #ifdef HAVE_PROJECT_QUOTA
-       if (rcg && (rcg != -EDQUOT || flags == NULL))
+       if (rcg && (rcg != -EDQUOT || local_flags == NULL))
                RETURN(rcg);
 
        /* and now project quota */
        qi->lqi_id.qid_projid = projid;
        qi->lqi_type = PRJQUOTA;
-       rcp = osd_declare_qid(env, oh, qi, obj, true, flags);
+       rcp = osd_declare_qid(env, oh, qi, obj, true, local_flags);
 
-       if (force && (rcp == -EDQUOT || rcp == -EINPROGRESS))
+       if (force && (rcp == -EDQUOT || rcp == -EINPROGRESS)) {
+               CDEBUG(D_QUOTA, "forced to ignore quota flags = %#x\n",
+                      local_flags ? *local_flags : -1);
                /* as before, ignore EDQUOT & EINPROGRESS for root */
                rcp = 0;
+       }
 #endif
 
        RETURN(rcu ? rcu : (rcg ? rcg : rcp));