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