aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ocfs2/dcache.c2
-rw-r--r--fs/ocfs2/dcache.h27
-rw-r--r--fs/ocfs2/dlmglue.c475
-rw-r--r--fs/ocfs2/dlmglue.h11
-rw-r--r--fs/ocfs2/ocfs2_lockid.h25
5 files changed, 436 insertions, 104 deletions
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c
index 1a01380e3878..aea457718946 100644
--- a/fs/ocfs2/dcache.c
+++ b/fs/ocfs2/dcache.c
@@ -87,6 +87,8 @@ bail:
87 return ret; 87 return ret;
88} 88}
89 89
90DEFINE_SPINLOCK(dentry_attach_lock);
91
90struct dentry_operations ocfs2_dentry_ops = { 92struct dentry_operations ocfs2_dentry_ops = {
91 .d_revalidate = ocfs2_dentry_revalidate, 93 .d_revalidate = ocfs2_dentry_revalidate,
92}; 94};
diff --git a/fs/ocfs2/dcache.h b/fs/ocfs2/dcache.h
index 90072771114b..f1423c2134ee 100644
--- a/fs/ocfs2/dcache.h
+++ b/fs/ocfs2/dcache.h
@@ -28,4 +28,31 @@
28 28
29extern struct dentry_operations ocfs2_dentry_ops; 29extern struct dentry_operations ocfs2_dentry_ops;
30 30
31struct ocfs2_dentry_lock {
32 unsigned int dl_count;
33 u64 dl_parent_blkno;
34
35 /*
36 * The ocfs2_dentry_lock keeps an inode reference until
37 * dl_lockres has been destroyed. This is usually done in
38 * ->d_iput() anyway, so there should be minimal impact.
39 */
40 struct inode *dl_inode;
41 struct ocfs2_lock_res dl_lockres;
42};
43
44static inline void ocfs2_dentry_lock_put(struct ocfs2_super *osb,
45 struct ocfs2_dentry_lock *dl)
46{
47}
48
49static inline struct dentry *ocfs2_find_local_alias(struct inode *inode,
50 u64 parent_blkno,
51 int skip_unhashed)
52{
53 return NULL;
54}
55
56extern spinlock_t dentry_attach_lock;
57
31#endif /* OCFS2_DCACHE_H */ 58#endif /* OCFS2_DCACHE_H */
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 20c6ca8ac7fd..764d15defd88 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -46,6 +46,7 @@
46#include "ocfs2.h" 46#include "ocfs2.h"
47 47
48#include "alloc.h" 48#include "alloc.h"
49#include "dcache.h"
49#include "dlmglue.h" 50#include "dlmglue.h"
50#include "extent_map.h" 51#include "extent_map.h"
51#include "heartbeat.h" 52#include "heartbeat.h"
@@ -69,6 +70,9 @@ struct ocfs2_mask_waiter {
69static void ocfs2_inode_ast_func(void *opaque); 70static void ocfs2_inode_ast_func(void *opaque);
70static void ocfs2_inode_bast_func(void *opaque, 71static void ocfs2_inode_bast_func(void *opaque,
71 int level); 72 int level);
73static void ocfs2_dentry_ast_func(void *opaque);
74static void ocfs2_dentry_bast_func(void *opaque,
75 int level);
72static void ocfs2_super_ast_func(void *opaque); 76static void ocfs2_super_ast_func(void *opaque);
73static void ocfs2_super_bast_func(void *opaque, 77static void ocfs2_super_bast_func(void *opaque,
74 int level); 78 int level);
@@ -76,32 +80,57 @@ static void ocfs2_rename_ast_func(void *opaque);
76static void ocfs2_rename_bast_func(void *opaque, 80static void ocfs2_rename_bast_func(void *opaque,
77 int level); 81 int level);
78 82
83/*
84 * Return value from ocfs2_convert_worker_t functions.
85 *
86 * These control the precise actions of ocfs2_generic_unblock_lock()
87 * and ocfs2_process_blocked_lock()
88 *
89 */
90enum ocfs2_unblock_action {
91 UNBLOCK_CONTINUE = 0, /* Continue downconvert */
92 UNBLOCK_CONTINUE_POST = 1, /* Continue downconvert, fire
93 * ->post_unlock callback */
94 UNBLOCK_STOP_POST = 2, /* Do not downconvert, fire
95 * ->post_unlock() callback. */
96};
97
98struct ocfs2_unblock_ctl {
99 int requeue;
100 enum ocfs2_unblock_action unblock_action;
101};
102
79/* so far, all locks have gotten along with the same unlock ast */ 103/* so far, all locks have gotten along with the same unlock ast */
80static void ocfs2_unlock_ast_func(void *opaque, 104static void ocfs2_unlock_ast_func(void *opaque,
81 enum dlm_status status); 105 enum dlm_status status);
82static int ocfs2_do_unblock_meta(struct inode *inode,
83 int *requeue);
84static int ocfs2_unblock_meta(struct ocfs2_lock_res *lockres, 106static int ocfs2_unblock_meta(struct ocfs2_lock_res *lockres,
85 int *requeue); 107 struct ocfs2_unblock_ctl *ctl);
86static int ocfs2_unblock_data(struct ocfs2_lock_res *lockres, 108static int ocfs2_unblock_data(struct ocfs2_lock_res *lockres,
87 int *requeue); 109 struct ocfs2_unblock_ctl *ctl);
88static int ocfs2_unblock_inode_lock(struct ocfs2_lock_res *lockres, 110static int ocfs2_unblock_inode_lock(struct ocfs2_lock_res *lockres,
89 int *requeue); 111 struct ocfs2_unblock_ctl *ctl);
112static int ocfs2_unblock_dentry_lock(struct ocfs2_lock_res *lockres,
113 struct ocfs2_unblock_ctl *ctl);
90static int ocfs2_unblock_osb_lock(struct ocfs2_lock_res *lockres, 114static int ocfs2_unblock_osb_lock(struct ocfs2_lock_res *lockres,
91 int *requeue); 115 struct ocfs2_unblock_ctl *ctl);
92typedef void (ocfs2_convert_worker_t)(struct ocfs2_lock_res *, int); 116
93static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, 117static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb,
94 struct ocfs2_lock_res *lockres, 118 struct ocfs2_lock_res *lockres);
95 int *requeue,
96 ocfs2_convert_worker_t *worker);
97 119
98struct ocfs2_lock_res_ops { 120struct ocfs2_lock_res_ops {
99 void (*ast)(void *); 121 void (*ast)(void *);
100 void (*bast)(void *, int); 122 void (*bast)(void *, int);
101 void (*unlock_ast)(void *, enum dlm_status); 123 void (*unlock_ast)(void *, enum dlm_status);
102 int (*unblock)(struct ocfs2_lock_res *, int *); 124 int (*unblock)(struct ocfs2_lock_res *, struct ocfs2_unblock_ctl *);
125 void (*post_unlock)(struct ocfs2_super *, struct ocfs2_lock_res *);
103}; 126};
104 127
128typedef int (ocfs2_convert_worker_t)(struct ocfs2_lock_res *, int);
129static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb,
130 struct ocfs2_lock_res *lockres,
131 struct ocfs2_unblock_ctl *ctl,
132 ocfs2_convert_worker_t *worker);
133
105static struct ocfs2_lock_res_ops ocfs2_inode_rw_lops = { 134static struct ocfs2_lock_res_ops ocfs2_inode_rw_lops = {
106 .ast = ocfs2_inode_ast_func, 135 .ast = ocfs2_inode_ast_func,
107 .bast = ocfs2_inode_bast_func, 136 .bast = ocfs2_inode_bast_func,
@@ -116,9 +145,6 @@ static struct ocfs2_lock_res_ops ocfs2_inode_meta_lops = {
116 .unblock = ocfs2_unblock_meta, 145 .unblock = ocfs2_unblock_meta,
117}; 146};
118 147
119static void ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres,
120 int blocking);
121
122static struct ocfs2_lock_res_ops ocfs2_inode_data_lops = { 148static struct ocfs2_lock_res_ops ocfs2_inode_data_lops = {
123 .ast = ocfs2_inode_ast_func, 149 .ast = ocfs2_inode_ast_func,
124 .bast = ocfs2_inode_bast_func, 150 .bast = ocfs2_inode_bast_func,
@@ -140,6 +166,14 @@ static struct ocfs2_lock_res_ops ocfs2_rename_lops = {
140 .unblock = ocfs2_unblock_osb_lock, 166 .unblock = ocfs2_unblock_osb_lock,
141}; 167};
142 168
169static struct ocfs2_lock_res_ops ocfs2_dentry_lops = {
170 .ast = ocfs2_dentry_ast_func,
171 .bast = ocfs2_dentry_bast_func,
172 .unlock_ast = ocfs2_unlock_ast_func,
173 .unblock = ocfs2_unblock_dentry_lock,
174 .post_unlock = ocfs2_dentry_post_unlock,
175};
176
143static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres) 177static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres)
144{ 178{
145 return lockres->l_type == OCFS2_LOCK_TYPE_META || 179 return lockres->l_type == OCFS2_LOCK_TYPE_META ||
@@ -172,6 +206,13 @@ static inline struct inode *ocfs2_lock_res_inode(struct ocfs2_lock_res *lockres)
172 return (struct inode *) lockres->l_priv; 206 return (struct inode *) lockres->l_priv;
173} 207}
174 208
209static inline struct ocfs2_dentry_lock *ocfs2_lock_res_dl(struct ocfs2_lock_res *lockres)
210{
211 BUG_ON(lockres->l_type != OCFS2_LOCK_TYPE_DENTRY);
212
213 return (struct ocfs2_dentry_lock *)lockres->l_priv;
214}
215
175static int ocfs2_lock_create(struct ocfs2_super *osb, 216static int ocfs2_lock_create(struct ocfs2_super *osb,
176 struct ocfs2_lock_res *lockres, 217 struct ocfs2_lock_res *lockres,
177 int level, 218 int level,
@@ -204,22 +245,6 @@ static inline int ocfs2_can_downconvert_meta_lock(struct inode *inode,
204 struct ocfs2_lock_res *lockres, 245 struct ocfs2_lock_res *lockres,
205 int new_level); 246 int new_level);
206 247
207static char *ocfs2_lock_type_strings[] = {
208 [OCFS2_LOCK_TYPE_META] = "Meta",
209 [OCFS2_LOCK_TYPE_DATA] = "Data",
210 [OCFS2_LOCK_TYPE_SUPER] = "Super",
211 [OCFS2_LOCK_TYPE_RENAME] = "Rename",
212 /* Need to differntiate from [R]ename.. serializing writes is the
213 * important job it does, anyway. */
214 [OCFS2_LOCK_TYPE_RW] = "Write/Read",
215};
216
217static char *ocfs2_lock_type_string(enum ocfs2_lock_type type)
218{
219 mlog_bug_on_msg(type >= OCFS2_NUM_LOCK_TYPES, "%d\n", type);
220 return ocfs2_lock_type_strings[type];
221}
222
223static void ocfs2_build_lock_name(enum ocfs2_lock_type type, 248static void ocfs2_build_lock_name(enum ocfs2_lock_type type,
224 u64 blkno, 249 u64 blkno,
225 u32 generation, 250 u32 generation,
@@ -265,13 +290,9 @@ static void ocfs2_remove_lockres_tracking(struct ocfs2_lock_res *res)
265static void ocfs2_lock_res_init_common(struct ocfs2_super *osb, 290static void ocfs2_lock_res_init_common(struct ocfs2_super *osb,
266 struct ocfs2_lock_res *res, 291 struct ocfs2_lock_res *res,
267 enum ocfs2_lock_type type, 292 enum ocfs2_lock_type type,
268 u64 blkno,
269 u32 generation,
270 struct ocfs2_lock_res_ops *ops, 293 struct ocfs2_lock_res_ops *ops,
271 void *priv) 294 void *priv)
272{ 295{
273 ocfs2_build_lock_name(type, blkno, generation, res->l_name);
274
275 res->l_type = type; 296 res->l_type = type;
276 res->l_ops = ops; 297 res->l_ops = ops;
277 res->l_priv = priv; 298 res->l_priv = priv;
@@ -319,9 +340,59 @@ void ocfs2_inode_lock_res_init(struct ocfs2_lock_res *res,
319 break; 340 break;
320 }; 341 };
321 342
322 ocfs2_lock_res_init_common(OCFS2_SB(inode->i_sb), res, type, 343 ocfs2_build_lock_name(type, OCFS2_I(inode)->ip_blkno,
323 OCFS2_I(inode)->ip_blkno, 344 inode->i_generation, res->l_name);
324 inode->i_generation, ops, inode); 345 ocfs2_lock_res_init_common(OCFS2_SB(inode->i_sb), res, type, ops, inode);
346}
347
348static __u64 ocfs2_get_dentry_lock_ino(struct ocfs2_lock_res *lockres)
349{
350 __be64 inode_blkno_be;
351
352 memcpy(&inode_blkno_be, &lockres->l_name[OCFS2_DENTRY_LOCK_INO_START],
353 sizeof(__be64));
354
355 return be64_to_cpu(inode_blkno_be);
356}
357
358void ocfs2_dentry_lock_res_init(struct ocfs2_dentry_lock *dl,
359 u64 parent, struct inode *inode)
360{
361 int len;
362 u64 inode_blkno = OCFS2_I(inode)->ip_blkno;
363 __be64 inode_blkno_be = cpu_to_be64(inode_blkno);
364 struct ocfs2_lock_res *lockres = &dl->dl_lockres;
365
366 ocfs2_lock_res_init_once(lockres);
367
368 /*
369 * Unfortunately, the standard lock naming scheme won't work
370 * here because we have two 16 byte values to use. Instead,
371 * we'll stuff the inode number as a binary value. We still
372 * want error prints to show something without garbling the
373 * display, so drop a null byte in there before the inode
374 * number. A future version of OCFS2 will likely use all
375 * binary lock names. The stringified names have been a
376 * tremendous aid in debugging, but now that the debugfs
377 * interface exists, we can mangle things there if need be.
378 *
379 * NOTE: We also drop the standard "pad" value (the total lock
380 * name size stays the same though - the last part is all
381 * zeros due to the memset in ocfs2_lock_res_init_once()
382 */
383 len = snprintf(lockres->l_name, OCFS2_DENTRY_LOCK_INO_START,
384 "%c%016llx",
385 ocfs2_lock_type_char(OCFS2_LOCK_TYPE_DENTRY),
386 (long long)parent);
387
388 BUG_ON(len != (OCFS2_DENTRY_LOCK_INO_START - 1));
389
390 memcpy(&lockres->l_name[OCFS2_DENTRY_LOCK_INO_START], &inode_blkno_be,
391 sizeof(__be64));
392
393 ocfs2_lock_res_init_common(OCFS2_SB(inode->i_sb), lockres,
394 OCFS2_LOCK_TYPE_DENTRY, &ocfs2_dentry_lops,
395 dl);
325} 396}
326 397
327static void ocfs2_super_lock_res_init(struct ocfs2_lock_res *res, 398static void ocfs2_super_lock_res_init(struct ocfs2_lock_res *res,
@@ -330,8 +401,9 @@ static void ocfs2_super_lock_res_init(struct ocfs2_lock_res *res,
330 /* Superblock lockres doesn't come from a slab so we call init 401 /* Superblock lockres doesn't come from a slab so we call init
331 * once on it manually. */ 402 * once on it manually. */
332 ocfs2_lock_res_init_once(res); 403 ocfs2_lock_res_init_once(res);
404 ocfs2_build_lock_name(OCFS2_LOCK_TYPE_SUPER, OCFS2_SUPER_BLOCK_BLKNO,
405 0, res->l_name);
333 ocfs2_lock_res_init_common(osb, res, OCFS2_LOCK_TYPE_SUPER, 406 ocfs2_lock_res_init_common(osb, res, OCFS2_LOCK_TYPE_SUPER,
334 OCFS2_SUPER_BLOCK_BLKNO, 0,
335 &ocfs2_super_lops, osb); 407 &ocfs2_super_lops, osb);
336} 408}
337 409
@@ -341,7 +413,8 @@ static void ocfs2_rename_lock_res_init(struct ocfs2_lock_res *res,
341 /* Rename lockres doesn't come from a slab so we call init 413 /* Rename lockres doesn't come from a slab so we call init
342 * once on it manually. */ 414 * once on it manually. */
343 ocfs2_lock_res_init_once(res); 415 ocfs2_lock_res_init_once(res);
344 ocfs2_lock_res_init_common(osb, res, OCFS2_LOCK_TYPE_RENAME, 0, 0, 416 ocfs2_build_lock_name(OCFS2_LOCK_TYPE_RENAME, 0, 0, res->l_name);
417 ocfs2_lock_res_init_common(osb, res, OCFS2_LOCK_TYPE_RENAME,
345 &ocfs2_rename_lops, osb); 418 &ocfs2_rename_lops, osb);
346} 419}
347 420
@@ -627,9 +700,10 @@ static void ocfs2_generic_bast_func(struct ocfs2_super *osb,
627 ocfs2_schedule_blocked_lock(osb, lockres); 700 ocfs2_schedule_blocked_lock(osb, lockres);
628 spin_unlock_irqrestore(&lockres->l_lock, flags); 701 spin_unlock_irqrestore(&lockres->l_lock, flags);
629 702
703 wake_up(&lockres->l_event);
704
630 ocfs2_kick_vote_thread(osb); 705 ocfs2_kick_vote_thread(osb);
631 706
632 wake_up(&lockres->l_event);
633 mlog_exit_void(); 707 mlog_exit_void();
634} 708}
635 709
@@ -690,9 +764,9 @@ static void ocfs2_generic_ast_func(struct ocfs2_lock_res *lockres,
690 /* set it to something invalid so if we get called again we 764 /* set it to something invalid so if we get called again we
691 * can catch it. */ 765 * can catch it. */
692 lockres->l_action = OCFS2_AST_INVALID; 766 lockres->l_action = OCFS2_AST_INVALID;
693 spin_unlock_irqrestore(&lockres->l_lock, flags);
694 767
695 wake_up(&lockres->l_event); 768 wake_up(&lockres->l_event);
769 spin_unlock_irqrestore(&lockres->l_lock, flags);
696} 770}
697 771
698static void ocfs2_super_ast_func(void *opaque) 772static void ocfs2_super_ast_func(void *opaque)
@@ -757,6 +831,27 @@ static void ocfs2_rename_bast_func(void *opaque,
757 mlog_exit_void(); 831 mlog_exit_void();
758} 832}
759 833
834static void ocfs2_dentry_ast_func(void *opaque)
835{
836 struct ocfs2_lock_res *lockres = opaque;
837
838 BUG_ON(!lockres);
839
840 ocfs2_generic_ast_func(lockres, 1);
841}
842
843static void ocfs2_dentry_bast_func(void *opaque, int level)
844{
845 struct ocfs2_lock_res *lockres = opaque;
846 struct ocfs2_dentry_lock *dl = lockres->l_priv;
847 struct ocfs2_super *osb = OCFS2_SB(dl->dl_inode->i_sb);
848
849 mlog(0, "Dentry bast: level: %d, name: %s\n", level,
850 lockres->l_name);
851
852 ocfs2_generic_bast_func(osb, lockres, level);
853}
854
760static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres, 855static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres,
761 int convert) 856 int convert)
762{ 857{
@@ -1076,10 +1171,11 @@ static void ocfs2_cluster_unlock(struct ocfs2_super *osb,
1076 mlog_exit_void(); 1171 mlog_exit_void();
1077} 1172}
1078 1173
1079static int ocfs2_create_new_inode_lock(struct inode *inode, 1174int ocfs2_create_new_lock(struct ocfs2_super *osb,
1080 struct ocfs2_lock_res *lockres) 1175 struct ocfs2_lock_res *lockres,
1176 int ex)
1081{ 1177{
1082 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 1178 int level = ex ? LKM_EXMODE : LKM_PRMODE;
1083 unsigned long flags; 1179 unsigned long flags;
1084 1180
1085 spin_lock_irqsave(&lockres->l_lock, flags); 1181 spin_lock_irqsave(&lockres->l_lock, flags);
@@ -1087,7 +1183,7 @@ static int ocfs2_create_new_inode_lock(struct inode *inode,
1087 lockres_or_flags(lockres, OCFS2_LOCK_LOCAL); 1183 lockres_or_flags(lockres, OCFS2_LOCK_LOCAL);
1088 spin_unlock_irqrestore(&lockres->l_lock, flags); 1184 spin_unlock_irqrestore(&lockres->l_lock, flags);
1089 1185
1090 return ocfs2_lock_create(osb, lockres, LKM_EXMODE, LKM_LOCAL); 1186 return ocfs2_lock_create(osb, lockres, level, LKM_LOCAL);
1091} 1187}
1092 1188
1093/* Grants us an EX lock on the data and metadata resources, skipping 1189/* Grants us an EX lock on the data and metadata resources, skipping
@@ -1099,6 +1195,7 @@ static int ocfs2_create_new_inode_lock(struct inode *inode,
1099int ocfs2_create_new_inode_locks(struct inode *inode) 1195int ocfs2_create_new_inode_locks(struct inode *inode)
1100{ 1196{
1101 int ret; 1197 int ret;
1198 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
1102 1199
1103 BUG_ON(!inode); 1200 BUG_ON(!inode);
1104 BUG_ON(!ocfs2_inode_is_new(inode)); 1201 BUG_ON(!ocfs2_inode_is_new(inode));
@@ -1115,22 +1212,19 @@ int ocfs2_create_new_inode_locks(struct inode *inode)
1115 * on a resource which has an invalid one -- we'll set it 1212 * on a resource which has an invalid one -- we'll set it
1116 * valid when we release the EX. */ 1213 * valid when we release the EX. */
1117 1214
1118 ret = ocfs2_create_new_inode_lock(inode, 1215 ret = ocfs2_create_new_lock(osb, &OCFS2_I(inode)->ip_rw_lockres, 1);
1119 &OCFS2_I(inode)->ip_rw_lockres);
1120 if (ret) { 1216 if (ret) {
1121 mlog_errno(ret); 1217 mlog_errno(ret);
1122 goto bail; 1218 goto bail;
1123 } 1219 }
1124 1220
1125 ret = ocfs2_create_new_inode_lock(inode, 1221 ret = ocfs2_create_new_lock(osb, &OCFS2_I(inode)->ip_meta_lockres, 1);
1126 &OCFS2_I(inode)->ip_meta_lockres);
1127 if (ret) { 1222 if (ret) {
1128 mlog_errno(ret); 1223 mlog_errno(ret);
1129 goto bail; 1224 goto bail;
1130 } 1225 }
1131 1226
1132 ret = ocfs2_create_new_inode_lock(inode, 1227 ret = ocfs2_create_new_lock(osb, &OCFS2_I(inode)->ip_data_lockres, 1);
1133 &OCFS2_I(inode)->ip_data_lockres);
1134 if (ret) { 1228 if (ret) {
1135 mlog_errno(ret); 1229 mlog_errno(ret);
1136 goto bail; 1230 goto bail;
@@ -1809,6 +1903,34 @@ void ocfs2_rename_unlock(struct ocfs2_super *osb)
1809 ocfs2_cluster_unlock(osb, lockres, LKM_EXMODE); 1903 ocfs2_cluster_unlock(osb, lockres, LKM_EXMODE);
1810} 1904}
1811 1905
1906int ocfs2_dentry_lock(struct dentry *dentry, int ex)
1907{
1908 int ret;
1909 int level = ex ? LKM_EXMODE : LKM_PRMODE;
1910 struct ocfs2_dentry_lock *dl = dentry->d_fsdata;
1911 struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
1912
1913 BUG_ON(!dl);
1914
1915 if (ocfs2_is_hard_readonly(osb))
1916 return -EROFS;
1917
1918 ret = ocfs2_cluster_lock(osb, &dl->dl_lockres, level, 0, 0);
1919 if (ret < 0)
1920 mlog_errno(ret);
1921
1922 return ret;
1923}
1924
1925void ocfs2_dentry_unlock(struct dentry *dentry, int ex)
1926{
1927 int level = ex ? LKM_EXMODE : LKM_PRMODE;
1928 struct ocfs2_dentry_lock *dl = dentry->d_fsdata;
1929 struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
1930
1931 ocfs2_cluster_unlock(osb, &dl->dl_lockres, level);
1932}
1933
1812/* Reference counting of the dlm debug structure. We want this because 1934/* Reference counting of the dlm debug structure. We want this because
1813 * open references on the debug inodes can live on after a mount, so 1935 * open references on the debug inodes can live on after a mount, so
1814 * we can't rely on the ocfs2_super to always exist. */ 1936 * we can't rely on the ocfs2_super to always exist. */
@@ -1939,9 +2061,16 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void *v)
1939 if (!lockres) 2061 if (!lockres)
1940 return -EINVAL; 2062 return -EINVAL;
1941 2063
1942 seq_printf(m, "0x%x\t" 2064 seq_printf(m, "0x%x\t", OCFS2_DLM_DEBUG_STR_VERSION);
1943 "%.*s\t" 2065
1944 "%d\t" 2066 if (lockres->l_type == OCFS2_LOCK_TYPE_DENTRY)
2067 seq_printf(m, "%.*s%08x\t", OCFS2_DENTRY_LOCK_INO_START - 1,
2068 lockres->l_name,
2069 (unsigned int)ocfs2_get_dentry_lock_ino(lockres));
2070 else
2071 seq_printf(m, "%.*s\t", OCFS2_LOCK_ID_MAX_LEN, lockres->l_name);
2072
2073 seq_printf(m, "%d\t"
1945 "0x%lx\t" 2074 "0x%lx\t"
1946 "0x%x\t" 2075 "0x%x\t"
1947 "0x%x\t" 2076 "0x%x\t"
@@ -1949,8 +2078,6 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void *v)
1949 "%u\t" 2078 "%u\t"
1950 "%d\t" 2079 "%d\t"
1951 "%d\t", 2080 "%d\t",
1952 OCFS2_DLM_DEBUG_STR_VERSION,
1953 OCFS2_LOCK_ID_MAX_LEN, lockres->l_name,
1954 lockres->l_level, 2081 lockres->l_level,
1955 lockres->l_flags, 2082 lockres->l_flags,
1956 lockres->l_action, 2083 lockres->l_action,
@@ -2311,25 +2438,21 @@ void ocfs2_mark_lockres_freeing(struct ocfs2_lock_res *lockres)
2311 spin_unlock_irqrestore(&lockres->l_lock, flags); 2438 spin_unlock_irqrestore(&lockres->l_lock, flags);
2312} 2439}
2313 2440
2314static void ocfs2_drop_osb_locks(struct ocfs2_super *osb) 2441void ocfs2_simple_drop_lockres(struct ocfs2_super *osb,
2442 struct ocfs2_lock_res *lockres)
2315{ 2443{
2316 int status; 2444 int ret;
2317
2318 mlog_entry_void();
2319
2320 ocfs2_mark_lockres_freeing(&osb->osb_super_lockres);
2321
2322 status = ocfs2_drop_lock(osb, &osb->osb_super_lockres, NULL);
2323 if (status < 0)
2324 mlog_errno(status);
2325
2326 ocfs2_mark_lockres_freeing(&osb->osb_rename_lockres);
2327 2445
2328 status = ocfs2_drop_lock(osb, &osb->osb_rename_lockres, NULL); 2446 ocfs2_mark_lockres_freeing(lockres);
2329 if (status < 0) 2447 ret = ocfs2_drop_lock(osb, lockres, NULL);
2330 mlog_errno(status); 2448 if (ret)
2449 mlog_errno(ret);
2450}
2331 2451
2332 mlog_exit(status); 2452static void ocfs2_drop_osb_locks(struct ocfs2_super *osb)
2453{
2454 ocfs2_simple_drop_lockres(osb, &osb->osb_super_lockres);
2455 ocfs2_simple_drop_lockres(osb, &osb->osb_rename_lockres);
2333} 2456}
2334 2457
2335static void ocfs2_meta_pre_drop(struct ocfs2_lock_res *lockres, void *data) 2458static void ocfs2_meta_pre_drop(struct ocfs2_lock_res *lockres, void *data)
@@ -2599,7 +2722,7 @@ leave:
2599 2722
2600static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, 2723static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb,
2601 struct ocfs2_lock_res *lockres, 2724 struct ocfs2_lock_res *lockres,
2602 int *requeue, 2725 struct ocfs2_unblock_ctl *ctl,
2603 ocfs2_convert_worker_t *worker) 2726 ocfs2_convert_worker_t *worker)
2604{ 2727{
2605 unsigned long flags; 2728 unsigned long flags;
@@ -2615,7 +2738,7 @@ static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb,
2615 2738
2616recheck: 2739recheck:
2617 if (lockres->l_flags & OCFS2_LOCK_BUSY) { 2740 if (lockres->l_flags & OCFS2_LOCK_BUSY) {
2618 *requeue = 1; 2741 ctl->requeue = 1;
2619 ret = ocfs2_prepare_cancel_convert(osb, lockres); 2742 ret = ocfs2_prepare_cancel_convert(osb, lockres);
2620 spin_unlock_irqrestore(&lockres->l_lock, flags); 2743 spin_unlock_irqrestore(&lockres->l_lock, flags);
2621 if (ret) { 2744 if (ret) {
@@ -2631,7 +2754,7 @@ recheck:
2631 if ((lockres->l_blocking == LKM_EXMODE) 2754 if ((lockres->l_blocking == LKM_EXMODE)
2632 && (lockres->l_ex_holders || lockres->l_ro_holders)) { 2755 && (lockres->l_ex_holders || lockres->l_ro_holders)) {
2633 spin_unlock_irqrestore(&lockres->l_lock, flags); 2756 spin_unlock_irqrestore(&lockres->l_lock, flags);
2634 *requeue = 1; 2757 ctl->requeue = 1;
2635 ret = 0; 2758 ret = 0;
2636 goto leave; 2759 goto leave;
2637 } 2760 }
@@ -2641,7 +2764,7 @@ recheck:
2641 if (lockres->l_blocking == LKM_PRMODE && 2764 if (lockres->l_blocking == LKM_PRMODE &&
2642 lockres->l_ex_holders) { 2765 lockres->l_ex_holders) {
2643 spin_unlock_irqrestore(&lockres->l_lock, flags); 2766 spin_unlock_irqrestore(&lockres->l_lock, flags);
2644 *requeue = 1; 2767 ctl->requeue = 1;
2645 ret = 0; 2768 ret = 0;
2646 goto leave; 2769 goto leave;
2647 } 2770 }
@@ -2659,7 +2782,10 @@ recheck:
2659 blocking = lockres->l_blocking; 2782 blocking = lockres->l_blocking;
2660 spin_unlock_irqrestore(&lockres->l_lock, flags); 2783 spin_unlock_irqrestore(&lockres->l_lock, flags);
2661 2784
2662 worker(lockres, blocking); 2785 ctl->unblock_action = worker(lockres, blocking);
2786
2787 if (ctl->unblock_action == UNBLOCK_STOP_POST)
2788 goto leave;
2663 2789
2664 spin_lock_irqsave(&lockres->l_lock, flags); 2790 spin_lock_irqsave(&lockres->l_lock, flags);
2665 if (blocking != lockres->l_blocking) { 2791 if (blocking != lockres->l_blocking) {
@@ -2669,7 +2795,7 @@ recheck:
2669 } 2795 }
2670 2796
2671downconvert: 2797downconvert:
2672 *requeue = 0; 2798 ctl->requeue = 0;
2673 new_level = ocfs2_highest_compat_lock_level(lockres->l_blocking); 2799 new_level = ocfs2_highest_compat_lock_level(lockres->l_blocking);
2674 2800
2675 ocfs2_prepare_downconvert(lockres, new_level); 2801 ocfs2_prepare_downconvert(lockres, new_level);
@@ -2680,14 +2806,12 @@ leave:
2680 return ret; 2806 return ret;
2681} 2807}
2682 2808
2683static void ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres, 2809static int ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres,
2684 int blocking) 2810 int blocking)
2685{ 2811{
2686 struct inode *inode; 2812 struct inode *inode;
2687 struct address_space *mapping; 2813 struct address_space *mapping;
2688 2814
2689 mlog_entry_void();
2690
2691 inode = ocfs2_lock_res_inode(lockres); 2815 inode = ocfs2_lock_res_inode(lockres);
2692 mapping = inode->i_mapping; 2816 mapping = inode->i_mapping;
2693 2817
@@ -2708,11 +2832,11 @@ static void ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres,
2708 filemap_fdatawait(mapping); 2832 filemap_fdatawait(mapping);
2709 } 2833 }
2710 2834
2711 mlog_exit_void(); 2835 return UNBLOCK_CONTINUE;
2712} 2836}
2713 2837
2714int ocfs2_unblock_data(struct ocfs2_lock_res *lockres, 2838int ocfs2_unblock_data(struct ocfs2_lock_res *lockres,
2715 int *requeue) 2839 struct ocfs2_unblock_ctl *ctl)
2716{ 2840{
2717 int status; 2841 int status;
2718 struct inode *inode; 2842 struct inode *inode;
@@ -2726,22 +2850,20 @@ int ocfs2_unblock_data(struct ocfs2_lock_res *lockres,
2726 mlog(0, "unblock inode %llu\n", 2850 mlog(0, "unblock inode %llu\n",
2727 (unsigned long long)OCFS2_I(inode)->ip_blkno); 2851 (unsigned long long)OCFS2_I(inode)->ip_blkno);
2728 2852
2729 status = ocfs2_generic_unblock_lock(osb, 2853 status = ocfs2_generic_unblock_lock(osb, lockres, ctl,
2730 lockres,
2731 requeue,
2732 ocfs2_data_convert_worker); 2854 ocfs2_data_convert_worker);
2733 if (status < 0) 2855 if (status < 0)
2734 mlog_errno(status); 2856 mlog_errno(status);
2735 2857
2736 mlog(0, "inode %llu, requeue = %d\n", 2858 mlog(0, "inode %llu, requeue = %d\n",
2737 (unsigned long long)OCFS2_I(inode)->ip_blkno, *requeue); 2859 (unsigned long long)OCFS2_I(inode)->ip_blkno, ctl->requeue);
2738 2860
2739 mlog_exit(status); 2861 mlog_exit(status);
2740 return status; 2862 return status;
2741} 2863}
2742 2864
2743static int ocfs2_unblock_inode_lock(struct ocfs2_lock_res *lockres, 2865static int ocfs2_unblock_inode_lock(struct ocfs2_lock_res *lockres,
2744 int *requeue) 2866 struct ocfs2_unblock_ctl *ctl)
2745{ 2867{
2746 int status; 2868 int status;
2747 struct inode *inode; 2869 struct inode *inode;
@@ -2753,9 +2875,7 @@ static int ocfs2_unblock_inode_lock(struct ocfs2_lock_res *lockres,
2753 inode = ocfs2_lock_res_inode(lockres); 2875 inode = ocfs2_lock_res_inode(lockres);
2754 2876
2755 status = ocfs2_generic_unblock_lock(OCFS2_SB(inode->i_sb), 2877 status = ocfs2_generic_unblock_lock(OCFS2_SB(inode->i_sb),
2756 lockres, 2878 lockres, ctl, NULL);
2757 requeue,
2758 NULL);
2759 if (status < 0) 2879 if (status < 0)
2760 mlog_errno(status); 2880 mlog_errno(status);
2761 2881
@@ -2763,9 +2883,8 @@ static int ocfs2_unblock_inode_lock(struct ocfs2_lock_res *lockres,
2763 return status; 2883 return status;
2764} 2884}
2765 2885
2766 2886static int ocfs2_unblock_meta(struct ocfs2_lock_res *lockres,
2767int ocfs2_unblock_meta(struct ocfs2_lock_res *lockres, 2887 struct ocfs2_unblock_ctl *ctl)
2768 int *requeue)
2769{ 2888{
2770 int status; 2889 int status;
2771 struct inode *inode; 2890 struct inode *inode;
@@ -2777,21 +2896,165 @@ int ocfs2_unblock_meta(struct ocfs2_lock_res *lockres,
2777 mlog(0, "unblock inode %llu\n", 2896 mlog(0, "unblock inode %llu\n",
2778 (unsigned long long)OCFS2_I(inode)->ip_blkno); 2897 (unsigned long long)OCFS2_I(inode)->ip_blkno);
2779 2898
2780 status = ocfs2_do_unblock_meta(inode, requeue); 2899 status = ocfs2_do_unblock_meta(inode, &ctl->requeue);
2781 if (status < 0) 2900 if (status < 0)
2782 mlog_errno(status); 2901 mlog_errno(status);
2783 2902
2784 mlog(0, "inode %llu, requeue = %d\n", 2903 mlog(0, "inode %llu, requeue = %d\n",
2785 (unsigned long long)OCFS2_I(inode)->ip_blkno, *requeue); 2904 (unsigned long long)OCFS2_I(inode)->ip_blkno, ctl->requeue);
2786 2905
2787 mlog_exit(status); 2906 mlog_exit(status);
2788 return status; 2907 return status;
2789} 2908}
2790 2909
2910/*
2911 * Does the final reference drop on our dentry lock. Right now this
2912 * happens in the vote thread, but we could choose to simplify the
2913 * dlmglue API and push these off to the ocfs2_wq in the future.
2914 */
2915static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb,
2916 struct ocfs2_lock_res *lockres)
2917{
2918 struct ocfs2_dentry_lock *dl = ocfs2_lock_res_dl(lockres);
2919 ocfs2_dentry_lock_put(osb, dl);
2920}
2921
2922/*
2923 * d_delete() matching dentries before the lock downconvert.
2924 *
2925 * At this point, any process waiting to destroy the
2926 * dentry_lock due to last ref count is stopped by the
2927 * OCFS2_LOCK_QUEUED flag.
2928 *
2929 * We have two potential problems
2930 *
2931 * 1) If we do the last reference drop on our dentry_lock (via dput)
2932 * we'll wind up in ocfs2_release_dentry_lock(), waiting on
2933 * the downconvert to finish. Instead we take an elevated
2934 * reference and push the drop until after we've completed our
2935 * unblock processing.
2936 *
2937 * 2) There might be another process with a final reference,
2938 * waiting on us to finish processing. If this is the case, we
2939 * detect it and exit out - there's no more dentries anyway.
2940 */
2941static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres,
2942 int blocking)
2943{
2944 struct ocfs2_dentry_lock *dl = ocfs2_lock_res_dl(lockres);
2945 struct ocfs2_inode_info *oi = OCFS2_I(dl->dl_inode);
2946 struct dentry *dentry;
2947 unsigned long flags;
2948 int extra_ref = 0;
2949
2950 /*
2951 * This node is blocking another node from getting a read
2952 * lock. This happens when we've renamed within a
2953 * directory. We've forced the other nodes to d_delete(), but
2954 * we never actually dropped our lock because it's still
2955 * valid. The downconvert code will retain a PR for this node,
2956 * so there's no further work to do.
2957 */
2958 if (blocking == LKM_PRMODE)
2959 return UNBLOCK_CONTINUE;
2960
2961 /*
2962 * Mark this inode as potentially orphaned. The code in
2963 * ocfs2_delete_inode() will figure out whether it actually
2964 * needs to be freed or not.
2965 */
2966 spin_lock(&oi->ip_lock);
2967 oi->ip_flags |= OCFS2_INODE_MAYBE_ORPHANED;
2968 spin_unlock(&oi->ip_lock);
2969
2970 /*
2971 * Yuck. We need to make sure however that the check of
2972 * OCFS2_LOCK_FREEING and the extra reference are atomic with
2973 * respect to a reference decrement or the setting of that
2974 * flag.
2975 */
2976 spin_lock_irqsave(&lockres->l_lock, flags);
2977 spin_lock(&dentry_attach_lock);
2978 if (!(lockres->l_flags & OCFS2_LOCK_FREEING)
2979 && dl->dl_count) {
2980 dl->dl_count++;
2981 extra_ref = 1;
2982 }
2983 spin_unlock(&dentry_attach_lock);
2984 spin_unlock_irqrestore(&lockres->l_lock, flags);
2985
2986 mlog(0, "extra_ref = %d\n", extra_ref);
2987
2988 /*
2989 * We have a process waiting on us in ocfs2_dentry_iput(),
2990 * which means we can't have any more outstanding
2991 * aliases. There's no need to do any more work.
2992 */
2993 if (!extra_ref)
2994 return UNBLOCK_CONTINUE;
2995
2996 spin_lock(&dentry_attach_lock);
2997 while (1) {
2998 dentry = ocfs2_find_local_alias(dl->dl_inode,
2999 dl->dl_parent_blkno, 1);
3000 if (!dentry)
3001 break;
3002 spin_unlock(&dentry_attach_lock);
3003
3004 mlog(0, "d_delete(%.*s);\n", dentry->d_name.len,
3005 dentry->d_name.name);
3006
3007 /*
3008 * The following dcache calls may do an
3009 * iput(). Normally we don't want that from the
3010 * downconverting thread, but in this case it's ok
3011 * because the requesting node already has an
3012 * exclusive lock on the inode, so it can't be queued
3013 * for a downconvert.
3014 */
3015 d_delete(dentry);
3016 dput(dentry);
3017
3018 spin_lock(&dentry_attach_lock);
3019 }
3020 spin_unlock(&dentry_attach_lock);
3021
3022 /*
3023 * If we are the last holder of this dentry lock, there is no
3024 * reason to downconvert so skip straight to the unlock.
3025 */
3026 if (dl->dl_count == 1)
3027 return UNBLOCK_STOP_POST;
3028
3029 return UNBLOCK_CONTINUE_POST;
3030}
3031
3032static int ocfs2_unblock_dentry_lock(struct ocfs2_lock_res *lockres,
3033 struct ocfs2_unblock_ctl *ctl)
3034{
3035 int ret;
3036 struct ocfs2_dentry_lock *dl = ocfs2_lock_res_dl(lockres);
3037 struct ocfs2_super *osb = OCFS2_SB(dl->dl_inode->i_sb);
3038
3039 mlog(0, "unblock dentry lock: %llu\n",
3040 (unsigned long long)OCFS2_I(dl->dl_inode)->ip_blkno);
3041
3042 ret = ocfs2_generic_unblock_lock(osb,
3043 lockres,
3044 ctl,
3045 ocfs2_dentry_convert_worker);
3046 if (ret < 0)
3047 mlog_errno(ret);
3048
3049 mlog(0, "requeue = %d, post = %d\n", ctl->requeue, ctl->unblock_action);
3050
3051 return ret;
3052}
3053
2791/* Generic unblock function for any lockres whose private data is an 3054/* Generic unblock function for any lockres whose private data is an
2792 * ocfs2_super pointer. */ 3055 * ocfs2_super pointer. */
2793static int ocfs2_unblock_osb_lock(struct ocfs2_lock_res *lockres, 3056static int ocfs2_unblock_osb_lock(struct ocfs2_lock_res *lockres,
2794 int *requeue) 3057 struct ocfs2_unblock_ctl *ctl)
2795{ 3058{
2796 int status; 3059 int status;
2797 struct ocfs2_super *osb; 3060 struct ocfs2_super *osb;
@@ -2804,7 +3067,7 @@ static int ocfs2_unblock_osb_lock(struct ocfs2_lock_res *lockres,
2804 3067
2805 status = ocfs2_generic_unblock_lock(osb, 3068 status = ocfs2_generic_unblock_lock(osb,
2806 lockres, 3069 lockres,
2807 requeue, 3070 ctl,
2808 NULL); 3071 NULL);
2809 if (status < 0) 3072 if (status < 0)
2810 mlog_errno(status); 3073 mlog_errno(status);
@@ -2817,7 +3080,7 @@ void ocfs2_process_blocked_lock(struct ocfs2_super *osb,
2817 struct ocfs2_lock_res *lockres) 3080 struct ocfs2_lock_res *lockres)
2818{ 3081{
2819 int status; 3082 int status;
2820 int requeue = 0; 3083 struct ocfs2_unblock_ctl ctl = {0, 0,};
2821 unsigned long flags; 3084 unsigned long flags;
2822 3085
2823 /* Our reference to the lockres in this function can be 3086 /* Our reference to the lockres in this function can be
@@ -2842,21 +3105,25 @@ void ocfs2_process_blocked_lock(struct ocfs2_super *osb,
2842 goto unqueue; 3105 goto unqueue;
2843 spin_unlock_irqrestore(&lockres->l_lock, flags); 3106 spin_unlock_irqrestore(&lockres->l_lock, flags);
2844 3107
2845 status = lockres->l_ops->unblock(lockres, &requeue); 3108 status = lockres->l_ops->unblock(lockres, &ctl);
2846 if (status < 0) 3109 if (status < 0)
2847 mlog_errno(status); 3110 mlog_errno(status);
2848 3111
2849 spin_lock_irqsave(&lockres->l_lock, flags); 3112 spin_lock_irqsave(&lockres->l_lock, flags);
2850unqueue: 3113unqueue:
2851 if (lockres->l_flags & OCFS2_LOCK_FREEING || !requeue) { 3114 if (lockres->l_flags & OCFS2_LOCK_FREEING || !ctl.requeue) {
2852 lockres_clear_flags(lockres, OCFS2_LOCK_QUEUED); 3115 lockres_clear_flags(lockres, OCFS2_LOCK_QUEUED);
2853 } else 3116 } else
2854 ocfs2_schedule_blocked_lock(osb, lockres); 3117 ocfs2_schedule_blocked_lock(osb, lockres);
2855 3118
2856 mlog(0, "lockres %s, requeue = %s.\n", lockres->l_name, 3119 mlog(0, "lockres %s, requeue = %s.\n", lockres->l_name,
2857 requeue ? "yes" : "no"); 3120 ctl.requeue ? "yes" : "no");
2858 spin_unlock_irqrestore(&lockres->l_lock, flags); 3121 spin_unlock_irqrestore(&lockres->l_lock, flags);
2859 3122
3123 if (ctl.unblock_action != UNBLOCK_CONTINUE
3124 && lockres->l_ops->post_unlock)
3125 lockres->l_ops->post_unlock(osb, lockres);
3126
2860 mlog_exit_void(); 3127 mlog_exit_void();
2861} 3128}
2862 3129
diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h
index 243ae862ece5..340251567e99 100644
--- a/fs/ocfs2/dlmglue.h
+++ b/fs/ocfs2/dlmglue.h
@@ -27,6 +27,8 @@
27#ifndef DLMGLUE_H 27#ifndef DLMGLUE_H
28#define DLMGLUE_H 28#define DLMGLUE_H
29 29
30#include "dcache.h"
31
30#define OCFS2_LVB_VERSION 3 32#define OCFS2_LVB_VERSION 3
31 33
32struct ocfs2_meta_lvb { 34struct ocfs2_meta_lvb {
@@ -58,8 +60,12 @@ void ocfs2_lock_res_init_once(struct ocfs2_lock_res *res);
58void ocfs2_inode_lock_res_init(struct ocfs2_lock_res *res, 60void ocfs2_inode_lock_res_init(struct ocfs2_lock_res *res,
59 enum ocfs2_lock_type type, 61 enum ocfs2_lock_type type,
60 struct inode *inode); 62 struct inode *inode);
63void ocfs2_dentry_lock_res_init(struct ocfs2_dentry_lock *dl,
64 u64 parent, struct inode *inode);
61void ocfs2_lock_res_free(struct ocfs2_lock_res *res); 65void ocfs2_lock_res_free(struct ocfs2_lock_res *res);
62int ocfs2_create_new_inode_locks(struct inode *inode); 66int ocfs2_create_new_inode_locks(struct inode *inode);
67int ocfs2_create_new_lock(struct ocfs2_super *osb,
68 struct ocfs2_lock_res *lockres, int ex);
63int ocfs2_drop_inode_locks(struct inode *inode); 69int ocfs2_drop_inode_locks(struct inode *inode);
64int ocfs2_data_lock_full(struct inode *inode, 70int ocfs2_data_lock_full(struct inode *inode,
65 int write, 71 int write,
@@ -93,7 +99,12 @@ void ocfs2_super_unlock(struct ocfs2_super *osb,
93 int ex); 99 int ex);
94int ocfs2_rename_lock(struct ocfs2_super *osb); 100int ocfs2_rename_lock(struct ocfs2_super *osb);
95void ocfs2_rename_unlock(struct ocfs2_super *osb); 101void ocfs2_rename_unlock(struct ocfs2_super *osb);
102int ocfs2_dentry_lock(struct dentry *dentry, int ex);
103void ocfs2_dentry_unlock(struct dentry *dentry, int ex);
104
96void ocfs2_mark_lockres_freeing(struct ocfs2_lock_res *lockres); 105void ocfs2_mark_lockres_freeing(struct ocfs2_lock_res *lockres);
106void ocfs2_simple_drop_lockres(struct ocfs2_super *osb,
107 struct ocfs2_lock_res *lockres);
97 108
98/* for the vote thread */ 109/* for the vote thread */
99void ocfs2_process_blocked_lock(struct ocfs2_super *osb, 110void ocfs2_process_blocked_lock(struct ocfs2_super *osb,
diff --git a/fs/ocfs2/ocfs2_lockid.h b/fs/ocfs2/ocfs2_lockid.h
index 7dd9e1e705b0..4d5d5655c185 100644
--- a/fs/ocfs2/ocfs2_lockid.h
+++ b/fs/ocfs2/ocfs2_lockid.h
@@ -35,12 +35,15 @@
35#define OCFS2_LOCK_ID_MAX_LEN 32 35#define OCFS2_LOCK_ID_MAX_LEN 32
36#define OCFS2_LOCK_ID_PAD "000000" 36#define OCFS2_LOCK_ID_PAD "000000"
37 37
38#define OCFS2_DENTRY_LOCK_INO_START 18
39
38enum ocfs2_lock_type { 40enum ocfs2_lock_type {
39 OCFS2_LOCK_TYPE_META = 0, 41 OCFS2_LOCK_TYPE_META = 0,
40 OCFS2_LOCK_TYPE_DATA, 42 OCFS2_LOCK_TYPE_DATA,
41 OCFS2_LOCK_TYPE_SUPER, 43 OCFS2_LOCK_TYPE_SUPER,
42 OCFS2_LOCK_TYPE_RENAME, 44 OCFS2_LOCK_TYPE_RENAME,
43 OCFS2_LOCK_TYPE_RW, 45 OCFS2_LOCK_TYPE_RW,
46 OCFS2_LOCK_TYPE_DENTRY,
44 OCFS2_NUM_LOCK_TYPES 47 OCFS2_NUM_LOCK_TYPES
45}; 48};
46 49
@@ -63,6 +66,9 @@ static inline char ocfs2_lock_type_char(enum ocfs2_lock_type type)
63 case OCFS2_LOCK_TYPE_RW: 66 case OCFS2_LOCK_TYPE_RW:
64 c = 'W'; 67 c = 'W';
65 break; 68 break;
69 case OCFS2_LOCK_TYPE_DENTRY:
70 c = 'N';
71 break;
66 default: 72 default:
67 c = '\0'; 73 c = '\0';
68 } 74 }
@@ -70,4 +76,23 @@ static inline char ocfs2_lock_type_char(enum ocfs2_lock_type type)
70 return c; 76 return c;
71} 77}
72 78
79static char *ocfs2_lock_type_strings[] = {
80 [OCFS2_LOCK_TYPE_META] = "Meta",
81 [OCFS2_LOCK_TYPE_DATA] = "Data",
82 [OCFS2_LOCK_TYPE_SUPER] = "Super",
83 [OCFS2_LOCK_TYPE_RENAME] = "Rename",
84 /* Need to differntiate from [R]ename.. serializing writes is the
85 * important job it does, anyway. */
86 [OCFS2_LOCK_TYPE_RW] = "Write/Read",
87 [OCFS2_LOCK_TYPE_DENTRY] = "Dentry",
88};
89
90static inline const char *ocfs2_lock_type_string(enum ocfs2_lock_type type)
91{
92#ifdef __KERNEL__
93 mlog_bug_on_msg(type >= OCFS2_NUM_LOCK_TYPES, "%d\n", type);
94#endif
95 return ocfs2_lock_type_strings[type];
96}
97
73#endif /* OCFS2_LOCKID_H */ 98#endif /* OCFS2_LOCKID_H */