Whamcloud - gitweb
LU-9210 statahead: missing barrier before wake_up
[fs/lustre-release.git] / lustre / llite / statahead.c
index 384bd20..c11c682 100644 (file)
  *
  * You should have received a copy of the GNU General Public License
  * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
+ * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * GPL HEADER END
  */
@@ -27,7 +23,7 @@
  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2011, 2015, Intel Corporation.
+ * Copyright (c) 2011, 2016, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
@@ -183,8 +179,8 @@ static inline int is_omitted_entry(struct ll_statahead_info *sai, __u64 index)
 
 /* allocate sa_entry and hash it to allow scanner process to find it */
 static struct sa_entry *
-sa_alloc(struct ll_statahead_info *sai, __u64 index, const char *name, int len,
-        const struct lu_fid *fid)
+sa_alloc(struct dentry *parent, struct ll_statahead_info *sai, __u64 index,
+        const char *name, int len, const struct lu_fid *fid)
 {
        struct ll_inode_info *lli;
        struct sa_entry *entry;
@@ -197,7 +193,7 @@ sa_alloc(struct ll_statahead_info *sai, __u64 index, const char *name, int len,
        if (unlikely(entry == NULL))
                RETURN(ERR_PTR(-ENOMEM));
 
-       CDEBUG(D_READA, "alloc sa entry %.*s(%p) index "LPU64"\n",
+       CDEBUG(D_READA, "alloc sa entry %.*s(%p) index %llu\n",
               len, name, entry, index);
 
        entry->se_index = index;
@@ -207,7 +203,7 @@ sa_alloc(struct ll_statahead_info *sai, __u64 index, const char *name, int len,
        dname = (char *)entry + sizeof(struct sa_entry);
        memcpy(dname, name, len);
        dname[len] = 0;
-       entry->se_qstr.hash = full_name_hash(name, len);
+       entry->se_qstr.hash = ll_full_name_hash(parent, name, len);
        entry->se_qstr.len = len;
        entry->se_qstr.name = dname;
        entry->se_fid = *fid;
@@ -227,7 +223,7 @@ sa_alloc(struct ll_statahead_info *sai, __u64 index, const char *name, int len,
 /* free sa_entry, which should have been unhashed and not in any list */
 static void sa_free(struct ll_statahead_info *sai, struct sa_entry *entry)
 {
-       CDEBUG(D_READA, "free sa entry %.*s(%p) index "LPU64"\n",
+       CDEBUG(D_READA, "free sa entry %.*s(%p) index %llu\n",
               entry->se_qstr.len, entry->se_qstr.name, entry,
               entry->se_index);
 
@@ -510,6 +506,18 @@ static void ll_agl_trigger(struct inode *inode, struct ll_statahead_info *sai)
                 RETURN_EXIT;
         }
 
+       /* In case of restore, the MDT has the right size and has already
+        * sent it back without granting the layout lock, inode is up-to-date.
+        * Then AGL (async glimpse lock) is useless.
+        * Also to glimpse we need the layout, in case of a runninh restore
+        * the MDT holds the layout lock so the glimpse will block up to the
+        * end of restore (statahead/agl will block) */
+       if (ll_file_test_flag(lli, LLIF_FILE_RESTORING)) {
+               lli->lli_agl_index = 0;
+               iput(inode);
+               RETURN_EXIT;
+       }
+
         /* Someone is in glimpse (sync or async), do nothing. */
        rc = down_write_trylock(&lli->lli_glimpse_sem);
         if (rc == 0) {
@@ -540,7 +548,7 @@ static void ll_agl_trigger(struct inode *inode, struct ll_statahead_info *sai)
         }
 
         CDEBUG(D_READA, "Handling (init) async glimpse: inode = "
-               DFID", idx = "LPU64"\n", PFID(&lli->lli_fid), index);
+              DFID", idx = %llu\n", PFID(&lli->lli_fid), index);
 
         cl_agl(inode);
         lli->lli_agl_index = 0;
@@ -548,7 +556,7 @@ static void ll_agl_trigger(struct inode *inode, struct ll_statahead_info *sai)
        up_write(&lli->lli_glimpse_sem);
 
         CDEBUG(D_READA, "Handled (init) async glimpse: inode= "
-               DFID", idx = "LPU64", rc = %d\n",
+              DFID", idx = %llu, rc = %d\n",
                PFID(&lli->lli_fid), index, rc);
 
         iput(inode);
@@ -592,7 +600,7 @@ static void sa_instantiate(struct ll_statahead_info *sai,
                }
        }
 
-        it->d.lustre.it_lock_handle = entry->se_handle;
+       it->it_lock_handle = entry->se_handle;
        rc = md_revalidate_lock(ll_i2mdexp(dir), it, ll_inode2fid(dir), NULL);
         if (rc != 1)
                 GOTO(out, rc = -EAGAIN);
@@ -683,7 +691,7 @@ static int ll_statahead_interpret(struct ptlrpc_request *req,
                 * thread enqueues lock on parent in readdir and another
                 * process enqueues lock on child with parent lock held, eg.
                 * unlink. */
-               handle = it->d.lustre.it_lock_handle;
+               handle = it->it_lock_handle;
                ll_intent_drop_lock(it);
        }
 
@@ -705,6 +713,8 @@ static int ll_statahead_interpret(struct ptlrpc_request *req,
                list_add_tail(&entry->se_list, &sai->sai_interim_entries);
        }
        sai->sai_replied++;
+
+       smp_mb();
        if (waitq != NULL)
                wake_up(waitq);
        spin_unlock(&lli->lli_sa_lock);
@@ -789,7 +799,7 @@ static int sa_revalidate(struct inode *dir, struct sa_entry *entry,
 {
        struct inode *inode = dentry->d_inode;
        struct lookup_intent it = { .it_op = IT_GETATTR,
-                                   .d.lustre.it_lock_handle = 0 };
+                                   .it_lock_handle = 0 };
        struct md_enqueue_info *minfo;
        int rc;
        ENTRY;
@@ -804,7 +814,7 @@ static int sa_revalidate(struct inode *dir, struct sa_entry *entry,
        rc = md_revalidate_lock(ll_i2mdexp(dir), &it, ll_inode2fid(inode),
                                NULL);
        if (rc == 1) {
-               entry->se_handle = it.d.lustre.it_lock_handle;
+               entry->se_handle = it.it_lock_handle;
                ll_intent_release(&it);
                RETURN(1);
        }
@@ -838,7 +848,7 @@ static void sa_statahead(struct dentry *parent, const char *name, int len,
        int rc;
        ENTRY;
 
-       entry = sa_alloc(sai, sai->sai_index, name, len, fid);
+       entry = sa_alloc(parent, sai, sai->sai_index, name, len, fid);
        if (IS_ERR(entry))
                RETURN_EXIT;
 
@@ -994,8 +1004,6 @@ static int ll_statahead_thread(void *arg)
        if (IS_ERR(op_data))
                GOTO(out, rc = PTR_ERR(op_data));
 
-       op_data->op_max_pages = ll_i2sbi(dir)->ll_md_brw_pages;
-
        if (sbi->ll_flags & LL_SBI_AGL_ENABLED)
                ll_start_agl(parent, sai);
 
@@ -1019,8 +1027,8 @@ static int ll_statahead_thread(void *arg)
                sai->sai_in_readpage = 0;
                if (IS_ERR(page)) {
                        rc = PTR_ERR(page);
-                       CDEBUG(D_READA, "error reading dir "DFID" at "LPU64
-                              "/"LPU64" opendir_pid = %u: rc = %d\n",
+                       CDEBUG(D_READA, "error reading dir "DFID" at %llu"
+                              "/%llu opendir_pid = %u: rc = %d\n",
                               PFID(ll_inode2fid(dir)), pos, sai->sai_index,
                               lli->lli_opendir_pid, rc);
                        break;
@@ -1119,8 +1127,8 @@ static int ll_statahead_thread(void *arg)
                        rc = -EFAULT;
                        atomic_inc(&sbi->ll_sa_wrong);
                        CDEBUG(D_READA, "Statahead for dir "DFID" hit "
-                              "ratio too low: hit/miss "LPU64"/"LPU64
-                              ", sent/replied "LPU64"/"LPU64", stopping "
+                              "ratio too low: hit/miss %llu/%llu"
+                              ", sent/replied %llu/%llu, stopping "
                               "statahead thread: pid %d\n",
                               PFID(&lli->lli_fid), sai->sai_hit,
                               sai->sai_miss, sai->sai_sent,
@@ -1237,8 +1245,12 @@ void ll_deauthorize_statahead(struct inode *dir, void *key)
                /*
                 * statahead thread may not quit yet because it needs to cache
                 * entries, now it's time to tell it to quit.
+                *
+                * In case sai is released, wake_up() is called inside spinlock,
+                * so we have to call smp_mb() explicitely to serialize ops.
                 */
                thread_set_flags(&sai->sai_thread, SVC_STOPPING);
+               smp_mb();
                wake_up(&sai->sai_thread.t_ctl_waitq);
        }
        spin_unlock(&lli->lli_sa_lock);
@@ -1278,7 +1290,6 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry)
        /**
         *FIXME choose the start offset of the readdir
         */
-       op_data->op_max_pages = ll_i2sbi(dir)->ll_md_brw_pages;
 
        ll_dir_chain_init(&chain);
        page = ll_get_dir_page(dir, op_data, 0, &chain);
@@ -1291,7 +1302,7 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry)
                        struct ll_inode_info *lli = ll_i2info(dir);
 
                        rc = PTR_ERR(page);
-                       CERROR("%s: reading dir "DFID" at "LPU64
+                       CERROR("%s: reading dir "DFID" at %llu"
                               "opendir_pid = %u : rc = %d\n",
                               ll_get_fsname(dir->i_sb, NULL, 0),
                               PFID(ll_inode2fid(dir)), pos,
@@ -1461,7 +1472,7 @@ static int revalidate_statahead_dentry(struct inode *dir,
        if (entry->se_state == SA_ENTRY_SUCC && entry->se_inode != NULL) {
                struct inode *inode = entry->se_inode;
                struct lookup_intent it = { .it_op = IT_GETATTR,
-                                           .d.lustre.it_lock_handle =
+                                           .it_lock_handle =
                                                entry->se_handle };
                __u64 bits;