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 + -
显示快捷键?