Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / lustre / kernel_patches / patches / quota-support-64-bit-quota-format.patch
1 From: Jan Kara <jack@suse.cz>
2
3 Implement conversion functions for new version (version 1) of quota format
4 which supports 64-bit block and inode limits and 64-bit inode usage.  The
5 original implementation has been written by Andrew Perepechko.
6
7 Signed-off-by: Andrew Perepechko <andrew.perepechko@sun.com>
8 Signed-off-by: Jan Kara <jack@suse.cz>
9 Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
10 ---
11
12  fs/quota_v2.c   |  140 ++++++++++++++++++++++++++++++++++++----------
13  fs/quotaio_v2.h |   26 ++++++--
14  2 files changed, 132 insertions(+), 34 deletions(-)
15
16 diff -puN fs/quota_v2.c~quota-support-64-bit-quota-format fs/quota_v2.c
17 --- a/fs/quota_v2.c~quota-support-64-bit-quota-format
18 +++ a/fs/quota_v2.c
19 @@ -23,14 +23,24 @@ MODULE_LICENSE("GPL");
20  
21  #define __QUOTA_V2_PARANOIA
22  
23 -static void v2_mem2diskdqb(void *dp, struct dquot *dquot);
24 -static void v2_disk2memdqb(struct dquot *dquot, void *dp);
25 -static int v2_is_id(void *dp, struct dquot *dquot);
26 -
27 -static struct qtree_fmt_operations v2_qtree_ops = {
28 -       .mem2disk_dqblk = v2_mem2diskdqb,
29 -       .disk2mem_dqblk = v2_disk2memdqb,
30 -       .is_id = v2_is_id,
31 +static void v2r0_mem2diskdqb(void *dp, struct dquot *dquot);
32 +static void v2r0_disk2memdqb(struct dquot *dquot, void *dp);
33 +static int v2r0_is_id(void *dp, struct dquot *dquot);
34 +
35 +static struct qtree_fmt_operations v2r0_qtree_ops = {
36 +       .mem2disk_dqblk = v2r0_mem2diskdqb,
37 +       .disk2mem_dqblk = v2r0_disk2memdqb,
38 +       .is_id = v2r0_is_id,
39 +};
40 +
41 +static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot);
42 +static void v2r1_disk2memdqb(struct dquot *dquot, void *dp);
43 +static int v2r1_is_id(void *dp, struct dquot *dquot);
44 +
45 +static struct qtree_fmt_operations v2r1_qtree_ops = {
46 +       .mem2disk_dqblk = v2r1_mem2diskdqb,
47 +       .disk2mem_dqblk = v2r1_disk2memdqb,
48 +       .is_id = v2r1_is_id,
49  };
50  
51  #define QUOTABLOCK_BITS 10
52 @@ -46,8 +56,7 @@ static inline qsize_t v2_qbtos(qsize_t b
53         return blocks << QUOTABLOCK_BITS;
54  }
55  
56 -/* Check whether given file is really vfsv0 quotafile */
57 -static int v2_check_quota_file(struct super_block *sb, int type)
58 +static int v2_check_quota_file_header(struct super_block *sb, int type)
59  {
60         struct v2_disk_dqheader dqhead;
61         ssize_t size;
62 @@ -58,12 +67,20 @@ static int v2_check_quota_file(struct su
63         if (size != sizeof(struct v2_disk_dqheader)) {
64                 printk("quota_v2: failed read expected=%zd got=%zd\n",
65                         sizeof(struct v2_disk_dqheader), size);
66 -               return 0;
67 +               return -EIO;
68         }
69 -       if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||
70 -           le32_to_cpu(dqhead.dqh_version) != quota_versions[type])
71 -               return 0;
72 -       return 1;
73 +       if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type])
74 +               return -ENOENT;
75 +       if (le32_to_cpu(dqhead.dqh_version) > quota_versions[type])
76 +               return -EOPNOTSUPP;
77 +       return le32_to_cpu(dqhead.dqh_version);
78 +}
79 +
80 +
81 +/* Check whether given file is really vfsv0 quotafile */
82 +static int v2_check_quota_file(struct super_block *sb, int type)
83 +{
84 +       return v2_check_quota_file_header(sb, type) >= 0;
85  }
86  
87  /* Read information header from quota file */
88 @@ -73,7 +90,13 @@ static int v2_read_file_info(struct supe
89         struct mem_dqinfo *info = sb_dqinfo(sb, type);
90         struct qtree_mem_dqinfo *qinfo;
91         ssize_t size;
92 +       int version = v2_check_quota_file_header(sb, type);
93  
94 +       if (version < 0) {
95 +               printk(KERN_WARNING "Cannot identify quota file version on "
96 +                      "device %s: %d\n", sb->s_id, version);
97 +               return -1;
98 +       }
99         size = sb->s_op->quota_read(sb, type, (char *)&dinfo,
100                sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
101         if (size != sizeof(struct v2_disk_dqinfo)) {
102 @@ -88,9 +111,14 @@ static int v2_read_file_info(struct supe
103                 return -1;
104         }
105         qinfo = info->dqi_priv;
106 -       /* limits are stored as unsigned 32-bit data */
107 -       info->dqi_maxblimit = 0xffffffff;
108 -       info->dqi_maxilimit = 0xffffffff;
109 +       if (version == 0) {
110 +               /* limits are stored as unsigned 32-bit data */
111 +               info->dqi_maxblimit = 0xffffffff;
112 +               info->dqi_maxilimit = 0xffffffff;
113 +       } else {
114 +               info->dqi_maxblimit = 0x7fffffffffffffffULL;
115 +               info->dqi_maxilimit = 0x7fffffffffffffffULL;
116 +       }
117         info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
118         info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
119         info->dqi_flags = le32_to_cpu(dinfo.dqi_flags);
120 @@ -102,8 +130,13 @@ static int v2_read_file_info(struct supe
121         qinfo->dqi_blocksize_bits = V2_DQBLKSIZE_BITS;
122         qinfo->dqi_usable_bs = 1 << V2_DQBLKSIZE_BITS;
123         qinfo->dqi_qtree_depth = qtree_depth(qinfo);
124 -       qinfo->dqi_entry_size = sizeof(struct v2_disk_dqblk);
125 -       qinfo->dqi_ops = &v2_qtree_ops;
126 +       if (version == 0) {
127 +               qinfo->dqi_entry_size = sizeof(struct v2r0_disk_dqblk);
128 +               qinfo->dqi_ops = &v2r0_qtree_ops;
129 +       } else {
130 +               qinfo->dqi_entry_size = sizeof(struct v2r1_disk_dqblk);
131 +               qinfo->dqi_ops = &v2r1_qtree_ops;
132 +       }
133         return 0;
134  }
135  
136 @@ -134,9 +167,9 @@ static int v2_write_file_info(struct sup
137         return 0;
138  }
139  
140 -static void v2_disk2memdqb(struct dquot *dquot, void *dp)
141 +static void v2r0_disk2memdqb(struct dquot *dquot, void *dp)
142  {
143 -       struct v2_disk_dqblk *d = dp, empty;
144 +       struct v2r0_disk_dqblk *d = dp, empty;
145         struct mem_dqblk *m = &dquot->dq_dqb;
146  
147         m->dqb_ihardlimit = le32_to_cpu(d->dqb_ihardlimit);
148 @@ -148,15 +181,15 @@ static void v2_disk2memdqb(struct dquot 
149         m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
150         m->dqb_btime = le64_to_cpu(d->dqb_btime);
151         /* We need to escape back all-zero structure */
152 -       memset(&empty, 0, sizeof(struct v2_disk_dqblk));
153 +       memset(&empty, 0, sizeof(struct v2r0_disk_dqblk));
154         empty.dqb_itime = cpu_to_le64(1);
155 -       if (!memcmp(&empty, dp, sizeof(struct v2_disk_dqblk)))
156 +       if (!memcmp(&empty, dp, sizeof(struct v2r0_disk_dqblk)))
157                 m->dqb_itime = 0;
158  }
159  
160 -static void v2_mem2diskdqb(void *dp, struct dquot *dquot)
161 +static void v2r0_mem2diskdqb(void *dp, struct dquot *dquot)
162  {
163 -       struct v2_disk_dqblk *d = dp;
164 +       struct v2r0_disk_dqblk *d = dp;
165         struct mem_dqblk *m = &dquot->dq_dqb;
166         struct qtree_mem_dqinfo *info =
167                         sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
168 @@ -174,9 +207,60 @@ static void v2_mem2diskdqb(void *dp, str
169                 d->dqb_itime = cpu_to_le64(1);
170  }
171  
172 -static int v2_is_id(void *dp, struct dquot *dquot)
173 +static int v2r0_is_id(void *dp, struct dquot *dquot)
174 +{
175 +       struct v2r0_disk_dqblk *d = dp;
176 +       struct qtree_mem_dqinfo *info =
177 +                       sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
178 +
179 +       if (qtree_entry_unused(info, dp))
180 +               return 0;
181 +       return le32_to_cpu(d->dqb_id) == dquot->dq_id;
182 +}
183 +
184 +static void v2r1_disk2memdqb(struct dquot *dquot, void *dp)
185 +{
186 +       struct v2r1_disk_dqblk *d = dp, empty;
187 +       struct mem_dqblk *m = &dquot->dq_dqb;
188 +
189 +       m->dqb_ihardlimit = le64_to_cpu(d->dqb_ihardlimit);
190 +       m->dqb_isoftlimit = le64_to_cpu(d->dqb_isoftlimit);
191 +       m->dqb_curinodes = le64_to_cpu(d->dqb_curinodes);
192 +       m->dqb_itime = le64_to_cpu(d->dqb_itime);
193 +       m->dqb_bhardlimit = v2_qbtos(le64_to_cpu(d->dqb_bhardlimit));
194 +       m->dqb_bsoftlimit = v2_qbtos(le64_to_cpu(d->dqb_bsoftlimit));
195 +       m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
196 +       m->dqb_btime = le64_to_cpu(d->dqb_btime);
197 +       /* We need to escape back all-zero structure */
198 +       memset(&empty, 0, sizeof(struct v2r1_disk_dqblk));
199 +       empty.dqb_itime = cpu_to_le64(1);
200 +       if (!memcmp(&empty, dp, sizeof(struct v2r1_disk_dqblk)))
201 +               m->dqb_itime = 0;
202 +}
203 +
204 +static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot)
205 +{
206 +       struct v2r1_disk_dqblk *d = dp;
207 +       struct mem_dqblk *m = &dquot->dq_dqb;
208 +       struct qtree_mem_dqinfo *info =
209 +                       sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
210 +
211 +       d->dqb_ihardlimit = cpu_to_le64(m->dqb_ihardlimit);
212 +       d->dqb_isoftlimit = cpu_to_le64(m->dqb_isoftlimit);
213 +       d->dqb_curinodes = cpu_to_le64(m->dqb_curinodes);
214 +       d->dqb_itime = cpu_to_le64(m->dqb_itime);
215 +       d->dqb_bhardlimit = cpu_to_le64(v2_stoqb(m->dqb_bhardlimit));
216 +       d->dqb_bsoftlimit = cpu_to_le64(v2_stoqb(m->dqb_bsoftlimit));
217 +       d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
218 +       d->dqb_btime = cpu_to_le64(m->dqb_btime);
219 +       d->dqb_id = cpu_to_le32(dquot->dq_id);
220 +       if (qtree_entry_unused(info, dp))
221 +               d->dqb_itime = cpu_to_le64(1);
222 +}
223 +
224 +static int v2r1_is_id(void *dp, struct dquot *dquot)
225  {
226 -       struct v2_disk_dqblk *d = dp;
227 +       struct v2r1_disk_dqblk *d = dp;
228         struct qtree_mem_dqinfo *info =
229                         sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
230  
231 diff -puN fs/quotaio_v2.h~quota-support-64-bit-quota-format fs/quotaio_v2.h
232 --- a/fs/quotaio_v2.h~quota-support-64-bit-quota-format
233 +++ a/fs/quotaio_v2.h
234 @@ -17,8 +17,8 @@
235  }
236  
237  #define V2_INITQVERSIONS {\
238 -       0,              /* USRQUOTA */\
239 -       0               /* GRPQUOTA */\
240 +       1,              /* USRQUOTA */\
241 +       1               /* GRPQUOTA */\
242  }
243  
244  /* First generic header */
245 @@ -28,11 +28,11 @@ struct v2_disk_dqheader {
246  };
247  
248  /*
249 - * The following structure defines the format of the disk quota file
250 - * (as it appears on disk) - the file is a radix tree whose leaves point
251 - * to blocks of these structures.
252 + * The following structure defines the format of the disk quota file in version
253 + * 0 - the file is a radix tree whose leaves point to blocks of these
254 + * structures.
255   */
256 -struct v2_disk_dqblk {
257 +struct v2r0_disk_dqblk {
258         __le32 dqb_id;          /* id this quota applies to */
259         __le32 dqb_ihardlimit;  /* absolute limit on allocated inodes */
260         __le32 dqb_isoftlimit;  /* preferred inode limit */
261 @@ -44,6 +44,20 @@ struct v2_disk_dqblk {
262         __le64 dqb_itime;       /* time limit for excessive inode use */
263  };
264  
265 +/* The same structure in quota file version 1 */
266 +struct v2r1_disk_dqblk {
267 +       __le32 dqb_id;          /* id this quota applies to */
268 +       __le32 dqb_padding;     /* padding field */
269 +       __le64 dqb_ihardlimit;  /* absolute limit on allocated inodes */
270 +       __le64 dqb_isoftlimit;  /* preferred inode limit */
271 +       __le64 dqb_curinodes;   /* current # allocated inodes */
272 +       __le64 dqb_bhardlimit;  /* absolute limit on disk space */
273 +       __le64 dqb_bsoftlimit;  /* preferred limit on disk space */
274 +       __le64 dqb_curspace;    /* current space occupied (in bytes) */
275 +       __le64 dqb_btime;       /* time limit for excessive disk use */
276 +       __le64 dqb_itime;       /* time limit for excessive inode use */
277 +};
278 +
279  /* Header with type and version specific information */
280  struct v2_disk_dqinfo {
281         __le32 dqi_bgrace;      /* Time before block soft limit becomes hard limit */
282 _