xfs: only update mount/resv fields on success in __xfs_ag_resv_init
authorChristoph Hellwig <hch@lst.de>
Wed, 25 Jan 2017 15:49:34 +0000 (07:49 -0800)
committerDarrick J. Wong <darrick.wong@oracle.com>
Wed, 25 Jan 2017 15:49:34 +0000 (07:49 -0800)
Try to reserve the blocks first and only then update the fields in
or hanging off the mount structure.  This way we can call __xfs_ag_resv_init
again after a previous failure.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
fs/xfs/libxfs/xfs_ag_resv.c

index d346d42c54d1590250040f0b36c05367287e7bf5..94234bff40dc98baea71fe3f86651521b590ac72 100644 (file)
@@ -200,22 +200,27 @@ __xfs_ag_resv_init(
        struct xfs_mount                *mp = pag->pag_mount;
        struct xfs_ag_resv              *resv;
        int                             error;
+       xfs_extlen_t                    reserved;
 
-       resv = xfs_perag_resv(pag, type);
        if (used > ask)
                ask = used;
-       resv->ar_asked = ask;
-       resv->ar_reserved = resv->ar_orig_reserved = ask - used;
-       mp->m_ag_max_usable -= ask;
+       reserved = ask - used;
 
-       trace_xfs_ag_resv_init(pag, type, ask);
-
-       error = xfs_mod_fdblocks(mp, -(int64_t)resv->ar_reserved, true);
-       if (error)
+       error = xfs_mod_fdblocks(mp, -(int64_t)reserved, true);
+       if (error) {
                trace_xfs_ag_resv_init_error(pag->pag_mount, pag->pag_agno,
                                error, _RET_IP_);
+               return error;
+       }
 
-       return error;
+       mp->m_ag_max_usable -= ask;
+
+       resv = xfs_perag_resv(pag, type);
+       resv->ar_asked = ask;
+       resv->ar_reserved = resv->ar_orig_reserved = reserved;
+
+       trace_xfs_ag_resv_init(pag, type, ask);
+       return 0;
 }
 
 /* Create a per-AG block reservation. */