lustre_quota_fmt.c

来自「lustre 1.6.5 source code」· C语言 代码 · 共 1,080 行 · 第 1/3 页

C
1,080
字号
                goto out_buf;        if (info->dqi_free_entry) {                if ((err = read_blk(filp, info->dqi_free_entry, tmpbuf)) < 0)                        goto out_buf;                ((struct lustre_disk_dqdbheader *)tmpbuf)->dqdh_prev_free =                    cpu_to_le32(blk);                if ((err = write_blk(filp, info->dqi_free_entry, tmpbuf)) < 0)                        goto out_buf;        }        freedqbuf(tmpbuf);        info->dqi_free_entry = blk;        lustre_mark_info_dirty(info);        return 0;out_buf:        freedqbuf(tmpbuf);        return err;}/* Find space for dquot */static uint find_free_dqentry(struct lustre_dquot *dquot, int *err,                               lustre_quota_version_t version){        struct lustre_quota_info *lqi = dquot->dq_info;        struct file *filp = lqi->qi_files[dquot->dq_type];        struct lustre_mem_dqinfo *info = &lqi->qi_info[dquot->dq_type];        uint blk, i;        struct lustre_disk_dqdbheader *dh;        void *ddquot;        int dqblk_sz = lustre_disk_dqblk_sz[version];        int dqstrinblk = lustre_dqstrinblk[version];        char fakedquot[dqblk_sz];        dqbuf_t buf;        *err = 0;        if (!(buf = getdqbuf())) {                *err = -ENOMEM;                return 0;        }        dh = (struct lustre_disk_dqdbheader *)buf;        ddquot = GETENTRIES(buf, version);        if (info->dqi_free_entry) {                blk = info->dqi_free_entry;                if ((*err = read_blk(filp, blk, buf)) < 0)                        goto out_buf;        } else {                blk = get_free_dqblk(filp, info);                if ((int)blk < 0) {                        *err = blk;                        freedqbuf(buf);                        return 0;                }                memset(buf, 0, LUSTRE_DQBLKSIZE);                info->dqi_free_entry = blk; /* This is enough as block is                                                already zeroed and entry list                                               is empty... */                lustre_mark_info_dirty(info);        }        /* Will block be full */        if (le16_to_cpu(dh->dqdh_entries) + 1 >= dqstrinblk)                if ((*err = remove_free_dqentry(filp, info, buf, blk)) < 0) {                        CERROR("VFS: Can't remove block %u"                               " from entry free list.\n", blk);                        goto out_buf;                }        dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries) + 1);        memset(fakedquot, 0, dqblk_sz);        /* Find free structure in block */        for (i = 0; i < dqstrinblk &&             memcmp(fakedquot, (char*)ddquot + i * dqblk_sz,                     sizeof(fakedquot)); i++);        if (i == dqstrinblk) {                CERROR("VFS: Data block full but it shouldn't.\n");                *err = -EIO;                goto out_buf;        }        if ((*err = write_blk(filp, blk, buf)) < 0) {                CERROR("VFS: Can't write quota data block %u.\n", blk);                goto out_buf;        }        dquot->dq_off =            (blk << LUSTRE_DQBLKSIZE_BITS) +            sizeof(struct lustre_disk_dqdbheader) +            i * dqblk_sz;        freedqbuf(buf);        return blk;out_buf:        freedqbuf(buf);        return 0;}/* Insert reference to structure into the trie */static int do_insert_tree(struct lustre_dquot *dquot, uint * treeblk, int depth,                           lustre_quota_version_t version){        struct lustre_quota_info *lqi = dquot->dq_info;        struct file *filp = lqi->qi_files[dquot->dq_type];        struct lustre_mem_dqinfo *info = &lqi->qi_info[dquot->dq_type];        dqbuf_t buf;        int ret = 0, newson = 0, newact = 0;        u32 *ref;        uint newblk;        if (!(buf = getdqbuf()))                return -ENOMEM;        if (!*treeblk) {                ret = get_free_dqblk(filp, info);                if (ret < 0)                        goto out_buf;                *treeblk = ret;                memset(buf, 0, LUSTRE_DQBLKSIZE);                newact = 1;        } else {                if ((ret = read_blk(filp, *treeblk, buf)) < 0) {                        CERROR("VFS: Can't read tree quota block %u.\n",                               *treeblk);                        goto out_buf;                }        }        ref = (u32 *) buf;        newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);        if (!newblk)                newson = 1;        if (depth == LUSTRE_DQTREEDEPTH - 1) {                if (newblk) {                        CERROR("VFS: Inserting already present quota entry "                               "(block %u).\n",                                ref[GETIDINDEX(dquot->dq_id, depth)]);                        ret = -EIO;                        goto out_buf;                }                newblk = find_free_dqentry(dquot, &ret, version);        } else                ret = do_insert_tree(dquot, &newblk, depth + 1, version);        if (newson && ret >= 0) {                ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(newblk);                ret = write_blk(filp, *treeblk, buf);        } else if (newact && ret < 0)                put_free_dqblk(filp, info, buf, *treeblk);out_buf:        freedqbuf(buf);        return ret;}/* Wrapper for inserting quota structure into tree */static inline int dq_insert_tree(struct lustre_dquot *dquot,                                  lustre_quota_version_t version){        int tmp = LUSTRE_DQTREEOFF;        return do_insert_tree(dquot, &tmp, 0, version);}/* *  We don't have to be afraid of deadlocks as we never have quotas on quota files... */static int lustre_write_dquot(struct lustre_dquot *dquot,                               lustre_quota_version_t version){        int type = dquot->dq_type;        struct file *filp;        mm_segment_t fs;        loff_t offset;        ssize_t ret;        int dqblk_sz = lustre_disk_dqblk_sz[version];        char ddquot[dqblk_sz], empty[dqblk_sz];        ret = mem2diskdqb(ddquot, &dquot->dq_dqb, dquot->dq_id, version);        if (ret < 0)                return ret;        if (!dquot->dq_off)                if ((ret = dq_insert_tree(dquot, version)) < 0) {                        CERROR("VFS: Error %Zd occurred while creating quota.\n",                               ret);                        return ret;                }        filp = dquot->dq_info->qi_files[type];        offset = dquot->dq_off;        /* Argh... We may need to write structure full of zeroes but that would be         * treated as an empty place by the rest of the code. Format change would         * be definitely cleaner but the problems probably are not worth it */        memset(empty, 0, dqblk_sz);        if (!memcmp(empty, ddquot, dqblk_sz))                DQF_PUT(ddquot, version, dqb_itime, 1);        fs = get_fs();        set_fs(KERNEL_DS);        ret = filp->f_op->write(filp, ddquot,                                dqblk_sz, &offset);        set_fs(fs);        if (ret != dqblk_sz) {                printk(KERN_WARNING "VFS: dquota write failed on dev %s\n",                       filp->f_dentry->d_sb->s_id);                if (ret >= 0)                        ret = -ENOSPC;        } else                ret = 0;        return ret;}/* Free dquot entry in data block */static int free_dqentry(struct lustre_dquot *dquot, uint blk,                         lustre_quota_version_t version){        struct file *filp = dquot->dq_info->qi_files[dquot->dq_type];        struct lustre_mem_dqinfo *info =            &dquot->dq_info->qi_info[dquot->dq_type];        struct lustre_disk_dqdbheader *dh;        dqbuf_t buf = getdqbuf();        int dqstrinblk = lustre_dqstrinblk[version];        int ret = 0;        if (!buf)                return -ENOMEM;        if (dquot->dq_off >> LUSTRE_DQBLKSIZE_BITS != blk) {                CERROR("VFS: Quota structure has offset to other block (%u) "                       "than it should (%u).\n", blk,                        (uint)(dquot->dq_off >> LUSTRE_DQBLKSIZE_BITS));                goto out_buf;        }        if ((ret = read_blk(filp, blk, buf)) < 0) {                CERROR("VFS: Can't read quota data block %u\n", blk);                goto out_buf;        }        dh = (struct lustre_disk_dqdbheader *)buf;        dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries) - 1);        if (!le16_to_cpu(dh->dqdh_entries)) {   /* Block got free? */                if ((ret = remove_free_dqentry(filp, info, buf, blk)) < 0 ||                    (ret = put_free_dqblk(filp, info, buf, blk)) < 0) {                        CERROR("VFS: Can't move quota data block (%u) "                               "to free list.\n", blk);                        goto out_buf;                }        } else {                memset(buf + (dquot->dq_off & ((1<<LUSTRE_DQBLKSIZE_BITS) - 1)),                       0, lustre_disk_dqblk_sz[version]);                if (le16_to_cpu(dh->dqdh_entries) == dqstrinblk - 1) {                        /* Insert will write block itself */                        if ((ret =                             insert_free_dqentry(filp, info, buf, blk)) < 0) {                                CERROR("VFS: Can't insert quota data block (%u) "                                       "to free entry list.\n", blk);                                goto out_buf;                        }                } else if ((ret = write_blk(filp, blk, buf)) < 0) {                        CERROR("VFS: Can't write quota data block %u\n", blk);                        goto out_buf;                }        }        dquot->dq_off = 0;      /* Quota is now unattached */out_buf:        freedqbuf(buf);        return ret;}/* Remove reference to dquot from tree */static int remove_tree(struct lustre_dquot *dquot, uint * blk, int depth,                        lustre_quota_version_t version){        struct file *filp = dquot->dq_info->qi_files[dquot->dq_type];        struct lustre_mem_dqinfo *info =            &dquot->dq_info->qi_info[dquot->dq_type];        dqbuf_t buf = getdqbuf();        int ret = 0;        uint newblk;        u32 *ref = (u32 *) buf;        if (!buf)                return -ENOMEM;        if ((ret = read_blk(filp, *blk, buf)) < 0) {                CERROR("VFS: Can't read quota data block %u\n", *blk);                goto out_buf;        }        newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);        if (depth == LUSTRE_DQTREEDEPTH - 1) {                ret = free_dqentry(dquot, newblk, version);                newblk = 0;        } else                ret = remove_tree(dquot, &newblk, depth + 1, version);        if (ret >= 0 && !newblk) {                int i;                ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(0);                for (i = 0; i < LUSTRE_DQBLKSIZE && !buf[i]; i++)                        /* Block got empty? */ ;                /* don't put the root block into free blk list! */                if (i == LUSTRE_DQBLKSIZE && *blk != LUSTRE_DQTREEOFF) {                        put_free_dqblk(filp, info, buf, *blk);                        *blk = 0;                } else if ((ret = write_blk(filp, *blk, buf)) < 0)                        CERROR("VFS: Can't write quota tree block %u.\n", *blk);        }out_buf:        freedqbuf(buf);        return ret;}/* Delete dquot from tree */static int lustre_delete_dquot(struct lustre_dquot *dquot,                                 lustre_quota_version_t version){        uint tmp = LUSTRE_DQTREEOFF;        if (!dquot->dq_off)     /* Even not allocated? */                return 0;        return remove_tree(dquot, &tmp, 0, version);}/* Find entry in block */static loff_t find_block_dqentry(struct lustre_dquot *dquot, uint blk,                                  lustre_quota_version_t version){        struct file *filp = dquot->dq_info->qi_files[dquot->dq_type];        dqbuf_t buf = getdqbuf();        loff_t ret = 0;        int i;        char *ddquot = GETENTRIES(buf, version);        int dqblk_sz = lustre_disk_dqblk_sz[version];        int dqstrinblk = lustre_dqstrinblk[version];        if (!buf)                return -ENOMEM;        if ((ret = read_blk(filp, blk, buf)) < 0) {                CERROR("VFS: Can't read quota tree block %u.\n", blk);                goto out_buf;        }        if (dquot->dq_id)                for (i = 0; i < dqstrinblk &&                      DQF_GET(ddquot+i*dqblk_sz, version, dqb_id) != dquot->dq_id;                     i++) ;        else {                  /* ID 0 as a bit more complicated searching... */                char fakedquot[dqblk_sz];                memset(fakedquot, 0, sizeof(fakedquot));                for (i = 0; i < dqstrinblk; i++)                        if (!DQF_GET(ddquot + i*dqblk_sz, version, dqb_id)                            && memcmp(fakedquot, ddquot + i*dqblk_sz,                                      dqblk_sz))                                break;        }        if (i == dqstrinblk) {                CERROR("VFS: Quota for id %u referenced but not present.\n",                       dquot->dq_id);                ret = -EIO;                goto out_buf;        } else                ret =                    (blk << LUSTRE_DQBLKSIZE_BITS) +                    sizeof(struct lustre_disk_dqdbheader) +                    i * dqblk_sz;out_buf:        freedqbuf(buf);        return ret;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?