lustre_quota_fmt.c

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

C
1,080
字号
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * * Lustre administrative quota format. * *  from *  linux/fs/quota_v2.c */#ifndef EXPORT_SYMTAB# define EXPORT_SYMTAB#endif#include <linux/errno.h>#include <linux/fs.h>#include <linux/mount.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/module.h>#include <linux/slab.h>#include <linux/quotaio_v1.h>#include <asm/byteorder.h>#include <asm/uaccess.h>#include <lustre_quota.h>#include <obd_support.h>#include "lustre_quota_fmt.h"static const uint lustre_initqversions[][MAXQUOTAS] = {        [LUSTRE_QUOTA_V1] = LUSTRE_INITQVERSIONS,        [LUSTRE_QUOTA_V2] = LUSTRE_INITQVERSIONS_V2};static const int lustre_dqstrinblk[] = {        [LUSTRE_QUOTA_V1] = LUSTRE_DQSTRINBLK,        [LUSTRE_QUOTA_V2] = LUSTRE_DQSTRINBLK_V2};static const int lustre_disk_dqblk_sz[] = {        [LUSTRE_QUOTA_V1] = sizeof(struct lustre_disk_dqblk),        [LUSTRE_QUOTA_V2] = sizeof(struct lustre_disk_dqblk_v2)};int check_quota_file(struct file *f, struct inode *inode, int type,                      lustre_quota_version_t version){        struct lustre_disk_dqheader dqhead;        mm_segment_t fs;        ssize_t size;        loff_t offset = 0;        static const uint quota_magics[] = LUSTRE_INITQMAGICS;        const uint *quota_versions = lustre_initqversions[version];        if (f) {                fs = get_fs();                set_fs(KERNEL_DS);                size = f->f_op->read(f, (char *)&dqhead,                                     sizeof(struct lustre_disk_dqheader),                                      &offset);                set_fs(fs);        } else { #ifndef KERNEL_SUPPORTS_QUOTA_READ                size = 0;#else                struct super_block *sb = inode->i_sb;                size = sb->s_op->quota_read(sb, type, (char *)&dqhead,                                             sizeof(struct lustre_disk_dqheader), 0);#endif        }        if (size != sizeof(struct lustre_disk_dqheader))                return -EINVAL;        if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||            le32_to_cpu(dqhead.dqh_version) != quota_versions[type])                return -EINVAL;        return 0;}/* Check whether given file is really lustre admin quotafile */int lustre_check_quota_file(struct lustre_quota_info *lqi, int type){        struct file *f = lqi->qi_files[type];        return check_quota_file(f, NULL, type, lqi->qi_version);}int lustre_read_quota_file_info(struct file* f, struct lustre_mem_dqinfo* info){        mm_segment_t fs;        struct lustre_disk_dqinfo dinfo;        ssize_t size;        loff_t offset = LUSTRE_DQINFOOFF;        fs = get_fs();        set_fs(KERNEL_DS);        size = f->f_op->read(f, (char *)&dinfo,                              sizeof(struct lustre_disk_dqinfo), &offset);        set_fs(fs);        if (size != sizeof(struct lustre_disk_dqinfo)) {                CERROR("Can't read info structure on device %s.\n",                       f->f_vfsmnt->mnt_sb->s_id);                return -EINVAL;        }        info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);        info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);        info->dqi_flags = le32_to_cpu(dinfo.dqi_flags);        info->dqi_blocks = le32_to_cpu(dinfo.dqi_blocks);        info->dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk);        info->dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry);        return 0;}/* Read information header from quota file */int lustre_read_quota_info(struct lustre_quota_info *lqi, int type){        return lustre_read_quota_file_info(lqi->qi_files[type], &lqi->qi_info[type]);}/* Write information header to quota file */int lustre_write_quota_info(struct lustre_quota_info *lqi, int type){        mm_segment_t fs;        struct lustre_disk_dqinfo dinfo;        struct lustre_mem_dqinfo *info = &lqi->qi_info[type];        struct file *f = lqi->qi_files[type];        ssize_t size;        loff_t offset = LUSTRE_DQINFOOFF;        info->dqi_flags &= ~DQF_INFO_DIRTY;        dinfo.dqi_bgrace = cpu_to_le32(info->dqi_bgrace);        dinfo.dqi_igrace = cpu_to_le32(info->dqi_igrace);        dinfo.dqi_flags = cpu_to_le32(info->dqi_flags & DQF_MASK);        dinfo.dqi_blocks = cpu_to_le32(info->dqi_blocks);        dinfo.dqi_free_blk = cpu_to_le32(info->dqi_free_blk);        dinfo.dqi_free_entry = cpu_to_le32(info->dqi_free_entry);        fs = get_fs();        set_fs(KERNEL_DS);        size = f->f_op->write(f, (char *)&dinfo,                               sizeof(struct lustre_disk_dqinfo), &offset);        set_fs(fs);        if (size != sizeof(struct lustre_disk_dqinfo)) {                printk(KERN_WARNING                       "Can't write info structure on device %s.\n",                       f->f_vfsmnt->mnt_sb->s_id);                return -1;        }        return 0;}#define DQ2MQ(v) ((sizeof(v) == sizeof(__u64)) ? \                le64_to_cpu(v) : le32_to_cpu(v))#define MQ2DQ(v,newv) ((sizeof(v) == sizeof(__u64)) ? \                (v = cpu_to_le64((__u64)newv)) : (v = cpu_to_le32((__u32)newv)))#define DQF_GET(var,ver,field) ((ver == LUSTRE_QUOTA_V1)?\                DQ2MQ(((struct lustre_disk_dqblk*)(var))->field):\                DQ2MQ(((struct lustre_disk_dqblk_v2*)(var))->field))#define DQF_PUT(var,ver,field,val) ((ver == LUSTRE_QUOTA_V1)?\                MQ2DQ(((struct lustre_disk_dqblk*)(var))->field, val):\                MQ2DQ(((struct lustre_disk_dqblk_v2*)(var))->field, val))void disk2memdqb(struct lustre_mem_dqblk *m, void *d,                 lustre_quota_version_t version){        m->dqb_ihardlimit = DQF_GET(d, version, dqb_ihardlimit);        m->dqb_isoftlimit = DQF_GET(d, version, dqb_isoftlimit);        m->dqb_curinodes = DQF_GET(d, version, dqb_curinodes);        m->dqb_itime = DQF_GET(d, version, dqb_itime);        m->dqb_bhardlimit = DQF_GET(d, version, dqb_bhardlimit);        m->dqb_bsoftlimit = DQF_GET(d, version, dqb_bsoftlimit);        m->dqb_curspace = DQF_GET(d, version, dqb_curspace);        m->dqb_btime = DQF_GET(d, version, dqb_btime);}static int check_quota_bounds(struct lustre_mem_dqblk *m,                               lustre_quota_version_t version){        return (version == LUSTRE_QUOTA_V1  &&                m->dqb_ihardlimit <= MAX_UL &&                m->dqb_isoftlimit <= MAX_UL &&                m->dqb_curinodes <= MAX_UL  &&                m->dqb_bhardlimit <= MAX_UL &&                m->dqb_bsoftlimit <= MAX_UL) ||                version != LUSTRE_QUOTA_V1;}static int mem2diskdqb(void *d, struct lustre_mem_dqblk *m,                       qid_t id, lustre_quota_version_t version){        if (!check_quota_bounds(m, version))                return -EINVAL;        DQF_PUT(d, version, dqb_ihardlimit, m->dqb_ihardlimit);        DQF_PUT(d, version, dqb_isoftlimit, m->dqb_isoftlimit);        DQF_PUT(d, version, dqb_curinodes, m->dqb_curinodes);        DQF_PUT(d, version, dqb_itime, m->dqb_itime);        DQF_PUT(d, version, dqb_bhardlimit, m->dqb_bhardlimit);        DQF_PUT(d, version, dqb_bsoftlimit, m->dqb_bsoftlimit);        DQF_PUT(d, version, dqb_curspace, m->dqb_curspace);        DQF_PUT(d, version, dqb_btime, m->dqb_btime);        DQF_PUT(d, version, dqb_id, id);        return 0;}dqbuf_t getdqbuf(void){        dqbuf_t buf = kmalloc(LUSTRE_DQBLKSIZE, GFP_NOFS);        if (!buf)                printk(KERN_WARNING                       "VFS: Not enough memory for quota buffers.\n");        return buf;}void freedqbuf(dqbuf_t buf){        kfree(buf);}ssize_t read_blk(struct file *filp, uint blk, dqbuf_t buf){        mm_segment_t fs;        ssize_t ret;        loff_t offset = blk << LUSTRE_DQBLKSIZE_BITS;        memset(buf, 0, LUSTRE_DQBLKSIZE);        fs = get_fs();        set_fs(KERNEL_DS);        ret = filp->f_op->read(filp, (char *)buf, LUSTRE_DQBLKSIZE, &offset);        set_fs(fs);        return ret;}ssize_t write_blk(struct file *filp, uint blk, dqbuf_t buf){        mm_segment_t fs;        ssize_t ret;        loff_t offset = blk << LUSTRE_DQBLKSIZE_BITS;        fs = get_fs();        set_fs(KERNEL_DS);        ret = filp->f_op->write(filp, (char *)buf, LUSTRE_DQBLKSIZE, &offset);        set_fs(fs);        return ret;}void lustre_mark_info_dirty(struct lustre_mem_dqinfo *info){        set_bit(DQF_INFO_DIRTY_B, &info->dqi_flags);}/* Remove empty block from list and return it */int get_free_dqblk(struct file *filp, struct lustre_mem_dqinfo *info){        dqbuf_t buf = getdqbuf();        struct lustre_disk_dqdbheader *dh =            (struct lustre_disk_dqdbheader *)buf;        int ret, blk;        if (!buf)                return -ENOMEM;        if (info->dqi_free_blk) {                blk = info->dqi_free_blk;                if ((ret = read_blk(filp, blk, buf)) < 0)                        goto out_buf;                info->dqi_free_blk = le32_to_cpu(dh->dqdh_next_free);        } else {                memset(buf, 0, LUSTRE_DQBLKSIZE);                /* Assure block allocation... */                if ((ret = write_blk(filp, info->dqi_blocks, buf)) < 0)                        goto out_buf;                blk = info->dqi_blocks++;        }        lustre_mark_info_dirty(info);        ret = blk;out_buf:        freedqbuf(buf);        return ret;}/* Insert empty block to the list */int put_free_dqblk(struct file *filp, struct lustre_mem_dqinfo *info,                   dqbuf_t buf, uint blk){        struct lustre_disk_dqdbheader *dh =            (struct lustre_disk_dqdbheader *)buf;        int err;        dh->dqdh_next_free = cpu_to_le32(info->dqi_free_blk);        dh->dqdh_prev_free = cpu_to_le32(0);        dh->dqdh_entries = cpu_to_le16(0);        info->dqi_free_blk = blk;        lustre_mark_info_dirty(info);        if ((err = write_blk(filp, blk, buf)) < 0)                /* Some strange block. We had better leave it... */                return err;        return 0;}/* Remove given block from the list of blocks with free entries */int remove_free_dqentry(struct file *filp,                        struct lustre_mem_dqinfo *info, dqbuf_t buf,                        uint blk){        dqbuf_t tmpbuf = getdqbuf();        struct lustre_disk_dqdbheader *dh =            (struct lustre_disk_dqdbheader *)buf;        uint nextblk = le32_to_cpu(dh->dqdh_next_free), prevblk =            le32_to_cpu(dh->dqdh_prev_free);        int err;        if (!tmpbuf)                return -ENOMEM;        if (nextblk) {                if ((err = read_blk(filp, nextblk, tmpbuf)) < 0)                        goto out_buf;                ((struct lustre_disk_dqdbheader *)tmpbuf)->dqdh_prev_free =                    dh->dqdh_prev_free;                if ((err = write_blk(filp, nextblk, tmpbuf)) < 0)                        goto out_buf;        }        if (prevblk) {                if ((err = read_blk(filp, prevblk, tmpbuf)) < 0)                        goto out_buf;                ((struct lustre_disk_dqdbheader *)tmpbuf)->dqdh_next_free =                    dh->dqdh_next_free;                if ((err = write_blk(filp, prevblk, tmpbuf)) < 0)                        goto out_buf;        } else {                info->dqi_free_entry = nextblk;                lustre_mark_info_dirty(info);        }        freedqbuf(tmpbuf);        dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0);        err = write_blk(filp, blk, buf);        if (err < 0)      /* No matter whether write succeeds block is out of list */                CERROR("VFS: Can't write block (%u) with "                       "free entries (rc=%d).\n", blk, err);        return 0;out_buf:        freedqbuf(tmpbuf);        return err;}/* Insert given block to the beginning of list with free entries */int insert_free_dqentry(struct file *filp,                        struct lustre_mem_dqinfo *info, dqbuf_t buf,                        uint blk){        dqbuf_t tmpbuf = getdqbuf();        struct lustre_disk_dqdbheader *dh =            (struct lustre_disk_dqdbheader *)buf;        int err;        if (!tmpbuf)                return -ENOMEM;        dh->dqdh_next_free = cpu_to_le32(info->dqi_free_entry);        dh->dqdh_prev_free = cpu_to_le32(0);        if ((err = write_blk(filp, blk, buf)) < 0)

⌨️ 快捷键说明

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