1 #include <linux/errno.h>
3 #include <linux/quota.h>
4 #include <linux/quotaops.h>
5 #include <linux/dqblk_v1.h>
6 #include <linux/quotaio_v1.h>
7 #include <linux/kernel.h>
8 #include <linux/init.h>
9 #include <linux/module.h>
11 #include <asm/byteorder.h>
13 MODULE_AUTHOR("Jan Kara");
14 MODULE_DESCRIPTION("Old quota format support");
15 MODULE_LICENSE("GPL");
17 static void v1_disk2mem_dqblk(struct mem_dqblk
*m
, struct v1_disk_dqblk
*d
)
19 m
->dqb_ihardlimit
= d
->dqb_ihardlimit
;
20 m
->dqb_isoftlimit
= d
->dqb_isoftlimit
;
21 m
->dqb_curinodes
= d
->dqb_curinodes
;
22 m
->dqb_bhardlimit
= d
->dqb_bhardlimit
;
23 m
->dqb_bsoftlimit
= d
->dqb_bsoftlimit
;
24 m
->dqb_curspace
= ((qsize_t
)d
->dqb_curblocks
) << QUOTABLOCK_BITS
;
25 m
->dqb_itime
= d
->dqb_itime
;
26 m
->dqb_btime
= d
->dqb_btime
;
29 static void v1_mem2disk_dqblk(struct v1_disk_dqblk
*d
, struct mem_dqblk
*m
)
31 d
->dqb_ihardlimit
= m
->dqb_ihardlimit
;
32 d
->dqb_isoftlimit
= m
->dqb_isoftlimit
;
33 d
->dqb_curinodes
= m
->dqb_curinodes
;
34 d
->dqb_bhardlimit
= m
->dqb_bhardlimit
;
35 d
->dqb_bsoftlimit
= m
->dqb_bsoftlimit
;
36 d
->dqb_curblocks
= toqb(m
->dqb_curspace
);
37 d
->dqb_itime
= m
->dqb_itime
;
38 d
->dqb_btime
= m
->dqb_btime
;
41 static int v1_read_dqblk(struct dquot
*dquot
)
43 int type
= dquot
->dq_type
;
44 struct v1_disk_dqblk dqblk
;
46 if (!sb_dqopt(dquot
->dq_sb
)->files
[type
])
49 /* Set structure to 0s in case read fails/is after end of file */
50 memset(&dqblk
, 0, sizeof(struct v1_disk_dqblk
));
51 dquot
->dq_sb
->s_op
->quota_read(dquot
->dq_sb
, type
, (char *)&dqblk
, sizeof(struct v1_disk_dqblk
), v1_dqoff(dquot
->dq_id
));
53 v1_disk2mem_dqblk(&dquot
->dq_dqb
, &dqblk
);
54 if (dquot
->dq_dqb
.dqb_bhardlimit
== 0 && dquot
->dq_dqb
.dqb_bsoftlimit
== 0 &&
55 dquot
->dq_dqb
.dqb_ihardlimit
== 0 && dquot
->dq_dqb
.dqb_isoftlimit
== 0)
56 set_bit(DQ_FAKE_B
, &dquot
->dq_flags
);
62 static int v1_commit_dqblk(struct dquot
*dquot
)
64 short type
= dquot
->dq_type
;
66 struct v1_disk_dqblk dqblk
;
68 v1_mem2disk_dqblk(&dqblk
, &dquot
->dq_dqb
);
69 if (dquot
->dq_id
== 0) {
70 dqblk
.dqb_btime
= sb_dqopt(dquot
->dq_sb
)->info
[type
].dqi_bgrace
;
71 dqblk
.dqb_itime
= sb_dqopt(dquot
->dq_sb
)->info
[type
].dqi_igrace
;
74 if (sb_dqopt(dquot
->dq_sb
)->files
[type
])
75 ret
= dquot
->dq_sb
->s_op
->quota_write(dquot
->dq_sb
, type
, (char *)&dqblk
,
76 sizeof(struct v1_disk_dqblk
), v1_dqoff(dquot
->dq_id
));
77 if (ret
!= sizeof(struct v1_disk_dqblk
)) {
78 printk(KERN_WARNING
"VFS: dquota write failed on dev %s\n",
92 /* Magics of new quota format */
93 #define V2_INITQMAGICS {\
94 0xd9c01f11, /* USRQUOTA */\
95 0xd9c01927 /* GRPQUOTA */\
98 /* Header of new quota format */
99 struct v2_disk_dqheader
{
100 __le32 dqh_magic
; /* Magic number identifying file */
101 __le32 dqh_version
; /* File version */
104 static int v1_check_quota_file(struct super_block
*sb
, int type
)
106 struct inode
*inode
= sb_dqopt(sb
)->files
[type
];
109 struct v2_disk_dqheader dqhead
;
112 static const uint quota_magics
[] = V2_INITQMAGICS
;
114 isize
= i_size_read(inode
);
117 blocks
= isize
>> BLOCK_SIZE_BITS
;
118 off
= isize
& (BLOCK_SIZE
- 1);
119 if ((blocks
% sizeof(struct v1_disk_dqblk
) * BLOCK_SIZE
+ off
) % sizeof(struct v1_disk_dqblk
))
121 /* Doublecheck whether we didn't get file with new format - with old quotactl() this could happen */
122 size
= sb
->s_op
->quota_read(sb
, type
, (char *)&dqhead
, sizeof(struct v2_disk_dqheader
), 0);
123 if (size
!= sizeof(struct v2_disk_dqheader
))
124 return 1; /* Probably not new format */
125 if (le32_to_cpu(dqhead
.dqh_magic
) != quota_magics
[type
])
126 return 1; /* Definitely not new format */
127 printk(KERN_INFO
"VFS: %s: Refusing to turn on old quota format on given file. It probably contains newer quota format.\n", sb
->s_id
);
128 return 0; /* Seems like a new format file -> refuse it */
131 static int v1_read_file_info(struct super_block
*sb
, int type
)
133 struct quota_info
*dqopt
= sb_dqopt(sb
);
134 struct v1_disk_dqblk dqblk
;
137 if ((ret
= sb
->s_op
->quota_read(sb
, type
, (char *)&dqblk
, sizeof(struct v1_disk_dqblk
), v1_dqoff(0))) != sizeof(struct v1_disk_dqblk
)) {
143 /* limits are stored as unsigned 32-bit data */
144 dqopt
->info
[type
].dqi_maxblimit
= 0xffffffff;
145 dqopt
->info
[type
].dqi_maxilimit
= 0xffffffff;
146 dqopt
->info
[type
].dqi_igrace
= dqblk
.dqb_itime
? dqblk
.dqb_itime
: MAX_IQ_TIME
;
147 dqopt
->info
[type
].dqi_bgrace
= dqblk
.dqb_btime
? dqblk
.dqb_btime
: MAX_DQ_TIME
;
152 static int v1_write_file_info(struct super_block
*sb
, int type
)
154 struct quota_info
*dqopt
= sb_dqopt(sb
);
155 struct v1_disk_dqblk dqblk
;
158 dqopt
->info
[type
].dqi_flags
&= ~DQF_INFO_DIRTY
;
159 if ((ret
= sb
->s_op
->quota_read(sb
, type
, (char *)&dqblk
,
160 sizeof(struct v1_disk_dqblk
), v1_dqoff(0))) != sizeof(struct v1_disk_dqblk
)) {
165 dqblk
.dqb_itime
= dqopt
->info
[type
].dqi_igrace
;
166 dqblk
.dqb_btime
= dqopt
->info
[type
].dqi_bgrace
;
167 ret
= sb
->s_op
->quota_write(sb
, type
, (char *)&dqblk
,
168 sizeof(struct v1_disk_dqblk
), v1_dqoff(0));
169 if (ret
== sizeof(struct v1_disk_dqblk
))
177 static struct quota_format_ops v1_format_ops
= {
178 .check_quota_file
= v1_check_quota_file
,
179 .read_file_info
= v1_read_file_info
,
180 .write_file_info
= v1_write_file_info
,
181 .free_file_info
= NULL
,
182 .read_dqblk
= v1_read_dqblk
,
183 .commit_dqblk
= v1_commit_dqblk
,
186 static struct quota_format_type v1_quota_format
= {
187 .qf_fmt_id
= QFMT_VFS_OLD
,
188 .qf_ops
= &v1_format_ops
,
189 .qf_owner
= THIS_MODULE
192 static int __init
init_v1_quota_format(void)
194 return register_quota_format(&v1_quota_format
);
197 static void __exit
exit_v1_quota_format(void)
199 unregister_quota_format(&v1_quota_format
);
202 module_init(init_v1_quota_format
);
203 module_exit(exit_v1_quota_format
);