LCOV - code coverage report
Current view: top level - fs/xfs/libxfs - xfs_dquot_buf.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc4-xfsx @ Mon Jul 31 20:08:34 PDT 2023 Lines: 95 112 84.8 %
Date: 2023-07-31 20:08:34 Functions: 11 12 91.7 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Copyright (c) 2000-2006 Silicon Graphics, Inc.
       4             :  * Copyright (c) 2013 Red Hat, Inc.
       5             :  * All Rights Reserved.
       6             :  */
       7             : #include "xfs.h"
       8             : #include "xfs_fs.h"
       9             : #include "xfs_shared.h"
      10             : #include "xfs_format.h"
      11             : #include "xfs_log_format.h"
      12             : #include "xfs_trans_resv.h"
      13             : #include "xfs_mount.h"
      14             : #include "xfs_inode.h"
      15             : #include "xfs_quota.h"
      16             : #include "xfs_trans.h"
      17             : #include "xfs_qm.h"
      18             : #include "xfs_error.h"
      19             : 
      20             : int
      21     7743768 : xfs_calc_dquots_per_chunk(
      22             :         unsigned int            nbblks) /* basic block units */
      23             : {
      24     7743768 :         ASSERT(nbblks > 0);
      25     7743768 :         return BBTOB(nbblks) / sizeof(struct xfs_dqblk);
      26             : }
      27             : 
      28             : /*
      29             :  * Do some primitive error checking on ondisk dquot data structures.
      30             :  *
      31             :  * The xfs_dqblk structure /contains/ the xfs_disk_dquot structure;
      32             :  * we verify them separately because at some points we have only the
      33             :  * smaller xfs_disk_dquot structure available.
      34             :  */
      35             : 
      36             : xfs_failaddr_t
      37  1183292612 : xfs_dquot_verify(
      38             :         struct xfs_mount        *mp,
      39             :         struct xfs_disk_dquot   *ddq,
      40             :         xfs_dqid_t              id)     /* used only during quotacheck */
      41             : {
      42  1183292612 :         __u8                    ddq_type;
      43             : 
      44             :         /*
      45             :          * We can encounter an uninitialized dquot buffer for 2 reasons:
      46             :          * 1. If we crash while deleting the quotainode(s), and those blks got
      47             :          *    used for user data. This is because we take the path of regular
      48             :          *    file deletion; however, the size field of quotainodes is never
      49             :          *    updated, so all the tricks that we play in itruncate_finish
      50             :          *    don't quite matter.
      51             :          *
      52             :          * 2. We don't play the quota buffers when there's a quotaoff logitem.
      53             :          *    But the allocation will be replayed so we'll end up with an
      54             :          *    uninitialized quota block.
      55             :          *
      56             :          * This is all fine; things are still consistent, and we haven't lost
      57             :          * any quota information. Just don't complain about bad dquot blks.
      58             :          */
      59  1183292612 :         if (ddq->d_magic != cpu_to_be16(XFS_DQUOT_MAGIC))
      60           0 :                 return __this_address;
      61  1183292612 :         if (ddq->d_version != XFS_DQUOT_VERSION)
      62           0 :                 return __this_address;
      63             : 
      64  1183292612 :         if (ddq->d_type & ~XFS_DQTYPE_ANY)
      65           0 :                 return __this_address;
      66  1183292612 :         ddq_type = ddq->d_type & XFS_DQTYPE_REC_MASK;
      67  1183292612 :         if (ddq_type != XFS_DQTYPE_USER &&
      68  1183292612 :             ddq_type != XFS_DQTYPE_PROJ &&
      69  1183292612 :             ddq_type != XFS_DQTYPE_GROUP)
      70           0 :                 return __this_address;
      71             : 
      72  1183292612 :         if ((ddq->d_type & XFS_DQTYPE_BIGTIME) &&
      73             :             !xfs_has_bigtime(mp))
      74           0 :                 return __this_address;
      75             : 
      76  1183292612 :         if ((ddq->d_type & XFS_DQTYPE_BIGTIME) && !ddq->d_id)
      77           0 :                 return __this_address;
      78             : 
      79  1183292612 :         if (id != -1 && id != be32_to_cpu(ddq->d_id))
      80           0 :                 return __this_address;
      81             : 
      82  1183292612 :         if (!ddq->d_id)
      83             :                 return NULL;
      84             : 
      85  1180265222 :         if (ddq->d_blk_softlimit &&
      86       38553 :             be64_to_cpu(ddq->d_bcount) > be64_to_cpu(ddq->d_blk_softlimit) &&
      87        1601 :             !ddq->d_btimer)
      88           0 :                 return __this_address;
      89             : 
      90  1180265222 :         if (ddq->d_ino_softlimit &&
      91       38403 :             be64_to_cpu(ddq->d_icount) > be64_to_cpu(ddq->d_ino_softlimit) &&
      92        1820 :             !ddq->d_itimer)
      93           0 :                 return __this_address;
      94             : 
      95  1180265222 :         if (ddq->d_rtb_softlimit &&
      96          30 :             be64_to_cpu(ddq->d_rtbcount) > be64_to_cpu(ddq->d_rtb_softlimit) &&
      97           0 :             !ddq->d_rtbtimer)
      98           0 :                 return __this_address;
      99             : 
     100             :         return NULL;
     101             : }
     102             : 
     103             : xfs_failaddr_t
     104  1175835485 : xfs_dqblk_verify(
     105             :         struct xfs_mount        *mp,
     106             :         struct xfs_dqblk        *dqb,
     107             :         xfs_dqid_t              id)     /* used only during quotacheck */
     108             : {
     109  2351663420 :         if (xfs_has_crc(mp) &&
     110  1175827946 :             !uuid_equal(&dqb->dd_uuid, &mp->m_sb.sb_meta_uuid))
     111          90 :                 return __this_address;
     112             : 
     113  1175835384 :         return xfs_dquot_verify(mp, &dqb->dd_diskdq, id);
     114             : }
     115             : 
     116             : /*
     117             :  * Do some primitive error checking on ondisk dquot data structures.
     118             :  */
     119             : void
     120         420 : xfs_dqblk_repair(
     121             :         struct xfs_mount        *mp,
     122             :         struct xfs_dqblk        *dqb,
     123             :         xfs_dqid_t              id,
     124             :         xfs_dqtype_t            type)
     125             : {
     126             :         /*
     127             :          * Typically, a repair is only requested by quotacheck.
     128             :          */
     129         420 :         ASSERT(id != -1);
     130         420 :         memset(dqb, 0, sizeof(struct xfs_dqblk));
     131             : 
     132         420 :         dqb->dd_diskdq.d_magic = cpu_to_be16(XFS_DQUOT_MAGIC);
     133         420 :         dqb->dd_diskdq.d_version = XFS_DQUOT_VERSION;
     134         420 :         dqb->dd_diskdq.d_type = type;
     135         420 :         dqb->dd_diskdq.d_id = cpu_to_be32(id);
     136             : 
     137         420 :         if (xfs_has_crc(mp)) {
     138          90 :                 uuid_copy(&dqb->dd_uuid, &mp->m_sb.sb_meta_uuid);
     139          90 :                 xfs_update_cksum((char *)dqb, sizeof(struct xfs_dqblk),
     140             :                                  XFS_DQUOT_CRC_OFF);
     141             :         }
     142         420 : }
     143             : 
     144             : STATIC bool
     145     3742475 : xfs_dquot_buf_verify_crc(
     146             :         struct xfs_mount        *mp,
     147             :         struct xfs_buf          *bp,
     148             :         bool                    readahead)
     149             : {
     150     3742475 :         struct xfs_dqblk        *d = (struct xfs_dqblk *)bp->b_addr;
     151     3742475 :         int                     ndquots;
     152     3742475 :         int                     i;
     153             : 
     154     3742475 :         if (!xfs_has_crc(mp))
     155             :                 return true;
     156             : 
     157             :         /*
     158             :          * if we are in log recovery, the quota subsystem has not been
     159             :          * initialised so we have no quotainfo structure. In that case, we need
     160             :          * to manually calculate the number of dquots in the buffer.
     161             :          */
     162     3742400 :         if (mp->m_quotainfo)
     163     2865868 :                 ndquots = mp->m_quotainfo->qi_dqperchunk;
     164             :         else
     165      876532 :                 ndquots = xfs_calc_dquots_per_chunk(bp->b_length);
     166             : 
     167   115936259 :         for (i = 0; i < ndquots; i++, d++) {
     168   112193893 :                 if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk),
     169             :                                  XFS_DQUOT_CRC_OFF)) {
     170          34 :                         if (!readahead)
     171          18 :                                 xfs_buf_verifier_error(bp, -EFSBADCRC, __func__,
     172           9 :                                         d, sizeof(*d), __this_address);
     173          34 :                         return false;
     174             :                 }
     175             :         }
     176             :         return true;
     177             : }
     178             : 
     179             : STATIC xfs_failaddr_t
     180    39193322 : xfs_dquot_buf_verify(
     181             :         struct xfs_mount        *mp,
     182             :         struct xfs_buf          *bp,
     183             :         bool                    readahead)
     184             : {
     185    39193322 :         struct xfs_dqblk        *dqb = bp->b_addr;
     186    39193322 :         xfs_failaddr_t          fa;
     187    39193322 :         xfs_dqid_t              id = 0;
     188    39193322 :         int                     ndquots;
     189    39193322 :         int                     i;
     190             : 
     191             :         /*
     192             :          * if we are in log recovery, the quota subsystem has not been
     193             :          * initialised so we have no quotainfo structure. In that case, we need
     194             :          * to manually calculate the number of dquots in the buffer.
     195             :          */
     196    39193322 :         if (mp->m_quotainfo)
     197    32383638 :                 ndquots = mp->m_quotainfo->qi_dqperchunk;
     198             :         else
     199     6809684 :                 ndquots = xfs_calc_dquots_per_chunk(bp->b_length);
     200             : 
     201             :         /*
     202             :          * On the first read of the buffer, verify that each dquot is valid.
     203             :          * We don't know what the id of the dquot is supposed to be, just that
     204             :          * they should be increasing monotonically within the buffer. If the
     205             :          * first id is corrupt, then it will fail on the second dquot in the
     206             :          * buffer so corruptions could point to the wrong dquot in this case.
     207             :          */
     208  1214844173 :         for (i = 0; i < ndquots; i++) {
     209  1175650850 :                 struct xfs_disk_dquot   *ddq;
     210             : 
     211  1175650850 :                 ddq = &dqb[i].dd_diskdq;
     212             : 
     213  1175650850 :                 if (i == 0)
     214    39193322 :                         id = be32_to_cpu(ddq->d_id);
     215             : 
     216  1175650850 :                 fa = xfs_dqblk_verify(mp, &dqb[i], id + i);
     217  1175650851 :                 if (fa) {
     218           0 :                         if (!readahead)
     219           0 :                                 xfs_buf_verifier_error(bp, -EFSCORRUPTED,
     220             :                                         __func__, &dqb[i],
     221             :                                         sizeof(struct xfs_dqblk), fa);
     222           0 :                         return fa;
     223             :                 }
     224             :         }
     225             : 
     226             :         return NULL;
     227             : }
     228             : 
     229             : static xfs_failaddr_t
     230           0 : xfs_dquot_buf_verify_struct(
     231             :         struct xfs_buf          *bp)
     232             : {
     233           0 :         struct xfs_mount        *mp = bp->b_mount;
     234             : 
     235           0 :         return xfs_dquot_buf_verify(mp, bp, false);
     236             : }
     237             : 
     238             : static void
     239     2865943 : xfs_dquot_buf_read_verify(
     240             :         struct xfs_buf          *bp)
     241             : {
     242     2865943 :         struct xfs_mount        *mp = bp->b_mount;
     243             : 
     244     2865943 :         if (!xfs_dquot_buf_verify_crc(mp, bp, false))
     245             :                 return;
     246     2865934 :         xfs_dquot_buf_verify(mp, bp, false);
     247             : }
     248             : 
     249             : /*
     250             :  * readahead errors are silent and simply leave the buffer as !done so a real
     251             :  * read will then be run with the xfs_dquot_buf_ops verifier. See
     252             :  * xfs_inode_buf_verify() for why we use EIO and ~XBF_DONE here rather than
     253             :  * reporting the failure.
     254             :  */
     255             : static void
     256      876532 : xfs_dquot_buf_readahead_verify(
     257             :         struct xfs_buf  *bp)
     258             : {
     259      876532 :         struct xfs_mount        *mp = bp->b_mount;
     260             : 
     261     1753039 :         if (!xfs_dquot_buf_verify_crc(mp, bp, true) ||
     262      876507 :             xfs_dquot_buf_verify(mp, bp, true) != NULL) {
     263          25 :                 xfs_buf_ioerror(bp, -EIO);
     264          25 :                 bp->b_flags &= ~XBF_DONE;
     265             :         }
     266      876532 : }
     267             : 
     268             : /*
     269             :  * we don't calculate the CRC here as that is done when the dquot is flushed to
     270             :  * the buffer after the update is done. This ensures that the dquot in the
     271             :  * buffer always has an up-to-date CRC value.
     272             :  */
     273             : static void
     274    35450884 : xfs_dquot_buf_write_verify(
     275             :         struct xfs_buf          *bp)
     276             : {
     277    35450884 :         struct xfs_mount        *mp = bp->b_mount;
     278             : 
     279    35450884 :         xfs_dquot_buf_verify(mp, bp, false);
     280    35450884 : }
     281             : 
     282             : const struct xfs_buf_ops xfs_dquot_buf_ops = {
     283             :         .name = "xfs_dquot",
     284             :         .magic16 = { cpu_to_be16(XFS_DQUOT_MAGIC),
     285             :                      cpu_to_be16(XFS_DQUOT_MAGIC) },
     286             :         .verify_read = xfs_dquot_buf_read_verify,
     287             :         .verify_write = xfs_dquot_buf_write_verify,
     288             :         .verify_struct = xfs_dquot_buf_verify_struct,
     289             : };
     290             : 
     291             : const struct xfs_buf_ops xfs_dquot_buf_ra_ops = {
     292             :         .name = "xfs_dquot_ra",
     293             :         .magic16 = { cpu_to_be16(XFS_DQUOT_MAGIC),
     294             :                      cpu_to_be16(XFS_DQUOT_MAGIC) },
     295             :         .verify_read = xfs_dquot_buf_readahead_verify,
     296             :         .verify_write = xfs_dquot_buf_write_verify,
     297             : };
     298             : 
     299             : /* Convert an on-disk timer value into an incore timer value. */
     300             : time64_t
     301    96711546 : xfs_dquot_from_disk_ts(
     302             :         struct xfs_disk_dquot   *ddq,
     303             :         __be32                  dtimer)
     304             : {
     305    96711546 :         uint32_t                t = be32_to_cpu(dtimer);
     306             : 
     307    96711546 :         if (t != 0 && (ddq->d_type & XFS_DQTYPE_BIGTIME))
     308        1258 :                 return xfs_dq_bigtime_to_unix(t);
     309             : 
     310    96710288 :         return t;
     311             : }
     312             : 
     313             : /* Convert an incore timer value into an on-disk timer value. */
     314             : __be32
     315 23356791131 : xfs_dquot_to_disk_ts(
     316             :         struct xfs_dquot        *dqp,
     317             :         time64_t                timer)
     318             : {
     319 23356791131 :         uint32_t                t = timer;
     320             : 
     321 23356791131 :         if (timer != 0 && (dqp->q_type & XFS_DQTYPE_BIGTIME))
     322       55982 :                 t = xfs_dq_unix_to_bigtime(timer);
     323             : 
     324 23356791131 :         return cpu_to_be32(t);
     325             : }

Generated by: LCOV version 1.14