fsfilt_ext3.c

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

C
1,853
字号
        OBD_ALLOC_PTR(info);        if (!info)                RETURN(-ENOMEM);        OBD_ALLOC_PTR(dqblk);        if (!dqblk) {                OBD_FREE_PTR(info);                RETURN(-ENOMEM);        }        DQINFO_COPY(info, &oqc->qc_dqinfo);        DQBLK_COPY(dqblk, &oqc->qc_dqblk);        qcop = sb->s_qcop;        if (oqc->qc_cmd == Q_QUOTAON || oqc->qc_cmd == Q_QUOTAOFF) {                for (i = 0; i < MAXQUOTAS; i++) {                        if (!Q_TYPESET(oqc, i))                                continue;                        if (oqc->qc_cmd == Q_QUOTAON) {                                if (!qcop->quota_on)                                        GOTO(out, rc = -ENOSYS);                                rc = qcop->quota_on(sb, i, oqc->qc_id,                                                    (char *)op_quotafile[i]);                        } else if (oqc->qc_cmd == Q_QUOTAOFF) {                                if (!qcop->quota_off)                                        GOTO(out, rc = -ENOSYS);                                rc = qcop->quota_off(sb, i);                        }                        if (rc == -EBUSY)                                error = rc;                        else if (rc)                                GOTO(out, rc);                }                GOTO(out, rc ?: error);        }        switch (oqc->qc_cmd) {        case Q_GETOINFO:        case Q_GETINFO:                if (!qcop->get_info)                        GOTO(out, rc = -ENOSYS);                rc = qcop->get_info(sb, oqc->qc_type, info);                break;        case Q_SETQUOTA:        case Q_INITQUOTA:                if (!qcop->set_dqblk)                        GOTO(out, rc = -ENOSYS);                rc = qcop->set_dqblk(sb, oqc->qc_type, oqc->qc_id, dqblk);                break;        case Q_GETOQUOTA:        case Q_GETQUOTA:                if (!qcop->get_dqblk)                        GOTO(out, rc = -ENOSYS);                rc = qcop->get_dqblk(sb, oqc->qc_type, oqc->qc_id, dqblk);                if (!rc)                        dqblk->dqb_valid = QIF_LIMITS | QIF_USAGE;                break;        case Q_SYNC:                if (!sb->s_qcop->quota_sync)                        GOTO(out, rc = -ENOSYS);                qcop->quota_sync(sb, oqc->qc_type);                break;        default:                CERROR("unsupported quotactl command: %d", oqc->qc_cmd);                LBUG();        }out:        DQINFO_COPY(&oqc->qc_dqinfo, info);        DQBLK_COPY(&oqc->qc_dqblk, dqblk);        OBD_FREE_PTR(info);        OBD_FREE_PTR(dqblk);        if (rc)                CDEBUG(D_QUOTA, "quotactl command %#x, id %u, type %d "                                "failed: %d\n",                       oqc->qc_cmd, oqc->qc_id, oqc->qc_type, rc);        RETURN(rc);}struct chk_dqblk{        struct hlist_node       dqb_hash;        /* quotacheck hash */        struct list_head        dqb_list;        /* in list also */        qid_t                   dqb_id;          /* uid/gid */        short                   dqb_type;        /* USRQUOTA/GRPQUOTA */        qsize_t                 dqb_bhardlimit;  /* block hard limit */        qsize_t                 dqb_bsoftlimit;  /* block soft limit */        qsize_t                 dqb_curspace;    /* current space */        qsize_t                 dqb_ihardlimit;  /* inode hard limit */        qsize_t                 dqb_isoftlimit;  /* inode soft limit */        qsize_t                 dqb_curinodes;   /* current inodes */        __u64                   dqb_btime;       /* block grace time */        __u64                   dqb_itime;       /* inode grace time */        __u32                   dqb_valid;       /* flag for above fields */};static inline unsigned int chkquot_hash(qid_t id, int type)                                        __attribute__((__const__));static inline unsigned int chkquot_hash(qid_t id, int type){        return (id * (MAXQUOTAS - type)) % NR_DQHASH;}static inline struct chk_dqblk *find_chkquot(struct hlist_head *head, qid_t id, int type){        struct hlist_node *node;        struct chk_dqblk *cdqb;        hlist_for_each(node, head) {                cdqb = hlist_entry(node, struct chk_dqblk, dqb_hash);                if (cdqb->dqb_id == id && cdqb->dqb_type == type)                        return cdqb;        }        return NULL;}static struct chk_dqblk *alloc_chkquot(qid_t id, int type){        struct chk_dqblk *cdqb;        OBD_ALLOC_PTR(cdqb);        if (cdqb) {                INIT_HLIST_NODE(&cdqb->dqb_hash);                INIT_LIST_HEAD(&cdqb->dqb_list);                cdqb->dqb_id = id;                cdqb->dqb_type = type;        }        return cdqb;}static struct chk_dqblk *cqget(struct super_block *sb, struct hlist_head *hash, struct list_head *list,      qid_t id, int type, int first_check){        struct hlist_head *head = hash + chkquot_hash(id, type);        struct if_dqblk dqb;        struct chk_dqblk *cdqb;        int rc;        cdqb = find_chkquot(head, id, type);        if (cdqb)                return cdqb;        cdqb = alloc_chkquot(id, type);        if (!cdqb)                return NULL;        if (!first_check) {                rc = sb->s_qcop->get_dqblk(sb, type, id, &dqb);                if (rc) {                        CERROR("get_dqblk of id %u, type %d failed: %d\n",                               id, type, rc);                } else {                        DQBLK_COPY(cdqb, &dqb);                        cdqb->dqb_curspace = 0;                        cdqb->dqb_curinodes = 0;                }        }        hlist_add_head(&cdqb->dqb_hash, head);        list_add_tail(&cdqb->dqb_list, list);        return cdqb;}static inline int quota_onoff(struct super_block *sb, int cmd, int type){        struct obd_quotactl *oqctl;        int rc;        OBD_ALLOC_PTR(oqctl);        if (!oqctl)                RETURN(-ENOMEM);        oqctl->qc_cmd = cmd;        oqctl->qc_id = QFMT_LDISKFS;        oqctl->qc_type = type;        rc = fsfilt_ext3_quotactl(sb, oqctl);        OBD_FREE_PTR(oqctl);        return rc;}static inline int read_old_dqinfo(struct super_block *sb, int type,                                  struct if_dqinfo *dqinfo){        struct obd_quotactl *oqctl;        int rc;        ENTRY;        OBD_ALLOC_PTR(oqctl);        if (!oqctl)                RETURN(-ENOMEM);        oqctl->qc_cmd = Q_GETINFO;        oqctl->qc_type = type;        rc = fsfilt_ext3_quotactl(sb, oqctl);        if (!rc)                ((struct obd_dqinfo *)dqinfo)[type] = oqctl->qc_dqinfo;        OBD_FREE_PTR(oqctl);        RETURN(rc);}static inline struct ext3_group_desc *get_group_desc(struct super_block *sb, int group){        unsigned long desc_block, desc;        struct ext3_group_desc *gdp;        desc_block = group / EXT3_DESC_PER_BLOCK(sb);        desc = group % EXT3_DESC_PER_BLOCK(sb);        gdp = (struct ext3_group_desc *)              EXT3_SB(sb)->s_group_desc[desc_block]->b_data;        return gdp + desc;}static inline struct buffer_head *read_inode_bitmap(struct super_block *sb, unsigned long group){        struct ext3_group_desc *desc;        struct buffer_head *bh;        desc = get_group_desc(sb, group);        bh = sb_bread(sb, le32_to_cpu(desc->bg_inode_bitmap));        return bh;}static inline struct inode *ext3_iget_inuse(struct super_block *sb,                                     struct buffer_head *bitmap_bh,                                     int index, unsigned long ino){        struct inode *inode = NULL;        if (ext3_test_bit(index, bitmap_bh->b_data))                inode = iget(sb, ino);        return inode;}struct qchk_ctxt {        struct hlist_head       qckt_hash[NR_DQHASH];        /* quotacheck hash */        struct list_head        qckt_list;                   /* quotacheck list */        int                     qckt_first_check[MAXQUOTAS]; /* 1 if no old quotafile */        struct if_dqinfo        qckt_dqinfo[MAXQUOTAS];      /* old dqinfo */};static int add_inode_quota(struct inode *inode, struct qchk_ctxt *qctxt,                           struct obd_quotactl *oqc){        struct chk_dqblk *cdqb[MAXQUOTAS] = { NULL, };        loff_t size = 0;        qid_t qid[MAXQUOTAS];        int cnt, i, rc = 0;        if (!inode)                return 0;        qid[USRQUOTA] = inode->i_uid;        qid[GRPQUOTA] = inode->i_gid;        if (S_ISDIR(inode->i_mode) ||            S_ISREG(inode->i_mode) ||            S_ISLNK(inode->i_mode))                size = inode_get_bytes(inode);        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {                if (!Q_TYPESET(oqc, cnt))                        continue;                cdqb[cnt] = cqget(inode->i_sb, qctxt->qckt_hash,                                &qctxt->qckt_list, qid[cnt], cnt,                                qctxt->qckt_first_check[cnt]);                if (!cdqb[cnt]) {                        rc = -ENOMEM;                        break;                }                cdqb[cnt]->dqb_curspace += size;                cdqb[cnt]->dqb_curinodes++;        }        if (rc) {                for (i = 0; i < cnt; i++) {                        if (!Q_TYPESET(oqc, i))                                continue;                        LASSERT(cdqb[i]);                        cdqb[i]->dqb_curspace -= size;                        cdqb[i]->dqb_curinodes--;                }        }        return rc;}static int v2_write_dqheader(struct file *f, int type){        static const __u32 quota_magics[] = V2_INITQMAGICS;        static const __u32 quota_versions[] = V2_INITQVERSIONS;        struct v2_disk_dqheader dqhead;        loff_t offset = 0;        CLASSERT(ARRAY_SIZE(quota_magics) == ARRAY_SIZE(quota_versions));        LASSERT(0 <= type && type < ARRAY_SIZE(quota_magics));        dqhead.dqh_magic = cpu_to_le32(quota_magics[type]);        dqhead.dqh_version = cpu_to_le32(quota_versions[type]);        return cfs_user_write(f, (char *)&dqhead, sizeof(dqhead), &offset);}/* write dqinfo struct in a new quota file */static int v2_write_dqinfo(struct file *f, int type, struct if_dqinfo *info){        struct v2_disk_dqinfo dqinfo;        __u32 blocks = V2_DQTREEOFF + 1;        loff_t offset = V2_DQINFOOFF;        if (info) {                dqinfo.dqi_bgrace = cpu_to_le32(info->dqi_bgrace);                dqinfo.dqi_igrace = cpu_to_le32(info->dqi_igrace);                dqinfo.dqi_flags = cpu_to_le32(info->dqi_flags & DQF_MASK &                                               ~DQF_INFO_DIRTY);        } else {                dqinfo.dqi_bgrace = cpu_to_le32(MAX_DQ_TIME);                dqinfo.dqi_igrace = cpu_to_le32(MAX_IQ_TIME);                dqinfo.dqi_flags = 0;        }        dqinfo.dqi_blocks = cpu_to_le32(blocks);        dqinfo.dqi_free_blk = 0;        dqinfo.dqi_free_entry = 0;        return cfs_user_write(f, (char *)&dqinfo, sizeof(dqinfo), &offset);}static int create_new_quota_files(struct qchk_ctxt *qctxt,                                  struct obd_quotactl *oqc){        int i, rc = 0;        ENTRY;        for (i = 0; i < MAXQUOTAS; i++) {                struct if_dqinfo *info = qctxt->qckt_first_check[i]?                                         NULL : &qctxt->qckt_dqinfo[i];                struct file *file;                if (!Q_TYPESET(oqc, i))                        continue;                file = filp_open(op_quotafile[i], O_RDWR | O_CREAT | O_TRUNC,                                 0644);                if (IS_ERR(file)) {                        rc = PTR_ERR(file);                        CERROR("can't create %s file: rc = %d\n",                               op_quotafile[i], rc);                        GOTO(out, rc);                }                if (!S_ISREG(file->f_dentry->d_inode->i_mode)) {    

⌨️ 快捷键说明

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