+/* llite/llite_cl.c */
+extern struct lu_device_type vvp_device_type;
+
+/**
+ * Common IO arguments for various VFS I/O interfaces.
+ */
+
+int cl_sb_init(struct super_block *sb);
+int cl_sb_fini(struct super_block *sb);
+int cl_inode_init(struct inode *inode, struct lustre_md *md);
+void cl_inode_fini(struct inode *inode);
+
+enum cl_lock_mode vvp_mode_from_vma(struct vm_area_struct *vma);
+void ll_io_init(struct cl_io *io, const struct file *file, int write);
+
+void ras_update(struct ll_sb_info *sbi, struct inode *inode,
+ struct ll_readahead_state *ras, unsigned long index,
+ unsigned hit);
+void ll_ra_count_put(struct ll_sb_info *sbi, unsigned long len);
+int ll_is_file_contended(struct file *file);
+void ll_ra_stats_inc(struct address_space *mapping, enum ra_stat which);
+
+/* llite/llite_rmtacl.c */
+#ifdef CONFIG_FS_POSIX_ACL
+obd_valid rce_ops2valid(int ops);
+struct rmtacl_ctl_entry *rct_search(struct rmtacl_ctl_table *rct, pid_t key);
+int rct_add(struct rmtacl_ctl_table *rct, pid_t key, int ops);
+int rct_del(struct rmtacl_ctl_table *rct, pid_t key);
+void rct_init(struct rmtacl_ctl_table *rct);
+void rct_fini(struct rmtacl_ctl_table *rct);
+
+void ee_free(struct eacl_entry *ee);
+int ee_add(struct eacl_table *et, pid_t key, struct lu_fid *fid, int type,
+ ext_acl_xattr_header *header);
+struct eacl_entry *et_search_del(struct eacl_table *et, pid_t key,
+ struct lu_fid *fid, int type);
+void et_search_free(struct eacl_table *et, pid_t key);
+void et_init(struct eacl_table *et);
+void et_fini(struct eacl_table *et);
+#endif
+
+/* statahead.c */
+
+#define LL_SA_RPC_MIN 2
+#define LL_SA_RPC_DEF 32
+#define LL_SA_RPC_MAX 8192
+
+/* per inode struct, for dir only */
+struct ll_statahead_info {
+ struct inode *sai_inode;
+ unsigned int sai_generation; /* generation for statahead */
+ atomic_t sai_refcount; /* when access this struct, hold
+ * refcount */
+ unsigned int sai_sent; /* stat requests sent count */
+ unsigned int sai_replied; /* stat requests which received
+ * reply */
+ unsigned int sai_max; /* max ahead of lookup */
+ unsigned int sai_index; /* index of statahead entry */
+ unsigned int sai_index_next; /* index for the next statahead
+ * entry to be stated */
+ unsigned int sai_hit; /* hit count */
+ unsigned int sai_miss; /* miss count:
+ * for "ls -al" case, it includes
+ * hidden dentry miss;
+ * for "ls -l" case, it does not
+ * include hidden dentry miss.
+ * "sai_miss_hidden" is used for
+ * the later case.
+ */
+ unsigned int sai_consecutive_miss; /* consecutive miss */
+ unsigned int sai_miss_hidden;/* "ls -al", but first dentry
+ * is not a hidden one */
+ unsigned int sai_skip_hidden;/* skipped hidden dentry count */
+ unsigned int sai_ls_all:1; /* "ls -al", do stat-ahead for
+ * hidden entries */
+ cfs_waitq_t sai_waitq; /* stat-ahead wait queue */
+ struct ptlrpc_thread sai_thread; /* stat-ahead thread */
+ struct list_head sai_entries_sent; /* entries sent out */
+ struct list_head sai_entries_received; /* entries returned */
+ struct list_head sai_entries_stated; /* entries stated */
+};
+
+int do_statahead_enter(struct inode *dir, struct dentry **dentry, int lookup);
+void ll_statahead_exit(struct dentry *dentry, int result);
+void ll_stop_statahead(struct inode *inode, void *key);
+
+static inline
+void ll_statahead_mark(struct dentry *dentry)
+{
+ struct ll_inode_info *lli = ll_i2info(dentry->d_parent->d_inode);
+ struct ll_dentry_data *ldd = ll_d2d(dentry);
+
+ /* not the same process, don't mark */
+ if (lli->lli_opendir_pid != cfs_curproc_pid())
+ return;
+
+ spin_lock(&lli->lli_lock);
+ if (likely(lli->lli_sai != NULL && ldd != NULL))
+ ldd->lld_sa_generation = lli->lli_sai->sai_generation;
+ spin_unlock(&lli->lli_lock);
+}
+
+static inline
+int ll_statahead_enter(struct inode *dir, struct dentry **dentryp, int lookup)
+{
+ struct ll_sb_info *sbi = ll_i2sbi(dir);
+ struct ll_inode_info *lli = ll_i2info(dir);
+ struct ll_dentry_data *ldd = ll_d2d(*dentryp);
+
+ if (sbi->ll_sa_max == 0)
+ return -ENOTSUPP;
+
+ /* not the same process, don't statahead */
+ if (lli->lli_opendir_pid != cfs_curproc_pid())
+ return -EBADF;
+
+ /*
+ * When "ls" a dentry, the system trigger more than once "revalidate" or
+ * "lookup", for "getattr", for "getxattr", and maybe for others.
+ * Under patchless client mode, the operation intent is not accurate,
+ * it maybe misguide the statahead thread. For example:
+ * The "revalidate" call for "getattr" and "getxattr" of a dentry maybe
+ * have the same operation intent -- "IT_GETATTR".
+ * In fact, one dentry should has only one chance to interact with the
+ * statahead thread, otherwise the statahead windows will be confused.
+ * The solution is as following:
+ * Assign "lld_sa_generation" with "sai_generation" when a dentry
+ * "IT_GETATTR" for the first time, and the subsequent "IT_GETATTR"
+ * will bypass interacting with statahead thread for checking:
+ * "lld_sa_generation == lli_sai->sai_generation"
+ */
+ if (ldd && lli->lli_sai &&
+ ldd->lld_sa_generation == lli->lli_sai->sai_generation)
+ return -EAGAIN;
+
+ return do_statahead_enter(dir, dentryp, lookup);
+}
+
+static void inline ll_dops_init(struct dentry *de, int block)
+{
+ struct ll_dentry_data *lld = ll_d2d(de);
+
+ if (lld == NULL && block != 0) {
+ ll_set_dd(de);
+ lld = ll_d2d(de);
+ }
+
+ if (lld != NULL)
+ lld->lld_sa_generation = 0;
+
+ de->d_op = &ll_d_ops;
+}
+