+AC_DEFUN([LC_FUNC_HAVE_CAN_SLEEP_ARG],
+[AC_MSG_CHECKING([if kernel has third arg can_sleep in fs/locks.c: flock_lock_file_wait()])
+LB_LINUX_TRY_COMPILE([
+ #include <linux/fs.h>
+],[
+ int cansleep;
+ struct file *file;
+ struct file_lock *file_lock;
+ flock_lock_file_wait(file, file_lock, cansleep);
+],[
+ AC_DEFINE(HAVE_CAN_SLEEP_ARG, 1,
+ [kernel has third arg can_sleep in fs/locks.c: flock_lock_file_wait()])
+ AC_MSG_RESULT([yes])
+],[
+ AC_MSG_RESULT([no])
+])
+])
+
+#
+# LC_TASK_PPTR
+#
+# task struct has p_pptr instead of parent
+#
+AC_DEFUN([LC_TASK_PPTR],
+[AC_MSG_CHECKING([task p_pptr found])
+LB_LINUX_TRY_COMPILE([
+ #include <linux/sched.h>
+],[
+ struct task_struct *p;
+
+ p = p->p_pptr;
+],[
+ AC_MSG_RESULT([yes])
+ AC_DEFINE(HAVE_TASK_PPTR, 1, [task p_pptr found])
+],[
+ AC_MSG_RESULT([no])
+])
+])
+
+#
+# LC_FUNC_F_OP_FLOCK
+#
+# rhel4.2 kernel has f_op->flock field
+#
+AC_DEFUN([LC_FUNC_F_OP_FLOCK],
+[AC_MSG_CHECKING([if struct file_operations has flock field])
+LB_LINUX_TRY_COMPILE([
+ #include <linux/fs.h>
+],[
+ struct file_operations ll_file_operations_flock;
+ ll_file_operations_flock.flock = NULL;
+],[
+ AC_DEFINE(HAVE_F_OP_FLOCK, 1,
+ [struct file_operations has flock field])
+ AC_MSG_RESULT([yes])
+],[
+ AC_MSG_RESULT([no])
+])
+])
+
+# LC_INODE_I_MUTEX
+# after 2.6.15 inode have i_mutex intead of i_sem
+AC_DEFUN([LC_INODE_I_MUTEX],
+[AC_MSG_CHECKING([use inode have i_mutex ])
+LB_LINUX_TRY_COMPILE([
+ #include <linux/mutex.h>
+ #include <linux/fs.h>
+],[
+ struct inode i;
+
+ mutex_unlock(&i.i_mutex);
+],[
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_INODE_I_MUTEX, 1,
+ [after 2.6.15 inode have i_mutex intead of i_sem])
+],[
+ AC_MSG_RESULT(NO)
+])
+])
+
+
+# LC_DQUOTOFF_MUTEX
+# after 2.6.17 dquote use mutex instead if semaphore
+AC_DEFUN([LC_DQUOTOFF_MUTEX],
+[AC_MSG_CHECKING([use dqonoff_mutex])
+LB_LINUX_TRY_COMPILE([
+ #include <linux/mutex.h>
+ #include <linux/fs.h>
+ #include <linux/quota.h>
+],[
+ struct quota_info dq;
+
+ mutex_unlock(&dq.dqonoff_mutex);
+],[
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_DQUOTOFF_MUTEX, 1,
+ [after 2.6.17 dquote use mutex instead if semaphore])
+],[
+ AC_MSG_RESULT(NO)
+])
+])
+
+#
+# LC_STATFS_DENTRY_PARAM
+# starting from 2.6.18 linux kernel uses dentry instead of
+# super_block for first vfs_statfs argument
+#
+AC_DEFUN([LC_STATFS_DENTRY_PARAM],
+[AC_MSG_CHECKING([first vfs_statfs parameter is dentry])
+LB_LINUX_TRY_COMPILE([
+ #include <linux/fs.h>
+],[
+ int vfs_statfs(struct dentry *, struct kstatfs *);
+],[
+ AC_DEFINE(HAVE_STATFS_DENTRY_PARAM, 1,
+ [first parameter of vfs_statfs is dentry])
+ AC_MSG_RESULT([yes])
+],[
+ AC_MSG_RESULT([no])
+])
+])
+
+#
+# LC_VFS_KERN_MOUNT
+# starting from 2.6.18 kernel doesn't export do_kern_mount
+# and want to use vfs_kern_mount instead.
+#
+AC_DEFUN([LC_VFS_KERN_MOUNT],
+[AC_MSG_CHECKING([vfs_kern_mount exist in kernel])
+LB_LINUX_TRY_COMPILE([
+ #include <linux/mount.h>
+],[
+ vfs_kern_mount(NULL, 0, NULL, NULL);
+],[
+ AC_DEFINE(HAVE_VFS_KERN_MOUNT, 1,
+ [vfs_kern_mount exist in kernel])
+ AC_MSG_RESULT([yes])
+],[
+ AC_MSG_RESULT([no])
+])
+])
+
+#
+# LC_INVALIDATEPAGE_RETURN_INT
+# more 2.6 api changes. return type for the invalidatepage
+# address_space_operation is 'void' in new kernels but 'int' in old
+#
+AC_DEFUN([LC_INVALIDATEPAGE_RETURN_INT],
+[AC_MSG_CHECKING([invalidatepage has return int])
+LB_LINUX_TRY_COMPILE([
+ #include <linux/buffer_head.h>
+],[
+ int rc = block_invalidatepage(NULL, 0);
+],[
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_INVALIDATEPAGE_RETURN_INT, 1,
+ [Define if return type of invalidatepage should be int])
+],[
+ AC_MSG_RESULT(NO)
+])
+])
+
+# LC_UMOUNTBEGIN_HAS_VFSMOUNT
+# more 2.6 API changes. 2.6.18 umount_begin has different parameters
+AC_DEFUN([LC_UMOUNTBEGIN_HAS_VFSMOUNT],
+[AC_MSG_CHECKING([if umount_begin needs vfsmount parameter instead of super_block])
+tmp_flags="$EXTRA_KCFLAGS"
+EXTRA_KCFLAGS="-Werror"
+LB_LINUX_TRY_COMPILE([
+ #include <linux/fs.h>
+
+ struct vfsmount;
+ static void cfg_umount_begin (struct vfsmount *v, int flags)
+ {
+ ;
+ }
+
+ static struct super_operations cfg_super_operations = {
+ .umount_begin = cfg_umount_begin,
+ };
+],[
+ cfg_super_operations.umount_begin(NULL,0);
+],[
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_UMOUNTBEGIN_VFSMOUNT, 1,
+ [Define umount_begin need second argument])
+],[
+ AC_MSG_RESULT(NO)
+])
+EXTRA_KCFLAGS="$tmp_flags"
+])
+
+# 2.6.19 API changes
+# inode doesn't have i_blksize field
+AC_DEFUN([LC_INODE_BLKSIZE],
+[AC_MSG_CHECKING([inode has i_blksize field])
+LB_LINUX_TRY_COMPILE([
+#include <linux/fs.h>
+],[
+ struct inode i;
+ i.i_blksize = 0;
+],[
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_INODE_BLKSIZE, 1,
+ [struct inode has i_blksize field])
+],[
+ AC_MSG_RESULT(NO)
+])
+])
+
+# LC_VFS_READDIR_U64_INO
+# 2.6.19 use u64 for inode number instead of inode_t
+AC_DEFUN([LC_VFS_READDIR_U64_INO],
+[AC_MSG_CHECKING([check vfs_readdir need 64bit inode number])
+tmp_flags="$EXTRA_KCFLAGS"
+EXTRA_KCFLAGS="-Werror"
+LB_LINUX_TRY_COMPILE([
+#include <linux/fs.h>
+ int fillonedir(void * __buf, const char * name, int namlen, loff_t offset,
+ u64 ino, unsigned int d_type)
+ {
+ return 0;
+ }
+],[
+ filldir_t filter;
+
+ filter = fillonedir;
+ return 1;
+],[
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_VFS_READDIR_U64_INO, 1,
+ [if vfs_readdir need 64bit inode number])
+],[
+ AC_MSG_RESULT(NO)
+])
+EXTRA_KCFLAGS="$tmp_flags"
+])
+
+# LC_GENERIC_FILE_WRITE
+# 2.6.19 introduce do_sync_write instead of
+# generic_file_write
+AC_DEFUN([LC_GENERIC_FILE_WRITE],
+[AC_MSG_CHECKING([use generic_file_write])
+LB_LINUX_TRY_COMPILE([
+ #include <linux/fs.h>
+],[
+ int result = generic_file_read(NULL, NULL, 0, 0);
+],[
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_GENERIC_FILE_WRITE, 1,
+ [use generic_file_write])
+],[
+ AC_MSG_RESULT(NO)
+])
+])
+
+# LC_GENERIC_FILE_READ
+# 2.6.19 need to use do_sync_read instead of
+# generic_file_read
+AC_DEFUN([LC_GENERIC_FILE_READ],
+[AC_MSG_CHECKING([use generic_file_read])
+LB_LINUX_TRY_COMPILE([
+ #include <linux/fs.h>
+],[
+ int result = generic_file_read(NULL, NULL, 0, 0);
+],[
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_GENERIC_FILE_READ, 1,
+ [use generic_file_read])
+],[
+ AC_MSG_RESULT(NO)
+])
+])
+
+# LC_NR_PAGECACHE
+# 2.6.18 doesn't export nr_pagecahe
+AC_DEFUN([LC_NR_PAGECACHE],
+[AC_MSG_CHECKING([kernel export nr_pagecache])
+LB_LINUX_TRY_COMPILE([
+ #include <linux/pagemap.h>
+],[
+ return atomic_read(&nr_pagecache);
+],[
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_NR_PAGECACHE, 1,
+ [is kernel export nr_pagecache])
+],[
+ AC_MSG_RESULT(NO)
+])
+])
+
+# LC_WB_RANGE_START
+# 2.6.20 rename struct writeback fields
+AC_DEFUN([LC_WB_RANGE_START],
+[AC_MSG_CHECKING([kernel has range_start in struct writeback_control])
+LB_LINUX_TRY_COMPILE([
+ #include <linux/fs.h>
+ #include <linux/sched.h>
+ #include <linux/writeback.h>
+],[
+ struct writeback_control wb;
+
+ wb.range_start = 0;
+],[
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_WB_RANGE_START, 1,
+ [writeback control has range_start field])
+],[
+ AC_MSG_RESULT(NO)
+])