int (* fs_quotactl)(struct super_block *sb,
struct obd_quotactl *oqctl);
int (* fs_quotainfo)(struct lustre_quota_info *lqi, int type,
- int cmd, struct list_head *list);
+ int cmd);
+ int (* fs_qids)(struct file *file, struct inode *inode, int type,
+ struct list_head *list);
int (* fs_dquot)(struct lustre_dquot *dquot, int cmd);
};
static inline int fsfilt_quotainfo(struct obd_device *obd,
struct lustre_quota_info *lqi,
- int type, int cmd, struct list_head *list)
+ int type, int cmd)
{
if (obd->obd_fsops->fs_quotainfo)
- return obd->obd_fsops->fs_quotainfo(lqi, type, cmd, list);
+ return obd->obd_fsops->fs_quotainfo(lqi, type, cmd);
+ return -ENOTSUPP;
+}
+
+static inline int fsfilt_qids(struct obd_device *obd, struct file *file,
+ struct inode *inode, int type,
+ struct list_head *list)
+{
+ if (obd->obd_fsops->fs_qids)
+ return obd->obd_fsops->fs_qids(file, inode, type, list);
return -ENOTSUPP;
}
#define QFILE_RD_INFO 2
#define QFILE_WR_INFO 3
#define QFILE_INIT_INFO 4
-#define QFILE_GET_QIDS 5
-#define QFILE_RD_DQUOT 6
-#define QFILE_WR_DQUOT 7
+#define QFILE_RD_DQUOT 5
+#define QFILE_WR_DQUOT 6
/* admin quotafile operations */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
int lustre_read_dquot(struct lustre_dquot *dquot);
int lustre_commit_dquot(struct lustre_dquot *dquot);
int lustre_init_quota_info(struct lustre_quota_info *lqi, int type);
-int lustre_get_qids(struct lustre_quota_info *lqi, int type,
+int lustre_get_qids(struct file *file, struct inode *inode, int type,
struct list_head *list);
#else
#define GETIDINDEX(id, depth) (((id) >> ((LUSTRE_DQTREEDEPTH-(depth)-1)*8)) & 0xff)
#define GETENTRIES(buf) ((struct lustre_disk_dqblk *)(((char *)buf)+sizeof(struct lustre_disk_dqdbheader)))
-static int check_quota_file(struct file *f, int type)
+static int check_quota_file(struct file *f, struct inode *inode, int type)
{
struct lustre_disk_dqheader dqhead;
mm_segment_t fs;
static const uint quota_magics[] = LUSTRE_INITQMAGICS;
static const uint quota_versions[] = LUSTRE_INITQVERSIONS;
- fs = get_fs();
- set_fs(KERNEL_DS);
- size = f->f_op->read(f, (char *)&dqhead,
- sizeof(struct lustre_disk_dqheader), &offset);
- set_fs(fs);
+ 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 {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)
+ 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 0;
if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||
int lustre_check_quota_file(struct lustre_quota_info *lqi, int type)
{
struct file *f = lqi->qi_files[type];
- return check_quota_file(f, type);
+ return check_quota_file(f, NULL, type);
}
/* Read information header from quota file */
uint blk;
};
-static int walk_block_dqentry(struct file *filp, uint blk,
- struct list_head *list)
+static 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 {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)
+ 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)
{
dqbuf_t buf = getdqbuf();
loff_t ret = 0;
if (!buf)
return -ENOMEM;
- if ((ret = read_blk(filp, blk, buf)) < 0) {
+ if ((ret = quota_read(filp, inode, type, blk, buf)) < 0) {
printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
goto out_buf;
}
return ret;
}
-static int walk_tree_dqentry(struct file *filp, uint blk, int depth,
- struct list_head *list)
+static int walk_tree_dqentry(struct file *filp, struct inode *inode, int type,
+ uint blk, int depth, struct list_head *list)
{
dqbuf_t buf = getdqbuf();
loff_t ret = 0;
if (!buf)
return -ENOMEM;
- if ((ret = read_blk(filp, blk, buf)) < 0) {
+ if ((ret = quota_read(filp, inode, type, blk, buf)) < 0) {
printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
goto out_buf;
}
continue;
if (depth < LUSTRE_DQTREEDEPTH - 1)
- ret = walk_tree_dqentry(filp, blk, depth + 1, list);
+ ret = walk_tree_dqentry(filp, inode, type, blk,
+ depth + 1, list);
else
- ret = walk_block_dqentry(filp, blk, list);
+ ret = walk_block_dqentry(filp, inode, type, blk, list);
}
out_buf:
freedqbuf(buf);
}
/* Walk through the quota file (v2 format) to get all ids with quota limit */
-int lustre_get_qids(struct lustre_quota_info *lqi, int type,
+int lustre_get_qids(struct file *fp, struct inode *inode, int type,
struct list_head *list)
{
- struct file *fp = lqi->qi_files[type];
struct list_head blk_list;
struct dqblk *blk_item, *tmp;
dqbuf_t buf = NULL;
struct lustre_disk_dqblk *ddquot;
int rc;
- if (!check_quota_file(fp, type)) {
+ if (!check_quota_file(fp, inode, type)) {
printk(KERN_ERR "unknown quota file format!\n");
return -EINVAL;
}
}
INIT_LIST_HEAD(&blk_list);
- rc = walk_tree_dqentry(fp, LUSTRE_DQTREEOFF, 0, &blk_list);
+ rc = walk_tree_dqentry(fp, inode, type, LUSTRE_DQTREEOFF, 0, &blk_list);
if (rc) {
printk(KERN_ERR "walk through quota file failed!(%d)\n", rc);
goto out_free;
struct lustre_disk_dqblk fakedquot;
memset(buf, 0, LUSTRE_DQBLKSIZE);
- if ((ret = read_blk(fp, blk_item->blk, buf)) < 0) {
+ if ((ret = quota_read(fp, inode, type, blk_item->blk, buf))<0) {
printk(KERN_ERR
"VFS: Can't read quota tree block %u.\n",
blk_item->blk);
static int quotfmt_test_5(struct lustre_quota_info *lqi)
{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)
int i, rc = 0;
for (i = USRQUOTA; i < MAXQUOTAS && !rc; i++) {
struct dquot_id *dqid, *tmp;
INIT_LIST_HEAD(&list);
- rc = lustre_get_qids(lqi, i, &list);
+ rc = lustre_get_qids(lqi->qi_files[i], NULL, i, &list);
if (rc) {
CERROR("%s get all %ss (rc:%d):\n",
rc ? "error" : "success",
printk("\n");
}
return rc;
+#else
+ CWARN("kernel version >= 2.6.12, test skipped\n");
+ return 0;
+#endif
}
static int quotfmt_run_tests(struct obd_device *obd, struct obd_device *tgt)
CERROR("walk through quota file failed\n");
GOTO(out, rc);
}
+
out:
CWARN("=== Finalize quotafile test\n");
rc = quotfmt_finalize(lqi, tgt, &saved);
struct ext3_sb_info *sbi = EXT3_SB(sb);
int i, group;
struct qchk_ctxt *qctxt;
- struct lustre_quota_info *dummy = NULL;
struct quota_info *dqopt = sb_dqopt(sb);
struct buffer_head *bitmap_bh = NULL;
unsigned long ino;
/* read old quota limits from old quota file. (only for the user
* has limits but hasn't file) */
#ifdef HAVE_QUOTA_SUPPORT
- OBD_ALLOC_PTR(dummy);
- if (!dummy) {
- CERROR("Not enough memory\n");
- GOTO(out, rc = -ENOMEM);
- }
for (i = 0; i < MAXQUOTAS; i++) {
struct list_head id_list;
struct dquot_id *dqid, *tmp;
if (qctxt->qckt_first_check[i])
continue;
-
- dummy->qi_files[i] = dqopt->files[i];
- LASSERT(dummy->qi_files[i] != NULL);
+
+ LASSERT(dqopt->files[i] != NULL);
INIT_LIST_HEAD(&id_list);
-
- rc = lustre_get_qids(dummy, i, &id_list);
- if (rc) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)
+ rc = lustre_get_qids(dqopt->files[i], NULL, i, &id_list);
+#else
+ rc = lustre_get_qids(NULL, dqopt->files[i], i, &id_list);
+#endif
+ if (rc)
CERROR("read old limits failed. (rc:%d)\n", rc);
- break;
- }
+
list_for_each_entry_safe(dqid, tmp, &id_list, di_link) {
list_del_init(&dqid->di_link);
-
- cqget(sb, qctxt->qckt_hash, &qctxt->qckt_list,
- dqid->di_id, i, qctxt->qckt_first_check[i]);
+
+ if (!rc)
+ cqget(sb, qctxt->qckt_hash, &qctxt->qckt_list,
+ dqid->di_id, i,
+ qctxt->qckt_first_check[i]);
kfree(dqid);
}
}
/* dump and free chk_dqblk */
rc = prune_chkquots(sb, qctxt, rc);
OBD_FREE_PTR(qctxt);
- if (dummy)
- OBD_FREE_PTR(dummy);
/* turn off quota, `lfs quotacheck` will turn on when all
* nodes quotacheck finish. */
#ifdef HAVE_QUOTA_SUPPORT
static int fsfilt_ext3_quotainfo(struct lustre_quota_info *lqi, int type,
- int cmd, struct list_head *list)
+ int cmd)
{
int rc = 0;
ENTRY;
case QFILE_INIT_INFO:
rc = lustre_init_quota_info(lqi, type);
break;
- case QFILE_GET_QIDS:
- rc = lustre_get_qids(lqi, type, list);
- break;
default:
CERROR("Unsupported admin quota file cmd %d\n", cmd);
LBUG();
RETURN(rc);
}
+static int fsfilt_ext3_qids(struct file *file, struct inode *inode, int type,
+ struct list_head *list)
+{
+ return lustre_get_qids(file, inode, type, list);
+}
+
static int fsfilt_ext3_dquot(struct lustre_dquot *dquot, int cmd)
{
int rc = 0;
.fs_quotacheck = fsfilt_ext3_quotacheck,
#ifdef HAVE_QUOTA_SUPPORT
.fs_quotainfo = fsfilt_ext3_quotainfo,
+ .fs_qids = fsfilt_ext3_qids,
.fs_dquot = fsfilt_ext3_dquot,
#endif
};
for (type = USRQUOTA; type < MAXQUOTAS; type++) {
struct qunit_data qdata;
struct quota_info *dqopt = sb_dqopt(qctxt->lqc_sb);
- struct lustre_quota_info *dummy;
struct list_head id_list;
struct dquot_id *dqid, *tmp;
int ret;
- OBD_ALLOC_PTR(dummy);
- if (!dummy) {
- CERROR("Not enough memory\n");
- rc = -ENOMEM;
- break;
- }
-
down(&dqopt->dqonoff_sem);
if (!sb_has_quota_enabled(qctxt->lqc_sb, type)) {
up(&dqopt->dqonoff_sem);
- OBD_FREE_PTR(dummy);
break;
}
- dummy->qi_files[type] = dqopt->files[type];
- LASSERT(dummy->qi_files[type] != NULL);
- INIT_LIST_HEAD(&id_list);
- rc = fsfilt_quotainfo(obd, dummy, type, QFILE_GET_QIDS, &id_list);
+ LASSERT(dqopt->files[type] != NULL);
+ INIT_LIST_HEAD(&id_list);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)
+ rc = fsfilt_qids(obd, dqopt->files[type], NULL, type, &id_list);
+#else
+ rc = fsfilt_qids(obd, NULL, dqopt->files[type], type, &id_list);
+#endif
up(&dqopt->dqonoff_sem);
-
- OBD_FREE_PTR(dummy);
if (rc)
CERROR("Get ids from quota file failed. (rc:%d)\n", rc);
}
qinfo->qi_files[i] = fp;
- rc = fsfilt_quotainfo(obd, qinfo, i, QFILE_INIT_INFO, NULL);
+ rc = fsfilt_quotainfo(obd, qinfo, i, QFILE_INIT_INFO);
filp_close(fp, 0);
qinfo->qi_files[i] = NULL;
}
qinfo->qi_files[i] = fp;
- rc = fsfilt_quotainfo(obd, qinfo, i, QFILE_RD_INFO, NULL);
+ rc = fsfilt_quotainfo(obd, qinfo, i, QFILE_RD_INFO);
if (rc) {
CERROR("error read quotainfo of %s! (rc:%d)\n",
name, rc);
qinfo->qi_info[oqctl->qc_type].dqi_igrace = dqinfo->dqi_igrace;
qinfo->qi_info[oqctl->qc_type].dqi_flags = dqinfo->dqi_flags;
- rc = fsfilt_quotainfo(obd, qinfo, oqctl->qc_type, QFILE_WR_INFO, NULL);
+ rc = fsfilt_quotainfo(obd, qinfo, oqctl->qc_type, QFILE_WR_INFO);
out:
up(&mds->mds_qonoff_sem);
continue;
}
INIT_LIST_HEAD(&id_list);
- rc = fsfilt_quotainfo(obd, qinfo, type, QFILE_GET_QIDS,
- &id_list);
+ rc = fsfilt_qids(obd, qinfo->qi_files[type], NULL, type,
+ &id_list);
up(&mds->mds_qonoff_sem);
if (rc)