]> nv-tegra.nvidia Code Review - linux-3.10.git/commitdiff
ocfs2: local mounts
authorSunil Mushran <Sunil.Mushran@oracle.com>
Wed, 6 Dec 2006 01:56:35 +0000 (17:56 -0800)
committerMark Fasheh <mark.fasheh@oracle.com>
Fri, 8 Dec 2006 01:37:53 +0000 (17:37 -0800)
This allows users to format an ocfs2 file system with a special flag,
OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT. When the file system sees this flag, it
will not use any cluster services, nor will it require a cluster
configuration, thus acting like a 'local' file system.

Signed-off-by: Sunil Mushran <sunil.mushran@oracle.com>
Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
fs/ocfs2/dlmglue.c
fs/ocfs2/heartbeat.c
fs/ocfs2/inode.c
fs/ocfs2/journal.c
fs/ocfs2/journal.h
fs/ocfs2/mmap.c
fs/ocfs2/namei.c
fs/ocfs2/ocfs2.h
fs/ocfs2/ocfs2_fs.h
fs/ocfs2/super.c
fs/ocfs2/vote.c

index 69fba16efbd1e08241ebe46551d12b506a442b15..e6220137bf691600be76ac97d86868347269d4d1 100644 (file)
@@ -770,7 +770,7 @@ static int ocfs2_lock_create(struct ocfs2_super *osb,
                             int dlm_flags)
 {
        int ret = 0;
-       enum dlm_status status;
+       enum dlm_status status = DLM_NORMAL;
        unsigned long flags;
 
        mlog_entry_void();
@@ -1138,6 +1138,7 @@ int ocfs2_rw_lock(struct inode *inode, int write)
 {
        int status, level;
        struct ocfs2_lock_res *lockres;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
        BUG_ON(!inode);
 
@@ -1147,6 +1148,9 @@ int ocfs2_rw_lock(struct inode *inode, int write)
             (unsigned long long)OCFS2_I(inode)->ip_blkno,
             write ? "EXMODE" : "PRMODE");
 
+       if (ocfs2_mount_local(osb))
+               return 0;
+
        lockres = &OCFS2_I(inode)->ip_rw_lockres;
 
        level = write ? LKM_EXMODE : LKM_PRMODE;
@@ -1164,6 +1168,7 @@ void ocfs2_rw_unlock(struct inode *inode, int write)
 {
        int level = write ? LKM_EXMODE : LKM_PRMODE;
        struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_rw_lockres;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
        mlog_entry_void();
 
@@ -1171,7 +1176,8 @@ void ocfs2_rw_unlock(struct inode *inode, int write)
             (unsigned long long)OCFS2_I(inode)->ip_blkno,
             write ? "EXMODE" : "PRMODE");
 
-       ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level);
+       if (!ocfs2_mount_local(osb))
+               ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level);
 
        mlog_exit_void();
 }
@@ -1182,6 +1188,7 @@ int ocfs2_data_lock_full(struct inode *inode,
 {
        int status = 0, level;
        struct ocfs2_lock_res *lockres;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
        BUG_ON(!inode);
 
@@ -1201,6 +1208,9 @@ int ocfs2_data_lock_full(struct inode *inode,
                goto out;
        }
 
+       if (ocfs2_mount_local(osb))
+               goto out;
+
        lockres = &OCFS2_I(inode)->ip_data_lockres;
 
        level = write ? LKM_EXMODE : LKM_PRMODE;
@@ -1269,6 +1279,7 @@ void ocfs2_data_unlock(struct inode *inode,
 {
        int level = write ? LKM_EXMODE : LKM_PRMODE;
        struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_data_lockres;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
        mlog_entry_void();
 
@@ -1276,7 +1287,8 @@ void ocfs2_data_unlock(struct inode *inode,
             (unsigned long long)OCFS2_I(inode)->ip_blkno,
             write ? "EXMODE" : "PRMODE");
 
-       if (!ocfs2_is_hard_readonly(OCFS2_SB(inode->i_sb)))
+       if (!ocfs2_is_hard_readonly(OCFS2_SB(inode->i_sb)) &&
+           !ocfs2_mount_local(osb))
                ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level);
 
        mlog_exit_void();
@@ -1467,8 +1479,9 @@ static int ocfs2_meta_lock_update(struct inode *inode,
 {
        int status = 0;
        struct ocfs2_inode_info *oi = OCFS2_I(inode);
-       struct ocfs2_lock_res *lockres;
+       struct ocfs2_lock_res *lockres = NULL;
        struct ocfs2_dinode *fe;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
        mlog_entry_void();
 
@@ -1483,10 +1496,12 @@ static int ocfs2_meta_lock_update(struct inode *inode,
        }
        spin_unlock(&oi->ip_lock);
 
-       lockres = &oi->ip_meta_lockres;
+       if (!ocfs2_mount_local(osb)) {
+               lockres = &oi->ip_meta_lockres;
 
-       if (!ocfs2_should_refresh_lock_res(lockres))
-               goto bail;
+               if (!ocfs2_should_refresh_lock_res(lockres))
+                       goto bail;
+       }
 
        /* This will discard any caching information we might have had
         * for the inode metadata. */
@@ -1496,7 +1511,7 @@ static int ocfs2_meta_lock_update(struct inode *inode,
         * map (directories, bitmap files, etc) */
        ocfs2_extent_map_trunc(inode, 0);
 
-       if (ocfs2_meta_lvb_is_trustable(inode, lockres)) {
+       if (lockres && ocfs2_meta_lvb_is_trustable(inode, lockres)) {
                mlog(0, "Trusting LVB on inode %llu\n",
                     (unsigned long long)oi->ip_blkno);
                ocfs2_refresh_inode_from_lvb(inode);
@@ -1543,7 +1558,8 @@ static int ocfs2_meta_lock_update(struct inode *inode,
 
        status = 0;
 bail_refresh:
-       ocfs2_complete_lock_res_refresh(lockres, status);
+       if (lockres)
+               ocfs2_complete_lock_res_refresh(lockres, status);
 bail:
        mlog_exit(status);
        return status;
@@ -1585,7 +1601,7 @@ int ocfs2_meta_lock_full(struct inode *inode,
                         int arg_flags)
 {
        int status, level, dlm_flags, acquired;
-       struct ocfs2_lock_res *lockres;
+       struct ocfs2_lock_res *lockres = NULL;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        struct buffer_head *local_bh = NULL;
 
@@ -1607,6 +1623,9 @@ int ocfs2_meta_lock_full(struct inode *inode,
                goto bail;
        }
 
+       if (ocfs2_mount_local(osb))
+               goto local;
+
        if (!(arg_flags & OCFS2_META_LOCK_RECOVERY))
                wait_event(osb->recovery_event,
                           ocfs2_node_map_is_empty(osb, &osb->recovery_map));
@@ -1636,6 +1655,7 @@ int ocfs2_meta_lock_full(struct inode *inode,
                wait_event(osb->recovery_event,
                           ocfs2_node_map_is_empty(osb, &osb->recovery_map));
 
+local:
        /*
         * We only see this flag if we're being called from
         * ocfs2_read_locked_inode(). It means we're locking an inode
@@ -1644,7 +1664,8 @@ int ocfs2_meta_lock_full(struct inode *inode,
         */
        if (inode->i_state & I_NEW) {
                status = 0;
-               ocfs2_complete_lock_res_refresh(lockres, 0);
+               if (lockres)
+                       ocfs2_complete_lock_res_refresh(lockres, 0);
                goto bail;
        }
 
@@ -1767,6 +1788,7 @@ void ocfs2_meta_unlock(struct inode *inode,
 {
        int level = ex ? LKM_EXMODE : LKM_PRMODE;
        struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_meta_lockres;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
        mlog_entry_void();
 
@@ -1774,7 +1796,8 @@ void ocfs2_meta_unlock(struct inode *inode,
             (unsigned long long)OCFS2_I(inode)->ip_blkno,
             ex ? "EXMODE" : "PRMODE");
 
-       if (!ocfs2_is_hard_readonly(OCFS2_SB(inode->i_sb)))
+       if (!ocfs2_is_hard_readonly(OCFS2_SB(inode->i_sb)) &&
+           !ocfs2_mount_local(osb))
                ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level);
 
        mlog_exit_void();
@@ -1783,7 +1806,7 @@ void ocfs2_meta_unlock(struct inode *inode,
 int ocfs2_super_lock(struct ocfs2_super *osb,
                     int ex)
 {
-       int status;
+       int status = 0;
        int level = ex ? LKM_EXMODE : LKM_PRMODE;
        struct ocfs2_lock_res *lockres = &osb->osb_super_lockres;
        struct buffer_head *bh;
@@ -1794,6 +1817,9 @@ int ocfs2_super_lock(struct ocfs2_super *osb,
        if (ocfs2_is_hard_readonly(osb))
                return -EROFS;
 
+       if (ocfs2_mount_local(osb))
+               goto bail;
+
        status = ocfs2_cluster_lock(osb, lockres, level, 0, 0);
        if (status < 0) {
                mlog_errno(status);
@@ -1832,7 +1858,8 @@ void ocfs2_super_unlock(struct ocfs2_super *osb,
        int level = ex ? LKM_EXMODE : LKM_PRMODE;
        struct ocfs2_lock_res *lockres = &osb->osb_super_lockres;
 
-       ocfs2_cluster_unlock(osb, lockres, level);
+       if (!ocfs2_mount_local(osb))
+               ocfs2_cluster_unlock(osb, lockres, level);
 }
 
 int ocfs2_rename_lock(struct ocfs2_super *osb)
@@ -1843,6 +1870,9 @@ int ocfs2_rename_lock(struct ocfs2_super *osb)
        if (ocfs2_is_hard_readonly(osb))
                return -EROFS;
 
+       if (ocfs2_mount_local(osb))
+               return 0;
+
        status = ocfs2_cluster_lock(osb, lockres, LKM_EXMODE, 0, 0);
        if (status < 0)
                mlog_errno(status);
@@ -1854,7 +1884,8 @@ void ocfs2_rename_unlock(struct ocfs2_super *osb)
 {
        struct ocfs2_lock_res *lockres = &osb->osb_rename_lockres;
 
-       ocfs2_cluster_unlock(osb, lockres, LKM_EXMODE);
+       if (!ocfs2_mount_local(osb))
+               ocfs2_cluster_unlock(osb, lockres, LKM_EXMODE);
 }
 
 int ocfs2_dentry_lock(struct dentry *dentry, int ex)
@@ -1869,6 +1900,9 @@ int ocfs2_dentry_lock(struct dentry *dentry, int ex)
        if (ocfs2_is_hard_readonly(osb))
                return -EROFS;
 
+       if (ocfs2_mount_local(osb))
+               return 0;
+
        ret = ocfs2_cluster_lock(osb, &dl->dl_lockres, level, 0, 0);
        if (ret < 0)
                mlog_errno(ret);
@@ -1882,7 +1916,8 @@ void ocfs2_dentry_unlock(struct dentry *dentry, int ex)
        struct ocfs2_dentry_lock *dl = dentry->d_fsdata;
        struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
 
-       ocfs2_cluster_unlock(osb, &dl->dl_lockres, level);
+       if (!ocfs2_mount_local(osb))
+               ocfs2_cluster_unlock(osb, &dl->dl_lockres, level);
 }
 
 /* Reference counting of the dlm debug structure. We want this because
@@ -2145,12 +2180,15 @@ static void ocfs2_dlm_shutdown_debug(struct ocfs2_super *osb)
 
 int ocfs2_dlm_init(struct ocfs2_super *osb)
 {
-       int status;
+       int status = 0;
        u32 dlm_key;
-       struct dlm_ctxt *dlm;
+       struct dlm_ctxt *dlm = NULL;
 
        mlog_entry_void();
 
+       if (ocfs2_mount_local(osb))
+               goto local;
+
        status = ocfs2_dlm_init_debug(osb);
        if (status < 0) {
                mlog_errno(status);
@@ -2178,11 +2216,12 @@ int ocfs2_dlm_init(struct ocfs2_super *osb)
                goto bail;
        }
 
+       dlm_register_eviction_cb(dlm, &osb->osb_eviction_cb);
+
+local:
        ocfs2_super_lock_res_init(&osb->osb_super_lockres, osb);
        ocfs2_rename_lock_res_init(&osb->osb_rename_lockres, osb);
 
-       dlm_register_eviction_cb(dlm, &osb->osb_eviction_cb);
-
        osb->dlm = dlm;
 
        status = 0;
index cbfd45a97a636f445246fa9c885b6b9e330269ec..8fc52d6d0ce7827a75f40f40986f9ea8ef07b752 100644 (file)
@@ -154,6 +154,9 @@ int ocfs2_register_hb_callbacks(struct ocfs2_super *osb)
 {
        int status;
 
+       if (ocfs2_mount_local(osb))
+               return 0;
+
        status = o2hb_register_callback(&osb->osb_hb_down);
        if (status < 0) {
                mlog_errno(status);
@@ -172,6 +175,9 @@ void ocfs2_clear_hb_callbacks(struct ocfs2_super *osb)
 {
        int status;
 
+       if (ocfs2_mount_local(osb))
+               return;
+
        status = o2hb_unregister_callback(&osb->osb_hb_down);
        if (status < 0)
                mlog_errno(status);
@@ -186,6 +192,9 @@ void ocfs2_stop_heartbeat(struct ocfs2_super *osb)
        int ret;
        char *argv[5], *envp[3];
 
+       if (ocfs2_mount_local(osb))
+               return;
+
        if (!osb->uuid_str) {
                /* This can happen if we don't get far enough in mount... */
                mlog(0, "No UUID with which to stop heartbeat!\n\n");
index 42e361f3054f5114d8e81fe911ca2fb21c86601d..e4d91493d7d74a9efa29e8e55ead977cee06de70 100644 (file)
@@ -423,7 +423,8 @@ static int ocfs2_read_locked_inode(struct inode *inode,
         * cluster lock before trusting anything anyway.
         */
        can_lock = !(args->fi_flags & OCFS2_FI_FLAG_SYSFILE)
-               && !(args->fi_flags & OCFS2_FI_FLAG_NOLOCK);
+               && !(args->fi_flags & OCFS2_FI_FLAG_NOLOCK)
+               && !ocfs2_mount_local(osb);
 
        /*
         * To maintain backwards compatibility with older versions of
index 1d7f4ab1e5ede4b362a5e8f2bcd4523269c5a456..825cb0ae1b4c812862bbff0d8da5608497611eb7 100644 (file)
@@ -144,8 +144,10 @@ handle_t *ocfs2_start_trans(struct ocfs2_super *osb, int max_buffs)
                        ocfs2_abort(osb->sb, "Detected aborted journal");
                        handle = ERR_PTR(-EROFS);
                }
-       } else
-               atomic_inc(&(osb->journal->j_num_trans));
+       } else {
+               if (!ocfs2_mount_local(osb))
+                       atomic_inc(&(osb->journal->j_num_trans));
+       }
 
        return handle;
 }
@@ -507,9 +509,23 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb)
 
        BUG_ON(atomic_read(&(osb->journal->j_num_trans)) != 0);
 
-       status = ocfs2_journal_toggle_dirty(osb, 0);
-       if (status < 0)
-               mlog_errno(status);
+       if (ocfs2_mount_local(osb)) {
+               journal_lock_updates(journal->j_journal);
+               status = journal_flush(journal->j_journal);
+               journal_unlock_updates(journal->j_journal);
+               if (status < 0)
+                       mlog_errno(status);
+       }
+
+       if (status == 0) {
+               /*
+                * Do not toggle if flush was unsuccessful otherwise
+                * will leave dirty metadata in a "clean" journal
+                */
+               status = ocfs2_journal_toggle_dirty(osb, 0);
+               if (status < 0)
+                       mlog_errno(status);
+       }
 
        /* Shutdown the kernel journal system */
        journal_destroy(journal->j_journal);
@@ -549,7 +565,7 @@ static void ocfs2_clear_journal_error(struct super_block *sb,
        }
 }
 
-int ocfs2_journal_load(struct ocfs2_journal *journal)
+int ocfs2_journal_load(struct ocfs2_journal *journal, int local)
 {
        int status = 0;
        struct ocfs2_super *osb;
@@ -576,14 +592,18 @@ int ocfs2_journal_load(struct ocfs2_journal *journal)
        }
 
        /* Launch the commit thread */
-       osb->commit_task = kthread_run(ocfs2_commit_thread, osb, "ocfs2cmt");
-       if (IS_ERR(osb->commit_task)) {
-               status = PTR_ERR(osb->commit_task);
+       if (!local) {
+               osb->commit_task = kthread_run(ocfs2_commit_thread, osb,
+                                              "ocfs2cmt");
+               if (IS_ERR(osb->commit_task)) {
+                       status = PTR_ERR(osb->commit_task);
+                       osb->commit_task = NULL;
+                       mlog(ML_ERROR, "unable to launch ocfs2commit thread, "
+                            "error=%d", status);
+                       goto done;
+               }
+       } else
                osb->commit_task = NULL;
-               mlog(ML_ERROR, "unable to launch ocfs2commit thread, error=%d",
-                    status);
-               goto done;
-       }
 
 done:
        mlog_exit(status);
index 899112ad813679da5035903c57cc79b6c2a97aea..e1216364d191566ba80b276796afb965fe8ebb61 100644 (file)
@@ -157,7 +157,7 @@ int    ocfs2_journal_init(struct ocfs2_journal *journal,
 void   ocfs2_journal_shutdown(struct ocfs2_super *osb);
 int    ocfs2_journal_wipe(struct ocfs2_journal *journal,
                          int full);
-int    ocfs2_journal_load(struct ocfs2_journal *journal);
+int    ocfs2_journal_load(struct ocfs2_journal *journal, int local);
 int    ocfs2_check_journals_nolocks(struct ocfs2_super *osb);
 void   ocfs2_recovery_thread(struct ocfs2_super *osb,
                             int node_num);
@@ -174,6 +174,9 @@ static inline void ocfs2_checkpoint_inode(struct inode *inode)
 {
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
+       if (ocfs2_mount_local(osb))
+               return;
+
        if (!ocfs2_inode_fully_checkpointed(inode)) {
                /* WARNING: This only kicks off a single
                 * checkpoint. If someone races you and adds more
index 69f85ae392dcc9ab0a830a71c576dabda1f779b0..51b02044768360cf7c272bbd1f9cff051c2ad33b 100644 (file)
@@ -83,10 +83,12 @@ static struct vm_operations_struct ocfs2_file_vm_ops = {
 int ocfs2_mmap(struct file *file, struct vm_area_struct *vma)
 {
        int ret = 0, lock_level = 0;
+       struct ocfs2_super *osb = OCFS2_SB(file->f_dentry->d_inode->i_sb);
 
        /* We don't want to support shared writable mappings yet. */
-       if (((vma->vm_flags & VM_SHARED) || (vma->vm_flags & VM_MAYSHARE))
-           && ((vma->vm_flags & VM_WRITE) || (vma->vm_flags & VM_MAYWRITE))) {
+       if (!ocfs2_mount_local(osb) &&
+           ((vma->vm_flags & VM_SHARED) || (vma->vm_flags & VM_MAYSHARE)) &&
+           ((vma->vm_flags & VM_WRITE) || (vma->vm_flags & VM_MAYWRITE))) {
                mlog(0, "disallow shared writable mmaps %lx\n", vma->vm_flags);
                /* This is -EINVAL because generic_file_readonly_mmap
                 * returns it in a similar situation. */
index 21db45ddf144c2ebbfb96237b6d1c9a8970776ae..9637039c263355676716b72b98eaa9f147867dfb 100644 (file)
@@ -587,9 +587,11 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
        }
 
        ocfs2_inode_set_new(osb, inode);
-       status = ocfs2_create_new_inode_locks(inode);
-       if (status < 0)
-               mlog_errno(status);
+       if (!ocfs2_mount_local(osb)) {
+               status = ocfs2_create_new_inode_locks(inode);
+               if (status < 0)
+                       mlog_errno(status);
+       }
 
        status = 0; /* error in ocfs2_create_new_inode_locks is not
                     * critical */
index b767fd7da6ebaeb44ed58a888b80cb2dd99ce545..db8e77cd35d34e1653a9adc841f0ab422f9c994d 100644 (file)
@@ -349,6 +349,11 @@ static inline int ocfs2_is_soft_readonly(struct ocfs2_super *osb)
        return ret;
 }
 
+static inline int ocfs2_mount_local(struct ocfs2_super *osb)
+{
+       return (osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT);
+}
+
 #define OCFS2_IS_VALID_DINODE(ptr)                                     \
        (!strcmp((ptr)->i_signature, OCFS2_INODE_SIGNATURE))
 
index 3330a5dc6be2f9aa5e42b2a3709906bcdd5bba97..2e90e89f1602f835205329ebe00e51ed29ddf54f 100644 (file)
@@ -86,7 +86,7 @@
        OCFS2_SB(sb)->s_feature_incompat &= ~(mask)
 
 #define OCFS2_FEATURE_COMPAT_SUPP      0
-#define OCFS2_FEATURE_INCOMPAT_SUPP    0
+#define OCFS2_FEATURE_INCOMPAT_SUPP    OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT
 #define OCFS2_FEATURE_RO_COMPAT_SUPP   0
 
 /*
@@ -97,6 +97,9 @@
 #define OCFS2_FEATURE_INCOMPAT_HEARTBEAT_DEV   0x0002
 
 
+/* Used to denote a non-clustered volume */
+#define OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT     0x0008
+
 /*
  * Flags on ocfs2_dinode.i_flags
  */
index 4bf39540e652fb85b99e62045bf3e84646e5f72d..a6d2f8cc165b85da7c3e607b361913a7db65e02f 100644 (file)
@@ -508,6 +508,27 @@ bail:
        return status;
 }
 
+static int ocfs2_verify_heartbeat(struct ocfs2_super *osb)
+{
+       if (ocfs2_mount_local(osb)) {
+               if (osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) {
+                       mlog(ML_ERROR, "Cannot heartbeat on a locally "
+                            "mounted device.\n");
+                       return -EINVAL;
+               }
+       }
+
+       if (!(osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL)) {
+               if (!ocfs2_mount_local(osb) && !ocfs2_is_hard_readonly(osb)) {
+                       mlog(ML_ERROR, "Heartbeat has to be started to mount "
+                            "a read-write clustered device.\n");
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
 static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
 {
        struct dentry *root;
@@ -516,16 +537,24 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
        struct inode *inode = NULL;
        struct ocfs2_super *osb = NULL;
        struct buffer_head *bh = NULL;
+       char nodestr[8];
 
        mlog_entry("%p, %p, %i", sb, data, silent);
 
-       /* for now we only have one cluster/node, make sure we see it
-        * in the heartbeat universe */
-       if (!o2hb_check_local_node_heartbeating()) {
+       if (!ocfs2_parse_options(sb, data, &parsed_opt, 0)) {
                status = -EINVAL;
                goto read_super_error;
        }
 
+       /* for now we only have one cluster/node, make sure we see it
+        * in the heartbeat universe */
+       if (parsed_opt & OCFS2_MOUNT_HB_LOCAL) {
+               if (!o2hb_check_local_node_heartbeating()) {
+                       status = -EINVAL;
+                       goto read_super_error;
+               }
+       }
+
        /* probe for superblock */
        status = ocfs2_sb_probe(sb, &bh, &sector_size);
        if (status < 0) {
@@ -541,11 +570,6 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
        }
        brelse(bh);
        bh = NULL;
-
-       if (!ocfs2_parse_options(sb, data, &parsed_opt, 0)) {
-               status = -EINVAL;
-               goto read_super_error;
-       }
        osb->s_mount_opt = parsed_opt;
 
        sb->s_magic = OCFS2_SUPER_MAGIC;
@@ -588,21 +612,16 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
        }
 
        if (!ocfs2_is_hard_readonly(osb)) {
-               /* If this isn't a hard readonly mount, then we need
-                * to make sure that heartbeat is in a valid state,
-                * and that we mark ourselves soft readonly is -oro
-                * was specified. */
-               if (!(osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL)) {
-                       mlog(ML_ERROR, "No heartbeat for device (%s)\n",
-                            sb->s_id);
-                       status = -EINVAL;
-                       goto read_super_error;
-               }
-
                if (sb->s_flags & MS_RDONLY)
                        ocfs2_set_ro_flag(osb, 0);
        }
 
+       status = ocfs2_verify_heartbeat(osb);
+       if (status < 0) {
+               mlog_errno(status);
+               goto read_super_error;
+       }
+
        osb->osb_debug_root = debugfs_create_dir(osb->uuid_str,
                                                 ocfs2_debugfs_root);
        if (!osb->osb_debug_root) {
@@ -635,9 +654,14 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
 
        ocfs2_complete_mount_recovery(osb);
 
-       printk(KERN_INFO "ocfs2: Mounting device (%s) on (node %d, slot %d) "
+       if (ocfs2_mount_local(osb))
+               snprintf(nodestr, sizeof(nodestr), "local");
+       else
+               snprintf(nodestr, sizeof(nodestr), "%d", osb->node_num);
+
+       printk(KERN_INFO "ocfs2: Mounting device (%s) on (node %s, slot %d) "
               "with %s data mode.\n",
-              osb->dev_str, osb->node_num, osb->slot_num,
+              osb->dev_str, nodestr, osb->slot_num,
               osb->s_mount_opt & OCFS2_MOUNT_DATA_WRITEBACK ? "writeback" :
               "ordered");
 
@@ -999,7 +1023,11 @@ static int ocfs2_fill_local_node_info(struct ocfs2_super *osb)
 
        /* XXX hold a ref on the node while mounte?  easy enough, if
         * desirable. */
-       osb->node_num = o2nm_this_node();
+       if (ocfs2_mount_local(osb))
+               osb->node_num = 0;
+       else
+               osb->node_num = o2nm_this_node();
+
        if (osb->node_num == O2NM_MAX_NODES) {
                mlog(ML_ERROR, "could not find this host's node number\n");
                status = -ENOENT;
@@ -1084,6 +1112,9 @@ static int ocfs2_mount_volume(struct super_block *sb)
                goto leave;
        }
 
+       if (ocfs2_mount_local(osb))
+               goto leave;
+
        /* This should be sent *after* we recovered our journal as it
         * will cause other nodes to unmark us as needing
         * recovery. However, we need to send it *before* dropping the
@@ -1114,6 +1145,7 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
 {
        int tmp;
        struct ocfs2_super *osb = NULL;
+       char nodestr[8];
 
        mlog_entry("(0x%p)\n", sb);
 
@@ -1177,8 +1209,13 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
 
        atomic_set(&osb->vol_state, VOLUME_DISMOUNTED);
 
-       printk(KERN_INFO "ocfs2: Unmounting device (%s) on (node %d)\n",
-              osb->dev_str, osb->node_num);
+       if (ocfs2_mount_local(osb))
+               snprintf(nodestr, sizeof(nodestr), "local");
+       else
+               snprintf(nodestr, sizeof(nodestr), "%d", osb->node_num);
+
+       printk(KERN_INFO "ocfs2: Unmounting device (%s) on (node %s)\n",
+              osb->dev_str, nodestr);
 
        ocfs2_delete_osb(osb);
        kfree(osb);
@@ -1536,6 +1573,7 @@ static int ocfs2_check_volume(struct ocfs2_super *osb)
 {
        int status = 0;
        int dirty;
+       int local;
        struct ocfs2_dinode *local_alloc = NULL; /* only used if we
                                                  * recover
                                                  * ourselves. */
@@ -1563,8 +1601,10 @@ static int ocfs2_check_volume(struct ocfs2_super *osb)
                     "recovering volume.\n");
        }
 
+       local = ocfs2_mount_local(osb);
+
        /* will play back anything left in the journal. */
-       ocfs2_journal_load(osb->journal);
+       ocfs2_journal_load(osb->journal, local);
 
        if (dirty) {
                /* recover my local alloc if we didn't unmount cleanly. */
index 5b4dca79990bfb4218e46d307128debe174f0ccb..0315a8b61ed67b221a33361cac82b052d7af46b5 100644 (file)
@@ -1000,6 +1000,9 @@ int ocfs2_register_net_handlers(struct ocfs2_super *osb)
 {
        int status = 0;
 
+       if (ocfs2_mount_local(osb))
+               return 0;
+
        status = o2net_register_handler(OCFS2_MESSAGE_TYPE_RESPONSE,
                                        osb->net_key,
                                        sizeof(struct ocfs2_response_msg),