Merge git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb
[sfrench/cifs-2.6.git] / fs / xfs / xfs_alloc.h
index 2d1f8928b2677dcb153cc8c9448ce41b3034fd83..5aec15d0651e836191d794edecddebc797cdf32c 100644 (file)
@@ -41,6 +41,27 @@ typedef enum xfs_alloctype
  * Flags for xfs_alloc_fix_freelist.
  */
 #define        XFS_ALLOC_FLAG_TRYLOCK  0x00000001  /* use trylock for buffer locking */
+#define        XFS_ALLOC_FLAG_FREEING  0x00000002  /* indicate caller is freeing extents*/
+
+/*
+ * In order to avoid ENOSPC-related deadlock caused by
+ * out-of-order locking of AGF buffer (PV 947395), we place
+ * constraints on the relationship among actual allocations for
+ * data blocks, freelist blocks, and potential file data bmap
+ * btree blocks. However, these restrictions may result in no
+ * actual space allocated for a delayed extent, for example, a data
+ * block in a certain AG is allocated but there is no additional
+ * block for the additional bmap btree block due to a split of the
+ * bmap btree of the file. The result of this may lead to an
+ * infinite loop in xfssyncd when the file gets flushed to disk and
+ * all delayed extents need to be actually allocated. To get around
+ * this, we explicitly set aside a few blocks which will not be
+ * reserved in delayed allocation. Considering the minimum number of
+ * needed freelist blocks is 4 fsbs _per AG_, a potential split of file's bmap
+ * btree requires 1 fsb, so we set the number of set-aside blocks
+ * to 4 + 4*agcount.
+ */
+#define XFS_ALLOC_SET_ASIDE(mp)  (4 + ((mp)->m_sb.sb_agcount * 4))
 
 /*
  * Argument structure for xfs_alloc routines.
@@ -70,6 +91,7 @@ typedef struct xfs_alloc_arg {
        char            wasfromfl;      /* set if allocation is from freelist */
        char            isfl;           /* set if is freelist blocks - !acctg */
        char            userdata;       /* set if this is user data */
+       xfs_fsblock_t   firstblock;     /* io first block allocated */
 } xfs_alloc_arg_t;
 
 /*
@@ -114,7 +136,8 @@ int                         /* error */
 xfs_alloc_get_freelist(
        struct xfs_trans *tp,   /* transaction pointer */
        struct xfs_buf  *agbp,  /* buffer containing the agf structure */
-       xfs_agblock_t   *bnop); /* block address retrieved from freelist */
+       xfs_agblock_t   *bnop,  /* block address retrieved from freelist */
+       int             btreeblk); /* destination is a AGF btree */
 
 /*
  * Log the given fields from the agf structure.
@@ -143,7 +166,8 @@ xfs_alloc_put_freelist(
        struct xfs_trans *tp,   /* transaction pointer */
        struct xfs_buf  *agbp,  /* buffer for a.g. freelist header */
        struct xfs_buf  *agflbp,/* buffer for a.g. free block array */
-       xfs_agblock_t   bno);   /* block being freed */
+       xfs_agblock_t   bno,    /* block being freed */
+       int             btreeblk); /* owner was a AGF btree */
 
 /*
  * Read in the allocation group header (free/alloc section).