X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Flvfs%2Flustre_quota_fmt.c;h=cb4d42d225d4a7a50bd8681bc11b3099acca05c5;hb=331efcd1f1d446fc3fcd71adfc8223df90b2ba4c;hp=83638d4df712cfae8b316c3dd3c8da3888ddbc44;hpb=a4777b2cbcc3860ad1024aae9eed81b8e4d0e745;p=fs%2Flustre-release.git diff --git a/lustre/lvfs/lustre_quota_fmt.c b/lustre/lvfs/lustre_quota_fmt.c index 83638d4..cb4d42d 100644 --- a/lustre/lvfs/lustre_quota_fmt.c +++ b/lustre/lvfs/lustre_quota_fmt.c @@ -26,7 +26,7 @@ * GPL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. */ /* @@ -50,7 +50,9 @@ #include #include #include -#include +#ifdef HAVE_QUOTAIO_V1_H +# include +#endif #include #include @@ -77,43 +79,32 @@ static const union { struct lustre_disk_dqblk_v2 r1; } fakedquot[] = { - [LUSTRE_QUOTA_V2] = {.r1 = {.dqb_itime = __constant_cpu_to_le64(1LLU)} } + [LUSTRE_QUOTA_V2] = {.r1 = {.dqb_itime = __constant_cpu_to_le64(1LLU)}} }; static const union { struct lustre_disk_dqblk_v2 r1; } emptydquot[] = { - [LUSTRE_QUOTA_V2] = {.r1 = { 0 } } + [LUSTRE_QUOTA_V2] = {.r1 = { 0 }} }; -int check_quota_file(struct file *f, struct inode *inode, int type, +extern void *lustre_quota_journal_start(struct inode *inode, int delete); +extern void lustre_quota_journal_stop(void *handle); +extern ssize_t lustre_read_quota(struct file *f, struct inode *inode, int type, + char *buf, int count, loff_t pos); +extern ssize_t lustre_write_quota(struct file *f, char *buf, int count, loff_t pos); + +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 - } + size = lustre_read_quota(f, inode, type, (char *)&dqhead, + sizeof(struct lustre_disk_dqheader), 0); if (size != sizeof(struct lustre_disk_dqheader)) return -EINVAL; if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] || @@ -133,16 +124,13 @@ int lustre_check_quota_file(struct lustre_quota_info *lqi, int type) 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); + size = lustre_read_quota(f, NULL, 0, (char *)&dinfo, + sizeof(struct lustre_disk_dqinfo), + LUSTRE_DQINFOOFF); + if (size != sizeof(struct lustre_disk_dqinfo)) { CDEBUG(D_ERROR, "Can't read info structure on device %s.\n", f->f_vfsmnt->mnt_sb->s_id); @@ -171,12 +159,10 @@ int lustre_read_quota_info(struct lustre_quota_info *lqi, int type) */ 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); @@ -185,11 +171,11 @@ int lustre_write_quota_info(struct lustre_quota_info *lqi, int type) 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); + + size = lustre_write_quota(f, (char *)&dinfo, + sizeof(struct lustre_disk_dqinfo), + LUSTRE_DQINFOOFF); + if (size != sizeof(struct lustre_disk_dqinfo)) { CDEBUG(D_WARNING, "Can't write info structure on device %s.\n", @@ -250,36 +236,35 @@ void freedqbuf(dqbuf_t buf) kfree(buf); } -ssize_t read_blk(struct file *filp, uint blk, dqbuf_t buf) +ssize_t read_blk(struct file *filp, struct inode *inode, int type, + 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); + ret = lustre_read_quota(filp, inode, type, (char *)buf, LUSTRE_DQBLKSIZE, + blk << LUSTRE_DQBLKSIZE_BITS); + + /* Reading past EOF just returns a block of zeros */ + if (ret == -EBADR) + ret = 0; + 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); + ret = lustre_write_quota(filp, (char *)buf, LUSTRE_DQBLKSIZE, + blk << LUSTRE_DQBLKSIZE_BITS); + return ret; } void lustre_mark_info_dirty(struct lustre_mem_dqinfo *info) { - set_bit(DQF_INFO_DIRTY_B, &info->dqi_flags); + cfs_set_bit(DQF_INFO_DIRTY_B, &info->dqi_flags); } /** @@ -296,7 +281,7 @@ int get_free_dqblk(struct file *filp, struct lustre_mem_dqinfo *info) return -ENOMEM; if (info->dqi_free_blk) { blk = info->dqi_free_blk; - if ((ret = read_blk(filp, blk, buf)) < 0) + if ((ret = read_blk(filp, NULL, 0, blk, buf)) < 0) goto out_buf; info->dqi_free_blk = le32_to_cpu(dh->dqdh_next_free); } else { @@ -351,7 +336,7 @@ int remove_free_dqentry(struct file *filp, if (!tmpbuf) return -ENOMEM; if (nextblk) { - if ((err = read_blk(filp, nextblk, tmpbuf)) < 0) + if ((err = read_blk(filp, NULL, 0, nextblk, tmpbuf)) < 0) goto out_buf; ((struct lustre_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = dh->dqdh_prev_free; @@ -359,7 +344,7 @@ int remove_free_dqentry(struct file *filp, goto out_buf; } if (prevblk) { - if ((err = read_blk(filp, prevblk, tmpbuf)) < 0) + if ((err = read_blk(filp, NULL, 0, prevblk, tmpbuf)) < 0) goto out_buf; ((struct lustre_disk_dqdbheader *)tmpbuf)->dqdh_next_free = dh->dqdh_next_free; @@ -400,7 +385,7 @@ int insert_free_dqentry(struct file *filp, if ((err = write_blk(filp, blk, buf)) < 0) goto out_buf; if (info->dqi_free_entry) { - if ((err = read_blk(filp, info->dqi_free_entry, tmpbuf)) < 0) + if ((err = read_blk(filp, NULL, 0, info->dqi_free_entry, tmpbuf)) < 0) goto out_buf; ((struct lustre_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = cpu_to_le32(blk); @@ -443,7 +428,7 @@ static uint find_free_dqentry(struct lustre_dquot *dquot, int *err, ddquot = GETENTRIES(buf, version); if (info->dqi_free_entry) { blk = info->dqi_free_entry; - if ((*err = read_blk(filp, blk, buf)) < 0) + if ((*err = read_blk(filp, NULL, 0, blk, buf)) < 0) goto out_buf; } else { blk = get_free_dqblk(filp, info); @@ -523,9 +508,8 @@ static int do_insert_tree(struct lustre_dquot *dquot, uint * treeblk, int depth, memset(buf, 0, LUSTRE_DQBLKSIZE); newact = 1; } else { - if ((ret = read_blk(filp, *treeblk, buf)) < 0) { - CDEBUG(D_ERROR, - "VFS: Can't read tree quota block %u.\n", + if ((ret = read_blk(filp, NULL, 0, *treeblk, buf)) < 0) { + CERROR("VFS: Can't read tree quota block %u.\n", *treeblk); goto out_buf; } @@ -577,7 +561,6 @@ static int lustre_write_dquot(struct lustre_dquot *dquot, { int type = dquot->dq_type; struct file *filp; - mm_segment_t fs; loff_t offset; ssize_t ret; int dqblk_sz = lustre_disk_dqblk_sz[version]; @@ -602,11 +585,8 @@ static int lustre_write_dquot(struct lustre_dquot *dquot, * it */ if (!memcmp((char *)&emptydquot[version], (char *)&ddquot, dqblk_sz)) ddquot.dqb_itime = cpu_to_le64(1); - fs = get_fs(); - set_fs(KERNEL_DS); - ret = filp->f_op->write(filp, (char *)&ddquot, - dqblk_sz, &offset); - set_fs(fs); + + ret = lustre_write_quota(filp, (char *)&ddquot, dqblk_sz, offset); if (ret != dqblk_sz) { CDEBUG(D_WARNING, "VFS: dquota write failed on dev %s\n", filp->f_dentry->d_sb->s_id); @@ -641,7 +621,7 @@ static int free_dqentry(struct lustre_dquot *dquot, uint blk, blk, (uint) (dquot->dq_off >> LUSTRE_DQBLKSIZE_BITS)); goto out_buf; } - if ((ret = read_blk(filp, blk, buf)) < 0) { + if ((ret = read_blk(filp, NULL, 0, blk, buf)) < 0) { CDEBUG(D_ERROR, "VFS: Can't read quota data block %u\n", blk); goto out_buf; } @@ -695,8 +675,8 @@ static int remove_tree(struct lustre_dquot *dquot, uint * blk, int depth, if (!buf) return -ENOMEM; - if ((ret = read_blk(filp, *blk, buf)) < 0) { - CDEBUG(D_ERROR, "VFS: Can't read quota data block %u\n", *blk); + if ((ret = read_blk(filp, NULL, 0, *blk, buf)) < 0) { + CERROR("VFS: Can't read quota data block %u\n", *blk); goto out_buf; } newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]); @@ -755,8 +735,8 @@ static loff_t find_block_dqentry(struct lustre_dquot *dquot, uint blk, if (!buf) return -ENOMEM; - if ((ret = read_blk(filp, blk, buf)) < 0) { - CDEBUG(D_ERROR, "VFS: Can't read quota tree block %u.\n", blk); + if ((ret = read_blk(filp, NULL, 0, blk, buf)) < 0) { + CERROR("VFS: Can't read quota tree block %u.\n", blk); goto out_buf; } if (dquot->dq_id) @@ -799,8 +779,8 @@ static loff_t find_tree_dqentry(struct lustre_dquot *dquot, uint blk, int depth, if (!buf) return -ENOMEM; - if ((ret = read_blk(filp, blk, buf)) < 0) { - CDEBUG(D_ERROR, "VFS: Can't read quota tree block %u.\n", blk); + if ((ret = read_blk(filp, NULL, 0, blk, buf)) < 0) { + CERROR("VFS: Can't read quota tree block %u.\n", blk); goto out_buf; } ret = 0; @@ -829,7 +809,6 @@ int lustre_read_dquot(struct lustre_dquot *dquot) { int type = dquot->dq_type; struct file *filp; - mm_segment_t fs; loff_t offset; int ret = 0, dqblk_sz; lustre_quota_version_t version; @@ -837,7 +816,7 @@ int lustre_read_dquot(struct lustre_dquot *dquot) /* Invalidated quota? */ if (!dquot->dq_info || !(filp = dquot->dq_info->qi_files[type])) { CDEBUG(D_ERROR, "VFS: Quota invalidated while reading!\n"); - return -EIO; + return -ESRCH; } version = dquot->dq_info->qi_version; @@ -851,17 +830,15 @@ int lustre_read_dquot(struct lustre_dquot *dquot) "VFS: Can't read quota structure for id %u.\n", dquot->dq_id); dquot->dq_off = 0; - set_bit(DQ_FAKE_B, &dquot->dq_flags); + cfs_set_bit(DQ_FAKE_B, &dquot->dq_flags); memset(&dquot->dq_dqb, 0, sizeof(struct lustre_mem_dqblk)); ret = offset; } else { struct lustre_disk_dqblk_v2 ddquot; dquot->dq_off = offset; - fs = get_fs(); - set_fs(KERNEL_DS); - if ((ret = filp->f_op->read(filp, (char *)&ddquot, - dqblk_sz, &offset)) != dqblk_sz) { + if ((ret = lustre_read_quota(filp, NULL, type, (char *)&ddquot, + dqblk_sz, offset)) != dqblk_sz) { if (ret >= 0) ret = -EIO; CDEBUG(D_ERROR, @@ -875,7 +852,6 @@ int lustre_read_dquot(struct lustre_dquot *dquot) (char *)&ddquot, dqblk_sz)) ddquot.dqb_itime = cpu_to_le64(0); } - set_fs(fs); disk2memdqb(&dquot->dq_dqb, &ddquot, version); } @@ -890,17 +866,30 @@ int lustre_commit_dquot(struct lustre_dquot *dquot) { int rc = 0; lustre_quota_version_t version = dquot->dq_info->qi_version; + void *handle; + struct inode *inode = dquot->dq_info->qi_files[dquot->dq_type]->f_dentry->d_inode; + int delete = 0; /* always clear the flag so we don't loop on an IO error... */ - clear_bit(DQ_MOD_B, &dquot->dq_flags); + cfs_clear_bit(DQ_MOD_B, &dquot->dq_flags); /* The block/inode usage in admin quotafile isn't the real usage * over all cluster, so keep the fake dquot entry on disk is * meaningless, just remove it */ - if (test_bit(DQ_FAKE_B, &dquot->dq_flags)) + if (cfs_test_bit(DQ_FAKE_B, &dquot->dq_flags)) + delete = 1; + handle = lustre_quota_journal_start(inode, delete); + if (unlikely(IS_ERR(handle))) { + rc = PTR_ERR(handle); + CERROR("fail to lustre_quota_journal_start: rc = %d\n", rc); + return rc; + } + + if (delete) rc = lustre_delete_dquot(dquot, version); else rc = lustre_write_dquot(dquot, version); + lustre_quota_journal_stop(handle); if (rc < 0) return rc; @@ -919,7 +908,6 @@ int lustre_init_quota_header(struct lustre_quota_info *lqi, int type, const uint* quota_versions = lustre_initqversions[lqi->qi_version]; struct lustre_disk_dqheader dqhead; ssize_t size; - loff_t offset = 0; struct file *fp = lqi->qi_files[type]; int rc = 0; @@ -927,8 +915,8 @@ int lustre_init_quota_header(struct lustre_quota_info *lqi, int type, dqhead.dqh_magic = cpu_to_le32(fakemagics ? fake_magics[type] : quota_magics[type]); dqhead.dqh_version = cpu_to_le32(quota_versions[type]); - size = fp->f_op->write(fp, (char *)&dqhead, - sizeof(struct lustre_disk_dqheader), &offset); + size = lustre_write_quota(fp, (char *)&dqhead, + sizeof(struct lustre_disk_dqheader), 0); if (size != sizeof(struct lustre_disk_dqheader)) { CDEBUG(D_ERROR, "error writing quoafile header (rc:%d)\n", rc); @@ -966,26 +954,8 @@ int lustre_init_quota_info(struct lustre_quota_info *lqi, int type) return lustre_init_quota_info_generic(lqi, type, 0); } -ssize_t quota_read(struct file *file, struct inode *inode, int type, - uint blk, dqbuf_t buf) -{ - if (file) { - return read_blk(file, blk, buf); - } else { -#ifndef KERNEL_SUPPORTS_QUOTA_READ - return -ENOTSUPP; -#else - struct super_block *sb = inode->i_sb; - memset(buf, 0, LUSTRE_DQBLKSIZE); - return sb->s_op->quota_read(sb, type, (char *)buf, - LUSTRE_DQBLKSIZE, - blk << LUSTRE_DQBLKSIZE_BITS); -#endif - } -} - static int walk_block_dqentry(struct file *filp, struct inode *inode, int type, - uint blk, struct list_head *list) + uint blk, cfs_list_t *list) { dqbuf_t buf = getdqbuf(); loff_t ret = 0; @@ -993,12 +963,12 @@ static int walk_block_dqentry(struct file *filp, struct inode *inode, int type, (struct lustre_disk_dqdbheader *)buf; struct dqblk *blk_item; struct dqblk *pos; - struct list_head *tmp; + cfs_list_t *tmp; if (!buf) return -ENOMEM; - if ((ret = quota_read(filp, inode, type, blk, buf)) < 0) { - CDEBUG(D_ERROR, "VFS: Can't read quota tree block %u.\n", blk); + if ((ret = read_blk(filp, inode, type, blk, buf)) < 0) { + CERROR("VFS: Can't read quota tree block %u.\n", blk); goto out_buf; } ret = 0; @@ -1006,12 +976,12 @@ static int walk_block_dqentry(struct file *filp, struct inode *inode, int type, if (!le32_to_cpu(dqhead->dqdh_entries)) goto out_buf; - if (list_empty(list)) { + if (cfs_list_empty(list)) { tmp = list; goto done; } - list_for_each_entry(pos, list, link) { + cfs_list_for_each_entry(pos, list, link) { if (blk == pos->blk) /* we got this blk already */ goto out_buf; if (blk > pos->blk) @@ -1026,9 +996,9 @@ done: goto out_buf; } blk_item->blk = blk; - INIT_LIST_HEAD(&blk_item->link); + CFS_INIT_LIST_HEAD(&blk_item->link); - list_add_tail(&blk_item->link, tmp); + cfs_list_add_tail(&blk_item->link, tmp); out_buf: freedqbuf(buf); @@ -1036,7 +1006,7 @@ out_buf: } int walk_tree_dqentry(struct file *filp, struct inode *inode, int type, - uint blk, int depth, struct list_head *list) + uint blk, int depth, cfs_list_t *list) { dqbuf_t buf = getdqbuf(); loff_t ret = 0; @@ -1045,8 +1015,8 @@ int walk_tree_dqentry(struct file *filp, struct inode *inode, int type, if (!buf) return -ENOMEM; - if ((ret = quota_read(filp, inode, type, blk, buf)) < 0) { - CDEBUG(D_ERROR, "VFS: Can't read quota tree block %u.\n", blk); + if ((ret = read_blk(filp, inode, type, blk, buf)) < 0) { + CERROR("VFS: Can't read quota tree block %u.\n", blk); goto out_buf; } ret = 0; @@ -1071,9 +1041,9 @@ out_buf: * Walk through the quota file (v2 format) to get all ids with quota limit */ int lustre_get_qids(struct file *fp, struct inode *inode, int type, - struct list_head *list) + cfs_list_t *list) { - struct list_head blk_list; + cfs_list_t blk_list; struct dqblk *blk_item, *tmp; dqbuf_t buf = NULL; struct lustre_disk_dqblk_v2 *ddquot; @@ -1082,6 +1052,8 @@ int lustre_get_qids(struct file *fp, struct inode *inode, int type, ENTRY; + LASSERT(ergo(fp == NULL, inode != NULL)); + if (check_quota_file(fp, inode, type, LUSTRE_QUOTA_V2) == 0) version = LUSTRE_QUOTA_V2; else { @@ -1089,18 +1061,18 @@ int lustre_get_qids(struct file *fp, struct inode *inode, int type, RETURN(-EINVAL); } - if (!list_empty(list)) { + if (!cfs_list_empty(list)) { CDEBUG(D_ERROR, "not empty list\n"); RETURN(-EINVAL); } - INIT_LIST_HEAD(&blk_list); + CFS_INIT_LIST_HEAD(&blk_list); rc = walk_tree_dqentry(fp, inode, type, LUSTRE_DQTREEOFF, 0, &blk_list); if (rc) { CDEBUG(D_ERROR, "walk through quota file failed!(%d)\n", rc); GOTO(out_free, rc); } - if (list_empty(&blk_list)) + if (cfs_list_empty(&blk_list)) RETURN(0); buf = getdqbuf(); @@ -1108,14 +1080,13 @@ int lustre_get_qids(struct file *fp, struct inode *inode, int type, RETURN(-ENOMEM); ddquot = (struct lustre_disk_dqblk_v2 *)GETENTRIES(buf, version); - list_for_each_entry(blk_item, &blk_list, link) { + cfs_list_for_each_entry(blk_item, &blk_list, link) { loff_t ret = 0; int i, dqblk_sz = lustre_disk_dqblk_sz[version]; memset(buf, 0, LUSTRE_DQBLKSIZE); - if ((ret = quota_read(fp, inode, type, blk_item->blk, buf))<0) { - CDEBUG(D_ERROR, - "VFS: Can't read quota tree block %u.\n", + if ((ret = read_blk(fp, inode, type, blk_item->blk, buf)) < 0) { + CERROR("VFS: Can't read quota tree block %u.\n", blk_item->blk); GOTO(out_free, rc = ret); } @@ -1127,19 +1098,24 @@ int lustre_get_qids(struct file *fp, struct inode *inode, int type, (char *)&ddquot[i], dqblk_sz)) continue; - dqid = kmalloc(sizeof(*dqid), GFP_NOFS); - if (!dqid) + OBD_ALLOC_GFP(dqid, sizeof(*dqid), GFP_NOFS); + if (!dqid) GOTO(out_free, rc = -ENOMEM); - dqid->di_id = le32_to_cpu(ddquot[i].dqb_id); - INIT_LIST_HEAD(&dqid->di_link); - list_add(&dqid->di_link, list); + dqid->di_id = le32_to_cpu(ddquot[i].dqb_id); + dqid->di_flag = le64_to_cpu(ddquot[i].dqb_ihardlimit) ? + QI_SET : 0; + dqid->di_flag |= le64_to_cpu(ddquot[i].dqb_bhardlimit) ? + QB_SET : 0; + + CFS_INIT_LIST_HEAD(&dqid->di_link); + cfs_list_add(&dqid->di_link, list); } } out_free: - list_for_each_entry_safe(blk_item, tmp, &blk_list, link) { - list_del_init(&blk_item->link); + cfs_list_for_each_entry_safe(blk_item, tmp, &blk_list, link) { + cfs_list_del_init(&blk_item->link); kfree(blk_item); } if (buf)