]> git.pld-linux.org Git - packages/xfsprogs.git/blob - misc.patch
- rel 3; misc fixes from upstream (to be dropped when merged; merged possibly in...
[packages/xfsprogs.git] / misc.patch
1 From: Darrick J. Wong <darrick.wong@oracle.com>\r
2 \r
3 When we added a new defer op type for agfl block freeing to the kernel,\r
4 we forgot to add that type to the userspace side of things.  This will\r
5 cause spontaneous combustion in xfs_repair if we try to rebuild\r
6 directories.\r
7 \r
8 Fixes: d5c1b462232 ("xfs: defer agfl block frees when dfops is available")\r
9 Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>\r
10 ---\r
11  libxfs/defer_item.c |   44 ++++++++++++++++++++++++++++++++++++++++++++\r
12  1 file changed, 44 insertions(+)\r
13 \r
14 diff --git a/libxfs/defer_item.c b/libxfs/defer_item.c\r
15 index b7185c1a..82aa32a8 100644\r
16 --- a/libxfs/defer_item.c\r
17 +++ b/libxfs/defer_item.c\r
18 @@ -118,11 +118,55 @@ static const struct xfs_defer_op_type xfs_extent_free_defer_type = {\r
19         .cancel_item    = xfs_extent_free_cancel_item,\r
20  };\r
21  \r
22 +/*\r
23 + * AGFL blocks are accounted differently in the reserve pools and are not\r
24 + * inserted into the busy extent list.\r
25 + */\r
26 +STATIC int\r
27 +xfs_agfl_free_finish_item(\r
28 +       struct xfs_trans                *tp,\r
29 +       struct list_head                *item,\r
30 +       void                            *done_item,\r
31 +       void                            **state)\r
32 +{\r
33 +       struct xfs_mount                *mp = tp->t_mountp;\r
34 +       struct xfs_extent_free_item     *free;\r
35 +       struct xfs_buf                  *agbp;\r
36 +       int                             error;\r
37 +       xfs_agnumber_t                  agno;\r
38 +       xfs_agblock_t                   agbno;\r
39 +\r
40 +       free = container_of(item, struct xfs_extent_free_item, xefi_list);\r
41 +       ASSERT(free->xefi_blockcount == 1);\r
42 +       agno = XFS_FSB_TO_AGNO(mp, free->xefi_startblock);\r
43 +       agbno = XFS_FSB_TO_AGBNO(mp, free->xefi_startblock);\r
44 +\r
45 +       error = xfs_alloc_read_agf(mp, tp, agno, 0, &agbp);\r
46 +       if (!error)\r
47 +               error = xfs_free_agfl_block(tp, agno, agbno, agbp,\r
48 +                                           &free->xefi_oinfo);\r
49 +       kmem_free(free);\r
50 +       return error;\r
51 +}\r
52 +\r
53 +/* sub-type with special handling for AGFL deferred frees */\r
54 +static const struct xfs_defer_op_type xfs_agfl_free_defer_type = {\r
55 +       .type           = XFS_DEFER_OPS_TYPE_AGFL_FREE,\r
56 +       .diff_items     = xfs_extent_free_diff_items,\r
57 +       .create_intent  = xfs_extent_free_create_intent,\r
58 +       .abort_intent   = xfs_extent_free_abort_intent,\r
59 +       .log_item       = xfs_extent_free_log_item,\r
60 +       .create_done    = xfs_extent_free_create_done,\r
61 +       .finish_item    = xfs_agfl_free_finish_item,\r
62 +       .cancel_item    = xfs_extent_free_cancel_item,\r
63 +};\r
64 +\r
65  /* Register the deferred op type. */\r
66  void\r
67  xfs_extent_free_init_defer_op(void)\r
68  {\r
69         xfs_defer_init_op_type(&xfs_extent_free_defer_type);\r
70 +       xfs_defer_init_op_type(&xfs_agfl_free_defer_type);\r
71  }\r
72  \r
73  /* Reverse Mapping */\r
74 Subject: [PATCH 1/2] xfs_repair: initialize realloced bplist in\r
75  longform_dir2_entry_check\r
76 From:   Eric Sandeen <sandeen@sandeen.net>\r
77 \r
78 If we need to realloc the bplist[] array holding buffers for a given\r
79 directory, we don't initialize the new slots.  This causes a problem\r
80 if the directory has holes, because those slots never get filled in.\r
81 \r
82 At the end of the function we call libxfs_putbuf for every non-null\r
83 slot, and any uninitialized slots are segfault landmines.\r
84 \r
85 Make sure we initialize all new slots to NULL for this reason.\r
86 \r
87 Reported-by: Oleg Davydov <burunduk3@gmail.com>\r
88 Signed-off-by: Eric Sandeen <sandeen@redhat.com>\r
89 ---\r
90 \r
91 diff --git a/repair/phase6.c b/repair/phase6.c\r
92 index b87c751..9d24a4f 100644\r
93 --- a/repair/phase6.c\r
94 +++ b/repair/phase6.c\r
95 @@ -2348,6 +2348,8 @@ longform_dir2_entry_check(xfs_mount_t     *mp,\r
96  \r
97                 db = xfs_dir2_da_to_db(mp->m_dir_geo, da_bno);\r
98                 if (db >= num_bps) {\r
99 +                       int last_size = num_bps;\r
100 +\r
101                         /* more data blocks than expected */\r
102                         num_bps = db + 1;\r
103                         bplist = realloc(bplist, num_bps * sizeof(struct xfs_buf*));\r
104 @@ -2355,6 +2357,9 @@ longform_dir2_entry_check(xfs_mount_t     *mp,\r
105                                 do_error(_("realloc failed in %s (%zu bytes)\n"),\r
106                                         __func__,\r
107                                         num_bps * sizeof(struct xfs_buf*));\r
108 +                       /* Initialize the new elements */\r
109 +                       for (i = last_size; i < num_bps; i++)\r
110 +                               bplist[i] = NULL;\r
111                 }\r
112  \r
113                 if (isblock)\r
114 \r
115 Subject: [PATCH 2/2] xfs_repair: continue after xfs_bunmapi deadlock avoidance\r
116 From:   Eric Sandeen <sandeen@sandeen.net>\r
117 \r
118 After commit:\r
119 \r
120 15a8bcc xfs: fix multi-AG deadlock in xfs_bunmapi\r
121 \r
122 xfs_bunmapi can legitimately return before all work is done.\r
123 Sadly nobody told xfs_repair, so it fires an assert:\r
124 \r
125  phase6.c:1410: longform_dir2_rebuild: Assertion `done' failed. \r
126 \r
127 Fix this by calling back in until all work is done, as we do\r
128 in the kernel.\r
129 \r
130 Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1641116\r
131 Reported-by: Tomasz Torcz <tomek@pipebreaker.pl>\r
132 Signed-off-by: Eric Sandeen <sandeen@redhat.com>\r
133 ---\r
134 \r
135 diff --git a/repair/phase6.c b/repair/phase6.c\r
136 index e017326..b87c751 100644\r
137 --- a/repair/phase6.c\r
138 +++ b/repair/phase6.c\r
139 @@ -1317,7 +1317,7 @@ longform_dir2_rebuild(\r
140         xfs_fileoff_t           lastblock;\r
141         xfs_inode_t             pip;\r
142         dir_hash_ent_t          *p;\r
143 -       int                     done;\r
144 +       int                     done = 0;\r
145  \r
146         /*\r
147          * trash directory completely and rebuild from scratch using the\r
148 @@ -1352,12 +1352,25 @@ longform_dir2_rebuild(\r
149                         error);\r
150  \r
151         /* free all data, leaf, node and freespace blocks */\r
152 -       error = -libxfs_bunmapi(tp, ip, 0, lastblock, XFS_BMAPI_METADATA, 0,\r
153 -                               &firstblock, &dfops, &done);\r
154 -       if (error) {\r
155 -               do_warn(_("xfs_bunmapi failed -- error - %d\n"), error);\r
156 -               goto out_bmap_cancel;\r
157 -       }\r
158 +       while (!done) {\r
159 +              error = -libxfs_bunmapi(tp, ip, 0, lastblock, XFS_BMAPI_METADATA,\r
160 +                                      0, &firstblock, &dfops, &done);\r
161 +              if (error) {\r
162 +                      do_warn(_("xfs_bunmapi failed -- error - %d\n"), error);\r
163 +                      goto out_bmap_cancel;\r
164 +              }\r
165 +              error = xfs_defer_finish(&tp, &dfops);\r
166 +              if (error) {\r
167 +                      do_warn(("defer_finish failed -- error - %d\n"), error);\r
168 +                      goto out_bmap_cancel;\r
169 +              }\r
170 +              /*\r
171 +               * Close out trans and start the next one in the chain.\r
172 +               */\r
173 +              error = xfs_trans_roll_inode(&tp, ip);\r
174 +              if (error)\r
175 +                       goto out_bmap_cancel;\r
176 +        }\r
177  \r
178         ASSERT(done);\r
179  \r
180 \r
181 From:   "Darrick J. Wong" <darrick.wong@oracle.com>\r
182 Subject: [PATCH] libxfs: check all defer ops types\r
183 \r
184 From: Darrick J. Wong <darrick.wong@oracle.com>\r
185 \r
186 Make sure we have all the defer ops types loaded before proceeding.\r
187 \r
188 Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>\r
189 ---\r
190  libxfs/init.c      |    5 +++++\r
191  libxfs/xfs_defer.c |   12 ++++++++++++\r
192  libxfs/xfs_defer.h |    1 +\r
193  3 files changed, 18 insertions(+)\r
194 \r
195 diff --git a/libxfs/init.c b/libxfs/init.c\r
196 index 750b8f20..d1fdc3a8 100644\r
197 --- a/libxfs/init.c\r
198 +++ b/libxfs/init.c\r
199 @@ -253,6 +253,11 @@ libxfs_init(libxfs_init_t *a)\r
200         xfs_rmap_update_init_defer_op();\r
201         xfs_refcount_update_init_defer_op();\r
202         xfs_bmap_update_init_defer_op();\r
203 +       if (!xfs_defer_check_all_present()) {\r
204 +               fprintf(stderr, _("%s: defer ops not all there\n"),\r
205 +                       progname);\r
206 +               goto done;\r
207 +       }\r
208  \r
209         radix_tree_init();\r
210  \r
211 diff --git a/libxfs/xfs_defer.c b/libxfs/xfs_defer.c\r
212 index 5a6da0f3..cd3a8ef3 100644\r
213 --- a/libxfs/xfs_defer.c\r
214 +++ b/libxfs/xfs_defer.c\r
215 @@ -545,3 +545,15 @@ xfs_defer_move(\r
216  \r
217         xfs_defer_reset(stp);\r
218  }\r
219 +\r
220 +/* Make sure we filled out all the defer_ops types. */\r
221 +bool\r
222 +xfs_defer_check_all_present(void)\r
223 +{\r
224 +       int             x;\r
225 +\r
226 +       for(x = 0; x < XFS_DEFER_OPS_TYPE_MAX; x++)\r
227 +               if (defer_op_types[x] == NULL)\r
228 +                       return false;\r
229 +       return true;\r
230 +}\r
231 diff --git a/libxfs/xfs_defer.h b/libxfs/xfs_defer.h\r
232 index 2584a5b9..bc7ae7ff 100644\r
233 --- a/libxfs/xfs_defer.h\r
234 +++ b/libxfs/xfs_defer.h\r
235 @@ -57,5 +57,6 @@ struct xfs_defer_op_type {\r
236  };\r
237  \r
238  void xfs_defer_init_op_type(const struct xfs_defer_op_type *type);\r
239 +bool xfs_defer_check_all_present(void);\r
240  \r
241  #endif /* __XFS_DEFER_H__ */\r
This page took 0.053314 seconds and 3 git commands to generate.