mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-24 09:13:20 -05:00
ocfs2: local mounts
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>
This commit is contained in:
parent
c99767974e
commit
c271c5c22b
11 changed files with 193 additions and 66 deletions
|
@ -770,7 +770,7 @@ static int ocfs2_lock_create(struct ocfs2_super *osb,
|
||||||
int dlm_flags)
|
int dlm_flags)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
enum dlm_status status;
|
enum dlm_status status = DLM_NORMAL;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
mlog_entry_void();
|
mlog_entry_void();
|
||||||
|
@ -1138,6 +1138,7 @@ int ocfs2_rw_lock(struct inode *inode, int write)
|
||||||
{
|
{
|
||||||
int status, level;
|
int status, level;
|
||||||
struct ocfs2_lock_res *lockres;
|
struct ocfs2_lock_res *lockres;
|
||||||
|
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
||||||
|
|
||||||
BUG_ON(!inode);
|
BUG_ON(!inode);
|
||||||
|
|
||||||
|
@ -1147,6 +1148,9 @@ int ocfs2_rw_lock(struct inode *inode, int write)
|
||||||
(unsigned long long)OCFS2_I(inode)->ip_blkno,
|
(unsigned long long)OCFS2_I(inode)->ip_blkno,
|
||||||
write ? "EXMODE" : "PRMODE");
|
write ? "EXMODE" : "PRMODE");
|
||||||
|
|
||||||
|
if (ocfs2_mount_local(osb))
|
||||||
|
return 0;
|
||||||
|
|
||||||
lockres = &OCFS2_I(inode)->ip_rw_lockres;
|
lockres = &OCFS2_I(inode)->ip_rw_lockres;
|
||||||
|
|
||||||
level = write ? LKM_EXMODE : LKM_PRMODE;
|
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;
|
int level = write ? LKM_EXMODE : LKM_PRMODE;
|
||||||
struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_rw_lockres;
|
struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_rw_lockres;
|
||||||
|
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
||||||
|
|
||||||
mlog_entry_void();
|
mlog_entry_void();
|
||||||
|
|
||||||
|
@ -1171,7 +1176,8 @@ void ocfs2_rw_unlock(struct inode *inode, int write)
|
||||||
(unsigned long long)OCFS2_I(inode)->ip_blkno,
|
(unsigned long long)OCFS2_I(inode)->ip_blkno,
|
||||||
write ? "EXMODE" : "PRMODE");
|
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();
|
mlog_exit_void();
|
||||||
}
|
}
|
||||||
|
@ -1182,6 +1188,7 @@ int ocfs2_data_lock_full(struct inode *inode,
|
||||||
{
|
{
|
||||||
int status = 0, level;
|
int status = 0, level;
|
||||||
struct ocfs2_lock_res *lockres;
|
struct ocfs2_lock_res *lockres;
|
||||||
|
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
||||||
|
|
||||||
BUG_ON(!inode);
|
BUG_ON(!inode);
|
||||||
|
|
||||||
|
@ -1201,6 +1208,9 @@ int ocfs2_data_lock_full(struct inode *inode,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ocfs2_mount_local(osb))
|
||||||
|
goto out;
|
||||||
|
|
||||||
lockres = &OCFS2_I(inode)->ip_data_lockres;
|
lockres = &OCFS2_I(inode)->ip_data_lockres;
|
||||||
|
|
||||||
level = write ? LKM_EXMODE : LKM_PRMODE;
|
level = write ? LKM_EXMODE : LKM_PRMODE;
|
||||||
|
@ -1269,6 +1279,7 @@ void ocfs2_data_unlock(struct inode *inode,
|
||||||
{
|
{
|
||||||
int level = write ? LKM_EXMODE : LKM_PRMODE;
|
int level = write ? LKM_EXMODE : LKM_PRMODE;
|
||||||
struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_data_lockres;
|
struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_data_lockres;
|
||||||
|
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
||||||
|
|
||||||
mlog_entry_void();
|
mlog_entry_void();
|
||||||
|
|
||||||
|
@ -1276,7 +1287,8 @@ void ocfs2_data_unlock(struct inode *inode,
|
||||||
(unsigned long long)OCFS2_I(inode)->ip_blkno,
|
(unsigned long long)OCFS2_I(inode)->ip_blkno,
|
||||||
write ? "EXMODE" : "PRMODE");
|
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);
|
ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level);
|
||||||
|
|
||||||
mlog_exit_void();
|
mlog_exit_void();
|
||||||
|
@ -1467,8 +1479,9 @@ static int ocfs2_meta_lock_update(struct inode *inode,
|
||||||
{
|
{
|
||||||
int status = 0;
|
int status = 0;
|
||||||
struct ocfs2_inode_info *oi = OCFS2_I(inode);
|
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_dinode *fe;
|
||||||
|
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
||||||
|
|
||||||
mlog_entry_void();
|
mlog_entry_void();
|
||||||
|
|
||||||
|
@ -1483,10 +1496,12 @@ static int ocfs2_meta_lock_update(struct inode *inode,
|
||||||
}
|
}
|
||||||
spin_unlock(&oi->ip_lock);
|
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))
|
if (!ocfs2_should_refresh_lock_res(lockres))
|
||||||
goto bail;
|
goto bail;
|
||||||
|
}
|
||||||
|
|
||||||
/* This will discard any caching information we might have had
|
/* This will discard any caching information we might have had
|
||||||
* for the inode metadata. */
|
* for the inode metadata. */
|
||||||
|
@ -1496,7 +1511,7 @@ static int ocfs2_meta_lock_update(struct inode *inode,
|
||||||
* map (directories, bitmap files, etc) */
|
* map (directories, bitmap files, etc) */
|
||||||
ocfs2_extent_map_trunc(inode, 0);
|
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",
|
mlog(0, "Trusting LVB on inode %llu\n",
|
||||||
(unsigned long long)oi->ip_blkno);
|
(unsigned long long)oi->ip_blkno);
|
||||||
ocfs2_refresh_inode_from_lvb(inode);
|
ocfs2_refresh_inode_from_lvb(inode);
|
||||||
|
@ -1543,7 +1558,8 @@ static int ocfs2_meta_lock_update(struct inode *inode,
|
||||||
|
|
||||||
status = 0;
|
status = 0;
|
||||||
bail_refresh:
|
bail_refresh:
|
||||||
ocfs2_complete_lock_res_refresh(lockres, status);
|
if (lockres)
|
||||||
|
ocfs2_complete_lock_res_refresh(lockres, status);
|
||||||
bail:
|
bail:
|
||||||
mlog_exit(status);
|
mlog_exit(status);
|
||||||
return status;
|
return status;
|
||||||
|
@ -1585,7 +1601,7 @@ int ocfs2_meta_lock_full(struct inode *inode,
|
||||||
int arg_flags)
|
int arg_flags)
|
||||||
{
|
{
|
||||||
int status, level, dlm_flags, acquired;
|
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 ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
||||||
struct buffer_head *local_bh = NULL;
|
struct buffer_head *local_bh = NULL;
|
||||||
|
|
||||||
|
@ -1607,6 +1623,9 @@ int ocfs2_meta_lock_full(struct inode *inode,
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ocfs2_mount_local(osb))
|
||||||
|
goto local;
|
||||||
|
|
||||||
if (!(arg_flags & OCFS2_META_LOCK_RECOVERY))
|
if (!(arg_flags & OCFS2_META_LOCK_RECOVERY))
|
||||||
wait_event(osb->recovery_event,
|
wait_event(osb->recovery_event,
|
||||||
ocfs2_node_map_is_empty(osb, &osb->recovery_map));
|
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,
|
wait_event(osb->recovery_event,
|
||||||
ocfs2_node_map_is_empty(osb, &osb->recovery_map));
|
ocfs2_node_map_is_empty(osb, &osb->recovery_map));
|
||||||
|
|
||||||
|
local:
|
||||||
/*
|
/*
|
||||||
* We only see this flag if we're being called from
|
* We only see this flag if we're being called from
|
||||||
* ocfs2_read_locked_inode(). It means we're locking an inode
|
* 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) {
|
if (inode->i_state & I_NEW) {
|
||||||
status = 0;
|
status = 0;
|
||||||
ocfs2_complete_lock_res_refresh(lockres, 0);
|
if (lockres)
|
||||||
|
ocfs2_complete_lock_res_refresh(lockres, 0);
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1767,6 +1788,7 @@ void ocfs2_meta_unlock(struct inode *inode,
|
||||||
{
|
{
|
||||||
int level = ex ? LKM_EXMODE : LKM_PRMODE;
|
int level = ex ? LKM_EXMODE : LKM_PRMODE;
|
||||||
struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_meta_lockres;
|
struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_meta_lockres;
|
||||||
|
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
||||||
|
|
||||||
mlog_entry_void();
|
mlog_entry_void();
|
||||||
|
|
||||||
|
@ -1774,7 +1796,8 @@ void ocfs2_meta_unlock(struct inode *inode,
|
||||||
(unsigned long long)OCFS2_I(inode)->ip_blkno,
|
(unsigned long long)OCFS2_I(inode)->ip_blkno,
|
||||||
ex ? "EXMODE" : "PRMODE");
|
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);
|
ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level);
|
||||||
|
|
||||||
mlog_exit_void();
|
mlog_exit_void();
|
||||||
|
@ -1783,7 +1806,7 @@ void ocfs2_meta_unlock(struct inode *inode,
|
||||||
int ocfs2_super_lock(struct ocfs2_super *osb,
|
int ocfs2_super_lock(struct ocfs2_super *osb,
|
||||||
int ex)
|
int ex)
|
||||||
{
|
{
|
||||||
int status;
|
int status = 0;
|
||||||
int level = ex ? LKM_EXMODE : LKM_PRMODE;
|
int level = ex ? LKM_EXMODE : LKM_PRMODE;
|
||||||
struct ocfs2_lock_res *lockres = &osb->osb_super_lockres;
|
struct ocfs2_lock_res *lockres = &osb->osb_super_lockres;
|
||||||
struct buffer_head *bh;
|
struct buffer_head *bh;
|
||||||
|
@ -1794,6 +1817,9 @@ int ocfs2_super_lock(struct ocfs2_super *osb,
|
||||||
if (ocfs2_is_hard_readonly(osb))
|
if (ocfs2_is_hard_readonly(osb))
|
||||||
return -EROFS;
|
return -EROFS;
|
||||||
|
|
||||||
|
if (ocfs2_mount_local(osb))
|
||||||
|
goto bail;
|
||||||
|
|
||||||
status = ocfs2_cluster_lock(osb, lockres, level, 0, 0);
|
status = ocfs2_cluster_lock(osb, lockres, level, 0, 0);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
|
@ -1832,7 +1858,8 @@ void ocfs2_super_unlock(struct ocfs2_super *osb,
|
||||||
int level = ex ? LKM_EXMODE : LKM_PRMODE;
|
int level = ex ? LKM_EXMODE : LKM_PRMODE;
|
||||||
struct ocfs2_lock_res *lockres = &osb->osb_super_lockres;
|
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)
|
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))
|
if (ocfs2_is_hard_readonly(osb))
|
||||||
return -EROFS;
|
return -EROFS;
|
||||||
|
|
||||||
|
if (ocfs2_mount_local(osb))
|
||||||
|
return 0;
|
||||||
|
|
||||||
status = ocfs2_cluster_lock(osb, lockres, LKM_EXMODE, 0, 0);
|
status = ocfs2_cluster_lock(osb, lockres, LKM_EXMODE, 0, 0);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
|
@ -1854,7 +1884,8 @@ void ocfs2_rename_unlock(struct ocfs2_super *osb)
|
||||||
{
|
{
|
||||||
struct ocfs2_lock_res *lockres = &osb->osb_rename_lockres;
|
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)
|
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))
|
if (ocfs2_is_hard_readonly(osb))
|
||||||
return -EROFS;
|
return -EROFS;
|
||||||
|
|
||||||
|
if (ocfs2_mount_local(osb))
|
||||||
|
return 0;
|
||||||
|
|
||||||
ret = ocfs2_cluster_lock(osb, &dl->dl_lockres, level, 0, 0);
|
ret = ocfs2_cluster_lock(osb, &dl->dl_lockres, level, 0, 0);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
mlog_errno(ret);
|
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_dentry_lock *dl = dentry->d_fsdata;
|
||||||
struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
|
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
|
/* 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 ocfs2_dlm_init(struct ocfs2_super *osb)
|
||||||
{
|
{
|
||||||
int status;
|
int status = 0;
|
||||||
u32 dlm_key;
|
u32 dlm_key;
|
||||||
struct dlm_ctxt *dlm;
|
struct dlm_ctxt *dlm = NULL;
|
||||||
|
|
||||||
mlog_entry_void();
|
mlog_entry_void();
|
||||||
|
|
||||||
|
if (ocfs2_mount_local(osb))
|
||||||
|
goto local;
|
||||||
|
|
||||||
status = ocfs2_dlm_init_debug(osb);
|
status = ocfs2_dlm_init_debug(osb);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
|
@ -2178,11 +2216,12 @@ int ocfs2_dlm_init(struct ocfs2_super *osb)
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dlm_register_eviction_cb(dlm, &osb->osb_eviction_cb);
|
||||||
|
|
||||||
|
local:
|
||||||
ocfs2_super_lock_res_init(&osb->osb_super_lockres, osb);
|
ocfs2_super_lock_res_init(&osb->osb_super_lockres, osb);
|
||||||
ocfs2_rename_lock_res_init(&osb->osb_rename_lockres, osb);
|
ocfs2_rename_lock_res_init(&osb->osb_rename_lockres, osb);
|
||||||
|
|
||||||
dlm_register_eviction_cb(dlm, &osb->osb_eviction_cb);
|
|
||||||
|
|
||||||
osb->dlm = dlm;
|
osb->dlm = dlm;
|
||||||
|
|
||||||
status = 0;
|
status = 0;
|
||||||
|
|
|
@ -154,6 +154,9 @@ int ocfs2_register_hb_callbacks(struct ocfs2_super *osb)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
|
if (ocfs2_mount_local(osb))
|
||||||
|
return 0;
|
||||||
|
|
||||||
status = o2hb_register_callback(&osb->osb_hb_down);
|
status = o2hb_register_callback(&osb->osb_hb_down);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
|
@ -172,6 +175,9 @@ void ocfs2_clear_hb_callbacks(struct ocfs2_super *osb)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
|
if (ocfs2_mount_local(osb))
|
||||||
|
return;
|
||||||
|
|
||||||
status = o2hb_unregister_callback(&osb->osb_hb_down);
|
status = o2hb_unregister_callback(&osb->osb_hb_down);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
|
@ -186,6 +192,9 @@ void ocfs2_stop_heartbeat(struct ocfs2_super *osb)
|
||||||
int ret;
|
int ret;
|
||||||
char *argv[5], *envp[3];
|
char *argv[5], *envp[3];
|
||||||
|
|
||||||
|
if (ocfs2_mount_local(osb))
|
||||||
|
return;
|
||||||
|
|
||||||
if (!osb->uuid_str) {
|
if (!osb->uuid_str) {
|
||||||
/* This can happen if we don't get far enough in mount... */
|
/* This can happen if we don't get far enough in mount... */
|
||||||
mlog(0, "No UUID with which to stop heartbeat!\n\n");
|
mlog(0, "No UUID with which to stop heartbeat!\n\n");
|
||||||
|
|
|
@ -423,7 +423,8 @@ static int ocfs2_read_locked_inode(struct inode *inode,
|
||||||
* cluster lock before trusting anything anyway.
|
* cluster lock before trusting anything anyway.
|
||||||
*/
|
*/
|
||||||
can_lock = !(args->fi_flags & OCFS2_FI_FLAG_SYSFILE)
|
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
|
* To maintain backwards compatibility with older versions of
|
||||||
|
|
|
@ -144,8 +144,10 @@ handle_t *ocfs2_start_trans(struct ocfs2_super *osb, int max_buffs)
|
||||||
ocfs2_abort(osb->sb, "Detected aborted journal");
|
ocfs2_abort(osb->sb, "Detected aborted journal");
|
||||||
handle = ERR_PTR(-EROFS);
|
handle = ERR_PTR(-EROFS);
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
atomic_inc(&(osb->journal->j_num_trans));
|
if (!ocfs2_mount_local(osb))
|
||||||
|
atomic_inc(&(osb->journal->j_num_trans));
|
||||||
|
}
|
||||||
|
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
@ -507,9 +509,23 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb)
|
||||||
|
|
||||||
BUG_ON(atomic_read(&(osb->journal->j_num_trans)) != 0);
|
BUG_ON(atomic_read(&(osb->journal->j_num_trans)) != 0);
|
||||||
|
|
||||||
status = ocfs2_journal_toggle_dirty(osb, 0);
|
if (ocfs2_mount_local(osb)) {
|
||||||
if (status < 0)
|
journal_lock_updates(journal->j_journal);
|
||||||
mlog_errno(status);
|
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 */
|
/* Shutdown the kernel journal system */
|
||||||
journal_destroy(journal->j_journal);
|
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;
|
int status = 0;
|
||||||
struct ocfs2_super *osb;
|
struct ocfs2_super *osb;
|
||||||
|
@ -576,14 +592,18 @@ int ocfs2_journal_load(struct ocfs2_journal *journal)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Launch the commit thread */
|
/* Launch the commit thread */
|
||||||
osb->commit_task = kthread_run(ocfs2_commit_thread, osb, "ocfs2cmt");
|
if (!local) {
|
||||||
if (IS_ERR(osb->commit_task)) {
|
osb->commit_task = kthread_run(ocfs2_commit_thread, osb,
|
||||||
status = PTR_ERR(osb->commit_task);
|
"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;
|
osb->commit_task = NULL;
|
||||||
mlog(ML_ERROR, "unable to launch ocfs2commit thread, error=%d",
|
|
||||||
status);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
mlog_exit(status);
|
mlog_exit(status);
|
||||||
|
|
|
@ -157,7 +157,7 @@ int ocfs2_journal_init(struct ocfs2_journal *journal,
|
||||||
void ocfs2_journal_shutdown(struct ocfs2_super *osb);
|
void ocfs2_journal_shutdown(struct ocfs2_super *osb);
|
||||||
int ocfs2_journal_wipe(struct ocfs2_journal *journal,
|
int ocfs2_journal_wipe(struct ocfs2_journal *journal,
|
||||||
int full);
|
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);
|
int ocfs2_check_journals_nolocks(struct ocfs2_super *osb);
|
||||||
void ocfs2_recovery_thread(struct ocfs2_super *osb,
|
void ocfs2_recovery_thread(struct ocfs2_super *osb,
|
||||||
int node_num);
|
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);
|
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
||||||
|
|
||||||
|
if (ocfs2_mount_local(osb))
|
||||||
|
return;
|
||||||
|
|
||||||
if (!ocfs2_inode_fully_checkpointed(inode)) {
|
if (!ocfs2_inode_fully_checkpointed(inode)) {
|
||||||
/* WARNING: This only kicks off a single
|
/* WARNING: This only kicks off a single
|
||||||
* checkpoint. If someone races you and adds more
|
* checkpoint. If someone races you and adds more
|
||||||
|
|
|
@ -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 ocfs2_mmap(struct file *file, struct vm_area_struct *vma)
|
||||||
{
|
{
|
||||||
int ret = 0, lock_level = 0;
|
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. */
|
/* We don't want to support shared writable mappings yet. */
|
||||||
if (((vma->vm_flags & VM_SHARED) || (vma->vm_flags & VM_MAYSHARE))
|
if (!ocfs2_mount_local(osb) &&
|
||||||
&& ((vma->vm_flags & VM_WRITE) || (vma->vm_flags & VM_MAYWRITE))) {
|
((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);
|
mlog(0, "disallow shared writable mmaps %lx\n", vma->vm_flags);
|
||||||
/* This is -EINVAL because generic_file_readonly_mmap
|
/* This is -EINVAL because generic_file_readonly_mmap
|
||||||
* returns it in a similar situation. */
|
* returns it in a similar situation. */
|
||||||
|
|
|
@ -587,9 +587,11 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
|
||||||
}
|
}
|
||||||
|
|
||||||
ocfs2_inode_set_new(osb, inode);
|
ocfs2_inode_set_new(osb, inode);
|
||||||
status = ocfs2_create_new_inode_locks(inode);
|
if (!ocfs2_mount_local(osb)) {
|
||||||
if (status < 0)
|
status = ocfs2_create_new_inode_locks(inode);
|
||||||
mlog_errno(status);
|
if (status < 0)
|
||||||
|
mlog_errno(status);
|
||||||
|
}
|
||||||
|
|
||||||
status = 0; /* error in ocfs2_create_new_inode_locks is not
|
status = 0; /* error in ocfs2_create_new_inode_locks is not
|
||||||
* critical */
|
* critical */
|
||||||
|
|
|
@ -349,6 +349,11 @@ static inline int ocfs2_is_soft_readonly(struct ocfs2_super *osb)
|
||||||
return ret;
|
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) \
|
#define OCFS2_IS_VALID_DINODE(ptr) \
|
||||||
(!strcmp((ptr)->i_signature, OCFS2_INODE_SIGNATURE))
|
(!strcmp((ptr)->i_signature, OCFS2_INODE_SIGNATURE))
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@
|
||||||
OCFS2_SB(sb)->s_feature_incompat &= ~(mask)
|
OCFS2_SB(sb)->s_feature_incompat &= ~(mask)
|
||||||
|
|
||||||
#define OCFS2_FEATURE_COMPAT_SUPP 0
|
#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
|
#define OCFS2_FEATURE_RO_COMPAT_SUPP 0
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -97,6 +97,9 @@
|
||||||
#define OCFS2_FEATURE_INCOMPAT_HEARTBEAT_DEV 0x0002
|
#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
|
* Flags on ocfs2_dinode.i_flags
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -508,6 +508,27 @@ bail:
|
||||||
return status;
|
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)
|
static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
{
|
{
|
||||||
struct dentry *root;
|
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 inode *inode = NULL;
|
||||||
struct ocfs2_super *osb = NULL;
|
struct ocfs2_super *osb = NULL;
|
||||||
struct buffer_head *bh = NULL;
|
struct buffer_head *bh = NULL;
|
||||||
|
char nodestr[8];
|
||||||
|
|
||||||
mlog_entry("%p, %p, %i", sb, data, silent);
|
mlog_entry("%p, %p, %i", sb, data, silent);
|
||||||
|
|
||||||
/* for now we only have one cluster/node, make sure we see it
|
if (!ocfs2_parse_options(sb, data, &parsed_opt, 0)) {
|
||||||
* in the heartbeat universe */
|
|
||||||
if (!o2hb_check_local_node_heartbeating()) {
|
|
||||||
status = -EINVAL;
|
status = -EINVAL;
|
||||||
goto read_super_error;
|
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 */
|
/* probe for superblock */
|
||||||
status = ocfs2_sb_probe(sb, &bh, §or_size);
|
status = ocfs2_sb_probe(sb, &bh, §or_size);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
|
@ -541,11 +570,6 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
}
|
}
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
bh = NULL;
|
bh = NULL;
|
||||||
|
|
||||||
if (!ocfs2_parse_options(sb, data, &parsed_opt, 0)) {
|
|
||||||
status = -EINVAL;
|
|
||||||
goto read_super_error;
|
|
||||||
}
|
|
||||||
osb->s_mount_opt = parsed_opt;
|
osb->s_mount_opt = parsed_opt;
|
||||||
|
|
||||||
sb->s_magic = OCFS2_SUPER_MAGIC;
|
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 (!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)
|
if (sb->s_flags & MS_RDONLY)
|
||||||
ocfs2_set_ro_flag(osb, 0);
|
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,
|
osb->osb_debug_root = debugfs_create_dir(osb->uuid_str,
|
||||||
ocfs2_debugfs_root);
|
ocfs2_debugfs_root);
|
||||||
if (!osb->osb_debug_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);
|
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",
|
"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" :
|
osb->s_mount_opt & OCFS2_MOUNT_DATA_WRITEBACK ? "writeback" :
|
||||||
"ordered");
|
"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
|
/* XXX hold a ref on the node while mounte? easy enough, if
|
||||||
* desirable. */
|
* 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) {
|
if (osb->node_num == O2NM_MAX_NODES) {
|
||||||
mlog(ML_ERROR, "could not find this host's node number\n");
|
mlog(ML_ERROR, "could not find this host's node number\n");
|
||||||
status = -ENOENT;
|
status = -ENOENT;
|
||||||
|
@ -1084,6 +1112,9 @@ static int ocfs2_mount_volume(struct super_block *sb)
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ocfs2_mount_local(osb))
|
||||||
|
goto leave;
|
||||||
|
|
||||||
/* This should be sent *after* we recovered our journal as it
|
/* This should be sent *after* we recovered our journal as it
|
||||||
* will cause other nodes to unmark us as needing
|
* will cause other nodes to unmark us as needing
|
||||||
* recovery. However, we need to send it *before* dropping the
|
* 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;
|
int tmp;
|
||||||
struct ocfs2_super *osb = NULL;
|
struct ocfs2_super *osb = NULL;
|
||||||
|
char nodestr[8];
|
||||||
|
|
||||||
mlog_entry("(0x%p)\n", sb);
|
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);
|
atomic_set(&osb->vol_state, VOLUME_DISMOUNTED);
|
||||||
|
|
||||||
printk(KERN_INFO "ocfs2: Unmounting device (%s) on (node %d)\n",
|
if (ocfs2_mount_local(osb))
|
||||||
osb->dev_str, osb->node_num);
|
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);
|
ocfs2_delete_osb(osb);
|
||||||
kfree(osb);
|
kfree(osb);
|
||||||
|
@ -1536,6 +1573,7 @@ static int ocfs2_check_volume(struct ocfs2_super *osb)
|
||||||
{
|
{
|
||||||
int status = 0;
|
int status = 0;
|
||||||
int dirty;
|
int dirty;
|
||||||
|
int local;
|
||||||
struct ocfs2_dinode *local_alloc = NULL; /* only used if we
|
struct ocfs2_dinode *local_alloc = NULL; /* only used if we
|
||||||
* recover
|
* recover
|
||||||
* ourselves. */
|
* ourselves. */
|
||||||
|
@ -1563,8 +1601,10 @@ static int ocfs2_check_volume(struct ocfs2_super *osb)
|
||||||
"recovering volume.\n");
|
"recovering volume.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local = ocfs2_mount_local(osb);
|
||||||
|
|
||||||
/* will play back anything left in the journal. */
|
/* will play back anything left in the journal. */
|
||||||
ocfs2_journal_load(osb->journal);
|
ocfs2_journal_load(osb->journal, local);
|
||||||
|
|
||||||
if (dirty) {
|
if (dirty) {
|
||||||
/* recover my local alloc if we didn't unmount cleanly. */
|
/* recover my local alloc if we didn't unmount cleanly. */
|
||||||
|
|
|
@ -1000,6 +1000,9 @@ int ocfs2_register_net_handlers(struct ocfs2_super *osb)
|
||||||
{
|
{
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|
||||||
|
if (ocfs2_mount_local(osb))
|
||||||
|
return 0;
|
||||||
|
|
||||||
status = o2net_register_handler(OCFS2_MESSAGE_TYPE_RESPONSE,
|
status = o2net_register_handler(OCFS2_MESSAGE_TYPE_RESPONSE,
|
||||||
osb->net_key,
|
osb->net_key,
|
||||||
sizeof(struct ocfs2_response_msg),
|
sizeof(struct ocfs2_response_msg),
|
||||||
|
|
Loading…
Add table
Reference in a new issue