diff --git a/include/sys/kmem.h b/include/sys/kmem.h index d4b3bf680..d6b428551 100644 --- a/include/sys/kmem.h +++ b/include/sys/kmem.h @@ -46,6 +46,8 @@ extern void strfree(char *str); #define KM_PUBLIC_MASK (KM_SLEEP | KM_NOSLEEP | KM_PUSHPAGE) +static int spl_fstrans_check(void); + /* * Convert a KM_* flags mask to its Linux GFP_* counterpart. The conversion * function is context aware which means that KM_SLEEP allocations can be @@ -60,7 +62,7 @@ kmem_flags_convert(int flags) lflags |= GFP_ATOMIC | __GFP_NORETRY; } else { lflags |= GFP_KERNEL; - if ((current->flags & PF_FSTRANS)) + if (spl_fstrans_check()) lflags &= ~(__GFP_IO|__GFP_FS); } @@ -78,17 +80,34 @@ typedef struct { unsigned int saved_flags; } fstrans_cookie_t; +/* + * Introduced in Linux 3.9, however this cannot be solely relied on before + * Linux 3.18 as it doesn't turn off __GFP_FS as it should. + */ #ifdef PF_MEMALLOC_NOIO -#define SPL_FSTRANS (PF_FSTRANS|PF_MEMALLOC_NOIO) +#define __SPL_PF_MEMALLOC_NOIO (PF_MEMALLOC_NOIO) #else -#define SPL_FSTRANS (PF_FSTRANS) +#define __SPL_PF_MEMALLOC_NOIO (0) #endif +/* + * PF_FSTRANS is removed from Linux 4.12 + */ +#ifdef PF_FSTRANS +#define __SPL_PF_FSTRANS (PF_FSTRANS) +#else +#define __SPL_PF_FSTRANS (0) +#endif + +#define SPL_FSTRANS (__SPL_PF_FSTRANS|__SPL_PF_MEMALLOC_NOIO) + static inline fstrans_cookie_t spl_fstrans_mark(void) { fstrans_cookie_t cookie; + BUILD_BUG_ON(SPL_FSTRANS == 0); + cookie.fstrans_thread = current; cookie.saved_flags = current->flags & SPL_FSTRANS; current->flags |= SPL_FSTRANS; @@ -109,7 +128,17 @@ spl_fstrans_unmark(fstrans_cookie_t cookie) static inline int spl_fstrans_check(void) { - return (current->flags & PF_FSTRANS); + return (current->flags & SPL_FSTRANS); +} + +/* + * specifically used to check PF_FSTRANS flag, cannot be relied on for + * checking spl_fstrans_mark(). + */ +static inline int +__spl_pf_fstrans_check(void) +{ + return (current->flags & __SPL_PF_FSTRANS); } #ifdef HAVE_ATOMIC64_T diff --git a/module/spl/spl-vnode.c b/module/spl/spl-vnode.c index 0902e1161..346e63c0f 100644 --- a/module/spl/spl-vnode.c +++ b/module/spl/spl-vnode.c @@ -558,13 +558,13 @@ int vn_fsync(vnode_t *vp, int flags, void *x3, void *x4) * May enter XFS which generates a warning when PF_FSTRANS is set. * To avoid this the flag is cleared over vfs_sync() and then reset. */ - fstrans = spl_fstrans_check(); + fstrans = __spl_pf_fstrans_check(); if (fstrans) - current->flags &= ~(PF_FSTRANS); + current->flags &= ~(__SPL_PF_FSTRANS); error = -spl_filp_fsync(vp->v_file, datasync); if (fstrans) - current->flags |= PF_FSTRANS; + current->flags |= __SPL_PF_FSTRANS; return (error); } /* vn_fsync() */ @@ -590,9 +590,9 @@ int vn_space(vnode_t *vp, int cmd, struct flock *bfp, int flag, * May enter XFS which generates a warning when PF_FSTRANS is set. * To avoid this the flag is cleared over vfs_sync() and then reset. */ - fstrans = spl_fstrans_check(); + fstrans = __spl_pf_fstrans_check(); if (fstrans) - current->flags &= ~(PF_FSTRANS); + current->flags &= ~(__SPL_PF_FSTRANS); /* * When supported by the underlying file system preferentially @@ -603,7 +603,7 @@ int vn_space(vnode_t *vp, int cmd, struct flock *bfp, int flag, bfp->l_start, bfp->l_len); if (fstrans) - current->flags |= PF_FSTRANS; + current->flags |= __SPL_PF_FSTRANS; if (error == 0) return (0);