@@ -153,6 +153,79 @@ xfs_dax_notify_failure_thaw(
153
153
thaw_super (sb , FREEZE_HOLDER_USERSPACE );
154
154
}
155
155
156
+ static int
157
+ xfs_dax_translate_range (
158
+ struct xfs_buftarg * btp ,
159
+ u64 offset ,
160
+ u64 len ,
161
+ xfs_daddr_t * daddr ,
162
+ uint64_t * bblen )
163
+ {
164
+ u64 dev_start = btp -> bt_dax_part_off ;
165
+ u64 dev_len = bdev_nr_bytes (btp -> bt_bdev );
166
+ u64 dev_end = dev_start + dev_len - 1 ;
167
+
168
+ /* Notify failure on the whole device. */
169
+ if (offset == 0 && len == U64_MAX ) {
170
+ offset = dev_start ;
171
+ len = dev_len ;
172
+ }
173
+
174
+ /* Ignore the range out of filesystem area */
175
+ if (offset + len - 1 < dev_start )
176
+ return - ENXIO ;
177
+ if (offset > dev_end )
178
+ return - ENXIO ;
179
+
180
+ /* Calculate the real range when it touches the boundary */
181
+ if (offset > dev_start )
182
+ offset -= dev_start ;
183
+ else {
184
+ len -= dev_start - offset ;
185
+ offset = 0 ;
186
+ }
187
+ if (offset + len - 1 > dev_end )
188
+ len = dev_end - offset + 1 ;
189
+
190
+ * daddr = BTOBB (offset );
191
+ * bblen = BTOBB (len );
192
+ return 0 ;
193
+ }
194
+
195
+ static int
196
+ xfs_dax_notify_logdev_failure (
197
+ struct xfs_mount * mp ,
198
+ u64 offset ,
199
+ u64 len ,
200
+ int mf_flags )
201
+ {
202
+ xfs_daddr_t daddr ;
203
+ uint64_t bblen ;
204
+ int error ;
205
+
206
+ /*
207
+ * Return ENXIO instead of shutting down the filesystem if the failed
208
+ * region is beyond the end of the log.
209
+ */
210
+ error = xfs_dax_translate_range (mp -> m_logdev_targp ,
211
+ offset , len , & daddr , & bblen );
212
+ if (error )
213
+ return error ;
214
+
215
+ /*
216
+ * In the pre-remove case the failure notification is attempting to
217
+ * trigger a force unmount. The expectation is that the device is
218
+ * still present, but its removal is in progress and can not be
219
+ * cancelled, proceed with accessing the log device.
220
+ */
221
+ if (mf_flags & MF_MEM_PRE_REMOVE )
222
+ return 0 ;
223
+
224
+ xfs_err (mp , "ondisk log corrupt, shutting down fs!" );
225
+ xfs_force_shutdown (mp , SHUTDOWN_CORRUPT_ONDISK );
226
+ return - EFSCORRUPTED ;
227
+ }
228
+
156
229
static int
157
230
xfs_dax_notify_ddev_failure (
158
231
struct xfs_mount * mp ,
@@ -263,8 +336,9 @@ xfs_dax_notify_failure(
263
336
int mf_flags )
264
337
{
265
338
struct xfs_mount * mp = dax_holder (dax_dev );
266
- u64 ddev_start ;
267
- u64 ddev_end ;
339
+ xfs_daddr_t daddr ;
340
+ uint64_t bblen ;
341
+ int error ;
268
342
269
343
if (!(mp -> m_super -> s_flags & SB_BORN )) {
270
344
xfs_warn (mp , "filesystem is not ready for notify_failure()!" );
@@ -279,51 +353,20 @@ xfs_dax_notify_failure(
279
353
280
354
if (mp -> m_logdev_targp && mp -> m_logdev_targp -> bt_daxdev == dax_dev &&
281
355
mp -> m_logdev_targp != mp -> m_ddev_targp ) {
282
- /*
283
- * In the pre-remove case the failure notification is attempting
284
- * to trigger a force unmount. The expectation is that the
285
- * device is still present, but its removal is in progress and
286
- * can not be cancelled, proceed with accessing the log device.
287
- */
288
- if (mf_flags & MF_MEM_PRE_REMOVE )
289
- return 0 ;
290
- xfs_err (mp , "ondisk log corrupt, shutting down fs!" );
291
- xfs_force_shutdown (mp , SHUTDOWN_CORRUPT_ONDISK );
292
- return - EFSCORRUPTED ;
356
+ return xfs_dax_notify_logdev_failure (mp , offset , len , mf_flags );
293
357
}
294
358
295
359
if (!xfs_has_rmapbt (mp )) {
296
360
xfs_debug (mp , "notify_failure() needs rmapbt enabled!" );
297
361
return - EOPNOTSUPP ;
298
362
}
299
363
300
- ddev_start = mp -> m_ddev_targp -> bt_dax_part_off ;
301
- ddev_end = ddev_start + bdev_nr_bytes (mp -> m_ddev_targp -> bt_bdev ) - 1 ;
302
-
303
- /* Notify failure on the whole device. */
304
- if (offset == 0 && len == U64_MAX ) {
305
- offset = ddev_start ;
306
- len = bdev_nr_bytes (mp -> m_ddev_targp -> bt_bdev );
307
- }
308
-
309
- /* Ignore the range out of filesystem area */
310
- if (offset + len - 1 < ddev_start )
311
- return - ENXIO ;
312
- if (offset > ddev_end )
313
- return - ENXIO ;
314
-
315
- /* Calculate the real range when it touches the boundary */
316
- if (offset > ddev_start )
317
- offset -= ddev_start ;
318
- else {
319
- len -= ddev_start - offset ;
320
- offset = 0 ;
321
- }
322
- if (offset + len - 1 > ddev_end )
323
- len = ddev_end - offset + 1 ;
364
+ error = xfs_dax_translate_range (mp -> m_ddev_targp , offset , len , & daddr ,
365
+ & bblen );
366
+ if (error )
367
+ return error ;
324
368
325
- return xfs_dax_notify_ddev_failure (mp , BTOBB (offset ), BTOBB (len ),
326
- mf_flags );
369
+ return xfs_dax_notify_ddev_failure (mp , daddr , bblen , mf_flags );
327
370
}
328
371
329
372
const struct dax_holder_operations xfs_dax_holder_operations = {
0 commit comments