1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * convert quota format.
11 # define EXPORT_SYMTAB
14 #include <linux/errno.h>
16 #include <linux/mount.h>
17 #include <linux/kernel.h>
18 #include <linux/init.h>
19 #include <linux/module.h>
20 #include <linux/slab.h>
21 #include <linux/quotaio_v1.h>
23 #include <asm/byteorder.h>
24 #include <asm/uaccess.h>
26 #include <lustre_quota.h>
27 #include <obd_support.h>
28 #include "lustre_quota_fmt.h"
30 static int admin_convert_dqinfo(struct file *fp_v1, struct file *fp_v2,
31 struct lustre_quota_info *lqi, int type)
33 struct lustre_mem_dqinfo *info_old, *info_new = &lqi->qi_info[type];
36 OBD_ALLOC_PTR(info_old);
40 rc = lustre_read_quota_file_info(fp_v1, info_old);
42 /* save essential fields: bgrace, igrace, flags */
43 info_new->dqi_bgrace = info_old->dqi_bgrace;
44 info_new->dqi_igrace = info_old->dqi_igrace;
45 info_new->dqi_flags = info_old->dqi_flags;
46 rc = lustre_write_quota_info(lqi, type);
49 OBD_FREE_PTR(info_old);
54 static int admin_convert_v1_to_v2(struct file *fp_v1, struct file *fp_v2,
55 struct lustre_quota_info *lqi, int type)
57 struct list_head blk_list;
58 struct dqblk *blk_item, *tmp;
60 struct lustre_disk_dqblk *ddquot;
61 struct lustre_dquot *dquot = NULL;
66 INIT_LIST_HEAD(&blk_list);
68 rc = admin_convert_dqinfo(fp_v1, fp_v2, lqi, type);
70 CERROR("could not copy dqinfo!(%d)\n", rc);
74 rc = walk_tree_dqentry(fp_v1, NULL, type, LUSTRE_DQTREEOFF, 0, &blk_list);
76 CERROR("walk through quota file failed!(%d)\n", rc);
79 if (list_empty(&blk_list))
84 GOTO(out_free, rc = -ENOMEM);
86 ddquot = (struct lustre_disk_dqblk*)GETENTRIES(buf, LUSTRE_QUOTA_V1);
90 GOTO(out_free, rc = -ENOMEM);
92 list_for_each_entry(blk_item, &blk_list, link) {
95 struct lustre_disk_dqblk fakedquot;
97 memset(buf, 0, LUSTRE_DQBLKSIZE);
98 if ((ret = quota_read(fp_v1, NULL, type, blk_item->blk, buf))<0) {
99 CERROR("VFS: Can't read quota tree block %u.\n",
101 GOTO(out_free, rc = ret);
104 memset(&fakedquot, 0, sizeof(struct lustre_disk_dqblk));
105 for (i = 0; i < LUSTRE_DQSTRINBLK; i++) {
106 /* skip empty entry */
108 (&fakedquot, ddquot + i,
109 sizeof(struct lustre_disk_dqblk)))
112 memset(dquot, 0, sizeof(*dquot));
114 dquot->dq_id = le32_to_cpu(ddquot[i].dqb_id);
115 dquot->dq_type = type;
116 dquot->dq_info = lqi;
118 disk2memdqb(&dquot->dq_dqb, &ddquot[i], LUSTRE_QUOTA_V1);
119 rc = lustre_commit_dquot(dquot);
128 list_for_each_entry_safe(blk_item, tmp, &blk_list, link) {
129 list_del_init(&blk_item->link);
139 int lustre_quota_convert(struct lustre_quota_info *lqi, int type)
141 struct file *f_v2 = lqi->qi_files[type];
142 const char *qf_v1[] = LUSTRE_ADMIN_QUOTAFILES_V1;
150 rc = lustre_init_quota_info_generic(lqi, type, 1);
152 CERROR("could not initialize new quota file(%d)\n", rc);
156 /* Open old quota file and copy to the new one */
157 sprintf(name, "OBJECTS/%s", qf_v1[type]);
158 f_v1 = filp_open(name, O_RDONLY, 0);
160 if (!check_quota_file(f_v1, NULL, type, LUSTRE_QUOTA_V1)) {
161 rc = admin_convert_v1_to_v2(f_v1, f_v2, lqi, type);
163 CERROR("failed to convert v1 quota file"
164 " to v2 quota file.\n");
166 CDEBUG(D_INFO, "Found v1 quota file, "
167 "successfully converted to v2.\n");
170 CERROR("old quota file is broken, "
171 "new quota file will be empty\n");
174 } else if (PTR_ERR(f_v1) != -ENOENT) /* No quota file is ok */
175 CERROR("old quota file can not be open, "
176 "new quota file will be empty (%ld)\n", PTR_ERR(f_v1));
178 /* mark corresponding quota file as correct */
180 lustre_init_quota_header(lqi, type, 0);
185 EXPORT_SYMBOL(lustre_quota_convert);