+ AC_DEFINE(HAVE_PROTECT_I_NLINK, 1,
+ [inode->i_nlink is protected from direct modification])
+])
+]) # LC_HAVE_PROTECT_I_NLINK
+
+#
+# 2.6.39 security_inode_init_security takes a 'struct qstr' parameter
+#
+# 3.2 security_inode_init_security takes a callback to set xattrs
+#
+AC_DEFUN([LC_HAVE_SECURITY_IINITSEC], [
+LB_CHECK_COMPILE([if security_inode_init_security takes a callback],
+security_inode_init_security_callback, [
+ #include <linux/security.h>
+],[
+ security_inode_init_security(NULL, NULL, NULL, (const initxattrs)NULL, NULL);
+],[
+ AC_DEFINE(HAVE_SECURITY_IINITSEC_CALLBACK, 1,
+ [security_inode_init_security takes a callback to set xattrs])
+],[
+ LB_CHECK_COMPILE([if security_inode_init_security takes a 'struct qstr' parameter],
+ security_inode_init_security_qstr, [
+ #include <linux/security.h>
+ ],[
+ security_inode_init_security(NULL, NULL, (struct qstr *)NULL, NULL, NULL, NULL);
+ ],[
+ AC_DEFINE(HAVE_SECURITY_IINITSEC_QSTR, 1,
+ [security_inode_init_security takes a 'struct qstr' parameter])
+ ])
+])
+]) # LC_HAVE_SECURITY_IINITSEC
+
+#
+# LC_HAVE_MIGRATE_HEADER
+#
+# 3.3 introduces migrate_mode.h and migratepage has 4 args
+#
+AC_DEFUN([LC_HAVE_MIGRATE_HEADER], [
+LB_CHECK_FILE([$LINUX/include/linux/migrate.h], [
+ AC_DEFINE(HAVE_MIGRATE_H, 1,
+ [kernel has include/linux/migrate.h])
+],[
+ LB_CHECK_FILE([$LINUX/include/linux/migrate_mode.h], [
+ AC_DEFINE(HAVE_MIGRATE_MODE_H, 1,
+ [kernel has include/linux/migrate_mode.h])
+ ])
+])
+]) # LC_HAVE_MIGRATE_HEADER
+
+#
+# LC_MIGRATEPAGE_4ARGS
+#
+AC_DEFUN([LC_MIGRATEPAGE_4ARGS], [
+LB_CHECK_COMPILE([if 'address_space_operations.migratepage' has 4 args],
+address_space_ops_migratepage_4args, [
+ #include <linux/fs.h>
+#ifdef HAVE_MIGRATE_H
+ #include <linux/migrate.h>
+#elif defined(HAVE_MIGRATE_MODE_H)
+ #include <linux/migrate_mode.h>
+#endif
+],[
+ struct address_space_operations aops;
+ aops.migratepage(NULL, NULL, NULL, MIGRATE_ASYNC);
+],[
+ AC_DEFINE(HAVE_MIGRATEPAGE_4ARGS, 1,
+ [address_space_operations.migratepage has 4 args])
+])
+]) # LC_MIGRATEPAGE_4ARGS
+
+#
+# LC_SUPEROPS_USE_DENTRY
+#
+# 3.3 switchs super_operations to use dentry as parameter (but not vfsmount)
+# see kernel commit 34c80b1d93e6e20ca9dea0baf583a5b5510d92d4
+#
+AC_DEFUN([LC_SUPEROPS_USE_DENTRY], [
+tmp_flags="$EXTRA_KCFLAGS"
+EXTRA_KCFLAGS="-Werror"
+LB_CHECK_COMPILE([if 'super_operations' use 'dentry' as parameter],
+super_ops_dentry, [
+ #include <linux/fs.h>
+ int show_options(struct seq_file *seq, struct dentry *root) {
+ return 0;
+ }
+],[
+ struct super_operations ops;
+ ops.show_options = show_options;
+],[
+ AC_DEFINE(HAVE_SUPEROPS_USE_DENTRY, 1,
+ [super_operations use dentry as parameter])
+])
+EXTRA_KCFLAGS="$tmp_flags"
+]) # LC_SUPEROPS_USE_DENTRY
+
+#
+# LC_INODEOPS_USE_UMODE_T
+#
+# 3.3 switchs inode_operations to use umode_t as parameter (but not int)
+# see kernel commit 1a67aafb5f72a436ca044293309fa7e6351d6a35
+#
+AC_DEFUN([LC_INODEOPS_USE_UMODE_T], [
+tmp_flags="$EXTRA_KCFLAGS"
+EXTRA_KCFLAGS="-Werror"
+LB_CHECK_COMPILE([if 'inode_operations' use 'umode_t' as parameter],
+inode_ops_umode_t, [
+ #include <linux/fs.h>
+ #include <linux/types.h>
+ int my_mknod(struct inode *dir, struct dentry *dchild,
+ umode_t mode, dev_t dev)
+ {
+ return 0;
+ }
+],[
+ struct inode_operations ops;
+ ops.mknod = my_mknod;
+],[
+ AC_DEFINE(HAVE_INODEOPS_USE_UMODE_T, 1,
+ [inode_operations use umode_t as parameter])
+])
+EXTRA_KCFLAGS="$tmp_flags"
+]) # LC_INODEOPS_USE_UMODE_T
+
+#
+# LC_KMAP_ATOMIC_HAS_1ARG
+#
+# 3.4 kmap_atomic removes second argument
+# see kernel commit 1ec9c5ddc17aa398f05646abfcbaf315b544e62f
+#
+AC_DEFUN([LC_KMAP_ATOMIC_HAS_1ARG], [
+LB_CHECK_COMPILE([if 'kmap_atomic' has only 1 argument],
+kmap_atomic_1arg, [
+ #include <linux/highmem.h>
+],[
+ kmap_atomic(NULL);
+],[
+ AC_DEFINE(HAVE_KMAP_ATOMIC_HAS_1ARG, 1,
+ [have kmap_atomic has only 1 argument])
+])
+]) # LC_KMAP_ATOMIC_HAS_1ARG
+
+#
+# LC_HAVE_D_MAKE_ROOT
+#
+# 3.4 converts d_alloc_root to d_make_root
+# see kernel commit 32991ab305ace7017c62f8eecbe5eb36dc32e13b
+#
+AC_DEFUN([LC_HAVE_D_MAKE_ROOT], [
+LB_CHECK_COMPILE([if have 'd_make_root'],
+d_make_root, [
+ #include <linux/fs.h>
+],[
+ d_make_root((struct inode *)NULL);
+],[
+ AC_DEFINE(HAVE_D_MAKE_ROOT, 1,
+ [have d_make_root])
+])
+]) # LC_HAVE_D_MAKE_ROOT
+
+#
+# LC_HAVE_CACHE_REGISTER
+#
+# 3.4 cache_register/cache_unregister are removed
+# see kernel commit 2c5f846747526e2b83c5f1b8e69016be0e2e87c0
+# Note, since 2.6.37 cache_register_net/cache_unregister_net
+# are defined, but not exported.
+# 3.3 cache_register_net/cache_unregister_net are
+# exported and replacing cache_register/cache_unregister in 3.4
+#
+AC_DEFUN([LC_HAVE_CACHE_REGISTER], [
+LB_CHECK_COMPILE([if have 'cache_register'],
+cache_register, [
+ #include <linux/sunrpc/cache.h>
+],[
+ cache_register(NULL);
+],[
+ AC_DEFINE(HAVE_CACHE_REGISTER, 1,
+ [have cache_register])
+])
+]) # LC_HAVE_CACHE_REGISTER
+
+#
+# LC_HAVE_CLEAR_INODE
+#
+# 3.5 renames end_writeback() back to clear_inode()...
+# see kernel commit dbd5768f87ff6fb0a4fe09c4d7b6c4a24de99430
+#
+AC_DEFUN([LC_HAVE_CLEAR_INODE], [
+LB_CHECK_COMPILE([if have 'clear_inode'],
+clear_inode, [
+ #include <linux/fs.h>
+],[
+ clear_inode((struct inode *)NULL);
+],[
+ AC_DEFINE(HAVE_CLEAR_INODE, 1,
+ [have clear_inode])
+])
+]) # LC_HAVE_CLEAR_INODE
+
+#
+# LC_HAVE_ENCODE_FH_PARENT
+#
+# 3.5 encode_fh has parent inode passed in directly
+# see kernel commit b0b0382b
+#
+AC_DEFUN([LC_HAVE_ENCODE_FH_PARENT], [
+tmp_flags="$EXTRA_KCFLAGS"
+EXTRA_KCFLAGS="-Werror"
+LB_CHECK_COMPILE([if 'encode_fh' have parent inode as parameter],
+encode_fh_parent_inode, [
+ #include <linux/exportfs.h>
+ #include <linux/fs.h>
+ #include <linux/types.h>
+ int ll_encode_fh(struct inode *i, __u32 *a, int *b, struct inode *p)
+ {
+ return 0;
+ }
+],[
+ struct export_operations exp_op;
+ exp_op.encode_fh = ll_encode_fh;
+],[
+ AC_DEFINE(HAVE_ENCODE_FH_PARENT, 1,
+ [have parent inode as parameter])
+])
+EXTRA_KCFLAGS="$tmp_flags"
+]) # LC_HAVE_ENCODE_FH_PARENT
+
+#
+# LC_FILE_LLSEEK_SIZE_5ARG
+#
+# 3.5 has generic_file_llseek_size with 5 args
+#
+AC_DEFUN([LC_FILE_LLSEEK_SIZE_5ARG], [
+LB_CHECK_COMPILE([if Linux kernel has 'generic_file_llseek_size' with 5 args],
+generic_file_llseek_size_5args, [
+ #include <linux/fs.h>
+],[
+ generic_file_llseek_size(NULL, 0, 0, 0, 0);
+], [
+ AC_DEFINE(HAVE_FILE_LLSEEK_SIZE_5ARGS, 1,
+ [kernel has generic_file_llseek_size with 5 args])
+])
+]) # LC_FILE_LLSEEK_SIZE_5ARG
+
+#
+# LC_LLITE_DATA_IS_LIST
+#
+# 3.6 switch i_dentry/d_alias from list to hlist
+#
+# In the upstream kernels d_alias first changes
+# to a hlist and then in later version, 3.11, gets
+# moved to the union d_u. Due to some distros having
+# d_alias in the d_u union as a struct list, which
+# has never existed upstream stream, we can't test
+# if d_alias is a list or hlist directly. If ever
+# i_dentry and d_alias even up different combos then
+# the build will fail. In that case then we will need
+# to separate out the i_dentry and d_alias test below.
+#
+AC_DEFUN([LC_DATA_FOR_LLITE_IS_LIST], [
+tmp_flags="$EXTRA_KCFLAGS"
+EXTRA_KCFLAGS="-Werror"
+LB_CHECK_COMPILE([if 'i_dentry/d_alias' uses 'list'],
+i_dentry_d_alias_list, [
+ #include <linux/fs.h>
+],[
+ struct inode inode;
+ INIT_LIST_HEAD(&inode.i_dentry);
+],[
+ AC_DEFINE(DATA_FOR_LLITE_IS_LIST, 1,
+ [both i_dentry/d_alias uses list])
+])
+EXTRA_KCFLAGS="$tmp_flags"
+]) # LC_DATA_FOR_LLITE_IS_LIST
+
+#
+# LC_DENTRY_OPEN_USE_PATH
+#
+# 3.6 dentry_open uses struct path as first argument
+# see kernel commit 765927b2
+#
+AC_DEFUN([LC_DENTRY_OPEN_USE_PATH], [
+tmp_flags="$EXTRA_KCFLAGS"
+EXTRA_KCFLAGS="-Werror"
+LB_CHECK_COMPILE([if 'dentry_open' uses 'struct path' as first argument],
+dentry_open_path, [
+ #include <linux/fs.h>
+ #include <linux/path.h>
+],[
+ struct path path;
+ dentry_open(&path, 0, NULL);
+],[
+ AC_DEFINE(HAVE_DENTRY_OPEN_USE_PATH, 1,
+ [dentry_open uses struct path as first argument])
+])
+EXTRA_KCFLAGS="$tmp_flags"
+]) # LC_DENTRY_OPEN_USE_PATH
+
+#
+# LC_HAVE_IOP_ATOMIC_OPEN
+#
+# 3.6 vfs adds iop->atomic_open
+#
+AC_DEFUN([LC_HAVE_IOP_ATOMIC_OPEN], [
+LB_CHECK_COMPILE([if 'iop' has 'atomic_open'],
+inode_ops_atomic_open, [
+ #include <linux/fs.h>
+],[
+ struct inode_operations iop;
+ iop.atomic_open = NULL;
+],[
+ AC_DEFINE(HAVE_IOP_ATOMIC_OPEN, 1,
+ [have iop atomic_open])
+])
+]) # LC_HAVE_IOP_ATOMIC_OPEN
+
+#
+# LC_HAVE_POSIXACL_USER_NS
+#
+# 3.7 posix_acl_{to,from}_xattr take struct user_namespace
+#
+AC_DEFUN([LC_HAVE_POSIXACL_USER_NS], [
+LB_CHECK_COMPILE([if 'posix_acl_to_xattr' takes 'struct user_namespace'],
+posix_acl_to_xattr_user_namespace, [
+ #include <linux/fs.h>
+ #include <linux/posix_acl_xattr.h>
+],[
+ posix_acl_to_xattr((struct user_namespace *)NULL, NULL, NULL, 0);
+],[
+ AC_DEFINE(HAVE_POSIXACL_USER_NS, 1,
+ [posix_acl_to_xattr takes struct user_namespace])
+])
+]) # LC_HAVE_POSIXACL_USER_NS
+
+#
+# LC_HAVE_FILE_F_INODE
+#
+# 3.8 struct file has new member f_inode
+#
+AC_DEFUN([LC_HAVE_FILE_F_INODE], [
+LB_CHECK_COMPILE([if 'struct file' has member 'f_inode'],
+file_f_inode, [
+ #include <linux/fs.h>
+],[
+ ((struct file *)0)->f_inode = NULL;
+],[
+ AC_DEFINE(HAVE_FILE_F_INODE, 1,
+ [struct file has member f_inode])
+])
+]) # LC_HAVE_FILE_F_INODE
+
+#
+# LC_HAVE_SUNRPC_UPCALL_HAS_3ARGS
+#
+AC_DEFUN([LC_HAVE_SUNRPC_UPCALL_HAS_3ARGS], [
+LB_CHECK_COMPILE([if 'sunrpc_cache_pipe_upcall' takes 3 args],
+sunrpc_cache_pipe_upcall_3args, [
+ #include <linux/sunrpc/cache.h>
+],[
+ sunrpc_cache_pipe_upcall(NULL, NULL, NULL);
+],[
+ AC_DEFINE(HAVE_SUNRPC_UPCALL_HAS_3ARGS, 1,
+ [sunrpc_cache_pipe_upcall takes 3 args])
+])
+]) # LC_HAVE_SUNRPC_UPCALL_HAS_3ARGS
+
+#
+# LC_HAVE_HLIST_FOR_EACH_3ARG
+#
+# 3.9 uses hlist_for_each_entry with 3 args
+# b67bfe0d42cac56c512dd5da4b1b347a23f4b70a
+#
+AC_DEFUN([LC_HAVE_HLIST_FOR_EACH_3ARG], [
+LB_CHECK_COMPILE([if 'hlist_for_each_entry' has 3 args],
+hlist_for_each_entry_3args, [
+ #include <linux/list.h>
+ #include <linux/fs.h>
+],[
+ struct hlist_head *head = NULL;
+ struct inode *inode;
+
+ hlist_for_each_entry(inode, head, i_hash) {
+ continue;
+ }
+],[
+ AC_DEFINE(HAVE_HLIST_FOR_EACH_3ARG, 1,
+ [hlist_for_each_entry has 3 args])
+])
+]) # LC_HAVE_HLIST_FOR_EACH_3ARG
+
+#
+# LC_HAVE_BIO_END_SECTOR
+#
+# 3.9 introduces bio_end_sector macro
+# f73a1c7d117d07a96d89475066188a2b79e53c48
+#
+AC_DEFUN([LC_HAVE_BIO_END_SECTOR], [
+LB_CHECK_COMPILE([if 'bio_end_sector' is defined],
+bio_end_sector, [
+ #include <linux/bio.h>
+],[
+ struct bio bio;
+
+ bio_end_sector(&bio);
+],[
+ AC_DEFINE(HAVE_BIO_END_SECTOR, 1,
+ [bio_end_sector is defined])
+])
+]) # LC_HAVE_BIO_END_SECTOR
+
+#
+# LC_HAVE_REMOVE_PROC_SUBTREE
+#
+# 3.10 introduced remove_proc_subtree
+#
+AC_DEFUN([LC_HAVE_REMOVE_PROC_SUBTREE], [
+LB_CHECK_COMPILE([if 'remove_proc_subtree' is defined],
+remove_proc_subtree, [
+ #include <linux/proc_fs.h>
+],[
+ remove_proc_subtree(NULL, NULL);
+], [
+ AC_DEFINE(HAVE_REMOVE_PROC_SUBTREE, 1,
+ [remove_proc_subtree is defined])
+])
+]) # LC_HAVE_REMOVE_PROC_SUBTREE
+
+#
+# LC_HAVE_PROC_REMOVE
+#
+# 3.10 introduced proc_remove
+#
+AC_DEFUN([LC_HAVE_PROC_REMOVE], [
+LB_CHECK_COMPILE([if 'proc_remove' is defined],
+proc_remove, [
+ #include <linux/proc_fs.h>
+],[
+ proc_remove(NULL);
+], [
+ AC_DEFINE(HAVE_PROC_REMOVE, 1,
+ [proc_remove is defined])
+])
+]) # LC_HAVE_PROC_REMOVE
+
+#
+# LC_BLKDEV_RELEASE_RETURN_INT
+#
+# 3.10 release for block device doesn't return int
+#
+AC_DEFUN([LC_BLKDEV_RELEASE_RETURN_INT], [
+LB_CHECK_COMPILE([if 'block_device_operations' release returns 'int'],
+block_device_ops_release_return_int, [
+ #include <linux/blkdev.h>
+],[
+ struct block_device_operations fops;
+ int i __attribute__ ((unused));
+
+ i = fops.release(NULL, 0);
+],[
+ AC_DEFINE(HAVE_BLKDEV_RELEASE_RETURN_INT, 1,
+ [block device release returns int])
+])
+]) # LC_BLKDEV_RELEASE_RETURN_INT
+
+#
+# LC_INVALIDATE_RANGE
+#
+# 3.11 invalidatepage requires the length of the range to invalidate
+#
+AC_DEFUN([LC_INVALIDATE_RANGE], [
+LB_CHECK_COMPILE([if 'address_space_operations.invalidatepage' requires 3 arguments],
+address_space_ops_invalidatepage_3args, [
+ #include <linux/fs.h>
+],[
+ struct address_space_operations a_ops;
+ a_ops.invalidatepage(NULL, 0, 0);
+],[
+ AC_DEFINE(HAVE_INVALIDATE_RANGE, 1,
+ [address_space_operations.invalidatepage needs 3 arguments])
+])
+]) # LC_INVALIDATE_RANGE
+
+#
+# LC_HAVE_DIR_CONTEXT
+#
+# 3.11 readdir now takes the new struct dir_context
+#
+AC_DEFUN([LC_HAVE_DIR_CONTEXT], [
+LB_CHECK_COMPILE([if 'dir_context' exist],
+dir_context, [
+ #include <linux/fs.h>
+],[
+ struct dir_context ctx;
+ ctx.pos = 0;
+],[
+ AC_DEFINE(HAVE_DIR_CONTEXT, 1,
+ [dir_context exist])
+])
+]) # LC_HAVE_DIR_CONTEXT
+
+#
+# LC_D_COMPARE_5ARGS
+#
+# 3.11 dentry_operations.d_compare() taken 5 arguments.
+#
+AC_DEFUN([LC_D_COMPARE_5ARGS], [
+LB_CHECK_COMPILE([if 'd_compare' taken 5 arguments],
+d_compare_5args, [
+ #include <linux/dcache.h>
+],[
+ ((struct dentry_operations*)0)->d_compare(NULL,NULL,0,NULL,NULL);
+],[
+ AC_DEFINE(HAVE_D_COMPARE_5ARGS, 1,
+ [d_compare need 5 arguments])
+])
+]) # LC_D_COMPARE_5ARGS
+
+#
+# LC_HAVE_DCOUNT
+#
+# 3.11 need to access d_count to get dentry reference count
+#
+AC_DEFUN([LC_HAVE_DCOUNT], [
+LB_CHECK_COMPILE([if 'd_count' exist],
+d_count, [
+ #include <linux/dcache.h>
+],[
+ struct dentry de;
+ d_count(&de);
+],[
+ AC_DEFINE(HAVE_D_COUNT, 1,
+ [d_count exist])
+])
+]) # LC_HAVE_DCOUNT
+
+#
+# LC_OLDSIZE_TRUNCATE_PAGECACHE
+#
+# 3.12 truncate_pagecache without oldsize parameter
+#
+AC_DEFUN([LC_OLDSIZE_TRUNCATE_PAGECACHE], [
+LB_CHECK_COMPILE([if 'truncate_pagecache' with 'old_size' parameter],
+truncate_pagecache_old_size, [
+ #include <linux/mm.h>
+],[
+ truncate_pagecache(NULL, 0, 0);
+],[
+ AC_DEFINE(HAVE_OLDSIZE_TRUNCATE_PAGECACHE, 1,
+ [with oldsize])
+])
+]) # LC_OLDSIZE_TRUNCATE_PAGECACHE
+
+#
+# LC_HAVE_DENTRY_D_U_D_ALIAS
+#
+# 3.11 kernel moved d_alias to the union d_u in struct dentry
+#
+# Some distros move d_alias to d_u but it is still a struct list
+#
+AC_DEFUN([LC_HAVE_DENTRY_D_U_D_ALIAS], [
+AS_IF([test "x$lb_cv_compile_i_dentry_d_alias_list" = xyes], [
+ LB_CHECK_COMPILE([if list 'dentry.d_u.d_alias' exist],
+ d_alias, [
+ #include <linux/list.h>
+ #include <linux/dcache.h>
+ ],[
+ struct dentry de;
+ INIT_LIST_HEAD(&de.d_u.d_alias);
+ ],[
+ AC_DEFINE(HAVE_DENTRY_D_U_D_ALIAS, 1,
+ [list dentry.d_u.d_alias exist])
+ ])
+],[
+ LB_CHECK_COMPILE([if hlist 'dentry.d_u.d_alias' exist],
+ d_alias, [
+ #include <linux/list.h>
+ #include <linux/dcache.h>
+ ],[
+ struct dentry de;
+ INIT_HLIST_NODE(&de.d_u.d_alias);
+ ],[
+ AC_DEFINE(HAVE_DENTRY_D_U_D_ALIAS, 1,
+ [hlist dentry.d_u.d_alias exist])
+ ])
+])
+]) # LC_HAVE_DENTRY_D_U_D_ALIAS
+
+#
+# LC_HAVE_DENTRY_D_CHILD
+#
+# 3.11 kernel d_child has been moved out of the union d_u
+# in struct dentry
+#
+AC_DEFUN([LC_HAVE_DENTRY_D_CHILD], [
+LB_CHECK_COMPILE([if 'dentry.d_child' exist],
+d_child, [
+ #include <linux/list.h>
+ #include <linux/dcache.h>
+],[
+ struct dentry de;
+ INIT_LIST_HEAD(&de.d_child);
+],[
+ AC_DEFINE(HAVE_DENTRY_D_CHILD, 1,
+ [dentry.d_child exist])
+])
+]) # LC_HAVE_DENTRY_D_CHILD
+
+#
+# LC_KIOCB_KI_LEFT
+#
+# 3.12 ki_left removed from struct kiocb
+#
+AC_DEFUN([LC_KIOCB_KI_LEFT], [
+LB_CHECK_COMPILE([if 'struct kiocb' with 'ki_left' member],
+kiocb_ki_left, [
+ #include <linux/aio.h>
+],[
+ ((struct kiocb*)0)->ki_left = 0;