/*
  This module does absolutely nothing at all. We just build it with debugging
  symbols and then read the DWARF symbols from it.  */

#include <linux/kconfig.h>

#include <linux/module.h>
#include <linux/version.h>

#include <linux/fs_struct.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/utsname.h>
#include <net/tcp.h>
#include <net/route.h>
#include <net/udp.h>
#include <net/sock.h>
#include <asm/alternative.h>
#include <linux/mount.h>
#include <linux/inetdevice.h>

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
#include <linux/fdtable.h>
#include <linux/elf.h>
#else
#include <linux/file.h>
#endif

#include <net/ip_fib.h>
#include <net/af_unix.h>
#include <linux/pid.h>

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
#include <linux/pid_namespace.h>
struct pid_namespace pid_namespace;
#endif

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
#include <linux/clocksource.h>
#include <linux/ktime.h>
#endif


#include <linux/radix-tree.h>
#include <linux/netfilter.h>
#include <linux/netfilter/x_tables.h>
#include <net/tcp.h>
#include <net/udp.h>

#include <linux/termios.h>
#include <asm/termbits.h>

#include <linux/notifier.h>
struct atomic_notifier_head atomic_notifier_head;

#include <linux/tty_driver.h>
struct tty_driver tty_driver;

#include <linux/tty.h>
struct tty_struct tty_struct;

struct udp_seq_afinfo udp_seq_afinfo;
struct tcp_seq_afinfo tcp_seq_afinfo;

struct files_struct files_struct;

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
struct uts_namespace uts_namespace;
#endif

struct socket_alloc socket_alloc;
struct sock sock;
struct inet_sock inet_sock;
struct vfsmount vfsmount;
struct in_device in_device;
struct fib_table fib_table;
struct unix_sock unix_sock;
struct pid pid;
struct radix_tree_root radix_tree_root;
#ifdef CONFIG_NETFILTER
struct nf_hook_ops nf_hook_ops;
struct nf_sockopt_ops nf_sockopt_ops;
#endif

/* Elf structures. We use the names from the ELF standard:

http://downloads.openwatcom.org/ftp/devel/docs/elf-64-gen.pdf
*/
Elf64_Ehdr A1;
Elf64_Shdr A2;
Elf64_Sym A3;
Elf64_Rel A4;
Elf64_Rela A5;
Elf64_Phdr A6;
Elf64_Dyn A7;
Elf64_Nhdr A8;

struct xt_table xt_table;

/********************************************************************
The following structs are not defined in headers, so we cant import
them. Hopefully they dont change too much.
*********************************************************************/

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
#include <net/net_namespace.h>
#endif

#include <net/ip.h>
#include <net/protocol.h>
#include <net/sock.h>
#include <net/ip_fib.h>
#include <linux/compiler.h>

#define EMBEDDED_HASH_SIZE (L1_CACHE_BYTES / sizeof(struct hlist_head))

#define __rcu

struct fn_zone {
  struct fn_zone     *fz_next;       /* Next not empty zone  */
  struct hlist_head  *fz_hash;       /* Hash table pointer   */
  seqlock_t               fz_lock;
  u32                     fz_hashmask;    /* (fz_divisor - 1)     */
  u8                      fz_order;       /* Zone order (0..32)   */
  u8                      fz_revorder;    /* 32 - fz_order        */
  __be32                  fz_mask;        /* inet_make_mask(order) */

  struct hlist_head       fz_embedded_hash[EMBEDDED_HASH_SIZE];

  int                     fz_nent;        /* Number of entries    */
  int                     fz_divisor;     /* Hash size (mask+1)   */
} fn_zone;

struct fn_hash {
  struct fn_zone    *fn_zones[33];
  struct fn_zone    *fn_zone_list;
} fn_hash;

struct fib_alias
{
    struct list_head        fa_list;
    struct fib_info         *fa_info;
    u8                      fa_tos;
    u8                      fa_type;
    u8                      fa_scope;
    u8                      fa_state;
#ifdef CONFIG_IP_FIB_TRIE
        struct rcu_head         rcu;
#endif
};

struct fib_node
{
    struct hlist_node       fn_hash;
    struct list_head        fn_alias;
    __be32                  fn_key;
    struct fib_alias        fn_embedded_alias;
};


struct fib_node fib_node;
struct fib_alias fib_alias;

/****************************************
 * RADIX_TREE START
 ****************************************/

struct rt_hash_bucket {
  struct rtable __rcu     *chain;
} rt_hash_bucket;


/* RedHat Enterprise kernels moved the radix_tree_node definition out of
   lib/radix-tree.c earlier than 3.15 so a simple LINUX_VERSION_CODE check
   doesn't work. We resort to checking if RADIX_TREE_MAP_SHIFT is defined
   instead as it's very closely related to struct radix_tree_node existing.
*/
#ifndef RADIX_TREE_MAP_SHIFT

#define RADIX_TREE_MAP_SHIFT    (CONFIG_BASE_SMALL ? 4 : 6)
#define RADIX_TREE_MAP_SIZE     (1UL << RADIX_TREE_MAP_SHIFT)
#define RADIX_TREE_MAP_MASK     (RADIX_TREE_MAP_SIZE-1)
#define RADIX_TREE_TAG_LONGS    ((RADIX_TREE_MAP_SIZE + BITS_PER_LONG - 1) / BITS_PER_LONG)

#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)
struct radix_tree_node {
    unsigned int    height;         /* Height from the bottom */
    unsigned int    count;
    union {
        struct radix_tree_node *parent; /* Used when ascending tree */
        struct rcu_head rcu_head;       /* Used when freeing node */
    };
    void            *slots[RADIX_TREE_MAP_SIZE];
    unsigned long   tags[RADIX_TREE_MAX_TAGS][RADIX_TREE_TAG_LONGS];
};

#else

struct radix_tree_node {
    unsigned int    height;         /* Height from the bottom */
    unsigned int    count;
    struct rcu_head rcu_head;
    void            *slots[RADIX_TREE_MAP_SIZE];
    unsigned long   tags[RADIX_TREE_MAX_TAGS][RADIX_TREE_TAG_LONGS];
};
#endif

#endif

/****************************************
 * RADIX_TREE END
 ****************************************/


#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
struct module_sect_attr
{
        struct module_attribute mattr;
        char *name;
        unsigned long address;
};

struct module_sect_attrs
{
        struct attribute_group grp;
        unsigned int nsections;
        struct module_sect_attr attrs[0];
};
#endif

struct module_sect_attrs module_sect_attrs;

#ifdef CONFIG_SLAB

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
/*
 * struct kmem_cache
 *
 * manages a cache.
 */

struct kmem_cache {
/* 1) per-cpu data, touched during every alloc/free */
	struct array_cache *array[NR_CPUS];
/* 2) Cache tunables. Protected by cache_chain_mutex */
	unsigned int batchcount;
	unsigned int limit;
	unsigned int shared;

	unsigned int buffer_size;
	u32 reciprocal_buffer_size;
/* 3) touched by every alloc & free from the backend */

	unsigned int flags;		/* constant flags */
	unsigned int num;		/* # of objs per slab */

/* 4) cache_grow/shrink */
	/* order of pgs per slab (2^n) */
	unsigned int gfporder;

	/* force GFP flags, e.g. GFP_DMA */
	gfp_t gfpflags;

	size_t colour;			/* cache colouring range */
	unsigned int colour_off;	/* colour offset */
	struct kmem_cache *slabp_cache;
	unsigned int slab_size;
	unsigned int dflags;		/* dynamic flags */

	/* constructor func */
	void (*ctor)(void *obj);

/* 5) cache creation/removal */
	const char *name;
	struct list_head next;

/* 6) statistics */
#if STATS
	unsigned long num_active;
	unsigned long num_allocations;
	unsigned long high_mark;
	unsigned long grown;
	unsigned long reaped;
	unsigned long errors;
	unsigned long max_freeable;
	unsigned long node_allocs;
	unsigned long node_frees;
	unsigned long node_overflow;
	atomic_t allochit;
	atomic_t allocmiss;
	atomic_t freehit;
	atomic_t freemiss;
#endif
#if DEBUG
	/*
	 * If debugging is enabled, then the allocator can add additional
	 * fields and/or padding to every object. buffer_size contains the total
	 * object size including these internal fields, the following two
	 * variables contain the offset to the user object and its size.
	 */
	int obj_offset;
	int obj_size;
#endif
	/*
	 * We put nodelists[] at the end of kmem_cache, because we want to size
	 * this array to nr_node_ids slots instead of MAX_NUMNODES
	 * (see kmem_cache_init())
	 * We still use [MAX_NUMNODES] and not [1] or [0] because cache_cache
	 * is statically defined, so we reserve the max number of nodes.
	 */
	struct kmem_list3 *nodelists[MAX_NUMNODES];
	/*
	 * Do not add fields after nodelists[]
	 */
};
#else

struct kmem_cache {
/* 1) per-cpu data, touched during every alloc/free */
        struct array_cache *array[NR_CPUS];
/* 2) Cache tunables. Protected by cache_chain_mutex */
        unsigned int batchcount;
        unsigned int limit;
        unsigned int shared;

        unsigned int buffer_size;
/* 3) touched by every alloc & free from the backend */
        struct kmem_list3 *nodelists[MAX_NUMNODES];

        unsigned int flags;             /* constant flags */
        unsigned int num;               /* # of objs per slab */

/* 4) cache_grow/shrink */
        /* order of pgs per slab (2^n) */
        unsigned int gfporder;

        /* force GFP flags, e.g. GFP_DMA */
        gfp_t gfpflags;

        size_t colour;                  /* cache colouring range */
        unsigned int colour_off;        /* colour offset */
        struct kmem_cache *slabp_cache;
        unsigned int slab_size;
        unsigned int dflags;            /* dynamic flags */

        /* constructor func */
        void (*ctor) (void *, struct kmem_cache *, unsigned long);

        /* de-constructor func */
        void (*dtor) (void *, struct kmem_cache *, unsigned long);

/* 5) cache creation/removal */
        const char *name;
        struct list_head next;

/* 6) statistics */
#if STATS
        unsigned long num_active;
        unsigned long num_allocations;
        unsigned long high_mark;
        unsigned long grown;
        unsigned long reaped;
        unsigned long errors;
        unsigned long max_freeable;
        unsigned long node_allocs;
        unsigned long node_frees;
        unsigned long node_overflow;
        atomic_t allochit;
        atomic_t allocmiss;
        atomic_t freehit;
        atomic_t freemiss;
#endif
#if DEBUG
        /*
         * If debugging is enabled, then the allocator can add additional
         * fields and/or padding to every object. buffer_size contains the total
         * object size including these internal fields, the following two
         * variables contain the offset to the user object and its size.
         */
        int obj_offset;
        int obj_size;
#endif
};

#endif /*kmem_cache decl*/

struct kmem_cache kmem_cache;
#endif

struct kmem_list3 {
         struct list_head slabs_partial; /* partial list first, better asm code */
         struct list_head slabs_full;
         struct list_head slabs_free;
        unsigned long free_objects;
         unsigned int free_limit;
         unsigned int colour_next;       /* Per-node cache coloring */
         spinlock_t list_lock;
         struct array_cache *shared;     /* shared per node */
         struct array_cache **alien;     /* on other nodes */
         unsigned long next_reap;        /* updated without locking */
         int free_touched;               /* updated without locking */
};

struct kmem_list3 kmem_list3;

struct slab {
     struct list_head list;
     unsigned long colouroff;
     void *s_mem;            /* including colour offset */
     unsigned int inuse;     /* num of objs active in slab */
     unsigned int free;
     unsigned short nodeid;
 };

struct slab slab;
#endif


/****************************************
 * TIMEKEEPING START
 ****************************************/

#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
struct tk_read_base {
        struct clocksource      *clock;
        cycle_t                 (*read)(struct clocksource *cs);
        cycle_t                 mask;
        cycle_t                 cycle_last;
        u32                     mult;
        u32                     shift;
        u64                     xtime_nsec;
        ktime_t                 base_mono;
};

struct timekeeper {
        struct tk_read_base     tkr;
        u64                     xtime_sec;
        struct timespec64       wall_to_monotonic;
        ktime_t                 offs_real;
        ktime_t                 offs_boot;
        ktime_t                 offs_tai;
        s32                     tai_offset;
        ktime_t                 base_raw;
        struct timespec64       raw_time;

        /* The following members are for timekeeping internal use */
        cycle_t                 cycle_interval;
        u64                     xtime_interval;
        s64                     xtime_remainder;
        u32                     raw_interval;
        /* The ntp_tick_length() value currently being used.
         * This cached copy ensures we consistently apply the tick
         * length for an entire tick, as ntp_tick_length may change
         * mid-tick, and we don't want to apply that new value to
         * the tick in progress.
         */
        u64                     ntp_tick;
        /* Difference between accumulated time and NTP time in ntp
         * shifted nano seconds. */
        s64                     ntp_error;
        u32                     ntp_error_shift;
        u32                     ntp_err_mult;
};

#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
struct timekeeper {
        /* Current clocksource used for timekeeping. */
        struct clocksource      *clock;
        /* NTP adjusted clock multiplier */
        u32                     mult;
        /* The shift value of the current clocksource. */
        u32                     shift;
        /* Number of clock cycles in one NTP interval. */
        cycle_t                 cycle_interval;
        /* Last cycle value (also stored in clock->cycle_last) */
        cycle_t                 cycle_last;
        /* Number of clock shifted nano seconds in one NTP interval. */
        u64                     xtime_interval;
        /* shifted nano seconds left over when rounding cycle_interval */
        s64                     xtime_remainder;
        /* Raw nano seconds accumulated per NTP interval. */
        u32                     raw_interval;

        /* Current CLOCK_REALTIME time in seconds */
        u64                     xtime_sec;
        /* Clock shifted nano seconds */
        u64                     xtime_nsec;

        /* Difference between accumulated time and NTP time in ntp
         * shifted nano seconds. */
        s64                     ntp_error;
        /* Shift conversion between clock shifted nano seconds and
         * ntp shifted nano seconds. */
        u32                     ntp_error_shift;

        /*
         * wall_to_monotonic is what we need to add to xtime (or xtime corrected
         * for sub jiffie times) to get to monotonic time.  Monotonic is pegged
         * at zero at system boot time, so wall_to_monotonic will be negative,
         * however, we will ALWAYS keep the tv_nsec part positive so we can use
         * the usual normalization.
         *
         * wall_to_monotonic is moved after resume from suspend for the
         * monotonic time not to jump. We need to add total_sleep_time to
         * wall_to_monotonic to get the real boot based time offset.
         *
         * - wall_to_monotonic is no longer the boot time, getboottime must be
         * used instead.
         */
        struct timespec         wall_to_monotonic;
        /* Offset clock monotonic -> clock realtime */
        ktime_t                 offs_real;
        /* time spent in suspend */
        struct timespec         total_sleep_time;
        /* Offset clock monotonic -> clock boottime */
        ktime_t                 offs_boot;
        /* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */
        struct timespec         raw_time;
        /* The current UTC to TAI offset in seconds */
        s32                     tai_offset;
        /* Offset clock monotonic -> clock tai */
        ktime_t                 offs_tai;

};
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
struct timekeeper {
        /* Current clocksource used for timekeeping. */
        struct clocksource      *clock;
        /* NTP adjusted clock multiplier */
        u32                     mult;
        /* The shift value of the current clocksource. */
        u32                     shift;
        /* Number of clock cycles in one NTP interval. */
        cycle_t                 cycle_interval;
        /* Number of clock shifted nano seconds in one NTP interval. */
        u64                     xtime_interval;
        /* shifted nano seconds left over when rounding cycle_interval */
        s64                     xtime_remainder;
        /* Raw nano seconds accumulated per NTP interval. */
        u32                     raw_interval;

        /* Current CLOCK_REALTIME time in seconds */
        u64                     xtime_sec;
        /* Clock shifted nano seconds */
        u64                     xtime_nsec;

        /* Difference between accumulated time and NTP time in ntp
         * shifted nano seconds. */
        s64                     ntp_error;
        /* Shift conversion between clock shifted nano seconds and
         * ntp shifted nano seconds. */
        u32                     ntp_error_shift;

        /*
         * wall_to_monotonic is what we need to add to xtime (or xtime corrected
         * for sub jiffie times) to get to monotonic time.  Monotonic is pegged
         * at zero at system boot time, so wall_to_monotonic will be negative,
         * however, we will ALWAYS keep the tv_nsec part positive so we can use
         * the usual normalization.
         *
         * wall_to_monotonic is moved after resume from suspend for the
         * monotonic time not to jump. We need to add total_sleep_time to
         * wall_to_monotonic to get the real boot based time offset.
         *
         * - wall_to_monotonic is no longer the boot time, getboottime must be
         * used instead.
         */
        struct timespec         wall_to_monotonic;
        /* Offset clock monotonic -> clock realtime */
        ktime_t                 offs_real;
        /* time spent in suspend */
        struct timespec         total_sleep_time;
        /* Offset clock monotonic -> clock boottime */
        ktime_t                 offs_boot;
        /* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */
        struct timespec         raw_time;
        /* Seqlock for all timekeeper values */
        seqlock_t               lock;
};
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
struct timekeeper {
        /* Current clocksource used for timekeeping. */
        struct clocksource      *clock;
        /* NTP adjusted clock multiplier */
        u32                     mult;
        /* The shift value of the current clocksource. */
        u32                     shift;
        /* Number of clock cycles in one NTP interval. */
        cycle_t                 cycle_interval;
        /* Number of clock shifted nano seconds in one NTP interval. */
        u64                     xtime_interval;
        /* shifted nano seconds left over when rounding cycle_interval */
        s64                     xtime_remainder;
        /* Raw nano seconds accumulated per NTP interval. */
        u32                     raw_interval;

        /* Current CLOCK_REALTIME time in seconds */
        u64                     xtime_sec;
        /* Clock shifted nano seconds */
        u64                     xtime_nsec;

        /* Difference between accumulated time and NTP time in ntp
         * shifted nano seconds. */
        s64                     ntp_error;
        /* Shift conversion between clock shifted nano seconds and
         * ntp shifted nano seconds. */
        u32                     ntp_error_shift;

        /*
         * wall_to_monotonic is what we need to add to xtime (or xtime corrected
         * for sub jiffie times) to get to monotonic time.  Monotonic is pegged
         * at zero at system boot time, so wall_to_monotonic will be negative,
         * however, we will ALWAYS keep the tv_nsec part positive so we can use
         * the usual normalization.
         *
         * wall_to_monotonic is moved after resume from suspend for the
         * monotonic time not to jump. We need to add total_sleep_time to
         * wall_to_monotonic to get the real boot based time offset.
         *
         * - wall_to_monotonic is no longer the boot time, getboottime must be
         * used instead.
         */
        struct timespec         wall_to_monotonic;
        /* Offset clock monotonic -> clock realtime */
        ktime_t                 offs_real;
        /* time spent in suspend */
        struct timespec         total_sleep_time;
        /* Offset clock monotonic -> clock boottime */
        ktime_t                 offs_boot;
        /* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */
        struct timespec         raw_time;
        /* Seqlock for all timekeeper values */
        seqlock_t               lock;
};
#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,6,31)

struct timekeeper {
	/* Current clocksource used for timekeeping. */
	struct clocksource *clock;
	/* NTP adjusted clock multiplier */
	u32	mult;
	/* The shift value of the current clocksource. */
	int	shift;

	/* Number of clock cycles in one NTP interval. */
	cycle_t cycle_interval;
	/* Number of clock shifted nano seconds in one NTP interval. */
	u64	xtime_interval;
	/* shifted nano seconds left over when rounding cycle_interval */
	s64	xtime_remainder;
	/* Raw nano seconds accumulated per NTP interval. */
	u32	raw_interval;

	/* Clock shifted nano seconds remainder not stored in xtime.tv_nsec. */
	u64	xtime_nsec;
	/* Difference between accumulated time and NTP time in ntp
	 * shifted nano seconds. */
	s64	ntp_error;
	/* Shift conversion between clock shifted nano seconds and
	 * ntp shifted nano seconds. */
	int	ntp_error_shift;

	/* The current time */
	struct timespec xtime;
	/*
	 * wall_to_monotonic is what we need to add to xtime (or xtime corrected
	 * for sub jiffie times) to get to monotonic time.  Monotonic is pegged
	 * at zero at system boot time, so wall_to_monotonic will be negative,
	 * however, we will ALWAYS keep the tv_nsec part positive so we can use
	 * the usual normalization.
	 *
	 * wall_to_monotonic is moved after resume from suspend for the
	 * monotonic time not to jump. We need to add total_sleep_time to
	 * wall_to_monotonic to get the real boot based time offset.
	 *
	 * - wall_to_monotonic is no longer the boot time, getboottime must be
	 * used instead.
	 */
	struct timespec wall_to_monotonic;
	/* time spent in suspend */
	struct timespec total_sleep_time;
	/* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */
	struct timespec raw_time;

	/* Offset clock monotonic -> clock realtime */
	ktime_t offs_real;

	/* Offset clock monotonic -> clock boottime */
	ktime_t offs_boot;

	/* Seqlock for all timekeeper values */
	seqlock_t lock;
};
#endif

struct timekeeper my_timekeeper;

/****************************************
 * TIMEKEEPING END
 ****************************************/

struct log {
         u64 ts_nsec;            /* timestamp in nanoseconds */
         u16 len;                /* length of entire record */
         u16 text_len;           /* length of text buffer */
         u16 dict_len;           /* length of dictionary buffer */
         u8 facility;            /* syslog facility */
         u8 flags:5;             /* internal record flags */
         u8 level:3;             /* syslog level */
};

struct log my_log;


/****************************************
 * MOUNT POINTS START
 ****************************************/

#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0)
struct mnt_namespace {
        atomic_t                count;
        unsigned int            proc_inum;
        struct mount *  root;
        struct list_head        list;
        struct user_namespace   *user_ns;
        u64                     seq;    /* Sequence number to prevent loops */
        wait_queue_head_t poll;
        u64 event;
};

struct mnt_pcp {
        int mnt_count;
        int mnt_writers;
};

struct mountpoint {
        struct hlist_node m_hash;
        struct dentry *m_dentry;
        int m_count;
};

struct mount {
        struct hlist_node mnt_hash;
        struct mount *mnt_parent;
        struct dentry *mnt_mountpoint;
        struct vfsmount mnt;
        struct rcu_head mnt_rcu;
#ifdef CONFIG_SMP
        struct mnt_pcp __percpu *mnt_pcp;
#else
        int mnt_count;
        int mnt_writers;
#endif
        struct list_head mnt_mounts;    /* list of children, anchored here */
        struct list_head mnt_child;     /* and going through their mnt_child */
        struct list_head mnt_instance;  /* mount instance on sb->s_mounts */
        const char *mnt_devname;        /* Name of device e.g. /dev/dsk/hda1 */
        struct list_head mnt_list;
        struct list_head mnt_expire;    /* link in fs-specific expiry list */
        struct list_head mnt_share;     /* circular list of shared mounts */
        struct list_head mnt_slave_list;/* list of slave mounts */
        struct list_head mnt_slave;     /* slave list entry */
        struct mount *mnt_master;       /* slave is on master->mnt_slave_list */
        struct mnt_namespace *mnt_ns;   /* containing namespace */
        struct mountpoint *mnt_mp;      /* where is it mounted */
#ifdef CONFIG_FSNOTIFY
        struct hlist_head mnt_fsnotify_marks;
        __u32 mnt_fsnotify_mask;
#endif
        int mnt_id;                     /* mount identifier */
        int mnt_group_id;               /* peer group identifier */
        int mnt_expiry_mark;            /* true if marked for expiry */
        int mnt_pinned;
        struct path mnt_ex_mountpoint;
};
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)
struct mnt_namespace {
        atomic_t                count;
        unsigned int            proc_inum;
        struct mount *  root;
        struct list_head        list;
        struct user_namespace   *user_ns;
        u64                     seq;    /* Sequence number to prevent loops */
        wait_queue_head_t poll;
        int event;
};

struct mnt_pcp {
        int mnt_count;
        int mnt_writers;
};

struct mountpoint {
        struct hlist_node m_hash;
        struct dentry *m_dentry;
        int m_count;
};

struct mount {
        struct hlist_node mnt_hash;
        struct mount *mnt_parent;
        struct dentry *mnt_mountpoint;
        struct vfsmount mnt;
        struct rcu_head mnt_rcu;
#ifdef CONFIG_SMP
        struct mnt_pcp __percpu *mnt_pcp;
#else
        int mnt_count;
        int mnt_writers;
#endif
        struct list_head mnt_mounts;    /* list of children, anchored here */
        struct list_head mnt_child;     /* and going through their mnt_child */
        struct list_head mnt_instance;  /* mount instance on sb->s_mounts */
        const char *mnt_devname;        /* Name of device e.g. /dev/dsk/hda1 */
        struct list_head mnt_list;
        struct list_head mnt_expire;    /* link in fs-specific expiry list */
        struct list_head mnt_share;     /* circular list of shared mounts */
        struct list_head mnt_slave_list;/* list of slave mounts */
        struct list_head mnt_slave;     /* slave list entry */
        struct mount *mnt_master;       /* slave is on master->mnt_slave_list */
        struct mnt_namespace *mnt_ns;   /* containing namespace */
        struct mountpoint *mnt_mp;      /* where is it mounted */
#ifdef CONFIG_FSNOTIFY
        struct hlist_head mnt_fsnotify_marks;
        __u32 mnt_fsnotify_mask;
#endif
        int mnt_id;                     /* mount identifier */
        int mnt_group_id;               /* peer group identifier */
        int mnt_expiry_mark;            /* true if marked for expiry */
        int mnt_pinned;
        struct path mnt_ex_mountpoint;
};
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)
struct mnt_namespace {
        atomic_t                count;
        unsigned int            proc_inum;
        struct mount *  root;
        struct list_head        list;
        struct user_namespace   *user_ns;
        u64                     seq;    /* Sequence number to prevent loops */
        wait_queue_head_t poll;
        int event;
};

struct mnt_pcp {
        int mnt_count;
        int mnt_writers;
};

struct mountpoint {
        struct list_head m_hash;
        struct dentry *m_dentry;
        int m_count;
};

struct mount {
        struct list_head mnt_hash;
        struct mount *mnt_parent;
        struct dentry *mnt_mountpoint;
        struct vfsmount mnt;
        struct rcu_head mnt_rcu;
#ifdef CONFIG_SMP
        struct mnt_pcp __percpu *mnt_pcp;
#else
        int mnt_count;
        int mnt_writers;
#endif
        struct list_head mnt_mounts;    /* list of children, anchored here */
        struct list_head mnt_child;     /* and going through their mnt_child */
        struct list_head mnt_instance;  /* mount instance on sb->s_mounts */
        const char *mnt_devname;        /* Name of device e.g. /dev/dsk/hda1 */
        struct list_head mnt_list;
        struct list_head mnt_expire;    /* link in fs-specific expiry list */
        struct list_head mnt_share;     /* circular list of shared mounts */
        struct list_head mnt_slave_list;/* list of slave mounts */
        struct list_head mnt_slave;     /* slave list entry */
        struct mount *mnt_master;       /* slave is on master->mnt_slave_list */
        struct mnt_namespace *mnt_ns;   /* containing namespace */
        struct mountpoint *mnt_mp;      /* where is it mounted */
#ifdef CONFIG_FSNOTIFY
        struct hlist_head mnt_fsnotify_marks;
        __u32 mnt_fsnotify_mask;
#endif
        int mnt_id;                     /* mount identifier */
        int mnt_group_id;               /* peer group identifier */
        int mnt_expiry_mark;            /* true if marked for expiry */
        int mnt_pinned;
        struct path mnt_ex_mountpoint;
};
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
struct mnt_namespace {
        atomic_t                count;
        unsigned int            proc_inum;
        struct mount *  root;
        struct list_head        list;
        struct user_namespace   *user_ns;
        u64                     seq;    /* Sequence number to prevent loops */
        wait_queue_head_t poll;
        int event;
};

struct mnt_pcp {
        int mnt_count;
        int mnt_writers;
};

struct mountpoint {
        struct list_head m_hash;
        struct dentry *m_dentry;
        int m_count;
};

struct mount {
        struct list_head mnt_hash;
        struct mount *mnt_parent;
        struct dentry *mnt_mountpoint;
        struct vfsmount mnt;
#ifdef CONFIG_SMP
        struct mnt_pcp __percpu *mnt_pcp;
#else
        int mnt_count;
        int mnt_writers;
#endif
        struct list_head mnt_mounts;    /* list of children, anchored here */
        struct list_head mnt_child;     /* and going through their mnt_child */
        struct list_head mnt_instance;  /* mount instance on sb->s_mounts */
        const char *mnt_devname;        /* Name of device e.g. /dev/dsk/hda1 */
        struct list_head mnt_list;
        struct list_head mnt_expire;    /* link in fs-specific expiry list */
        struct list_head mnt_share;     /* circular list of shared mounts */
        struct list_head mnt_slave_list;/* list of slave mounts */
        struct list_head mnt_slave;     /* slave list entry */
        struct mount *mnt_master;       /* slave is on master->mnt_slave_list */
        struct mnt_namespace *mnt_ns;   /* containing namespace */
        struct mountpoint *mnt_mp;      /* where is it mounted */
#ifdef CONFIG_FSNOTIFY
        struct hlist_head mnt_fsnotify_marks;
        __u32 mnt_fsnotify_mask;
#endif
        int mnt_id;                     /* mount identifier */
        int mnt_group_id;               /* peer group identifier */
        int mnt_expiry_mark;            /* true if marked for expiry */
        int mnt_pinned;
        int mnt_ghosts;
};
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
struct mnt_namespace {
        atomic_t                count;
        unsigned int            proc_inum;
        struct mount *  root;
        struct list_head        list;
        struct user_namespace   *user_ns;
        u64                     seq;    /* Sequence number to prevent loops */
        wait_queue_head_t poll;
        int event;
};

struct mnt_pcp {
        int mnt_count;
        int mnt_writers;
};

struct mount {
        struct list_head mnt_hash;
        struct mount *mnt_parent;
        struct dentry *mnt_mountpoint;
        struct vfsmount mnt;
#ifdef CONFIG_SMP
        struct mnt_pcp __percpu *mnt_pcp;
#else
        int mnt_count;
        int mnt_writers;
#endif
        struct list_head mnt_mounts;    /* list of children, anchored here */
        struct list_head mnt_child;     /* and going through their mnt_child */
        struct list_head mnt_instance;  /* mount instance on sb->s_mounts */
        const char *mnt_devname;        /* Name of device e.g. /dev/dsk/hda1 */
        struct list_head mnt_list;
        struct list_head mnt_expire;    /* link in fs-specific expiry list */
        struct list_head mnt_share;     /* circular list of shared mounts */
        struct list_head mnt_slave_list;/* list of slave mounts */
        struct list_head mnt_slave;     /* slave list entry */
        struct mount *mnt_master;       /* slave is on master->mnt_slave_list */
        struct mnt_namespace *mnt_ns;   /* containing namespace */
#ifdef CONFIG_FSNOTIFY
        struct hlist_head mnt_fsnotify_marks;
        __u32 mnt_fsnotify_mask;
#endif
        int mnt_id;                     /* mount identifier */
        int mnt_group_id;               /* peer group identifier */
        int mnt_expiry_mark;            /* true if marked for expiry */
        int mnt_pinned;
        int mnt_ghosts;
};
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
struct mnt_namespace {
        atomic_t                count;
        struct mount *  root;
        struct list_head        list;
        wait_queue_head_t poll;
        int event;
};

struct mnt_pcp {
        int mnt_count;
        int mnt_writers;
};

struct mount {
        struct list_head mnt_hash;
        struct mount *mnt_parent;
        struct dentry *mnt_mountpoint;
        struct vfsmount mnt;
#ifdef CONFIG_SMP
        struct mnt_pcp __percpu *mnt_pcp;
#else
        int mnt_count;
        int mnt_writers;
#endif
        struct list_head mnt_mounts;    /* list of children, anchored here */
        struct list_head mnt_child;     /* and going through their mnt_child */
        struct list_head mnt_instance;  /* mount instance on sb->s_mounts */
        const char *mnt_devname;        /* Name of device e.g. /dev/dsk/hda1 */
        struct list_head mnt_list;
        struct list_head mnt_expire;    /* link in fs-specific expiry list */
        struct list_head mnt_share;     /* circular list of shared mounts */
        struct list_head mnt_slave_list;/* list of slave mounts */
        struct list_head mnt_slave;     /* slave list entry */
        struct mount *mnt_master;       /* slave is on master->mnt_slave_list */
        struct mnt_namespace *mnt_ns;   /* containing namespace */
#ifdef CONFIG_FSNOTIFY
        struct hlist_head mnt_fsnotify_marks;
        __u32 mnt_fsnotify_mask;
#endif
        int mnt_id;                     /* mount identifier */
        int mnt_group_id;               /* peer group identifier */
        int mnt_expiry_mark;            /* true if marked for expiry */
        int mnt_pinned;
        int mnt_ghosts;
};

#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)
struct mnt_namespace {
        atomic_t                count;
        struct mount *  root;
        struct list_head        list;
        wait_queue_head_t poll;
        int event;
};

struct mnt_pcp {
        int mnt_count;
        int mnt_writers;
};

struct mount {
        struct list_head mnt_hash;
        struct mount *mnt_parent;
        struct dentry *mnt_mountpoint;
        struct vfsmount mnt;
#ifdef CONFIG_SMP
        struct mnt_pcp __percpu *mnt_pcp;
        atomic_t mnt_longterm;          /* how many of the refs are longterm */
#else
        int mnt_count;
        int mnt_writers;
#endif
        struct list_head mnt_mounts;    /* list of children, anchored here */
        struct list_head mnt_child;     /* and going through their mnt_child */
        struct list_head mnt_instance;  /* mount instance on sb->s_mounts */
        const char *mnt_devname;        /* Name of device e.g. /dev/dsk/hda1 */
        struct list_head mnt_list;
        struct list_head mnt_expire;    /* link in fs-specific expiry list */
        struct list_head mnt_share;     /* circular list of shared mounts */
        struct list_head mnt_slave_list;/* list of slave mounts */
        struct list_head mnt_slave;     /* slave list entry */
        struct mount *mnt_master;       /* slave is on master->mnt_slave_list */
        struct mnt_namespace *mnt_ns;   /* containing namespace */
#ifdef CONFIG_FSNOTIFY
        struct hlist_head mnt_fsnotify_marks;
        __u32 mnt_fsnotify_mask;
#endif
        int mnt_id;                     /* mount identifier */
        int mnt_group_id;               /* peer group identifier */
        int mnt_expiry_mark;            /* true if marked for expiry */
        int mnt_pinned;
        int mnt_ghosts;
};
#endif

/****************************************
 * MOUNT POINTS END
 ****************************************/


/****************************************
 * PROC START
 ****************************************/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
struct proc_dir_entry {
        unsigned int low_ino;
        umode_t mode;
        nlink_t nlink;
        kuid_t uid;
        kgid_t gid;
        loff_t size;
        const struct inode_operations *proc_iops;
        const struct file_operations *proc_fops;
        struct proc_dir_entry *next, *parent, *subdir;
        void *data;
        atomic_t count;         /* use count */
        atomic_t in_use;        /* number of callers into module in progress; */
                                /* negative -> it's going away RSN */
        struct completion *pde_unload_completion;
        struct list_head pde_openers;   /* who did ->open, but not ->release */
        spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */
        u8 namelen;
        char name[];
};
#else
/** Before 3.10, proc_dir_entry is defined in <linux/proc_fs.h> **/
#endif
/****************************************
 * PROC END
 ****************************************/
