Whamcloud - gitweb
Branch b1_6
[fs/lustre-release.git] / lustre / lvfs / lustre_quota_fmt_convert.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * convert quota format.
5  *
6  *  from
7  *  linux/fs/quota_v2.c
8  */
9
10 #ifndef EXPORT_SYMTAB
11 # define EXPORT_SYMTAB
12 #endif
13
14 #include <linux/errno.h>
15 #include <linux/fs.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>
22
23 #include <asm/byteorder.h>
24 #include <asm/uaccess.h>
25
26 #include <lustre_quota.h>
27 #include <obd_support.h>
28 #include "lustre_quota_fmt.h"
29
30 static int admin_convert_dqinfo(struct file *fp_v1, struct file *fp_v2,
31                                 struct lustre_quota_info *lqi, int type)
32 {
33         struct lustre_mem_dqinfo *info_old, *info_new = &lqi->qi_info[type];
34         int rc;
35
36         OBD_ALLOC_PTR(info_old);
37         if (info_old == NULL)
38                 return -ENOMEM;
39
40         rc = lustre_read_quota_file_info(fp_v1, info_old);
41         if (!rc) {
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);
47         }
48
49         OBD_FREE_PTR(info_old);
50
51         return rc;
52 }
53
54 static int admin_convert_v1_to_v2(struct file *fp_v1, struct file *fp_v2,
55                                   struct lustre_quota_info *lqi, int type)
56 {
57         struct list_head blk_list;
58         struct dqblk *blk_item, *tmp;
59         dqbuf_t buf = NULL;
60         struct lustre_disk_dqblk *ddquot;
61         struct lustre_dquot *dquot = NULL;
62         int rc;
63
64         ENTRY;
65
66         INIT_LIST_HEAD(&blk_list);
67
68         rc = admin_convert_dqinfo(fp_v1, fp_v2, lqi, type);
69         if (rc) {
70                 CERROR("could not copy dqinfo!(%d)\n", rc);
71                 GOTO(out_free, rc);
72         }
73
74         rc = walk_tree_dqentry(fp_v1, NULL, type, LUSTRE_DQTREEOFF, 0, &blk_list);
75         if (rc) {
76                 CERROR("walk through quota file failed!(%d)\n", rc);
77                 GOTO(out_free, rc);
78         }
79         if (list_empty(&blk_list))
80                 RETURN(0);
81
82         buf = getdqbuf();
83         if (!buf)
84                 GOTO(out_free, rc = -ENOMEM);
85
86         ddquot = (struct lustre_disk_dqblk*)GETENTRIES(buf, LUSTRE_QUOTA_V1);
87
88         OBD_ALLOC_PTR(dquot);
89         if (dquot == NULL)
90                 GOTO(out_free, rc = -ENOMEM);
91
92         list_for_each_entry(blk_item, &blk_list, link) {
93                 loff_t ret = 0;
94                 int i;
95                 struct lustre_disk_dqblk fakedquot;
96
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",
100                                blk_item->blk);
101                         GOTO(out_free, rc = ret);
102                 }
103
104                 memset(&fakedquot, 0, sizeof(struct lustre_disk_dqblk));
105                 for (i = 0; i < LUSTRE_DQSTRINBLK; i++) {
106                         /* skip empty entry */
107                         if (!memcmp
108                             (&fakedquot, ddquot + i,
109                              sizeof(struct lustre_disk_dqblk)))
110                                 continue;
111
112                         memset(dquot, 0, sizeof(*dquot));
113
114                         dquot->dq_id = le32_to_cpu(ddquot[i].dqb_id);
115                         dquot->dq_type = type;
116                         dquot->dq_info = lqi;
117
118                         disk2memdqb(&dquot->dq_dqb, &ddquot[i], LUSTRE_QUOTA_V1);
119                         rc = lustre_commit_dquot(dquot);
120                         if (rc < 0)
121                                 GOTO(out_free, rc);
122                 }
123         }
124
125         EXIT;
126
127 out_free:
128         list_for_each_entry_safe(blk_item, tmp, &blk_list, link) {
129                 list_del_init(&blk_item->link);
130                 kfree(blk_item);
131         }
132         if (buf)
133                 freedqbuf(buf);
134         if (dquot)
135                 OBD_FREE_PTR(dquot);
136         return rc;
137 }
138
139 int lustre_quota_convert(struct lustre_quota_info *lqi, int type)
140 {
141         struct file *f_v2 = lqi->qi_files[type];
142         const char *qf_v1[] = LUSTRE_ADMIN_QUOTAFILES_V1;
143         char name[64];
144         struct file *f_v1;
145         int rc = 0;
146         ENTRY;
147
148         LASSERT(f_v2);
149
150         rc = lustre_init_quota_info_generic(lqi, type, 1);
151         if (rc) {
152                 CERROR("could not initialize new quota file(%d)\n", rc);
153                 RETURN(rc);
154         }
155
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);
159         if (!IS_ERR(f_v1)) {
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);
162                         if (rc)
163                                 CERROR("failed to convert v1 quota file"
164                                        " to v2 quota file.\n");
165                         else
166                                 CDEBUG(D_INFO, "Found v1 quota file, "
167                                                "successfully converted to v2.\n");
168                 }
169                 else
170                         CERROR("old quota file is broken, "
171                                "new quota file will be empty\n");
172
173                 filp_close(f_v1, 0);
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));
177
178         /* mark corresponding quota file as correct */
179         if (!rc)
180                 lustre_init_quota_header(lqi, type, 0);
181
182         RETURN(rc);
183 }
184
185 EXPORT_SYMBOL(lustre_quota_convert);