Whamcloud - gitweb
- many fixes in GNS code after Nikita's code review. They are the following:
authoryury <yury>
Mon, 18 Apr 2005 12:13:53 +0000 (12:13 +0000)
committeryury <yury>
Mon, 18 Apr 2005 12:13:53 +0000 (12:13 +0000)
  - removed ll_d_lookup() as it is not used anymore.

  - removed struts from real_lookup() with calling revalidate() after lookup if dentry
    is marked GNS_MOUNTING. By now all this dentry marking is not needed anymore.

  - ll_gns_mount_object() is now called from ll_revalidate_it() and ll_lookup_it()

  - fixed deadlock when one thread T1 waits for mount completion and another one T2
    created by upcall script waits for dentry->d_inode->i_sem. By now -ERESTARTSYS
    is returned for T2 and others and whren they restart syscall, dentry is mounted
    already or some error occured and GNS state is READY for mount.

  - fixes in comments and header of llite_gns.c

  - fixed possible incorrect spin_unlock() in ll_gns_mount_object()

  - using lookup_one_len() for looking for mount object instead of d_lookup() which
    looks only in dcache.

  - fixed handling of negative mount object dentry in ll_gns_mount_object()

  - fixed readding mount object content. By now kernel_read() is used instead of
    readpage approach.

  - waking up all possible waiters on finishing GNS mount. Nevertheless in current
    stuff nobody seem waits for mount (-RESTARTSYS is used instead), completion
    exists and it is semanticaly correct to wake up all its waiters. In fact this
    is needed for possible future using. If it happen that nobody will wait on it
    and it is counted not needed, it will be removed.

lustre/include/linux/lvfs.h
lustre/kernel_patches/patches/vfs_gns-2.6-vanilla.patch
lustre/llite/dcache.c
lustre/llite/dir.c
lustre/llite/llite_gns.c
lustre/llite/llite_internal.h
lustre/llite/namei.c

index ffa1396..008fcb7 100644 (file)
@@ -172,18 +172,6 @@ static inline void ll_sleep(int t)
         schedule_timeout(t * HZ);
         set_current_state(TASK_RUNNING);
 }
-
-static inline struct dentry *
-ll_d_lookup(const char *name,
-           struct dentry *dparent, int len)
-{
-       struct qstr qstr;
-
-       qstr.len = len;
-       qstr.name = name;
-       qstr.hash = full_name_hash(name, len);
-       return d_lookup(dparent, &qstr);
-}
 #endif
 
 static inline int ll_id2str(char *str, __u64 id, __u32 generation)
index 0cb55e6..938e527 100644 (file)
@@ -1,23 +1,3 @@
-diff -rupN linux-2.6.7/fs/namei.c linux-2.6.7.new/fs/namei.c
---- linux-2.6.7/fs/namei.c     2005-03-29 18:54:13.000000000 +0300
-+++ linux-2.6.7.new/fs/namei.c 2005-03-31 14:42:01.605302456 +0300
-@@ -422,6 +422,16 @@ static struct dentry * real_lookup(struc
-                               result = dentry;
-               }
-               unlock_dir(dir, lock);
-+              if (!IS_ERR(result)) {
-+                      spin_lock(&result->d_lock);
-+                      if (result->d_flags & DCACHE_GNS_PENDING) {
-+                              spin_unlock(&result->d_lock);
-+                              if (result->d_op && result->d_op->d_revalidate)
-+                                      result->d_op->d_revalidate(result, nd);
-+                      } else {
-+                              spin_unlock(&result->d_lock);
-+                      }
-+              }
-               return result;
-       }
 diff -rupN linux-2.6.7/fs/namespace.c linux-2.6.7.new/fs/namespace.c
 --- linux-2.6.7/fs/namespace.c 2005-03-29 18:54:13.000000000 +0300
 +++ linux-2.6.7.new/fs/namespace.c     2005-03-30 17:51:39.000000000 +0300
index d74dc8b..bea6056 100644 (file)
@@ -294,30 +294,13 @@ int ll_revalidate_it(struct dentry *de, int flags, struct nameidata *nd,
 {
         struct lookup_intent lookup_it = { .it_op = IT_LOOKUP };
         struct ptlrpc_request *req = NULL;
+        int orig_it, err, rc = 0;
         struct obd_export *exp;
         struct it_cb_data icbd;
         struct lustre_id pid;
         struct lustre_id cid;
-        int orig_it, rc = 0;
         ENTRY;
 
-        spin_lock(&de->d_lock);
-
-        if ((de->d_flags & DCACHE_GNS_PENDING) &&
-            !(de->d_flags & DCACHE_GNS_MOUNTING))
-        {
-                spin_unlock(&de->d_lock);
-                        
-                if (nd) {
-                        int err = ll_gns_mount_object(de, nd->mnt);
-                        if (err)
-                                CERROR("can't mount %s, err = %d\n",
-                                       de->d_name.name, err);
-                }
-                RETURN(1);
-        }
-        spin_unlock(&de->d_lock);
-
         CDEBUG(D_VFSTRACE, "VFS Op:name=%s (%p), intent=%s\n", de->d_name.name,
                de, LL_IT2STR(it));
 
@@ -512,18 +495,23 @@ out:
             !(flags & LOOKUP_CONTINUE || (orig_it & (IT_CHDIR | IT_OPEN))))
                 return rc;
 
-        if (nd && !(de->d_flags & DCACHE_GNS_MOUNTING)) {
-                int err = ll_gns_mount_object(de, nd->mnt);
-                if (err)
-                        CERROR("can't mount %s, err = %d\n",
-                               de->d_name.name, err);
+        if (nd != NULL) {
+                err = ll_gns_mount_object(de, nd->mnt);
+                if (err == -ERESTARTSYS) {
+                        /* 
+                         * making system to restart syscall as currently GNS is
+                         * in mounting progress.
+                         */
+                        return err;
+                }
         }
         return rc;
 do_lookup:
         it = &lookup_it;
         if (ll_intent_alloc(it))
                 LBUG();
-// We did that already, right?  ll_inode2id(&pid, de->d_parent->d_inode);
+        
+        // We did that already, right?  ll_inode2id(&pid, de->d_parent->d_inode);
         rc = md_intent_lock(exp, &pid, de->d_name.name,
                             de->d_name.len, NULL, 0, NULL,
                             it, 0, &req, ll_mdc_blocking_ast);
index 1f25e82..826d798 100644 (file)
@@ -729,14 +729,12 @@ static int ll_dir_ioctl(struct inode *inode, struct file *file,
 
 int ll_dir_open(struct inode *inode, struct file *file)
 {
-        ENTRY;
-        RETURN(ll_file_open(inode, file));
+        return ll_file_open(inode, file);
 }
 
 int ll_dir_release(struct inode *inode, struct file *file)
 {
-        ENTRY;
-        RETURN(ll_file_release(inode, file));
+        return ll_file_release(inode, file);
 }
 
 struct file_operations ll_dir_operations = {
index d3ae81c..2cebcbc 100644 (file)
@@ -1,8 +1,12 @@
 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
  * vim:expandtab:shiftwidth=8:tabstop=8:
  *
- * Copyright (C) 2004 Cluster File Systems, Inc.
- *   Author: Phil Schwan <phil@clusterfs.com>
+ * Copyright (C) 2004, 2005 Cluster File Systems, Inc.
+ *
+ * Author: Phil Schwan <phil@clusterfs.com>
+ * Author: Oleg Drokin <green@clusterfs.com>
+ * Author: Yury Umanets <yury@clusterfs.com>
+ * Review: Nikita Danilov <nikita@clusterfs.com>
  *
  *   This file is part of Lustre, http://www.lustre.org.
  *
@@ -65,27 +69,24 @@ ll_gns_wait_for_mount(struct dentry *dentry,
                 spin_unlock(&sbi->ll_gns_lock);
         }
 
-        complete(&sbi->ll_gns_mount_finished);
+        complete_all(&sbi->ll_gns_mount_finished);
         RETURN(rc);
 }
 
 /*
  * tries to mount the mount object under passed @dentry. In the case of success
- * @dentry will become mount point and 0 will be retuned. Error code will be
+ * @dentry will become mount point and 0 will be returned. Error code will be
  * returned otherwise.
  */
-int ll_gns_mount_object(struct dentry *dentry,
-                        struct vfsmount *mnt)
+int
+ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
 {
         struct ll_dentry_data *lld = dentry->d_fsdata;
-        char *p, *path, *pathpage, *argv[4];
+        char *path, *pathpage, *datapage, *argv[4];
         struct file *mntinfo_fd = NULL;
-        struct address_space *mapping;
         int cleanup_phase = 0, rc = 0;
         struct ll_sb_info *sbi;
         struct dentry *dchild;
-        struct page *datapage;
-        filler_t *filler;
         ENTRY;
 
         if (mnt == NULL) {
@@ -103,23 +104,19 @@ int ll_gns_mount_object(struct dentry *dentry,
         sbi = ll_i2sbi(dentry->d_inode);
         LASSERT(sbi != NULL);
 
-        /* another thead is in progress of mouning some entry */
+        /* 
+         * another thead is in progress or just finished mounting the
+         * dentry. Handling that.
+         */
         spin_lock(&sbi->ll_gns_lock);
-        if (sbi->ll_gns_state == LL_GNS_MOUNTING) {
-                spin_unlock(&sbi->ll_gns_lock);
-
-                wait_for_completion(&sbi->ll_gns_mount_finished);
-                if (d_mountpoint(dentry))
-                        RETURN(0);
-        }
-
-        /* another thread mounted it already */
-        if (sbi->ll_gns_state == LL_GNS_FINISHED) {
+        if (sbi->ll_gns_state == LL_GNS_MOUNTING ||
+            sbi->ll_gns_state == LL_GNS_FINISHED)
+        {
                 spin_unlock(&sbi->ll_gns_lock);
-
-                /* we lost a race; just return */
-                if (d_mountpoint(dentry))
-                        RETURN(0);
+                CDEBUG(D_INODE"GNS is in progress now, throwing "
+                       "-ERESTARTSYS to restart syscall and let "
+                       "it finish.\n");
+                RETURN(-ERESTARTSYS);
         }
         LASSERT(sbi->ll_gns_state == LL_GNS_IDLE);
 
@@ -145,15 +142,15 @@ int ll_gns_mount_object(struct dentry *dentry,
                 GOTO(cleanup, rc = PTR_ERR(dchild));
         }
 
-        /* sychronizing with possible /proc/fs/...write */
+        /* synchronizing with possible /proc/fs/...write */
         down(&sbi->ll_gns_sem);
         
         /* 
          * mount object name is taken from sbi, where it is set in mount time or
          * via /proc/fs... tunable. It may be ".mntinfo" or so.
          */
-        dchild = ll_d_lookup(sbi->ll_gns_oname, dentry,
-                             strlen(sbi->ll_gns_oname));
+        dchild = lookup_one_len(sbi->ll_gns_oname, dentry,
+                                strlen(sbi->ll_gns_oname));
         up(&sbi->ll_gns_sem);
 
         if (!dchild)
@@ -167,6 +164,10 @@ int ll_gns_mount_object(struct dentry *dentry,
                 GOTO(cleanup, rc = PTR_ERR(dchild));
         }
 
+        /* mount object is not found */
+        if (!dchild->d_inode)
+                GOTO(cleanup, rc = -ENOENT);
+
         mntget(mnt);
 
         /* ok, mount object if found, opening it. */
@@ -190,27 +191,28 @@ int ll_gns_mount_object(struct dentry *dentry,
                 GOTO(cleanup, rc = -EFBIG);
         }
 
+        datapage = (char *)__get_free_page(GFP_KERNEL);
+        if (!datapage)
+                GOTO(cleanup, rc = -ENOMEM);
+
+        cleanup_phase = 3;
+        
         /* read data from mount object. */
-        mapping = mntinfo_fd->f_dentry->d_inode->i_mapping;
-        filler = (filler_t *)mapping->a_ops->readpage;
-        datapage = read_cache_page(mapping, 0, filler,
-                                   mntinfo_fd);
-        if (IS_ERR(datapage)) {
-                CERROR("can't read data from mount object %*s/%*s\n",
+        rc = kernel_read(mntinfo_fd, 0, datapage, PAGE_SIZE);
+        if (rc < 0) {
+                CERROR("can't read mount object %*s/%*s data, err %d\n",
                        (int)dentry->d_name.len, dentry->d_name.name,
-                       (int)dchild->d_name.len, dchild->d_name.name);
-                GOTO(cleanup, rc = PTR_ERR(datapage));
+                       (int)dchild->d_name.len, dchild->d_name.name,
+                       rc);
+                GOTO(cleanup, rc);
         }
 
-        p = kmap(datapage);
-        LASSERT(p != NULL);
-        p[PAGE_SIZE - 1] = '\0';
-        cleanup_phase = 3;
+        datapage[PAGE_SIZE - 1] = '\0';
 
         fput(mntinfo_fd);
         mntinfo_fd = NULL;
 
-        /* sychronizing with possible /proc/fs/...write */
+        /* synchronizing with possible /proc/fs/...write */
         down(&sbi->ll_gns_sem);
 
         /*
@@ -218,7 +220,7 @@ int ll_gns_mount_object(struct dentry *dentry,
          * may be /usr/lib/lustre/gns-upcall.sh
          */
         argv[0] = sbi->ll_gns_upcall;
-        argv[1] = p;
+        argv[1] = datapage;
         argv[2] = path;
         argv[3] = NULL;
         
@@ -234,7 +236,7 @@ int ll_gns_mount_object(struct dentry *dentry,
         /*
          * wait for mount completion. This is actually not need, because
          * USERMODEHELPER() returns only when usermode process finishes. But we
-         * doing this just for case USERMODEHELPER() semanthics will be changed
+         * doing this just for case USERMODEHELPER() semantics will be changed
          * or usermode upcall program will start mounting in backgound and
          * return instantly. --umka
          */
@@ -278,14 +280,20 @@ int ll_gns_mount_object(struct dentry *dentry,
 cleanup:
         switch (cleanup_phase) {
         case 3:
-                kunmap(datapage);
-                page_cache_release(datapage);
+                free_page((unsigned long)datapage);
         case 2:
                 if (mntinfo_fd != NULL)
                         fput(mntinfo_fd);
         case 1:
                 free_page((unsigned long)pathpage);
         case 0:
+                /* 
+                 * waking up all waiters after gns state is set to
+                 * LL_GNS_MOUNTING
+                 */
+                if (cleanup_phase > 0)
+                        complete_all(&sbi->ll_gns_mount_finished);
+                
                 spin_lock(&sbi->ll_gns_lock);
                 sbi->ll_gns_state = LL_GNS_IDLE;
                 spin_unlock(&sbi->ll_gns_lock);
@@ -362,7 +370,7 @@ int ll_gns_check_mounts(struct ll_sb_info *sbi, int flags)
 }
 
 /*
- * GNS timer callback function. It restarts gns timer and wakes up GNS cvontrol
+ * GNS timer callback function. It restarts gns timer and wakes up GNS control
  * thread to process mounts list.
  */
 void ll_gns_timer_callback(unsigned long data)
@@ -392,7 +400,7 @@ static int inline ll_gns_check_event(void)
         return rc;
 }
 
-/* should we staop GNS control thread? */
+/* should we stop GNS control thread? */
 static int inline ll_gns_check_stop(void)
 {
         mb();
@@ -447,10 +455,6 @@ static int ll_gns_thread_main(void *arg)
                 spin_unlock(&gns_lock);
         }
 
-        /* 
-         * letting know stop function know that thread is stoped and it may
-         * return.
-         */
         EXIT;
         gns_thread.t_flags = SVC_STOPPED;
 
index 8b6102d..367348d 100644 (file)
@@ -131,6 +131,7 @@ struct ll_readahead_state {
 extern kmem_cache_t *ll_file_data_slab;
 extern kmem_cache_t *ll_intent_slab;
 struct lustre_handle;
+
 struct ll_file_data {
         struct ll_readahead_state fd_ras;
         __u32 fd_flags;
index f8f9a17..4ad2ca1 100644 (file)
@@ -404,11 +404,16 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
             S_ISDIR(dentry->d_inode->i_mode) &&
             ((flags & LOOKUP_CONTINUE) || (orig_it & (IT_CHDIR | IT_OPEN))))
         {
-                spin_lock(&dentry->d_lock);
-                dentry->d_flags |= DCACHE_GNS_PENDING;
-                spin_unlock(&dentry->d_lock);
+                rc = ll_gns_mount_object(dentry, nd->mnt);
+                if (rc == -ERESTARTSYS) {
+                        /* 
+                         * making system to restart syscall as currently GNS is
+                         * in mounting progress.
+                         */
+                        GOTO(out, retval = rc);
+                }
         }
-
+        
         if (dentry == save)
                 GOTO(out, retval = NULL);
         else