aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/dlmglue.c
diff options
context:
space:
mode:
authorSrinivas Eeda <srinivas.eeda@oracle.com>2009-06-03 20:02:55 -0400
committerJoel Becker <joel.becker@oracle.com>2009-06-03 22:14:31 -0400
commit83273932fbefb6ceef9c0b82ac4d23900728f4d9 (patch)
tree7ece8471af3d2a22543542e990369aca47aa3d25 /fs/ocfs2/dlmglue.c
parentedd45c08499a3e9d4c25431cd2b6a9ce5f692c92 (diff)
ocfs2: timer to queue scan of all orphan slots
When a dentry is unlinked, the unlinking node takes an EX on the dentry lock before moving the dentry to the orphan directory. Other nodes that have this dentry in cache have a PR on the same dentry lock. When the EX is requested, the other nodes flag the corresponding inode as MAYBE_ORPHANED during downconvert. The inode is finally deleted when the last node to iput the inode sees that i_nlink==0 and the MAYBE_ORPHANED flag is set. A problem arises if a node is forced to free dentry locks because of memory pressure. If this happens, the node will no longer get downconvert notifications for the dentries that have been unlinked on another node. If it also happens that node is actively using the corresponding inode and happens to be the one performing the last iput on that inode, it will fail to delete the inode as it will not have the MAYBE_ORPHANED flag set. This patch fixes this shortcoming by introducing a periodic scan of the orphan directories to delete such inodes. Care has been taken to distribute the workload across the cluster so that no one node has to perform the task all the time. Signed-off-by: Srinivas Eeda <srinivas.eeda@oracle.com> Signed-off-by: Joel Becker <joel.becker@oracle.com>
Diffstat (limited to 'fs/ocfs2/dlmglue.c')
-rw-r--r--fs/ocfs2/dlmglue.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index e15fc7d50827..6cdeaa76f27f 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -248,6 +248,10 @@ static struct ocfs2_lock_res_ops ocfs2_nfs_sync_lops = {
248 .flags = 0, 248 .flags = 0,
249}; 249};
250 250
251static struct ocfs2_lock_res_ops ocfs2_orphan_scan_lops = {
252 .flags = LOCK_TYPE_REQUIRES_REFRESH|LOCK_TYPE_USES_LVB,
253};
254
251static struct ocfs2_lock_res_ops ocfs2_dentry_lops = { 255static struct ocfs2_lock_res_ops ocfs2_dentry_lops = {
252 .get_osb = ocfs2_get_dentry_osb, 256 .get_osb = ocfs2_get_dentry_osb,
253 .post_unlock = ocfs2_dentry_post_unlock, 257 .post_unlock = ocfs2_dentry_post_unlock,
@@ -637,6 +641,19 @@ static void ocfs2_nfs_sync_lock_res_init(struct ocfs2_lock_res *res,
637 &ocfs2_nfs_sync_lops, osb); 641 &ocfs2_nfs_sync_lops, osb);
638} 642}
639 643
644static void ocfs2_orphan_scan_lock_res_init(struct ocfs2_lock_res *res,
645 struct ocfs2_super *osb)
646{
647 struct ocfs2_orphan_scan_lvb *lvb;
648
649 ocfs2_lock_res_init_once(res);
650 ocfs2_build_lock_name(OCFS2_LOCK_TYPE_ORPHAN_SCAN, 0, 0, res->l_name);
651 ocfs2_lock_res_init_common(osb, res, OCFS2_LOCK_TYPE_ORPHAN_SCAN,
652 &ocfs2_orphan_scan_lops, osb);
653 lvb = ocfs2_dlm_lvb(&res->l_lksb);
654 lvb->lvb_version = OCFS2_ORPHAN_LVB_VERSION;
655}
656
640void ocfs2_file_lock_res_init(struct ocfs2_lock_res *lockres, 657void ocfs2_file_lock_res_init(struct ocfs2_lock_res *lockres,
641 struct ocfs2_file_private *fp) 658 struct ocfs2_file_private *fp)
642{ 659{
@@ -2352,6 +2369,37 @@ void ocfs2_inode_unlock(struct inode *inode,
2352 mlog_exit_void(); 2369 mlog_exit_void();
2353} 2370}
2354 2371
2372int ocfs2_orphan_scan_lock(struct ocfs2_super *osb, u32 *seqno, int ex)
2373{
2374 struct ocfs2_lock_res *lockres;
2375 struct ocfs2_orphan_scan_lvb *lvb;
2376 int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
2377 int status = 0;
2378
2379 lockres = &osb->osb_orphan_scan.os_lockres;
2380 status = ocfs2_cluster_lock(osb, lockres, level, 0, 0);
2381 if (status < 0)
2382 return status;
2383
2384 lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
2385 if (lvb->lvb_version == OCFS2_ORPHAN_LVB_VERSION)
2386 *seqno = be32_to_cpu(lvb->lvb_os_seqno);
2387 return status;
2388}
2389
2390void ocfs2_orphan_scan_unlock(struct ocfs2_super *osb, u32 seqno, int ex)
2391{
2392 struct ocfs2_lock_res *lockres;
2393 struct ocfs2_orphan_scan_lvb *lvb;
2394 int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
2395
2396 lockres = &osb->osb_orphan_scan.os_lockres;
2397 lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
2398 lvb->lvb_version = OCFS2_ORPHAN_LVB_VERSION;
2399 lvb->lvb_os_seqno = cpu_to_be32(seqno);
2400 ocfs2_cluster_unlock(osb, lockres, level);
2401}
2402
2355int ocfs2_super_lock(struct ocfs2_super *osb, 2403int ocfs2_super_lock(struct ocfs2_super *osb,
2356 int ex) 2404 int ex)
2357{ 2405{
@@ -2842,6 +2890,7 @@ local:
2842 ocfs2_super_lock_res_init(&osb->osb_super_lockres, osb); 2890 ocfs2_super_lock_res_init(&osb->osb_super_lockres, osb);
2843 ocfs2_rename_lock_res_init(&osb->osb_rename_lockres, osb); 2891 ocfs2_rename_lock_res_init(&osb->osb_rename_lockres, osb);
2844 ocfs2_nfs_sync_lock_res_init(&osb->osb_nfs_sync_lockres, osb); 2892 ocfs2_nfs_sync_lock_res_init(&osb->osb_nfs_sync_lockres, osb);
2893 ocfs2_orphan_scan_lock_res_init(&osb->osb_orphan_scan.os_lockres, osb);
2845 2894
2846 osb->cconn = conn; 2895 osb->cconn = conn;
2847 2896
@@ -2878,6 +2927,7 @@ void ocfs2_dlm_shutdown(struct ocfs2_super *osb,
2878 ocfs2_lock_res_free(&osb->osb_super_lockres); 2927 ocfs2_lock_res_free(&osb->osb_super_lockres);
2879 ocfs2_lock_res_free(&osb->osb_rename_lockres); 2928 ocfs2_lock_res_free(&osb->osb_rename_lockres);
2880 ocfs2_lock_res_free(&osb->osb_nfs_sync_lockres); 2929 ocfs2_lock_res_free(&osb->osb_nfs_sync_lockres);
2930 ocfs2_lock_res_free(&osb->osb_orphan_scan.os_lockres);
2881 2931
2882 ocfs2_cluster_disconnect(osb->cconn, hangup_pending); 2932 ocfs2_cluster_disconnect(osb->cconn, hangup_pending);
2883 osb->cconn = NULL; 2933 osb->cconn = NULL;
@@ -3061,6 +3111,7 @@ static void ocfs2_drop_osb_locks(struct ocfs2_super *osb)
3061 ocfs2_simple_drop_lockres(osb, &osb->osb_super_lockres); 3111 ocfs2_simple_drop_lockres(osb, &osb->osb_super_lockres);
3062 ocfs2_simple_drop_lockres(osb, &osb->osb_rename_lockres); 3112 ocfs2_simple_drop_lockres(osb, &osb->osb_rename_lockres);
3063 ocfs2_simple_drop_lockres(osb, &osb->osb_nfs_sync_lockres); 3113 ocfs2_simple_drop_lockres(osb, &osb->osb_nfs_sync_lockres);
3114 ocfs2_simple_drop_lockres(osb, &osb->osb_orphan_scan.os_lockres);
3064} 3115}
3065 3116
3066int ocfs2_drop_inode_locks(struct inode *inode) 3117int ocfs2_drop_inode_locks(struct inode *inode)