@@ -153,6 +153,79 @@ xfs_dax_notify_failure_thaw(
153153 thaw_super (sb , FREEZE_HOLDER_USERSPACE );
154154}
155155
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+
156229static int
157230xfs_dax_notify_ddev_failure (
158231 struct xfs_mount * mp ,
@@ -263,8 +336,9 @@ xfs_dax_notify_failure(
263336 int mf_flags )
264337{
265338 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 ;
268342
269343 if (!(mp -> m_super -> s_flags & SB_BORN )) {
270344 xfs_warn (mp , "filesystem is not ready for notify_failure()!" );
@@ -279,51 +353,20 @@ xfs_dax_notify_failure(
279353
280354 if (mp -> m_logdev_targp && mp -> m_logdev_targp -> bt_daxdev == dax_dev &&
281355 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 );
293357 }
294358
295359 if (!xfs_has_rmapbt (mp )) {
296360 xfs_debug (mp , "notify_failure() needs rmapbt enabled!" );
297361 return - EOPNOTSUPP ;
298362 }
299363
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 ;
324368
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 );
327370}
328371
329372const struct dax_holder_operations xfs_dax_holder_operations = {
0 commit comments