[enable Linux syscall probing (defaults to autodetect)])],
[],
[enable_linux_syscall_probing="maybe"])
+AC_ARG_ENABLE([linux-d_splice_alias-extra-iput],
+ [AS_HELP_STRING([--enable-linux-d_splice_alias-extra-iput],
+ [Linux has introduced an incompatible behavior change in the
+ d_splice_alias function with no reliable way to determine which
+ behavior will be produced. If Linux commit
+ 51486b900ee92856b977eacfc5bfbe6565028070 (or equivalent) has been
+ applied to your kernel, disable this option. If that commit is
+ not present in your kernel, enable this option. We apologize
+ that you are required to know this about your running kernel.])],
+ [],
+ [case $system in
+ *-linux*)
+ AS_IF([test "x$LOGNAME" != "xbuildslave" &&
+ test "x$LOGNAME" != "xbuildbot"],
+ [AC_ERROR([Linux users must specify either
+ --enable-linux-d_splice_alias-extra-iput or
+ --disable-linux-d_splice_alias-extra-iput])],
+ [enable_linux_d_splice_alias_extra_iput="no"])
+ esac
+ ])
AC_ARG_WITH([crosstools-dir],
[AS_HELP_STRING([--with-crosstools-dir=path],
[use path for native versions of rxgen, compile_et and config])
AC_CHECK_LINUX_FUNC([hlist_unhashed],
[#include <linux/list.h>],
[hlist_unhashed(0);])
+ AC_CHECK_LINUX_FUNC([ihold],
+ [#include <linux/fs.h>],
+ [ihold(NULL);])
AC_CHECK_LINUX_FUNC([i_size_read],
[#include <linux/fs.h>],
[i_size_read(NULL);])
fi
:
fi
+ if test "x$enable_linux_d_splice_alias_extra_iput" = xyes; then
+ AC_DEFINE(D_SPLICE_ALIAS_LEAK_ON_ERROR, 1, [for internal use])
+ fi
dnl Linux-only, but just enable always.
AC_DEFINE(AFS_CACHE_BYPASS, 1, [define to activate cache bypassing Unix client])
esac
ip->i_flags |= S_AUTOMOUNT;
#endif
}
+ /*
+ * Take an extra reference so the inode doesn't go away if
+ * d_splice_alias drops our reference on error.
+ */
+ if (ip)
+#ifdef HAVE_LINUX_IHOLD
+ ihold(ip);
+#else
+ igrab(ip);
+#endif
+
newdp = d_splice_alias(ip, dp);
done:
* d_splice_alias can return an error (EIO) if there is an existing
* connected directory alias for this dentry.
*/
- if (!IS_ERR(newdp))
+ if (!IS_ERR(newdp)) {
+ iput(ip);
return newdp;
- else {
+ } else {
d_add(dp, ip);
+ /*
+ * Depending on the kernel version, d_splice_alias may or may
+ * not drop the inode reference on error. If it didn't, do it
+ * here.
+ */
+#if defined(D_SPLICE_ALIAS_LEAK_ON_ERROR)
+ iput(ip);
+#endif
return NULL;
}
- } else
+ } else {
+ if (ip)
+ iput(ip);
return ERR_PTR(afs_convert_code(code));
+ }
}
static int