1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * vfsv0 quota IO operations on file 4 */ 5 6 #include <linux/errno.h> 7 #include <linux/fs.h> 8 #include <linux/mount.h> 9 #include <linux/dqblk_v2.h> 10 #include <linux/kernel.h> 11 #include <linux/init.h> 12 #include <linux/module.h> 13 #include <linux/slab.h> 14 #include <linux/quotaops.h> 15 16 #include <asm/byteorder.h> 17 18 #include "quota_tree.h" 19 #include "quotaio_v2.h" 20 21 MODULE_AUTHOR("Jan Kara"); 22 MODULE_DESCRIPTION("Quota format v2 support"); 23 MODULE_LICENSE("GPL"); 24 25 static void v2r0_mem2diskdqb(void *dp, struct dquot *dquot); 26 static void v2r0_disk2memdqb(struct dquot *dquot, void *dp); 27 static int v2r0_is_id(void *dp, struct dquot *dquot); 28 static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot); 29 static void v2r1_disk2memdqb(struct dquot *dquot, void *dp); 30 static int v2r1_is_id(void *dp, struct dquot *dquot); 31 32 static const struct qtree_fmt_operations v2r0_qtree_ops = { 33 .mem2disk_dqblk = v2r0_mem2diskdqb, 34 .disk2mem_dqblk = v2r0_disk2memdqb, 35 .is_id = v2r0_is_id, 36 }; 37 38 static const struct qtree_fmt_operations v2r1_qtree_ops = { 39 .mem2disk_dqblk = v2r1_mem2diskdqb, 40 .disk2mem_dqblk = v2r1_disk2memdqb, 41 .is_id = v2r1_is_id, 42 }; 43 44 #define QUOTABLOCK_BITS 10 45 #define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS) 46 47 static inline qsize_t v2_stoqb(qsize_t space) 48 { 49 return (space + QUOTABLOCK_SIZE - 1) >> QUOTABLOCK_BITS; 50 } 51 52 static inline qsize_t v2_qbtos(qsize_t blocks) 53 { 54 return blocks << QUOTABLOCK_BITS; 55 } 56 57 static int v2_read_header(struct super_block *sb, int type, 58 struct v2_disk_dqheader *dqhead) 59 { 60 ssize_t size; 61 62 size = sb->s_op->quota_read(sb, type, (char *)dqhead, 63 sizeof(struct v2_disk_dqheader), 0); 64 if (size != sizeof(struct v2_disk_dqheader)) { 65 quota_error(sb, "Failed header read: expected=%zd got=%zd", 66 sizeof(struct v2_disk_dqheader), size); 67 if (size < 0) 68 return size; 69 return -EIO; 70 } 71 return 0; 72 } 73 74 /* Check whether given file is really vfsv0 quotafile */ 75 static int v2_check_quota_file(struct super_block *sb, int type) 76 { 77 struct v2_disk_dqheader dqhead; 78 static const uint quota_magics[] = V2_INITQMAGICS; 79 static const uint quota_versions[] = V2_INITQVERSIONS; 80 81 if (v2_read_header(sb, type, &dqhead)) 82 return 0; 83 if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] || 84 le32_to_cpu(dqhead.dqh_version) > quota_versions[type]) 85 return 0; 86 return 1; 87 } 88 89 /* Read information header from quota file */ 90 static int v2_read_file_info(struct super_block *sb, int type) 91 { 92 struct v2_disk_dqinfo dinfo; 93 struct v2_disk_dqheader dqhead; 94 struct quota_info *dqopt = sb_dqopt(sb); 95 struct mem_dqinfo *info = &dqopt->info[type]; 96 struct qtree_mem_dqinfo *qinfo; 97 ssize_t size; 98 unsigned int version; 99 unsigned int memalloc; 100 int ret; 101 102 down_read(&dqopt->dqio_sem); 103 memalloc = memalloc_nofs_save(); 104 ret = v2_read_header(sb, type, &dqhead); 105 if (ret < 0) 106 goto out; 107 version = le32_to_cpu(dqhead.dqh_version); 108 if ((info->dqi_fmt_id == QFMT_VFS_V0 && version != 0) || 109 (info->dqi_fmt_id == QFMT_VFS_V1 && version != 1)) { 110 ret = -EINVAL; 111 goto out; 112 } 113 114 size = sb->s_op->quota_read(sb, type, (char *)&dinfo, 115 sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF); 116 if (size != sizeof(struct v2_disk_dqinfo)) { 117 quota_error(sb, "Can't read info structure"); 118 if (size < 0) 119 ret = size; 120 else 121 ret = -EIO; 122 goto out; 123 } 124 info->dqi_priv = kmalloc(sizeof(struct qtree_mem_dqinfo), GFP_KERNEL); 125 if (!info->dqi_priv) { 126 ret = -ENOMEM; 127 goto out; 128 } 129 qinfo = info->dqi_priv; 130 if (version == 0) { 131 /* limits are stored as unsigned 32-bit data */ 132 info->dqi_max_spc_limit = 0xffffffffLL << QUOTABLOCK_BITS; 133 info->dqi_max_ino_limit = 0xffffffff; 134 } else { 135 /* 136 * Used space is stored as unsigned 64-bit value in bytes but 137 * quota core supports only signed 64-bit values so use that 138 * as a limit 139 */ 140 info->dqi_max_spc_limit = 0x7fffffffffffffffLL; /* 2^63-1 */ 141 info->dqi_max_ino_limit = 0x7fffffffffffffffLL; 142 } 143 info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace); 144 info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace); 145 /* No flags currently supported */ 146 info->dqi_flags = 0; 147 qinfo->dqi_sb = sb; 148 qinfo->dqi_type = type; 149 qinfo->dqi_blocks = le32_to_cpu(dinfo.dqi_blocks); 150 qinfo->dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk); 151 qinfo->dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry); 152 qinfo->dqi_blocksize_bits = V2_DQBLKSIZE_BITS; 153 qinfo->dqi_usable_bs = 1 << V2_DQBLKSIZE_BITS; 154 qinfo->dqi_qtree_depth = qtree_depth(qinfo); 155 if (version == 0) { 156 qinfo->dqi_entry_size = sizeof(struct v2r0_disk_dqblk); 157 qinfo->dqi_ops = &v2r0_qtree_ops; 158 } else { 159 qinfo->dqi_entry_size = sizeof(struct v2r1_disk_dqblk); 160 qinfo->dqi_ops = &v2r1_qtree_ops; 161 } 162 ret = -EUCLEAN; 163 /* Some sanity checks of the read headers... */ 164 if ((loff_t)qinfo->dqi_blocks << qinfo->dqi_blocksize_bits > 165 i_size_read(sb_dqopt(sb)->files[type])) { 166 quota_error(sb, "Number of blocks too big for quota file size (%llu > %llu).", 167 (loff_t)qinfo->dqi_blocks << qinfo->dqi_blocksize_bits, 168 i_size_read(sb_dqopt(sb)->files[type])); 169 goto out_free; 170 } 171 if (qinfo->dqi_free_blk && (qinfo->dqi_free_blk <= QT_TREEOFF || 172 qinfo->dqi_free_blk >= qinfo->dqi_blocks)) { 173 quota_error(sb, "Free block number %u out of range (%u, %u).", 174 qinfo->dqi_free_blk, QT_TREEOFF, qinfo->dqi_blocks); 175 goto out_free; 176 } 177 if (qinfo->dqi_free_entry && (qinfo->dqi_free_entry <= QT_TREEOFF || 178 qinfo->dqi_free_entry >= qinfo->dqi_blocks)) { 179 quota_error(sb, "Block with free entry %u out of range (%u, %u).", 180 qinfo->dqi_free_entry, QT_TREEOFF, 181 qinfo->dqi_blocks); 182 goto out_free; 183 } 184 ret = 0; 185 out_free: 186 if (ret) { 187 kfree(info->dqi_priv); 188 info->dqi_priv = NULL; 189 } 190 out: 191 memalloc_nofs_restore(memalloc); 192 up_read(&dqopt->dqio_sem); 193 return ret; 194 } 195 196 /* Write information header to quota file */ 197 static int v2_write_file_info(struct super_block *sb, int type) 198 { 199 struct v2_disk_dqinfo dinfo; 200 struct quota_info *dqopt = sb_dqopt(sb); 201 struct mem_dqinfo *info = &dqopt->info[type]; 202 struct qtree_mem_dqinfo *qinfo = info->dqi_priv; 203 ssize_t size; 204 unsigned int memalloc; 205 206 down_write(&dqopt->dqio_sem); 207 memalloc = memalloc_nofs_save(); 208 spin_lock(&dq_data_lock); 209 info->dqi_flags &= ~DQF_INFO_DIRTY; 210 dinfo.dqi_bgrace = cpu_to_le32(info->dqi_bgrace); 211 dinfo.dqi_igrace = cpu_to_le32(info->dqi_igrace); 212 /* No flags currently supported */ 213 dinfo.dqi_flags = cpu_to_le32(0); 214 spin_unlock(&dq_data_lock); 215 dinfo.dqi_blocks = cpu_to_le32(qinfo->dqi_blocks); 216 dinfo.dqi_free_blk = cpu_to_le32(qinfo->dqi_free_blk); 217 dinfo.dqi_free_entry = cpu_to_le32(qinfo->dqi_free_entry); 218 size = sb->s_op->quota_write(sb, type, (char *)&dinfo, 219 sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF); 220 memalloc_nofs_restore(memalloc); 221 up_write(&dqopt->dqio_sem); 222 if (size != sizeof(struct v2_disk_dqinfo)) { 223 quota_error(sb, "Can't write info structure"); 224 return size < 0 ? size : -EIO; 225 } 226 return 0; 227 } 228 229 static void v2r0_disk2memdqb(struct dquot *dquot, void *dp) 230 { 231 struct v2r0_disk_dqblk *d = dp, empty; 232 struct mem_dqblk *m = &dquot->dq_dqb; 233 234 m->dqb_ihardlimit = le32_to_cpu(d->dqb_ihardlimit); 235 m->dqb_isoftlimit = le32_to_cpu(d->dqb_isoftlimit); 236 m->dqb_curinodes = le32_to_cpu(d->dqb_curinodes); 237 m->dqb_itime = le64_to_cpu(d->dqb_itime); 238 m->dqb_bhardlimit = v2_qbtos(le32_to_cpu(d->dqb_bhardlimit)); 239 m->dqb_bsoftlimit = v2_qbtos(le32_to_cpu(d->dqb_bsoftlimit)); 240 m->dqb_curspace = le64_to_cpu(d->dqb_curspace); 241 m->dqb_btime = le64_to_cpu(d->dqb_btime); 242 /* We need to escape back all-zero structure */ 243 memset(&empty, 0, sizeof(struct v2r0_disk_dqblk)); 244 empty.dqb_itime = cpu_to_le64(1); 245 if (!memcmp(&empty, dp, sizeof(struct v2r0_disk_dqblk))) 246 m->dqb_itime = 0; 247 } 248 249 static void v2r0_mem2diskdqb(void *dp, struct dquot *dquot) 250 { 251 struct v2r0_disk_dqblk *d = dp; 252 struct mem_dqblk *m = &dquot->dq_dqb; 253 struct qtree_mem_dqinfo *info = 254 sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv; 255 256 d->dqb_ihardlimit = cpu_to_le32(m->dqb_ihardlimit); 257 d->dqb_isoftlimit = cpu_to_le32(m->dqb_isoftlimit); 258 d->dqb_curinodes = cpu_to_le32(m->dqb_curinodes); 259 d->dqb_itime = cpu_to_le64(m->dqb_itime); 260 d->dqb_bhardlimit = cpu_to_le32(v2_stoqb(m->dqb_bhardlimit)); 261 d->dqb_bsoftlimit = cpu_to_le32(v2_stoqb(m->dqb_bsoftlimit)); 262 d->dqb_curspace = cpu_to_le64(m->dqb_curspace); 263 d->dqb_btime = cpu_to_le64(m->dqb_btime); 264 d->dqb_id = cpu_to_le32(from_kqid(&init_user_ns, dquot->dq_id)); 265 if (qtree_entry_unused(info, dp)) 266 d->dqb_itime = cpu_to_le64(1); 267 } 268 269 static int v2r0_is_id(void *dp, struct dquot *dquot) 270 { 271 struct v2r0_disk_dqblk *d = dp; 272 struct qtree_mem_dqinfo *info = 273 sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv; 274 275 if (qtree_entry_unused(info, dp)) 276 return 0; 277 return qid_eq(make_kqid(&init_user_ns, dquot->dq_id.type, 278 le32_to_cpu(d->dqb_id)), 279 dquot->dq_id); 280 } 281 282 static void v2r1_disk2memdqb(struct dquot *dquot, void *dp) 283 { 284 struct v2r1_disk_dqblk *d = dp, empty; 285 struct mem_dqblk *m = &dquot->dq_dqb; 286 287 m->dqb_ihardlimit = le64_to_cpu(d->dqb_ihardlimit); 288 m->dqb_isoftlimit = le64_to_cpu(d->dqb_isoftlimit); 289 m->dqb_curinodes = le64_to_cpu(d->dqb_curinodes); 290 m->dqb_itime = le64_to_cpu(d->dqb_itime); 291 m->dqb_bhardlimit = v2_qbtos(le64_to_cpu(d->dqb_bhardlimit)); 292 m->dqb_bsoftlimit = v2_qbtos(le64_to_cpu(d->dqb_bsoftlimit)); 293 m->dqb_curspace = le64_to_cpu(d->dqb_curspace); 294 m->dqb_btime = le64_to_cpu(d->dqb_btime); 295 /* We need to escape back all-zero structure */ 296 memset(&empty, 0, sizeof(struct v2r1_disk_dqblk)); 297 empty.dqb_itime = cpu_to_le64(1); 298 if (!memcmp(&empty, dp, sizeof(struct v2r1_disk_dqblk))) 299 m->dqb_itime = 0; 300 } 301 302 static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot) 303 { 304 struct v2r1_disk_dqblk *d = dp; 305 struct mem_dqblk *m = &dquot->dq_dqb; 306 struct qtree_mem_dqinfo *info = 307 sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv; 308 309 d->dqb_ihardlimit = cpu_to_le64(m->dqb_ihardlimit); 310 d->dqb_isoftlimit = cpu_to_le64(m->dqb_isoftlimit); 311 d->dqb_curinodes = cpu_to_le64(m->dqb_curinodes); 312 d->dqb_itime = cpu_to_le64(m->dqb_itime); 313 d->dqb_bhardlimit = cpu_to_le64(v2_stoqb(m->dqb_bhardlimit)); 314 d->dqb_bsoftlimit = cpu_to_le64(v2_stoqb(m->dqb_bsoftlimit)); 315 d->dqb_curspace = cpu_to_le64(m->dqb_curspace); 316 d->dqb_btime = cpu_to_le64(m->dqb_btime); 317 d->dqb_id = cpu_to_le32(from_kqid(&init_user_ns, dquot->dq_id)); 318 d->dqb_pad = 0; 319 if (qtree_entry_unused(info, dp)) 320 d->dqb_itime = cpu_to_le64(1); 321 } 322 323 static int v2r1_is_id(void *dp, struct dquot *dquot) 324 { 325 struct v2r1_disk_dqblk *d = dp; 326 struct qtree_mem_dqinfo *info = 327 sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv; 328 329 if (qtree_entry_unused(info, dp)) 330 return 0; 331 return qid_eq(make_kqid(&init_user_ns, dquot->dq_id.type, 332 le32_to_cpu(d->dqb_id)), 333 dquot->dq_id); 334 } 335 336 static int v2_read_dquot(struct dquot *dquot) 337 { 338 struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); 339 int ret; 340 unsigned int memalloc; 341 342 down_read(&dqopt->dqio_sem); 343 memalloc = memalloc_nofs_save(); 344 ret = qtree_read_dquot( 345 sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv, 346 dquot); 347 memalloc_nofs_restore(memalloc); 348 up_read(&dqopt->dqio_sem); 349 return ret; 350 } 351 352 static int v2_write_dquot(struct dquot *dquot) 353 { 354 struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); 355 int ret; 356 bool alloc = false; 357 unsigned int memalloc; 358 359 /* 360 * If space for dquot is already allocated, we don't need any 361 * protection as we'll only overwrite the place of dquot. We are 362 * still protected by concurrent writes of the same dquot by 363 * dquot->dq_lock. 364 */ 365 if (!dquot->dq_off) { 366 alloc = true; 367 down_write(&dqopt->dqio_sem); 368 } else { 369 down_read(&dqopt->dqio_sem); 370 } 371 memalloc = memalloc_nofs_save(); 372 ret = qtree_write_dquot( 373 sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv, 374 dquot); 375 memalloc_nofs_restore(memalloc); 376 if (alloc) 377 up_write(&dqopt->dqio_sem); 378 else 379 up_read(&dqopt->dqio_sem); 380 return ret; 381 } 382 383 static int v2_release_dquot(struct dquot *dquot) 384 { 385 struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); 386 unsigned int memalloc; 387 int ret; 388 389 down_write(&dqopt->dqio_sem); 390 memalloc = memalloc_nofs_save(); 391 ret = qtree_release_dquot(sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv, dquot); 392 memalloc_nofs_restore(memalloc); 393 up_write(&dqopt->dqio_sem); 394 395 return ret; 396 } 397 398 static int v2_free_file_info(struct super_block *sb, int type) 399 { 400 kfree(sb_dqinfo(sb, type)->dqi_priv); 401 return 0; 402 } 403 404 static int v2_get_next_id(struct super_block *sb, struct kqid *qid) 405 { 406 struct quota_info *dqopt = sb_dqopt(sb); 407 unsigned int memalloc; 408 int ret; 409 410 down_read(&dqopt->dqio_sem); 411 memalloc = memalloc_nofs_save(); 412 ret = qtree_get_next_id(sb_dqinfo(sb, qid->type)->dqi_priv, qid); 413 memalloc_nofs_restore(memalloc); 414 up_read(&dqopt->dqio_sem); 415 return ret; 416 } 417 418 static const struct quota_format_ops v2_format_ops = { 419 .check_quota_file = v2_check_quota_file, 420 .read_file_info = v2_read_file_info, 421 .write_file_info = v2_write_file_info, 422 .free_file_info = v2_free_file_info, 423 .read_dqblk = v2_read_dquot, 424 .commit_dqblk = v2_write_dquot, 425 .release_dqblk = v2_release_dquot, 426 .get_next_id = v2_get_next_id, 427 }; 428 429 static struct quota_format_type v2r0_quota_format = { 430 .qf_fmt_id = QFMT_VFS_V0, 431 .qf_ops = &v2_format_ops, 432 .qf_owner = THIS_MODULE 433 }; 434 435 static struct quota_format_type v2r1_quota_format = { 436 .qf_fmt_id = QFMT_VFS_V1, 437 .qf_ops = &v2_format_ops, 438 .qf_owner = THIS_MODULE 439 }; 440 441 static int __init init_v2_quota_format(void) 442 { 443 int ret; 444 445 ret = register_quota_format(&v2r0_quota_format); 446 if (ret) 447 return ret; 448 return register_quota_format(&v2r1_quota_format); 449 } 450 451 static void __exit exit_v2_quota_format(void) 452 { 453 unregister_quota_format(&v2r0_quota_format); 454 unregister_quota_format(&v2r1_quota_format); 455 } 456 457 module_init(init_v2_quota_format); 458 module_exit(exit_v2_quota_format); 459
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.