fsfilt_ext3.c

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

C
1,853
字号
                }        }        return err;}int fsfilt_map_nblocks(struct inode *inode, unsigned long block,                       unsigned long num, unsigned long *blocks,                       int *created, int create){#ifdef EXT3_EXT_HAS_NO_TREE        struct ext3_ext_base *base = inode;#else        struct ext3_extents_tree tree;        struct ext3_ext_base *base = &tree;#endif        struct bpointers bp;        int err;        CDEBUG(D_OTHER, "blocks %lu-%lu requested for inode %u\n",               block, block + num - 1, (unsigned) inode->i_ino);#ifndef EXT3_EXT_HAS_NO_TREE        ext3_init_tree_desc(base, inode);        tree.private = &bp;#endif        bp.blocks = blocks;        bp.created = created;        bp.start = block;        bp.init_num = bp.num = num;        bp.create = create;        ext3_down_truncate_sem(inode);        err = fsfilt_ext3_ext_walk_space(base, block, num, ext3_ext_new_extent_cb, &bp);        ext3_ext_invalidate_cache(base);        ext3_up_truncate_sem(inode);        return err;}int fsfilt_ext3_map_ext_inode_pages(struct inode *inode, struct page **page,                                    int pages, unsigned long *blocks,                                    int *created, int create){        int blocks_per_page = CFS_PAGE_SIZE >> inode->i_blkbits;        int rc = 0, i = 0;        struct page *fp = NULL;        int clen = 0;        CDEBUG(D_OTHER, "inode %lu: map %d pages from %lu\n",                inode->i_ino, pages, (*page)->index);        /* pages are sorted already. so, we just have to find         * contig. space and process them properly */        while (i < pages) {                if (fp == NULL) {                        /* start new extent */                        fp = *page++;                        clen = 1;                        i++;                        continue;                } else if (fp->index + clen == (*page)->index) {                        /* continue the extent */                        page++;                        clen++;                        i++;                        continue;                }                /* process found extent */                rc = fsfilt_map_nblocks(inode, fp->index * blocks_per_page,                                        clen * blocks_per_page, blocks,                                        created, create);                if (rc)                        GOTO(cleanup, rc);                /* look for next extent */                fp = NULL;                blocks += blocks_per_page * clen;                created += blocks_per_page * clen;        }        if (fp)                rc = fsfilt_map_nblocks(inode, fp->index * blocks_per_page,                                        clen * blocks_per_page, blocks,                                        created, create);cleanup:        return rc;}#endif /* EXT3_MULTIBLOCK_ALLOCATOR */extern int ext3_map_inode_page(struct inode *inode, struct page *page,                               unsigned long *blocks, int *created, int create);int fsfilt_ext3_map_bm_inode_pages(struct inode *inode, struct page **page,                                   int pages, unsigned long *blocks,                                   int *created, int create){        int blocks_per_page = CFS_PAGE_SIZE >> inode->i_blkbits;        unsigned long *b;        int rc = 0, i, *cr;        for (i = 0, cr = created, b = blocks; i < pages; i++, page++) {                rc = ext3_map_inode_page(inode, *page, b, cr, create);                if (rc) {                        CERROR("ino %lu, blk %lu cr %u create %d: rc %d\n",                               inode->i_ino, *b, *cr, create, rc);                        break;                }                b += blocks_per_page;                cr += blocks_per_page;        }        return rc;}int fsfilt_ext3_map_inode_pages(struct inode *inode, struct page **page,                                int pages, unsigned long *blocks,                                int *created, int create,                                struct semaphore *optional_sem){        int rc;#ifdef EXT3_MULTIBLOCK_ALLOCATOR        if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL) {                rc = fsfilt_ext3_map_ext_inode_pages(inode, page, pages,                                                     blocks, created, create);                return rc;        }#endif        if (optional_sem != NULL)                down(optional_sem);        rc = fsfilt_ext3_map_bm_inode_pages(inode, page, pages, blocks,                                            created, create);        if (optional_sem != NULL)                up(optional_sem);        return rc;}static int fsfilt_ext3_read_record(struct file * file, void *buf,                                   int size, loff_t *offs){        struct inode *inode = file->f_dentry->d_inode;        unsigned long block;        struct buffer_head *bh;        int err, blocksize, csize, boffs;        /* prevent reading after eof */        lock_kernel();        if (i_size_read(inode) < *offs + size) {                size = i_size_read(inode) - *offs;                unlock_kernel();                if (size < 0) {                        CERROR("size %llu is too short for read %u@%llu\n",                               i_size_read(inode), size, *offs);                        return -EIO;                } else if (size == 0) {                        return 0;                }        } else {                unlock_kernel();        }        blocksize = 1 << inode->i_blkbits;        while (size > 0) {                block = *offs >> inode->i_blkbits;                boffs = *offs & (blocksize - 1);                csize = min(blocksize - boffs, size);                bh = ext3_bread(NULL, inode, block, 0, &err);                if (!bh) {                        CERROR("can't read block: %d\n", err);                        return err;                }                memcpy(buf, bh->b_data + boffs, csize);                brelse(bh);                *offs += csize;                buf += csize;                size -= csize;        }        return 0;}static int fsfilt_ext3_write_record(struct file *file, void *buf, int bufsize,                                    loff_t *offs, int force_sync){        struct buffer_head *bh = NULL;        unsigned long block;        struct inode *inode = file->f_dentry->d_inode;        loff_t old_size = i_size_read(inode), offset = *offs;        loff_t new_size = i_size_read(inode);        handle_t *handle;        int err = 0, block_count = 0, blocksize, size, boffs;        /* Determine how many transaction credits are needed */        blocksize = 1 << inode->i_blkbits;        block_count = (*offs & (blocksize - 1)) + bufsize;        block_count = (block_count + blocksize - 1) >> inode->i_blkbits;        lock_24kernel();        handle = fsfilt_ext3_journal_start(inode,                               block_count * FSFILT_DATA_TRANS_BLOCKS(inode->i_sb) + 2);        unlock_24kernel();        if (IS_ERR(handle)) {                CERROR("can't start transaction for %d blocks (%d bytes)\n",                       block_count * FSFILT_DATA_TRANS_BLOCKS(inode->i_sb) + 2, bufsize);                return PTR_ERR(handle);        }        while (bufsize > 0) {                if (bh != NULL)                        brelse(bh);                block = offset >> inode->i_blkbits;                boffs = offset & (blocksize - 1);                size = min(blocksize - boffs, bufsize);                bh = ext3_bread(handle, inode, block, 1, &err);                if (!bh) {                        CERROR("can't read/create block: %d\n", err);                        goto out;                }                err = ext3_journal_get_write_access(handle, bh);                if (err) {                        CERROR("journal_get_write_access() returned error %d\n",                               err);                        goto out;                }                LASSERT(bh->b_data + boffs + size <= bh->b_data + bh->b_size);                memcpy(bh->b_data + boffs, buf, size);                err = ext3_journal_dirty_metadata(handle, bh);                if (err) {                        CERROR("journal_dirty_metadata() returned error %d\n",                               err);                        goto out;                }                if (offset + size > new_size)                        new_size = offset + size;                offset += size;                bufsize -= size;                buf += size;        }        if (force_sync)                handle->h_sync = 1; /* recovery likes this */out:        if (bh)                brelse(bh);        /* correct in-core and on-disk sizes */        if (new_size > i_size_read(inode)) {                lock_kernel();                if (new_size > i_size_read(inode))                        i_size_write(inode, new_size);                if (i_size_read(inode) > EXT3_I(inode)->i_disksize)                        EXT3_I(inode)->i_disksize = i_size_read(inode);                if (i_size_read(inode) > old_size)                        mark_inode_dirty(inode);                unlock_kernel();        }        lock_24kernel();        fsfilt_ext3_journal_stop(handle);        unlock_24kernel();        if (err == 0)                *offs = offset;        return err;}static int fsfilt_ext3_setup(struct super_block *sb){        struct ext3_sb_info *sbi = EXT3_SB(sb);#if 0        sbi->dx_lock = fsfilt_ext3_dx_lock;        sbi->dx_unlock = fsfilt_ext3_dx_unlock;#endif#ifdef S_PDIROPS        CWARN("Enabling PDIROPS\n");        set_opt(sbi->s_mount_opt, PDIROPS);        sb->s_flags |= S_PDIROPS;#endif        if (!EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX))                CWARN("filesystem doesn't have dir_index feature enabled\n");#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,6)) && HAVE_QUOTA_SUPPORT        /* enable journaled quota support */        /* kfreed in ext3_put_super() */        sbi->s_qf_names[USRQUOTA] = kstrdup("lquota.user", GFP_KERNEL);        if (!sbi->s_qf_names[USRQUOTA])                return -ENOMEM;        sbi->s_qf_names[GRPQUOTA] = kstrdup("lquota.group", GFP_KERNEL);        if (!sbi->s_qf_names[GRPQUOTA]) {                kfree(sbi->s_qf_names[USRQUOTA]);                sbi->s_qf_names[USRQUOTA] = NULL;                return -ENOMEM;        }        sbi->s_jquota_fmt = QFMT_VFS_V0;#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13))        set_opt(sbi->s_mount_opt, QUOTA);#endif#endif        return 0;}/* If fso is NULL, op is FSFILT operation, otherwise op is number of fso   objects. Logs is number of logfiles to update */static int fsfilt_ext3_get_op_len(int op, struct fsfilt_objinfo *fso, int logs){        if ( !fso ) {                switch(op) {                case FSFILT_OP_CREATE:                                 /* directory leaf, index & indirect & EA*/                        return 4 + 3 * logs;                case FSFILT_OP_UNLINK:                        return 3 * logs;                }        } else {                int i;                int needed = 0;                struct super_block *sb = fso->fso_dentry->d_inode->i_sb;                int blockpp = 1 << (CFS_PAGE_SHIFT - sb->s_blocksize_bits);                int addrpp = EXT3_ADDR_PER_BLOCK(sb) * blockpp;                for (i = 0; i < op; i++, fso++) {                        int nblocks = fso->fso_bufcnt * blockpp;                        int ndindirect = min(nblocks, addrpp + 1);                        int nindir = nblocks + ndindirect + 1;                        needed += nindir;                }                return needed + 3 * logs;        }        return 0;}static const char *op_quotafile[] = { "lquota.user", "lquota.group" };#define DQINFO_COPY(out, in)                    \do {                                            \        Q_COPY(out, in, dqi_bgrace);            \        Q_COPY(out, in, dqi_igrace);            \        Q_COPY(out, in, dqi_flags);             \        Q_COPY(out, in, dqi_valid);             \} while (0)#define DQBLK_COPY(out, in)                     \do {                                            \        Q_COPY(out, in, dqb_bhardlimit);        \        Q_COPY(out, in, dqb_bsoftlimit);        \        Q_COPY(out, in, dqb_curspace);          \        Q_COPY(out, in, dqb_ihardlimit);        \        Q_COPY(out, in, dqb_isoftlimit);        \        Q_COPY(out, in, dqb_curinodes);         \        Q_COPY(out, in, dqb_btime);             \        Q_COPY(out, in, dqb_itime);             \        Q_COPY(out, in, dqb_valid);             \} while (0)      static int fsfilt_ext3_quotactl(struct super_block *sb,                                struct obd_quotactl *oqc){        int i, rc = 0, error = 0;        struct quotactl_ops *qcop;        struct if_dqinfo *info;        struct if_dqblk *dqblk;        ENTRY;        if (!sb->s_qcop)                RETURN(-ENOSYS);

⌨️ 快捷键说明

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