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