Whamcloud - gitweb
LU-921 llite: warning in case of discarding dirty pages
[fs/lustre-release.git] / lustre / llite / llite_internal.h
index 7cfba13..58ff340 100644 (file)
@@ -1,6 +1,4 @@
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
+/*
  * GPL HEADER START
  *
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -28,9 +26,8 @@
 /*
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
- */
-/*
- * Copyright (c) 2011 Whamcloud, Inc.
+ *
+ * Copyright (c) 2011, 2012, Whamcloud, Inc.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
 #define VM_FAULT_RETRY 0
 #endif
 
+/* Kernel 3.1 kills LOOKUP_CONTINUE, LOOKUP_PARENT is equivalent to it.
+ * seem kernel commit 49084c3bb2055c401f3493c13edae14d49128ca0 */
+#ifndef LOOKUP_CONTINUE
+#define LOOKUP_CONTINUE LOOKUP_PARENT
+#endif
+
 /** Only used on client-side for indicating the tail of dir hash/offset. */
 #define LL_DIR_END_OFF          0x7fffffffffffffffULL
 #define LL_DIR_END_OFF_32BIT    0x7fffffffUL
@@ -135,7 +138,7 @@ struct ll_inode_info {
         struct posix_acl               *lli_posix_acl;
 
         cfs_hlist_head_t               *lli_remote_perms;
-        cfs_semaphore_t                 lli_rmtperm_sem;
+        cfs_mutex_t                     lli_rmtperm_mutex;
 
         /* identifying fields for both metadata and data stacks. */
         struct lu_fid                   lli_fid;
@@ -165,8 +168,8 @@ struct ll_inode_info {
         __u64                           lli_open_fd_write_count;
         __u64                           lli_open_fd_exec_count;
         /* Protects access to och pointers and their usage counters, also
-         * atomicity of check-update of lli_smd */
-        cfs_semaphore_t                 lli_och_sem;
+        * atomicity of check-update of lli_has_smd */
+        cfs_mutex_t                     lli_och_mutex;
 
         struct inode                    lli_vfs_inode;
 
@@ -180,7 +183,7 @@ struct ll_inode_info {
                 /* for directory */
                 struct {
                         /* serialize normal readdir and statahead-readdir. */
-                        cfs_semaphore_t                 d_readdir_sem;
+                        cfs_mutex_t                     d_readdir_mutex;
 
                         /* metadata statahead */
                         /* since parent-child threads can share the same @file
@@ -189,7 +192,6 @@ struct ll_inode_info {
                          * cleanup the dir readahead. */
                         void                           *d_opendir_key;
                         struct ll_statahead_info       *d_sai;
-                        __u64                           d_sa_pos;
                         struct posix_acl               *d_def_acl;
                         /* protect statahead stuff. */
                         cfs_spinlock_t                  d_sa_lock;
@@ -198,10 +200,9 @@ struct ll_inode_info {
                         pid_t                           d_opendir_pid;
                 } d;
 
-#define lli_readdir_sem         u.d.d_readdir_sem
+#define lli_readdir_mutex       u.d.d_readdir_mutex
 #define lli_opendir_key         u.d.d_opendir_key
 #define lli_sai                 u.d.d_sai
-#define lli_sa_pos              u.d.d_sa_pos
 #define lli_def_acl             u.d.d_def_acl
 #define lli_sa_lock             u.d.d_sa_lock
 #define lli_opendir_pid         u.d.d_opendir_pid
@@ -220,16 +221,25 @@ struct ll_inode_info {
                          * }
                          */
                         cfs_rw_semaphore_t              f_trunc_sem;
-                        cfs_semaphore_t                 f_write_sem;
+                        cfs_mutex_t                     f_write_mutex;
 
-                        /* for writepage() only to communicate to fsync */
-                        int                             f_async_rc;
-                        int                             f_write_rc;
+                       cfs_rw_semaphore_t              f_glimpse_sem;
+                       cfs_time_t                      f_glimpse_time;
+                       cfs_list_t                      f_agl_list;
+                       __u64                           f_agl_index;
 
-                        cfs_rw_semaphore_t              f_glimpse_sem;
-                        cfs_time_t                      f_glimpse_time;
-                        cfs_list_t                      f_agl_list;
-                        __u64                           f_agl_index;
+                        /* for writepage() only to communicate to fsync */
+                        int                            f_async_rc;
+
+                       /*
+                        * whenever a process try to read/write the file, the
+                        * jobid of the process will be saved here, and it'll
+                        * be packed into the write PRC when flush later.
+                        *
+                        * so the read/write statistics for jobid will not be
+                        * accurate if the file is shared by different jobs.
+                        */
+                       char                     f_jobid[JOBSTATS_JOBID_SIZE];
                 } f;
 
 #define lli_size_sem            u.f.f_size_sem
@@ -237,15 +247,15 @@ struct ll_inode_info {
 #define lli_symlink_name        u.f.f_symlink_name
 #define lli_maxbytes            u.f.f_maxbytes
 #define lli_trunc_sem           u.f.f_trunc_sem
-#define lli_write_sem           u.f.f_write_sem
-#define lli_async_rc            u.f.f_async_rc
-#define lli_write_rc            u.f.f_write_rc
-#define lli_glimpse_sem         u.f.f_glimpse_sem
-#define lli_glimpse_time        u.f.f_glimpse_time
-#define lli_agl_list            u.f.f_agl_list
-#define lli_agl_index           u.f.f_agl_index
+#define lli_write_mutex         u.f.f_write_mutex
+#define lli_glimpse_sem        u.f.f_glimpse_sem
+#define lli_glimpse_time       u.f.f_glimpse_time
+#define lli_agl_list           u.f.f_agl_list
+#define lli_agl_index          u.f.f_agl_index
+#define lli_async_rc           u.f.f_async_rc
+#define lli_jobid              u.f.f_jobid
 
-        } u;
+       } u;
 
         /* XXX: For following frequent used members, although they maybe special
          *      used for non-directory object, it is some time-wasting to check
@@ -257,20 +267,22 @@ struct ll_inode_info {
          *      In the future, if more members are added only for directory,
          *      some of the following members can be moved into u.f.
          */
-        struct lov_stripe_md           *lli_smd;
-        struct cl_object               *lli_clob;
+       bool                            lli_has_smd;
+       struct cl_object               *lli_clob;
+
+       /* mutex to request for layout lock exclusively. */
+       cfs_mutex_t                     lli_layout_mutex;
 };
 
 /*
  * Locking to guarantee consistency of non-atomic updates to long long i_size,
- * consistency between file size and KMS, and consistency within
- * ->lli_smd->lsm_oinfo[]'s.
+ * consistency between file size and KMS.
  *
- * Implemented by ->lli_size_sem and ->lsm_sem, nested in that order.
+ * Implemented by ->lli_size_sem and ->lsm_lock, nested in that order.
  */
 
-void ll_inode_size_lock(struct inode *inode, int lock_lsm);
-void ll_inode_size_unlock(struct inode *inode, int unlock_lsm);
+void ll_inode_size_lock(struct inode *inode);
+void ll_inode_size_unlock(struct inode *inode);
 
 // FIXME: replace the name of this with LL_I to conform to kernel stuff
 // static inline struct ll_inode_info *LL_I(struct inode *inode)
@@ -380,6 +392,9 @@ enum stats_track_type {
 #define LL_SBI_32BIT_API       0x2000 /* generate 32 bit inodes. */
 #define LL_SBI_64BIT_HASH      0x4000 /* support 64-bits dir hash/offset */
 #define LL_SBI_AGL_ENABLED     0x8000 /* enable agl */
+#define LL_SBI_VERBOSE        0x10000 /* verbose mount/umount */
+#define LL_SBI_LAYOUT_LOCK    0x20000 /* layout lock support */
+#define LL_SBI_USER_FID2PATH  0x40000 /* allow fid2path by unprivileged users */
 
 /* default value for ll_sb_info->contention_time */
 #define SBI_DEFAULT_CONTENTION_SECONDS     60
@@ -435,8 +450,7 @@ struct ll_sb_info {
 
         struct lprocfs_stats     *ll_stats; /* lprocfs stats counter */
 
-        unsigned long             ll_async_page_max;
-        unsigned long             ll_async_page_count;
+       struct cl_client_lru      ll_lru;
 
         struct lprocfs_stats     *ll_ra_stats;
 
@@ -474,7 +488,6 @@ struct ll_sb_info {
                                                  * clustred nfs */
         struct rmtacl_ctl_table   ll_rct;
         struct eacl_table         ll_et;
-        struct vfsmount          *ll_mnt;
 };
 
 #define LL_DEFAULT_MAX_RW_CHUNK      (32 * 1024 * 1024)
@@ -572,20 +585,19 @@ struct ll_readahead_state {
         unsigned long   ras_consecutive_stride_requests;
 };
 
-struct ll_file_dir {
-        __u64 lfd_pos;
-        __u64 lfd_next;
-};
-
 extern cfs_mem_cache_t *ll_file_data_slab;
 struct lustre_handle;
 struct ll_file_data {
         struct ll_readahead_state fd_ras;
         int fd_omode;
         struct ccc_grouplock fd_grouplock;
-        struct ll_file_dir fd_dir;
+       __u64 lfd_pos;
         __u32 fd_flags;
         struct file *fd_file;
+       /* Indicate whether need to report failure when close.
+        * true: failure is known, not report again.
+        * false: unknown failure, should report. */
+       bool fd_write_failed;
 };
 
 struct lov_stripe_md;
@@ -649,9 +661,10 @@ static void lprocfs_llite_init_vars(struct lprocfs_static_vars *lvars)
 void ll_release_page(struct page *page, int remove);
 extern struct file_operations ll_dir_operations;
 extern struct inode_operations ll_dir_inode_operations;
-struct page *ll_get_dir_page(struct file *filp, struct inode *dir, __u64 hash,
+struct page *ll_get_dir_page(struct inode *dir, __u64 hash,
                              struct ll_dir_chain *chain);
-int ll_readdir(struct file *filp, void *cookie, filldir_t filldir);
+int ll_dir_read(struct inode *inode, __u64 *_pos, void *cookie,
+               filldir_t filldir);
 
 int ll_get_mdt_idx(struct inode *inode);
 /* llite/namei.c */
@@ -665,16 +678,16 @@ struct lookup_intent *ll_convert_intent(struct open_intent *oit,
                                         int lookup_flags);
 int ll_lookup_it_finish(struct ptlrpc_request *request,
                         struct lookup_intent *it, void *data);
-struct dentry *ll_find_alias(struct inode *inode, struct dentry *de);
+struct dentry *ll_splice_alias(struct inode *inode, struct dentry *de);
 
 /* llite/rw.c */
 int ll_prepare_write(struct file *, struct page *, unsigned from, unsigned to);
 int ll_commit_write(struct file *, struct page *, unsigned from, unsigned to);
 int ll_writepage(struct page *page, struct writeback_control *wbc);
+int ll_writepages(struct address_space *, struct writeback_control *wbc);
 void ll_removepage(struct page *page);
 int ll_readpage(struct file *file, struct page *page);
 void ll_readahead_init(struct inode *inode, struct ll_readahead_state *ras);
-void ll_truncate(struct inode *inode);
 int ll_file_punch(struct inode *, loff_t, int);
 ssize_t ll_file_lockless_io(struct file *, char *, size_t, loff_t *, int);
 void ll_clear_file_contended(struct inode*);
@@ -715,7 +728,7 @@ void ll_done_writing_attr(struct inode *inode, struct md_op_data *op_data);
 int ll_som_update(struct inode *inode, struct md_op_data *op_data);
 int ll_inode_getattr(struct inode *inode, struct obdo *obdo,
                      __u64 ioepoch, int sync);
-int ll_md_setattr(struct inode *inode, struct md_op_data *op_data,
+int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data,
                   struct md_open_data **mod);
 void ll_pack_inode2opdata(struct inode *inode, struct md_op_data *op_data,
                           struct lustre_handle *fh);
@@ -745,25 +758,36 @@ int ll_dir_setstripe(struct inode *inode, struct lov_user_md *lump,
                      int set_default);
 int ll_dir_getstripe(struct inode *inode, struct lov_mds_md **lmm,
                      int *lmm_size, struct ptlrpc_request **request);
+#ifdef HAVE_FILE_FSYNC_4ARGS
+int ll_fsync(struct file *file, loff_t start, loff_t end, int data);
+#elif defined(HAVE_FILE_FSYNC_2ARGS)
+int ll_fsync(struct file *file, int data);
+#else
 int ll_fsync(struct file *file, struct dentry *dentry, int data);
+#endif
 int ll_do_fiemap(struct inode *inode, struct ll_user_fiemap *fiemap,
               int num_bytes);
 int ll_merge_lvb(struct inode *inode);
 int ll_get_grouplock(struct inode *inode, struct file *file, unsigned long arg);
 int ll_put_grouplock(struct inode *inode, struct file *file, unsigned long arg);
-int ll_fid2path(struct obd_export *exp, void *arg);
+int ll_fid2path(struct inode *inode, void *arg);
 
 /* llite/dcache.c */
+
 int ll_dops_init(struct dentry *de, int block, int init_sa);
-extern cfs_spinlock_t ll_lookup_lock;
 extern struct dentry_operations ll_d_ops;
 void ll_intent_drop_lock(struct lookup_intent *);
 void ll_intent_release(struct lookup_intent *);
-int ll_drop_dentry(struct dentry *dentry);
-void ll_unhash_aliases(struct inode *);
+void ll_invalidate_aliases(struct inode *);
 void ll_frob_intent(struct lookup_intent **itp, struct lookup_intent *deft);
 void ll_lookup_finish_locks(struct lookup_intent *it, struct dentry *dentry);
+#ifdef HAVE_D_COMPARE_7ARGS
+int ll_dcompare(const struct dentry *parent, const struct inode *pinode,
+               const struct dentry *dentry, const struct inode *inode,
+               unsigned int len, const char *str, const struct qstr *d_name);
+#else
 int ll_dcompare(struct dentry *parent, struct qstr *d_name, struct qstr *name);
+#endif
 int ll_revalidate_it_finish(struct ptlrpc_request *request,
                             struct lookup_intent *it, struct dentry *de);
 
@@ -777,13 +801,9 @@ void ll_put_super(struct super_block *sb);
 void ll_kill_super(struct super_block *sb);
 struct inode *ll_inode_from_lock(struct ldlm_lock *lock);
 void ll_clear_inode(struct inode *inode);
-int ll_setattr_raw(struct inode *inode, struct iattr *attr);
+int ll_setattr_raw(struct dentry *dentry, struct iattr *attr);
 int ll_setattr(struct dentry *de, struct iattr *attr);
-#ifndef HAVE_STATFS_DENTRY_PARAM
-int ll_statfs(struct super_block *sb, struct kstatfs *sfs);
-#else
 int ll_statfs(struct dentry *de, struct kstatfs *sfs);
-#endif
 int ll_statfs_internal(struct super_block *sb, struct obd_statfs *osfs,
                        __u64 max_age, __u32 flags);
 void ll_update_inode(struct inode *inode, struct lustre_md *md);
@@ -799,6 +819,7 @@ void ll_umount_begin(struct super_block *sb);
 #endif
 int ll_remount_fs(struct super_block *sb, int *flags, char *data);
 int ll_show_options(struct seq_file *seq, struct vfsmount *vfs);
+void ll_dirty_page_discard_warn(cfs_page_t *page, int ioret);
 int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req,
                   struct super_block *);
 void lustre_dump_dentry(struct dentry *, int recur);
@@ -811,6 +832,8 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data,
                                       const char *name, int namelen,
                                       int mode, __u32 opc, void *data);
 void ll_finish_md_op_data(struct md_op_data *op_data);
+int ll_get_obd_name(struct inode *inode, unsigned int cmd, unsigned long arg);
+char *ll_get_fsname(struct super_block *sb, char *buf, int buflen);
 
 /* llite/llite_nfs.c */
 extern struct export_operations lustre_export_operations;
@@ -1024,7 +1047,8 @@ struct ll_lock_tree_node * ll_node_from_inode(struct inode *inode, __u64 start,
                                               __u64 end, ldlm_mode_t mode);
 void policy_from_vma(ldlm_policy_data_t *policy,
                 struct vm_area_struct *vma, unsigned long addr, size_t count);
-struct vm_area_struct *our_vma(unsigned long addr, size_t count);
+struct vm_area_struct *our_vma(struct mm_struct *mm, unsigned long addr,
+                               size_t count);
 
 static inline void ll_invalidate_page(struct page *vmpage)
 {
@@ -1260,7 +1284,7 @@ ll_statahead_enter(struct inode *dir, struct dentry **dentryp, int only_unplug)
         struct ll_dentry_data *ldd;
 
         if (ll_i2sbi(dir)->ll_sa_max == 0)
-                return -ENOTSUPP;
+                return -EAGAIN;
 
         lli = ll_i2info(dir);
         /* not the same process, don't statahead */
@@ -1343,14 +1367,21 @@ void ll_iocontrol_unregister(void *magic);
 #define cl_inode_mode(inode) ((inode)->i_mode)
 #define cl_i2sbi ll_i2sbi
 
-static inline void cl_isize_lock(struct inode *inode, int lsmlock)
+static inline struct ll_file_data *cl_iattr2fd(struct inode *inode,
+                                               const struct iattr *attr)
+{
+        LASSERT(attr->ia_valid & ATTR_FILE);
+        return LUSTRE_FPRIVATE(attr->ia_file);
+}
+
+static inline void cl_isize_lock(struct inode *inode)
 {
-        ll_inode_size_lock(inode, lsmlock);
+       ll_inode_size_lock(inode);
 }
 
-static inline void cl_isize_unlock(struct inode *inode, int lsmlock)
+static inline void cl_isize_unlock(struct inode *inode)
 {
-        ll_inode_size_unlock(inode, lsmlock);
+       ll_inode_size_unlock(inode);
 }
 
 static inline void cl_isize_write_nolock(struct inode *inode, loff_t kms)
@@ -1361,9 +1392,9 @@ static inline void cl_isize_write_nolock(struct inode *inode, loff_t kms)
 
 static inline void cl_isize_write(struct inode *inode, loff_t kms)
 {
-        ll_inode_size_lock(inode, 0);
-        i_size_write(inode, kms);
-        ll_inode_size_unlock(inode, 0);
+       ll_inode_size_lock(inode);
+       i_size_write(inode, kms);
+       ll_inode_size_unlock(inode);
 }
 
 #define cl_isize_read(inode)             i_size_read(inode)
@@ -1379,6 +1410,9 @@ static inline int cl_merge_lvb(struct inode *inode)
 
 struct obd_capa *cl_capa_lookup(struct inode *inode, enum cl_req_type crt);
 
+int cl_sync_file_range(struct inode *inode, loff_t start, loff_t end,
+                      enum cl_fsync_mode mode);
+
 /** direct write pages */
 struct ll_dio_pages {
         /** page array to be written. we don't support
@@ -1434,31 +1468,60 @@ static inline void ll_set_lock_data(struct obd_export *exp, struct inode *inode,
                 *bits = it->d.lustre.it_lock_bits;
 }
 
-static inline void ll_dentry_rehash(struct dentry *dentry, int locked)
+static inline void ll_lock_dcache(struct inode *inode)
 {
-        if (!locked) {
-                cfs_spin_lock(&ll_lookup_lock);
-                spin_lock(&dcache_lock);
-        }
-        if (d_unhashed(dentry))
-                d_rehash_cond(dentry, 0);
-        if (!locked) {
-                spin_unlock(&dcache_lock);
-                cfs_spin_unlock(&ll_lookup_lock);
-        }
+#ifdef HAVE_DCACHE_LOCK
+       spin_lock(&dcache_lock);
+#else
+       spin_lock(&inode->i_lock);
+#endif
 }
 
-static inline void ll_dentry_reset_flags(struct dentry *dentry, __u64 bits)
+static inline void ll_unlock_dcache(struct inode *inode)
 {
-        if (bits & MDS_INODELOCK_LOOKUP &&
-            dentry->d_flags & DCACHE_LUSTRE_INVALID) {
-                lock_dentry(dentry);
-                dentry->d_flags &= ~DCACHE_LUSTRE_INVALID;
-                unlock_dentry(dentry);
-        }
+#ifdef HAVE_DCACHE_LOCK
+       spin_unlock(&dcache_lock);
+#else
+       spin_unlock(&inode->i_lock);
+#endif
+}
+
+static inline int d_lustre_invalid(const struct dentry *dentry)
+{
+       return dentry->d_flags & DCACHE_LUSTRE_INVALID;
 }
 
-#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2,7,50,0)
+static inline void __d_lustre_invalidate(struct dentry *dentry)
+{
+       dentry->d_flags |= DCACHE_LUSTRE_INVALID;
+}
+
+/*
+ * Mark dentry INVALID, if dentry refcount is zero (this is normally case for
+ * ll_md_blocking_ast), unhash this dentry, and let dcache to reclaim it later;
+ * else dput() of the last refcount will unhash this dentry and kill it.
+ */
+static inline void d_lustre_invalidate(struct dentry *dentry)
+{
+       CDEBUG(D_DENTRY, "invalidate dentry %.*s (%p) parent %p inode %p "
+              "refc %d\n", dentry->d_name.len, dentry->d_name.name, dentry,
+              dentry->d_parent, dentry->d_inode, d_refcount(dentry));
+
+       spin_lock(&dentry->d_lock);
+       __d_lustre_invalidate(dentry);
+       if (d_refcount(dentry) == 0)
+               __d_drop(dentry);
+       spin_unlock(&dentry->d_lock);
+}
+
+static inline void d_lustre_revalidate(struct dentry *dentry)
+{
+       spin_lock(&dentry->d_lock);
+       dentry->d_flags &= ~DCACHE_LUSTRE_INVALID;
+       spin_unlock(&dentry->d_lock);
+}
+
+#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 7, 50, 0)
 /* Compatibility for old (1.8) compiled userspace quota code */
 struct if_quotactl_18 {
         __u32                   qc_cmd;
@@ -1474,6 +1537,9 @@ struct if_quotactl_18 {
 /* End compatibility for old (1.8) compiled userspace quota code */
 #else
 #warning "remove old LL_IOC_QUOTACTL_18 compatibility code"
-#endif /* LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2,7,50,0) */
+#endif /* LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 7, 50, 0) */
+
+int ll_layout_conf(struct inode *inode, const struct cl_object_conf *conf);
+int ll_layout_refresh(struct inode *inode, __u32 *gen);
 
 #endif /* LLITE_INTERNAL_H */