From f0681062b8e369d9fb6f3ce10f4e3fc8cea5f910 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Fri, 8 Sep 2006 11:40:10 -0700 Subject: ocfs2: Update dlmglue for new dlmlock() API File system lock names are very regular right now, so we really only need to pass an extra parameter to dlmlock(). Signed-off-by: Mark Fasheh --- fs/ocfs2/dlmglue.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fs/ocfs2/dlmglue.c') diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 151b41781ea..20c6ca8ac7f 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -810,6 +810,7 @@ static int ocfs2_lock_create(struct ocfs2_super *osb, &lockres->l_lksb, dlm_flags, lockres->l_name, + OCFS2_LOCK_ID_MAX_LEN - 1, lockres->l_ops->ast, lockres, lockres->l_ops->bast); @@ -999,6 +1000,7 @@ again: &lockres->l_lksb, lkm_flags|LKM_CONVERT|LKM_VALBLK, lockres->l_name, + OCFS2_LOCK_ID_MAX_LEN - 1, lockres->l_ops->ast, lockres, lockres->l_ops->bast); @@ -2419,6 +2421,7 @@ static int ocfs2_downconvert_lock(struct ocfs2_super *osb, &lockres->l_lksb, dlm_flags, lockres->l_name, + OCFS2_LOCK_ID_MAX_LEN - 1, lockres->l_ops->ast, lockres, lockres->l_ops->bast); -- cgit v1.2.3 From d680efe9d8fe0eb99d9dd063a4def6b362cdb40d Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Fri, 8 Sep 2006 14:14:34 -0700 Subject: ocfs2: Add new cluster lock type Replace the dentry vote mechanism with a cluster lock which covers a set of dentries. This allows us to force d_delete() only on nodes which actually care about an unlink. Every node that does a ->lookup() gets a read only lock on the dentry, until an unlink during which the unlinking node, will request an exclusive lock, forcing the other nodes who care about that dentry to d_delete() it. The effect is that we retain a very lightweight ->d_revalidate(), and at the same time get to make large improvements to the average case performance of the ocfs2 unlink and rename operations. This patch adds the cluster lock type which OCFS2 can attach to dentries. A small number of fs/ocfs2/dcache.c functions are stubbed out so that this change can compile. Signed-off-by: Mark Fasheh --- fs/ocfs2/dlmglue.c | 475 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 371 insertions(+), 104 deletions(-) (limited to 'fs/ocfs2/dlmglue.c') diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 20c6ca8ac7f..764d15defd8 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -46,6 +46,7 @@ #include "ocfs2.h" #include "alloc.h" +#include "dcache.h" #include "dlmglue.h" #include "extent_map.h" #include "heartbeat.h" @@ -69,6 +70,9 @@ struct ocfs2_mask_waiter { static void ocfs2_inode_ast_func(void *opaque); static void ocfs2_inode_bast_func(void *opaque, int level); +static void ocfs2_dentry_ast_func(void *opaque); +static void ocfs2_dentry_bast_func(void *opaque, + int level); static void ocfs2_super_ast_func(void *opaque); static void ocfs2_super_bast_func(void *opaque, int level); @@ -76,32 +80,57 @@ static void ocfs2_rename_ast_func(void *opaque); static void ocfs2_rename_bast_func(void *opaque, int level); +/* + * Return value from ocfs2_convert_worker_t functions. + * + * These control the precise actions of ocfs2_generic_unblock_lock() + * and ocfs2_process_blocked_lock() + * + */ +enum ocfs2_unblock_action { + UNBLOCK_CONTINUE = 0, /* Continue downconvert */ + UNBLOCK_CONTINUE_POST = 1, /* Continue downconvert, fire + * ->post_unlock callback */ + UNBLOCK_STOP_POST = 2, /* Do not downconvert, fire + * ->post_unlock() callback. */ +}; + +struct ocfs2_unblock_ctl { + int requeue; + enum ocfs2_unblock_action unblock_action; +}; + /* so far, all locks have gotten along with the same unlock ast */ static void ocfs2_unlock_ast_func(void *opaque, enum dlm_status status); -static int ocfs2_do_unblock_meta(struct inode *inode, - int *requeue); static int ocfs2_unblock_meta(struct ocfs2_lock_res *lockres, - int *requeue); + struct ocfs2_unblock_ctl *ctl); static int ocfs2_unblock_data(struct ocfs2_lock_res *lockres, - int *requeue); + struct ocfs2_unblock_ctl *ctl); static int ocfs2_unblock_inode_lock(struct ocfs2_lock_res *lockres, - int *requeue); + struct ocfs2_unblock_ctl *ctl); +static int ocfs2_unblock_dentry_lock(struct ocfs2_lock_res *lockres, + struct ocfs2_unblock_ctl *ctl); static int ocfs2_unblock_osb_lock(struct ocfs2_lock_res *lockres, - int *requeue); -typedef void (ocfs2_convert_worker_t)(struct ocfs2_lock_res *, int); -static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, - struct ocfs2_lock_res *lockres, - int *requeue, - ocfs2_convert_worker_t *worker); + struct ocfs2_unblock_ctl *ctl); + +static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb, + struct ocfs2_lock_res *lockres); struct ocfs2_lock_res_ops { void (*ast)(void *); void (*bast)(void *, int); void (*unlock_ast)(void *, enum dlm_status); - int (*unblock)(struct ocfs2_lock_res *, int *); + int (*unblock)(struct ocfs2_lock_res *, struct ocfs2_unblock_ctl *); + void (*post_unlock)(struct ocfs2_super *, struct ocfs2_lock_res *); }; +typedef int (ocfs2_convert_worker_t)(struct ocfs2_lock_res *, int); +static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, + struct ocfs2_lock_res *lockres, + struct ocfs2_unblock_ctl *ctl, + ocfs2_convert_worker_t *worker); + static struct ocfs2_lock_res_ops ocfs2_inode_rw_lops = { .ast = ocfs2_inode_ast_func, .bast = ocfs2_inode_bast_func, @@ -116,9 +145,6 @@ static struct ocfs2_lock_res_ops ocfs2_inode_meta_lops = { .unblock = ocfs2_unblock_meta, }; -static void ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres, - int blocking); - static struct ocfs2_lock_res_ops ocfs2_inode_data_lops = { .ast = ocfs2_inode_ast_func, .bast = ocfs2_inode_bast_func, @@ -140,6 +166,14 @@ static struct ocfs2_lock_res_ops ocfs2_rename_lops = { .unblock = ocfs2_unblock_osb_lock, }; +static struct ocfs2_lock_res_ops ocfs2_dentry_lops = { + .ast = ocfs2_dentry_ast_func, + .bast = ocfs2_dentry_bast_func, + .unlock_ast = ocfs2_unlock_ast_func, + .unblock = ocfs2_unblock_dentry_lock, + .post_unlock = ocfs2_dentry_post_unlock, +}; + static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres) { 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) return (struct inode *) lockres->l_priv; } +static inline struct ocfs2_dentry_lock *ocfs2_lock_res_dl(struct ocfs2_lock_res *lockres) +{ + BUG_ON(lockres->l_type != OCFS2_LOCK_TYPE_DENTRY); + + return (struct ocfs2_dentry_lock *)lockres->l_priv; +} + static int ocfs2_lock_create(struct ocfs2_super *osb, struct ocfs2_lock_res *lockres, int level, @@ -204,22 +245,6 @@ static inline int ocfs2_can_downconvert_meta_lock(struct inode *inode, struct ocfs2_lock_res *lockres, int new_level); -static char *ocfs2_lock_type_strings[] = { - [OCFS2_LOCK_TYPE_META] = "Meta", - [OCFS2_LOCK_TYPE_DATA] = "Data", - [OCFS2_LOCK_TYPE_SUPER] = "Super", - [OCFS2_LOCK_TYPE_RENAME] = "Rename", - /* Need to differntiate from [R]ename.. serializing writes is the - * important job it does, anyway. */ - [OCFS2_LOCK_TYPE_RW] = "Write/Read", -}; - -static char *ocfs2_lock_type_string(enum ocfs2_lock_type type) -{ - mlog_bug_on_msg(type >= OCFS2_NUM_LOCK_TYPES, "%d\n", type); - return ocfs2_lock_type_strings[type]; -} - static void ocfs2_build_lock_name(enum ocfs2_lock_type type, u64 blkno, u32 generation, @@ -265,13 +290,9 @@ static void ocfs2_remove_lockres_tracking(struct ocfs2_lock_res *res) static void ocfs2_lock_res_init_common(struct ocfs2_super *osb, struct ocfs2_lock_res *res, enum ocfs2_lock_type type, - u64 blkno, - u32 generation, struct ocfs2_lock_res_ops *ops, void *priv) { - ocfs2_build_lock_name(type, blkno, generation, res->l_name); - res->l_type = type; res->l_ops = ops; res->l_priv = priv; @@ -319,9 +340,59 @@ void ocfs2_inode_lock_res_init(struct ocfs2_lock_res *res, break; }; - ocfs2_lock_res_init_common(OCFS2_SB(inode->i_sb), res, type, - OCFS2_I(inode)->ip_blkno, - inode->i_generation, ops, inode); + ocfs2_build_lock_name(type, OCFS2_I(inode)->ip_blkno, + inode->i_generation, res->l_name); + ocfs2_lock_res_init_common(OCFS2_SB(inode->i_sb), res, type, ops, inode); +} + +static __u64 ocfs2_get_dentry_lock_ino(struct ocfs2_lock_res *lockres) +{ + __be64 inode_blkno_be; + + memcpy(&inode_blkno_be, &lockres->l_name[OCFS2_DENTRY_LOCK_INO_START], + sizeof(__be64)); + + return be64_to_cpu(inode_blkno_be); +} + +void ocfs2_dentry_lock_res_init(struct ocfs2_dentry_lock *dl, + u64 parent, struct inode *inode) +{ + int len; + u64 inode_blkno = OCFS2_I(inode)->ip_blkno; + __be64 inode_blkno_be = cpu_to_be64(inode_blkno); + struct ocfs2_lock_res *lockres = &dl->dl_lockres; + + ocfs2_lock_res_init_once(lockres); + + /* + * Unfortunately, the standard lock naming scheme won't work + * here because we have two 16 byte values to use. Instead, + * we'll stuff the inode number as a binary value. We still + * want error prints to show something without garbling the + * display, so drop a null byte in there before the inode + * number. A future version of OCFS2 will likely use all + * binary lock names. The stringified names have been a + * tremendous aid in debugging, but now that the debugfs + * interface exists, we can mangle things there if need be. + * + * NOTE: We also drop the standard "pad" value (the total lock + * name size stays the same though - the last part is all + * zeros due to the memset in ocfs2_lock_res_init_once() + */ + len = snprintf(lockres->l_name, OCFS2_DENTRY_LOCK_INO_START, + "%c%016llx", + ocfs2_lock_type_char(OCFS2_LOCK_TYPE_DENTRY), + (long long)parent); + + BUG_ON(len != (OCFS2_DENTRY_LOCK_INO_START - 1)); + + memcpy(&lockres->l_name[OCFS2_DENTRY_LOCK_INO_START], &inode_blkno_be, + sizeof(__be64)); + + ocfs2_lock_res_init_common(OCFS2_SB(inode->i_sb), lockres, + OCFS2_LOCK_TYPE_DENTRY, &ocfs2_dentry_lops, + dl); } static 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, /* Superblock lockres doesn't come from a slab so we call init * once on it manually. */ ocfs2_lock_res_init_once(res); + ocfs2_build_lock_name(OCFS2_LOCK_TYPE_SUPER, OCFS2_SUPER_BLOCK_BLKNO, + 0, res->l_name); ocfs2_lock_res_init_common(osb, res, OCFS2_LOCK_TYPE_SUPER, - OCFS2_SUPER_BLOCK_BLKNO, 0, &ocfs2_super_lops, osb); } @@ -341,7 +413,8 @@ static void ocfs2_rename_lock_res_init(struct ocfs2_lock_res *res, /* Rename lockres doesn't come from a slab so we call init * once on it manually. */ ocfs2_lock_res_init_once(res); - ocfs2_lock_res_init_common(osb, res, OCFS2_LOCK_TYPE_RENAME, 0, 0, + ocfs2_build_lock_name(OCFS2_LOCK_TYPE_RENAME, 0, 0, res->l_name); + ocfs2_lock_res_init_common(osb, res, OCFS2_LOCK_TYPE_RENAME, &ocfs2_rename_lops, osb); } @@ -627,9 +700,10 @@ static void ocfs2_generic_bast_func(struct ocfs2_super *osb, ocfs2_schedule_blocked_lock(osb, lockres); spin_unlock_irqrestore(&lockres->l_lock, flags); + wake_up(&lockres->l_event); + ocfs2_kick_vote_thread(osb); - wake_up(&lockres->l_event); mlog_exit_void(); } @@ -690,9 +764,9 @@ static void ocfs2_generic_ast_func(struct ocfs2_lock_res *lockres, /* set it to something invalid so if we get called again we * can catch it. */ lockres->l_action = OCFS2_AST_INVALID; - spin_unlock_irqrestore(&lockres->l_lock, flags); wake_up(&lockres->l_event); + spin_unlock_irqrestore(&lockres->l_lock, flags); } static void ocfs2_super_ast_func(void *opaque) @@ -757,6 +831,27 @@ static void ocfs2_rename_bast_func(void *opaque, mlog_exit_void(); } +static void ocfs2_dentry_ast_func(void *opaque) +{ + struct ocfs2_lock_res *lockres = opaque; + + BUG_ON(!lockres); + + ocfs2_generic_ast_func(lockres, 1); +} + +static void ocfs2_dentry_bast_func(void *opaque, int level) +{ + struct ocfs2_lock_res *lockres = opaque; + struct ocfs2_dentry_lock *dl = lockres->l_priv; + struct ocfs2_super *osb = OCFS2_SB(dl->dl_inode->i_sb); + + mlog(0, "Dentry bast: level: %d, name: %s\n", level, + lockres->l_name); + + ocfs2_generic_bast_func(osb, lockres, level); +} + static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres, int convert) { @@ -1076,10 +1171,11 @@ static void ocfs2_cluster_unlock(struct ocfs2_super *osb, mlog_exit_void(); } -static int ocfs2_create_new_inode_lock(struct inode *inode, - struct ocfs2_lock_res *lockres) +int ocfs2_create_new_lock(struct ocfs2_super *osb, + struct ocfs2_lock_res *lockres, + int ex) { - struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); + int level = ex ? LKM_EXMODE : LKM_PRMODE; unsigned long flags; spin_lock_irqsave(&lockres->l_lock, flags); @@ -1087,7 +1183,7 @@ static int ocfs2_create_new_inode_lock(struct inode *inode, lockres_or_flags(lockres, OCFS2_LOCK_LOCAL); spin_unlock_irqrestore(&lockres->l_lock, flags); - return ocfs2_lock_create(osb, lockres, LKM_EXMODE, LKM_LOCAL); + return ocfs2_lock_create(osb, lockres, level, LKM_LOCAL); } /* 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, int ocfs2_create_new_inode_locks(struct inode *inode) { int ret; + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); BUG_ON(!inode); BUG_ON(!ocfs2_inode_is_new(inode)); @@ -1115,22 +1212,19 @@ int ocfs2_create_new_inode_locks(struct inode *inode) * on a resource which has an invalid one -- we'll set it * valid when we release the EX. */ - ret = ocfs2_create_new_inode_lock(inode, - &OCFS2_I(inode)->ip_rw_lockres); + ret = ocfs2_create_new_lock(osb, &OCFS2_I(inode)->ip_rw_lockres, 1); if (ret) { mlog_errno(ret); goto bail; } - ret = ocfs2_create_new_inode_lock(inode, - &OCFS2_I(inode)->ip_meta_lockres); + ret = ocfs2_create_new_lock(osb, &OCFS2_I(inode)->ip_meta_lockres, 1); if (ret) { mlog_errno(ret); goto bail; } - ret = ocfs2_create_new_inode_lock(inode, - &OCFS2_I(inode)->ip_data_lockres); + ret = ocfs2_create_new_lock(osb, &OCFS2_I(inode)->ip_data_lockres, 1); if (ret) { mlog_errno(ret); goto bail; @@ -1809,6 +1903,34 @@ void ocfs2_rename_unlock(struct ocfs2_super *osb) ocfs2_cluster_unlock(osb, lockres, LKM_EXMODE); } +int ocfs2_dentry_lock(struct dentry *dentry, int ex) +{ + int ret; + int level = ex ? LKM_EXMODE : LKM_PRMODE; + struct ocfs2_dentry_lock *dl = dentry->d_fsdata; + struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb); + + BUG_ON(!dl); + + if (ocfs2_is_hard_readonly(osb)) + return -EROFS; + + ret = ocfs2_cluster_lock(osb, &dl->dl_lockres, level, 0, 0); + if (ret < 0) + mlog_errno(ret); + + return ret; +} + +void ocfs2_dentry_unlock(struct dentry *dentry, int ex) +{ + int level = ex ? LKM_EXMODE : LKM_PRMODE; + 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); +} + /* Reference counting of the dlm debug structure. We want this because * open references on the debug inodes can live on after a mount, so * 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) if (!lockres) return -EINVAL; - seq_printf(m, "0x%x\t" - "%.*s\t" - "%d\t" + seq_printf(m, "0x%x\t", OCFS2_DLM_DEBUG_STR_VERSION); + + if (lockres->l_type == OCFS2_LOCK_TYPE_DENTRY) + seq_printf(m, "%.*s%08x\t", OCFS2_DENTRY_LOCK_INO_START - 1, + lockres->l_name, + (unsigned int)ocfs2_get_dentry_lock_ino(lockres)); + else + seq_printf(m, "%.*s\t", OCFS2_LOCK_ID_MAX_LEN, lockres->l_name); + + seq_printf(m, "%d\t" "0x%lx\t" "0x%x\t" "0x%x\t" @@ -1949,8 +2078,6 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void *v) "%u\t" "%d\t" "%d\t", - OCFS2_DLM_DEBUG_STR_VERSION, - OCFS2_LOCK_ID_MAX_LEN, lockres->l_name, lockres->l_level, lockres->l_flags, lockres->l_action, @@ -2311,25 +2438,21 @@ void ocfs2_mark_lockres_freeing(struct ocfs2_lock_res *lockres) spin_unlock_irqrestore(&lockres->l_lock, flags); } -static void ocfs2_drop_osb_locks(struct ocfs2_super *osb) +void ocfs2_simple_drop_lockres(struct ocfs2_super *osb, + struct ocfs2_lock_res *lockres) { - int status; - - mlog_entry_void(); - - ocfs2_mark_lockres_freeing(&osb->osb_super_lockres); - - status = ocfs2_drop_lock(osb, &osb->osb_super_lockres, NULL); - if (status < 0) - mlog_errno(status); - - ocfs2_mark_lockres_freeing(&osb->osb_rename_lockres); + int ret; - status = ocfs2_drop_lock(osb, &osb->osb_rename_lockres, NULL); - if (status < 0) - mlog_errno(status); + ocfs2_mark_lockres_freeing(lockres); + ret = ocfs2_drop_lock(osb, lockres, NULL); + if (ret) + mlog_errno(ret); +} - mlog_exit(status); +static void ocfs2_drop_osb_locks(struct ocfs2_super *osb) +{ + ocfs2_simple_drop_lockres(osb, &osb->osb_super_lockres); + ocfs2_simple_drop_lockres(osb, &osb->osb_rename_lockres); } static void ocfs2_meta_pre_drop(struct ocfs2_lock_res *lockres, void *data) @@ -2599,7 +2722,7 @@ leave: static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, struct ocfs2_lock_res *lockres, - int *requeue, + struct ocfs2_unblock_ctl *ctl, ocfs2_convert_worker_t *worker) { unsigned long flags; @@ -2615,7 +2738,7 @@ static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, recheck: if (lockres->l_flags & OCFS2_LOCK_BUSY) { - *requeue = 1; + ctl->requeue = 1; ret = ocfs2_prepare_cancel_convert(osb, lockres); spin_unlock_irqrestore(&lockres->l_lock, flags); if (ret) { @@ -2631,7 +2754,7 @@ recheck: if ((lockres->l_blocking == LKM_EXMODE) && (lockres->l_ex_holders || lockres->l_ro_holders)) { spin_unlock_irqrestore(&lockres->l_lock, flags); - *requeue = 1; + ctl->requeue = 1; ret = 0; goto leave; } @@ -2641,7 +2764,7 @@ recheck: if (lockres->l_blocking == LKM_PRMODE && lockres->l_ex_holders) { spin_unlock_irqrestore(&lockres->l_lock, flags); - *requeue = 1; + ctl->requeue = 1; ret = 0; goto leave; } @@ -2659,7 +2782,10 @@ recheck: blocking = lockres->l_blocking; spin_unlock_irqrestore(&lockres->l_lock, flags); - worker(lockres, blocking); + ctl->unblock_action = worker(lockres, blocking); + + if (ctl->unblock_action == UNBLOCK_STOP_POST) + goto leave; spin_lock_irqsave(&lockres->l_lock, flags); if (blocking != lockres->l_blocking) { @@ -2669,7 +2795,7 @@ recheck: } downconvert: - *requeue = 0; + ctl->requeue = 0; new_level = ocfs2_highest_compat_lock_level(lockres->l_blocking); ocfs2_prepare_downconvert(lockres, new_level); @@ -2680,14 +2806,12 @@ leave: return ret; } -static void ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres, - int blocking) +static int ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres, + int blocking) { struct inode *inode; struct address_space *mapping; - mlog_entry_void(); - inode = ocfs2_lock_res_inode(lockres); mapping = inode->i_mapping; @@ -2708,11 +2832,11 @@ static void ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres, filemap_fdatawait(mapping); } - mlog_exit_void(); + return UNBLOCK_CONTINUE; } int ocfs2_unblock_data(struct ocfs2_lock_res *lockres, - int *requeue) + struct ocfs2_unblock_ctl *ctl) { int status; struct inode *inode; @@ -2726,22 +2850,20 @@ int ocfs2_unblock_data(struct ocfs2_lock_res *lockres, mlog(0, "unblock inode %llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno); - status = ocfs2_generic_unblock_lock(osb, - lockres, - requeue, + status = ocfs2_generic_unblock_lock(osb, lockres, ctl, ocfs2_data_convert_worker); if (status < 0) mlog_errno(status); mlog(0, "inode %llu, requeue = %d\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, *requeue); + (unsigned long long)OCFS2_I(inode)->ip_blkno, ctl->requeue); mlog_exit(status); return status; } static int ocfs2_unblock_inode_lock(struct ocfs2_lock_res *lockres, - int *requeue) + struct ocfs2_unblock_ctl *ctl) { int status; struct inode *inode; @@ -2753,9 +2875,7 @@ static int ocfs2_unblock_inode_lock(struct ocfs2_lock_res *lockres, inode = ocfs2_lock_res_inode(lockres); status = ocfs2_generic_unblock_lock(OCFS2_SB(inode->i_sb), - lockres, - requeue, - NULL); + lockres, ctl, NULL); if (status < 0) mlog_errno(status); @@ -2763,9 +2883,8 @@ static int ocfs2_unblock_inode_lock(struct ocfs2_lock_res *lockres, return status; } - -int ocfs2_unblock_meta(struct ocfs2_lock_res *lockres, - int *requeue) +static int ocfs2_unblock_meta(struct ocfs2_lock_res *lockres, + struct ocfs2_unblock_ctl *ctl) { int status; struct inode *inode; @@ -2777,21 +2896,165 @@ int ocfs2_unblock_meta(struct ocfs2_lock_res *lockres, mlog(0, "unblock inode %llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno); - status = ocfs2_do_unblock_meta(inode, requeue); + status = ocfs2_do_unblock_meta(inode, &ctl->requeue); if (status < 0) mlog_errno(status); mlog(0, "inode %llu, requeue = %d\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, *requeue); + (unsigned long long)OCFS2_I(inode)->ip_blkno, ctl->requeue); mlog_exit(status); return status; } +/* + * Does the final reference drop on our dentry lock. Right now this + * happens in the vote thread, but we could choose to simplify the + * dlmglue API and push these off to the ocfs2_wq in the future. + */ +static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb, + struct ocfs2_lock_res *lockres) +{ + struct ocfs2_dentry_lock *dl = ocfs2_lock_res_dl(lockres); + ocfs2_dentry_lock_put(osb, dl); +} + +/* + * d_delete() matching dentries before the lock downconvert. + * + * At this point, any process waiting to destroy the + * dentry_lock due to last ref count is stopped by the + * OCFS2_LOCK_QUEUED flag. + * + * We have two potential problems + * + * 1) If we do the last reference drop on our dentry_lock (via dput) + * we'll wind up in ocfs2_release_dentry_lock(), waiting on + * the downconvert to finish. Instead we take an elevated + * reference and push the drop until after we've completed our + * unblock processing. + * + * 2) There might be another process with a final reference, + * waiting on us to finish processing. If this is the case, we + * detect it and exit out - there's no more dentries anyway. + */ +static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres, + int blocking) +{ + struct ocfs2_dentry_lock *dl = ocfs2_lock_res_dl(lockres); + struct ocfs2_inode_info *oi = OCFS2_I(dl->dl_inode); + struct dentry *dentry; + unsigned long flags; + int extra_ref = 0; + + /* + * This node is blocking another node from getting a read + * lock. This happens when we've renamed within a + * directory. We've forced the other nodes to d_delete(), but + * we never actually dropped our lock because it's still + * valid. The downconvert code will retain a PR for this node, + * so there's no further work to do. + */ + if (blocking == LKM_PRMODE) + return UNBLOCK_CONTINUE; + + /* + * Mark this inode as potentially orphaned. The code in + * ocfs2_delete_inode() will figure out whether it actually + * needs to be freed or not. + */ + spin_lock(&oi->ip_lock); + oi->ip_flags |= OCFS2_INODE_MAYBE_ORPHANED; + spin_unlock(&oi->ip_lock); + + /* + * Yuck. We need to make sure however that the check of + * OCFS2_LOCK_FREEING and the extra reference are atomic with + * respect to a reference decrement or the setting of that + * flag. + */ + spin_lock_irqsave(&lockres->l_lock, flags); + spin_lock(&dentry_attach_lock); + if (!(lockres->l_flags & OCFS2_LOCK_FREEING) + && dl->dl_count) { + dl->dl_count++; + extra_ref = 1; + } + spin_unlock(&dentry_attach_lock); + spin_unlock_irqrestore(&lockres->l_lock, flags); + + mlog(0, "extra_ref = %d\n", extra_ref); + + /* + * We have a process waiting on us in ocfs2_dentry_iput(), + * which means we can't have any more outstanding + * aliases. There's no need to do any more work. + */ + if (!extra_ref) + return UNBLOCK_CONTINUE; + + spin_lock(&dentry_attach_lock); + while (1) { + dentry = ocfs2_find_local_alias(dl->dl_inode, + dl->dl_parent_blkno, 1); + if (!dentry) + break; + spin_unlock(&dentry_attach_lock); + + mlog(0, "d_delete(%.*s);\n", dentry->d_name.len, + dentry->d_name.name); + + /* + * The following dcache calls may do an + * iput(). Normally we don't want that from the + * downconverting thread, but in this case it's ok + * because the requesting node already has an + * exclusive lock on the inode, so it can't be queued + * for a downconvert. + */ + d_delete(dentry); + dput(dentry); + + spin_lock(&dentry_attach_lock); + } + spin_unlock(&dentry_attach_lock); + + /* + * If we are the last holder of this dentry lock, there is no + * reason to downconvert so skip straight to the unlock. + */ + if (dl->dl_count == 1) + return UNBLOCK_STOP_POST; + + return UNBLOCK_CONTINUE_POST; +} + +static int ocfs2_unblock_dentry_lock(struct ocfs2_lock_res *lockres, + struct ocfs2_unblock_ctl *ctl) +{ + int ret; + struct ocfs2_dentry_lock *dl = ocfs2_lock_res_dl(lockres); + struct ocfs2_super *osb = OCFS2_SB(dl->dl_inode->i_sb); + + mlog(0, "unblock dentry lock: %llu\n", + (unsigned long long)OCFS2_I(dl->dl_inode)->ip_blkno); + + ret = ocfs2_generic_unblock_lock(osb, + lockres, + ctl, + ocfs2_dentry_convert_worker); + if (ret < 0) + mlog_errno(ret); + + mlog(0, "requeue = %d, post = %d\n", ctl->requeue, ctl->unblock_action); + + return ret; +} + /* Generic unblock function for any lockres whose private data is an * ocfs2_super pointer. */ static int ocfs2_unblock_osb_lock(struct ocfs2_lock_res *lockres, - int *requeue) + struct ocfs2_unblock_ctl *ctl) { int status; struct ocfs2_super *osb; @@ -2804,7 +3067,7 @@ static int ocfs2_unblock_osb_lock(struct ocfs2_lock_res *lockres, status = ocfs2_generic_unblock_lock(osb, lockres, - requeue, + ctl, NULL); if (status < 0) mlog_errno(status); @@ -2817,7 +3080,7 @@ void ocfs2_process_blocked_lock(struct ocfs2_super *osb, struct ocfs2_lock_res *lockres) { int status; - int requeue = 0; + struct ocfs2_unblock_ctl ctl = {0, 0,}; unsigned long flags; /* Our reference to the lockres in this function can be @@ -2842,21 +3105,25 @@ void ocfs2_process_blocked_lock(struct ocfs2_super *osb, goto unqueue; spin_unlock_irqrestore(&lockres->l_lock, flags); - status = lockres->l_ops->unblock(lockres, &requeue); + status = lockres->l_ops->unblock(lockres, &ctl); if (status < 0) mlog_errno(status); spin_lock_irqsave(&lockres->l_lock, flags); unqueue: - if (lockres->l_flags & OCFS2_LOCK_FREEING || !requeue) { + if (lockres->l_flags & OCFS2_LOCK_FREEING || !ctl.requeue) { lockres_clear_flags(lockres, OCFS2_LOCK_QUEUED); } else ocfs2_schedule_blocked_lock(osb, lockres); mlog(0, "lockres %s, requeue = %s.\n", lockres->l_name, - requeue ? "yes" : "no"); + ctl.requeue ? "yes" : "no"); spin_unlock_irqrestore(&lockres->l_lock, flags); + if (ctl.unblock_action != UNBLOCK_CONTINUE + && lockres->l_ops->post_unlock) + lockres->l_ops->post_unlock(osb, lockres); + mlog_exit_void(); } -- cgit v1.2.3 From 4d3b83f7364269b66cdda271f680bd99e77afd96 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Tue, 12 Sep 2006 15:22:18 -0700 Subject: ocfs2: Free up some space in the lvb lvb_version doesn't need to be a whole 32 bits. Make it an 8 bit field to free up some space. This should be backwards compatible until we use one of the fields, in which case we'd bump the lvb version anyway. Signed-off-by: Mark Fasheh --- fs/ocfs2/dlmglue.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'fs/ocfs2/dlmglue.c') diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 764d15defd8..f80fb14ee81 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -1413,7 +1413,7 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode) lvb = (struct ocfs2_meta_lvb *) lockres->l_lksb.lvb; - lvb->lvb_version = cpu_to_be32(OCFS2_LVB_VERSION); + lvb->lvb_version = OCFS2_LVB_VERSION; lvb->lvb_isize = cpu_to_be64(i_size_read(inode)); lvb->lvb_iclusters = cpu_to_be32(oi->ip_clusters); lvb->lvb_iuid = cpu_to_be32(inode->i_uid); @@ -1486,7 +1486,7 @@ static inline int ocfs2_meta_lvb_is_trustable(struct ocfs2_lock_res *lockres) { struct ocfs2_meta_lvb *lvb = (struct ocfs2_meta_lvb *) lockres->l_lksb.lvb; - if (be32_to_cpu(lvb->lvb_version) == OCFS2_LVB_VERSION) + if (lvb->lvb_version == OCFS2_LVB_VERSION) return 1; return 0; } @@ -3167,7 +3167,7 @@ void ocfs2_dump_meta_lvb_info(u64 level, mlog(level, "LVB information for %s (called from %s:%u):\n", lockres->l_name, function, line); mlog(level, "version: %u, clusters: %u\n", - be32_to_cpu(lvb->lvb_version), be32_to_cpu(lvb->lvb_iclusters)); + lvb->lvb_version, be32_to_cpu(lvb->lvb_iclusters)); mlog(level, "size: %llu, uid %u, gid %u, mode 0x%x\n", (unsigned long long)be64_to_cpu(lvb->lvb_isize), be32_to_cpu(lvb->lvb_iuid), be32_to_cpu(lvb->lvb_igid), -- cgit v1.2.3 From f9e2d82e6395cfa0802446b54b63cc412089d82c Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Tue, 12 Sep 2006 15:35:49 -0700 Subject: ocfs2: Encode i_generation in the meta data lvb When i_generation is removed from the lockname, this will help us determine whether a meta data lvb has information that is in sync with the local struct inode. Signed-off-by: Mark Fasheh --- fs/ocfs2/dlmglue.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'fs/ocfs2/dlmglue.c') diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index f80fb14ee81..6cd84dffbbf 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -1427,6 +1427,7 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode) lvb->lvb_imtime_packed = cpu_to_be64(ocfs2_pack_timespec(&inode->i_mtime)); lvb->lvb_iattr = cpu_to_be32(oi->ip_attr); + lvb->lvb_igeneration = cpu_to_be32(inode->i_generation); mlog_meta_lvb(0, lockres); @@ -1482,11 +1483,13 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode) mlog_exit_void(); } -static inline int ocfs2_meta_lvb_is_trustable(struct ocfs2_lock_res *lockres) +static inline int ocfs2_meta_lvb_is_trustable(struct inode *inode, + struct ocfs2_lock_res *lockres) { struct ocfs2_meta_lvb *lvb = (struct ocfs2_meta_lvb *) lockres->l_lksb.lvb; - if (lvb->lvb_version == OCFS2_LVB_VERSION) + if (lvb->lvb_version == OCFS2_LVB_VERSION + && be32_to_cpu(lvb->lvb_igeneration) == inode->i_generation) return 1; return 0; } @@ -1583,7 +1586,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(lockres)) { + if (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); @@ -3166,8 +3169,9 @@ void ocfs2_dump_meta_lvb_info(u64 level, mlog(level, "LVB information for %s (called from %s:%u):\n", lockres->l_name, function, line); - mlog(level, "version: %u, clusters: %u\n", - lvb->lvb_version, be32_to_cpu(lvb->lvb_iclusters)); + mlog(level, "version: %u, clusters: %u, generation: 0x%x\n", + lvb->lvb_version, be32_to_cpu(lvb->lvb_iclusters), + be32_to_cpu(lvb->lvb_igeneration)); mlog(level, "size: %llu, uid %u, gid %u, mode 0x%x\n", (unsigned long long)be64_to_cpu(lvb->lvb_isize), be32_to_cpu(lvb->lvb_iuid), be32_to_cpu(lvb->lvb_igid), -- cgit v1.2.3 From 24c19ef40474c3930597f31ae233dc06319bd881 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Fri, 22 Sep 2006 17:28:19 -0700 Subject: ocfs2: Remove i_generation from inode lock names OCFS2 puts inode meta data in the "lock value block" provided by the DLM. Typically, i_generation is encoded in the lock name so that a deleted inode on and a new one in the same block don't share the same lvb. Unfortunately, that scheme means that the read in ocfs2_read_locked_inode() is potentially thrown away as soon as the meta data lock is taken - we cannot encode the lock name without first knowing i_generation, which requires a disk read. This patch encodes i_generation in the inode meta data lvb, and removes the value from the inode meta data lock name. This way, the read can be covered by a lock, and at the same time we can distinguish between an up to date and a stale LVB. This will help cold-cache stat(2) performance in particular. Since this patch changes the protocol version, we take the opportunity to do a minor re-organization of two of the LVB fields. Signed-off-by: Mark Fasheh --- fs/ocfs2/dlmglue.c | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) (limited to 'fs/ocfs2/dlmglue.c') diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 6cd84dffbbf..ecb3cba2281 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -320,6 +320,7 @@ void ocfs2_lock_res_init_once(struct ocfs2_lock_res *res) void ocfs2_inode_lock_res_init(struct ocfs2_lock_res *res, enum ocfs2_lock_type type, + unsigned int generation, struct inode *inode) { struct ocfs2_lock_res_ops *ops; @@ -341,7 +342,7 @@ void ocfs2_inode_lock_res_init(struct ocfs2_lock_res *res, }; ocfs2_build_lock_name(type, OCFS2_I(inode)->ip_blkno, - inode->i_generation, res->l_name); + generation, res->l_name); ocfs2_lock_res_init_common(OCFS2_SB(inode->i_sb), res, type, ops, inode); } @@ -1173,17 +1174,19 @@ static void ocfs2_cluster_unlock(struct ocfs2_super *osb, int ocfs2_create_new_lock(struct ocfs2_super *osb, struct ocfs2_lock_res *lockres, - int ex) + int ex, + int local) { int level = ex ? LKM_EXMODE : LKM_PRMODE; unsigned long flags; + int lkm_flags = local ? LKM_LOCAL : 0; spin_lock_irqsave(&lockres->l_lock, flags); BUG_ON(lockres->l_flags & OCFS2_LOCK_ATTACHED); lockres_or_flags(lockres, OCFS2_LOCK_LOCAL); spin_unlock_irqrestore(&lockres->l_lock, flags); - return ocfs2_lock_create(osb, lockres, level, LKM_LOCAL); + return ocfs2_lock_create(osb, lockres, level, lkm_flags); } /* Grants us an EX lock on the data and metadata resources, skipping @@ -1212,19 +1215,23 @@ int ocfs2_create_new_inode_locks(struct inode *inode) * on a resource which has an invalid one -- we'll set it * valid when we release the EX. */ - ret = ocfs2_create_new_lock(osb, &OCFS2_I(inode)->ip_rw_lockres, 1); + ret = ocfs2_create_new_lock(osb, &OCFS2_I(inode)->ip_rw_lockres, 1, 1); if (ret) { mlog_errno(ret); goto bail; } - ret = ocfs2_create_new_lock(osb, &OCFS2_I(inode)->ip_meta_lockres, 1); + /* + * We don't want to use LKM_LOCAL on a meta data lock as they + * don't use a generation in their lock names. + */ + ret = ocfs2_create_new_lock(osb, &OCFS2_I(inode)->ip_meta_lockres, 1, 0); if (ret) { mlog_errno(ret); goto bail; } - ret = ocfs2_create_new_lock(osb, &OCFS2_I(inode)->ip_data_lockres, 1); + ret = ocfs2_create_new_lock(osb, &OCFS2_I(inode)->ip_data_lockres, 1, 1); if (ret) { mlog_errno(ret); goto bail; @@ -1413,6 +1420,16 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode) lvb = (struct ocfs2_meta_lvb *) lockres->l_lksb.lvb; + /* + * Invalidate the LVB of a deleted inode - this way other + * nodes are forced to go to disk and discover the new inode + * status. + */ + if (oi->ip_flags & OCFS2_INODE_DELETED) { + lvb->lvb_version = 0; + goto out; + } + lvb->lvb_version = OCFS2_LVB_VERSION; lvb->lvb_isize = cpu_to_be64(i_size_read(inode)); lvb->lvb_iclusters = cpu_to_be32(oi->ip_clusters); @@ -1429,6 +1446,7 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode) lvb->lvb_iattr = cpu_to_be32(oi->ip_attr); lvb->lvb_igeneration = cpu_to_be32(inode->i_generation); +out: mlog_meta_lvb(0, lockres); mlog_exit_void(); @@ -1727,6 +1745,18 @@ int ocfs2_meta_lock_full(struct inode *inode, wait_event(osb->recovery_event, ocfs2_node_map_is_empty(osb, &osb->recovery_map)); + /* + * We only see this flag if we're being called from + * ocfs2_read_locked_inode(). It means we're locking an inode + * which hasn't been populated yet, so clear the refresh flag + * and let the caller handle it. + */ + if (inode->i_state & I_NEW) { + status = 0; + ocfs2_complete_lock_res_refresh(lockres, 0); + goto bail; + } + /* This is fun. The caller may want a bh back, or it may * not. ocfs2_meta_lock_update definitely wants one in, but * may or may not read one, depending on what's in the -- cgit v1.2.3 From f625c9793b6cc64aeb1b6387039d09019c214352 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Tue, 12 Sep 2006 21:24:53 -0700 Subject: ocfs2: Clean up lock resource refresh flags Use of the refresh mechanism is lock-type wide, so move knowledge of that to the ocfs2_lock_res_ops structure. Signed-off-by: Mark Fasheh --- fs/ocfs2/dlmglue.c | 49 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 14 deletions(-) (limited to 'fs/ocfs2/dlmglue.c') diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index ecb3cba2281..c1891787fb9 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -117,14 +117,35 @@ static int ocfs2_unblock_osb_lock(struct ocfs2_lock_res *lockres, static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb, struct ocfs2_lock_res *lockres); +/* + * OCFS2 Lock Resource Operations + * + * These fine tune the behavior of the generic dlmglue locking infrastructure. + */ struct ocfs2_lock_res_ops { void (*ast)(void *); void (*bast)(void *, int); void (*unlock_ast)(void *, enum dlm_status); int (*unblock)(struct ocfs2_lock_res *, struct ocfs2_unblock_ctl *); void (*post_unlock)(struct ocfs2_super *, struct ocfs2_lock_res *); + + /* + * LOCK_TYPE_* flags which describe the specific requirements + * of a lock type. Descriptions of each individual flag follow. + */ + int flags; }; +/* + * Some locks want to "refresh" potentially stale data when a + * meaningful (PRMODE or EXMODE) lock level is first obtained. If this + * flag is set, the OCFS2_LOCK_NEEDS_REFRESH flag will be set on the + * individual lockres l_flags member from the ast function. It is + * expected that the locking wrapper will clear the + * OCFS2_LOCK_NEEDS_REFRESH flag when done. + */ +#define LOCK_TYPE_REQUIRES_REFRESH 0x1 + typedef int (ocfs2_convert_worker_t)(struct ocfs2_lock_res *, int); static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, struct ocfs2_lock_res *lockres, @@ -136,6 +157,7 @@ static struct ocfs2_lock_res_ops ocfs2_inode_rw_lops = { .bast = ocfs2_inode_bast_func, .unlock_ast = ocfs2_unlock_ast_func, .unblock = ocfs2_unblock_inode_lock, + .flags = 0, }; static struct ocfs2_lock_res_ops ocfs2_inode_meta_lops = { @@ -143,6 +165,7 @@ static struct ocfs2_lock_res_ops ocfs2_inode_meta_lops = { .bast = ocfs2_inode_bast_func, .unlock_ast = ocfs2_unlock_ast_func, .unblock = ocfs2_unblock_meta, + .flags = LOCK_TYPE_REQUIRES_REFRESH, }; static struct ocfs2_lock_res_ops ocfs2_inode_data_lops = { @@ -150,6 +173,7 @@ static struct ocfs2_lock_res_ops ocfs2_inode_data_lops = { .bast = ocfs2_inode_bast_func, .unlock_ast = ocfs2_unlock_ast_func, .unblock = ocfs2_unblock_data, + .flags = 0, }; static struct ocfs2_lock_res_ops ocfs2_super_lops = { @@ -157,6 +181,7 @@ static struct ocfs2_lock_res_ops ocfs2_super_lops = { .bast = ocfs2_super_bast_func, .unlock_ast = ocfs2_unlock_ast_func, .unblock = ocfs2_unblock_osb_lock, + .flags = LOCK_TYPE_REQUIRES_REFRESH, }; static struct ocfs2_lock_res_ops ocfs2_rename_lops = { @@ -164,6 +189,7 @@ static struct ocfs2_lock_res_ops ocfs2_rename_lops = { .bast = ocfs2_rename_bast_func, .unlock_ast = ocfs2_unlock_ast_func, .unblock = ocfs2_unblock_osb_lock, + .flags = 0, }; static struct ocfs2_lock_res_ops ocfs2_dentry_lops = { @@ -172,6 +198,7 @@ static struct ocfs2_lock_res_ops ocfs2_dentry_lops = { .unlock_ast = ocfs2_unlock_ast_func, .unblock = ocfs2_unblock_dentry_lock, .post_unlock = ocfs2_dentry_post_unlock, + .flags = 0, }; static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres) @@ -569,7 +596,8 @@ static inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lo * information is already up to data. Convert from NL to * *anything* however should mark ourselves as needing an * update */ - if (lockres->l_level == LKM_NLMODE) + if (lockres->l_level == LKM_NLMODE && + lockres->l_ops->flags & LOCK_TYPE_REQUIRES_REFRESH) lockres_or_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH); lockres->l_level = lockres->l_requested; @@ -586,7 +614,8 @@ static inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *loc BUG_ON(lockres->l_flags & OCFS2_LOCK_ATTACHED); if (lockres->l_requested > LKM_NLMODE && - !(lockres->l_flags & OCFS2_LOCK_LOCAL)) + !(lockres->l_flags & OCFS2_LOCK_LOCAL) && + lockres->l_ops->flags & LOCK_TYPE_REQUIRES_REFRESH) lockres_or_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH); lockres->l_level = lockres->l_requested; @@ -645,10 +674,6 @@ static void ocfs2_inode_ast_func(void *opaque) BUG(); } - /* data and rw locking ignores refresh flag for now. */ - if (lockres->l_type != OCFS2_LOCK_TYPE_META) - lockres_clear_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH); - /* set it to something invalid so if we get called again we * can catch it. */ lockres->l_action = OCFS2_AST_INVALID; @@ -730,8 +755,7 @@ static void ocfs2_inode_bast_func(void *opaque, int level) mlog_exit_void(); } -static void ocfs2_generic_ast_func(struct ocfs2_lock_res *lockres, - int ignore_refresh) +static void ocfs2_generic_ast_func(struct ocfs2_lock_res *lockres) { struct dlm_lockstatus *lksb = &lockres->l_lksb; unsigned long flags; @@ -759,9 +783,6 @@ static void ocfs2_generic_ast_func(struct ocfs2_lock_res *lockres, BUG(); } - if (ignore_refresh) - lockres_clear_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH); - /* set it to something invalid so if we get called again we * can catch it. */ lockres->l_action = OCFS2_AST_INVALID; @@ -778,7 +799,7 @@ static void ocfs2_super_ast_func(void *opaque) mlog(0, "Superblock AST fired\n"); BUG_ON(!ocfs2_is_super_lock(lockres)); - ocfs2_generic_ast_func(lockres, 0); + ocfs2_generic_ast_func(lockres); mlog_exit_void(); } @@ -809,7 +830,7 @@ static void ocfs2_rename_ast_func(void *opaque) BUG_ON(!ocfs2_is_rename_lock(lockres)); - ocfs2_generic_ast_func(lockres, 1); + ocfs2_generic_ast_func(lockres); mlog_exit_void(); } @@ -838,7 +859,7 @@ static void ocfs2_dentry_ast_func(void *opaque) BUG_ON(!lockres); - ocfs2_generic_ast_func(lockres, 1); + ocfs2_generic_ast_func(lockres); } static void ocfs2_dentry_bast_func(void *opaque, int level) -- cgit v1.2.3 From e92d57df273a3a7e57688e1d4f5a894870d550d2 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Tue, 12 Sep 2006 21:34:35 -0700 Subject: ocfs2: combine inode and generic AST functions There is extremely little difference between the two now. We can remove the callback from ocfs2_lock_res_ops as well. Signed-off-by: Mark Fasheh --- fs/ocfs2/dlmglue.c | 120 +++++------------------------------------------------ 1 file changed, 10 insertions(+), 110 deletions(-) (limited to 'fs/ocfs2/dlmglue.c') diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index c1891787fb9..7eb40a02c5a 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -67,16 +67,12 @@ struct ocfs2_mask_waiter { unsigned long mw_goal; }; -static void ocfs2_inode_ast_func(void *opaque); static void ocfs2_inode_bast_func(void *opaque, int level); -static void ocfs2_dentry_ast_func(void *opaque); static void ocfs2_dentry_bast_func(void *opaque, int level); -static void ocfs2_super_ast_func(void *opaque); static void ocfs2_super_bast_func(void *opaque, int level); -static void ocfs2_rename_ast_func(void *opaque); static void ocfs2_rename_bast_func(void *opaque, int level); @@ -123,7 +119,6 @@ static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb, * These fine tune the behavior of the generic dlmglue locking infrastructure. */ struct ocfs2_lock_res_ops { - void (*ast)(void *); void (*bast)(void *, int); void (*unlock_ast)(void *, enum dlm_status); int (*unblock)(struct ocfs2_lock_res *, struct ocfs2_unblock_ctl *); @@ -153,7 +148,6 @@ static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, ocfs2_convert_worker_t *worker); static struct ocfs2_lock_res_ops ocfs2_inode_rw_lops = { - .ast = ocfs2_inode_ast_func, .bast = ocfs2_inode_bast_func, .unlock_ast = ocfs2_unlock_ast_func, .unblock = ocfs2_unblock_inode_lock, @@ -161,7 +155,6 @@ static struct ocfs2_lock_res_ops ocfs2_inode_rw_lops = { }; static struct ocfs2_lock_res_ops ocfs2_inode_meta_lops = { - .ast = ocfs2_inode_ast_func, .bast = ocfs2_inode_bast_func, .unlock_ast = ocfs2_unlock_ast_func, .unblock = ocfs2_unblock_meta, @@ -169,7 +162,6 @@ static struct ocfs2_lock_res_ops ocfs2_inode_meta_lops = { }; static struct ocfs2_lock_res_ops ocfs2_inode_data_lops = { - .ast = ocfs2_inode_ast_func, .bast = ocfs2_inode_bast_func, .unlock_ast = ocfs2_unlock_ast_func, .unblock = ocfs2_unblock_data, @@ -177,7 +169,6 @@ static struct ocfs2_lock_res_ops ocfs2_inode_data_lops = { }; static struct ocfs2_lock_res_ops ocfs2_super_lops = { - .ast = ocfs2_super_ast_func, .bast = ocfs2_super_bast_func, .unlock_ast = ocfs2_unlock_ast_func, .unblock = ocfs2_unblock_osb_lock, @@ -185,7 +176,6 @@ static struct ocfs2_lock_res_ops ocfs2_super_lops = { }; static struct ocfs2_lock_res_ops ocfs2_rename_lops = { - .ast = ocfs2_rename_ast_func, .bast = ocfs2_rename_bast_func, .unlock_ast = ocfs2_unlock_ast_func, .unblock = ocfs2_unblock_osb_lock, @@ -193,7 +183,6 @@ static struct ocfs2_lock_res_ops ocfs2_rename_lops = { }; static struct ocfs2_lock_res_ops ocfs2_dentry_lops = { - .ast = ocfs2_dentry_ast_func, .bast = ocfs2_dentry_bast_func, .unlock_ast = ocfs2_unlock_ast_func, .unblock = ocfs2_unblock_dentry_lock, @@ -625,64 +614,6 @@ static inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *loc mlog_exit_void(); } -static void ocfs2_inode_ast_func(void *opaque) -{ - struct ocfs2_lock_res *lockres = opaque; - struct inode *inode; - struct dlm_lockstatus *lksb; - unsigned long flags; - - mlog_entry_void(); - - inode = ocfs2_lock_res_inode(lockres); - - mlog(0, "AST fired for inode %llu, l_action = %u, type = %s\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, lockres->l_action, - ocfs2_lock_type_string(lockres->l_type)); - - BUG_ON(!ocfs2_is_inode_lock(lockres)); - - spin_lock_irqsave(&lockres->l_lock, flags); - - lksb = &(lockres->l_lksb); - if (lksb->status != DLM_NORMAL) { - mlog(ML_ERROR, "ocfs2_inode_ast_func: lksb status value of %u " - "on inode %llu\n", lksb->status, - (unsigned long long)OCFS2_I(inode)->ip_blkno); - spin_unlock_irqrestore(&lockres->l_lock, flags); - mlog_exit_void(); - return; - } - - switch(lockres->l_action) { - case OCFS2_AST_ATTACH: - ocfs2_generic_handle_attach_action(lockres); - lockres_clear_flags(lockres, OCFS2_LOCK_LOCAL); - break; - case OCFS2_AST_CONVERT: - ocfs2_generic_handle_convert_action(lockres); - break; - case OCFS2_AST_DOWNCONVERT: - ocfs2_generic_handle_downconvert_action(lockres); - break; - default: - mlog(ML_ERROR, "lockres %s: ast fired with invalid action: %u " - "lockres flags = 0x%lx, unlock action: %u\n", - lockres->l_name, lockres->l_action, lockres->l_flags, - lockres->l_unlock_action); - - BUG(); - } - - /* set it to something invalid so if we get called again we - * can catch it. */ - lockres->l_action = OCFS2_AST_INVALID; - spin_unlock_irqrestore(&lockres->l_lock, flags); - wake_up(&lockres->l_event); - - mlog_exit_void(); -} - static int ocfs2_generic_handle_bast(struct ocfs2_lock_res *lockres, int level) { @@ -755,8 +686,9 @@ static void ocfs2_inode_bast_func(void *opaque, int level) mlog_exit_void(); } -static void ocfs2_generic_ast_func(struct ocfs2_lock_res *lockres) +static void ocfs2_locking_ast(void *opaque) { + struct ocfs2_lock_res *lockres = opaque; struct dlm_lockstatus *lksb = &lockres->l_lksb; unsigned long flags; @@ -772,6 +704,7 @@ static void ocfs2_generic_ast_func(struct ocfs2_lock_res *lockres) switch(lockres->l_action) { case OCFS2_AST_ATTACH: ocfs2_generic_handle_attach_action(lockres); + lockres_clear_flags(lockres, OCFS2_LOCK_LOCAL); break; case OCFS2_AST_CONVERT: ocfs2_generic_handle_convert_action(lockres); @@ -780,6 +713,10 @@ static void ocfs2_generic_ast_func(struct ocfs2_lock_res *lockres) ocfs2_generic_handle_downconvert_action(lockres); break; default: + mlog(ML_ERROR, "lockres %s: ast fired with invalid action: %u " + "lockres flags = 0x%lx, unlock action: %u\n", + lockres->l_name, lockres->l_action, lockres->l_flags, + lockres->l_unlock_action); BUG(); } @@ -791,19 +728,6 @@ static void ocfs2_generic_ast_func(struct ocfs2_lock_res *lockres) spin_unlock_irqrestore(&lockres->l_lock, flags); } -static void ocfs2_super_ast_func(void *opaque) -{ - struct ocfs2_lock_res *lockres = opaque; - - mlog_entry_void(); - mlog(0, "Superblock AST fired\n"); - - BUG_ON(!ocfs2_is_super_lock(lockres)); - ocfs2_generic_ast_func(lockres); - - mlog_exit_void(); -} - static void ocfs2_super_bast_func(void *opaque, int level) { @@ -820,21 +744,6 @@ static void ocfs2_super_bast_func(void *opaque, mlog_exit_void(); } -static void ocfs2_rename_ast_func(void *opaque) -{ - struct ocfs2_lock_res *lockres = opaque; - - mlog_entry_void(); - - mlog(0, "Rename AST fired\n"); - - BUG_ON(!ocfs2_is_rename_lock(lockres)); - - ocfs2_generic_ast_func(lockres); - - mlog_exit_void(); -} - static void ocfs2_rename_bast_func(void *opaque, int level) { @@ -853,15 +762,6 @@ static void ocfs2_rename_bast_func(void *opaque, mlog_exit_void(); } -static void ocfs2_dentry_ast_func(void *opaque) -{ - struct ocfs2_lock_res *lockres = opaque; - - BUG_ON(!lockres); - - ocfs2_generic_ast_func(lockres); -} - static void ocfs2_dentry_bast_func(void *opaque, int level) { struct ocfs2_lock_res *lockres = opaque; @@ -928,7 +828,7 @@ static int ocfs2_lock_create(struct ocfs2_super *osb, dlm_flags, lockres->l_name, OCFS2_LOCK_ID_MAX_LEN - 1, - lockres->l_ops->ast, + ocfs2_locking_ast, lockres, lockres->l_ops->bast); if (status != DLM_NORMAL) { @@ -1118,7 +1018,7 @@ again: lkm_flags|LKM_CONVERT|LKM_VALBLK, lockres->l_name, OCFS2_LOCK_ID_MAX_LEN - 1, - lockres->l_ops->ast, + ocfs2_locking_ast, lockres, lockres->l_ops->bast); if (status != DLM_NORMAL) { @@ -2599,7 +2499,7 @@ static int ocfs2_downconvert_lock(struct ocfs2_super *osb, dlm_flags, lockres->l_name, OCFS2_LOCK_ID_MAX_LEN - 1, - lockres->l_ops->ast, + ocfs2_locking_ast, lockres, lockres->l_ops->bast); if (status != DLM_NORMAL) { -- cgit v1.2.3 From 2a45f2d13e1dd91bc110801f5818379f2699509c Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Tue, 12 Sep 2006 21:36:58 -0700 Subject: ocfs2: remove ->unlock_ast() callback from ocfs2_lock_res_ops This was always defined to the same function in all locks, so clean things up by removing and passing ocfs2_unlock_ast() directly to the DLM. Signed-off-by: Mark Fasheh --- fs/ocfs2/dlmglue.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'fs/ocfs2/dlmglue.c') diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 7eb40a02c5a..7532f80b87b 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -96,9 +96,6 @@ struct ocfs2_unblock_ctl { enum ocfs2_unblock_action unblock_action; }; -/* so far, all locks have gotten along with the same unlock ast */ -static void ocfs2_unlock_ast_func(void *opaque, - enum dlm_status status); static int ocfs2_unblock_meta(struct ocfs2_lock_res *lockres, struct ocfs2_unblock_ctl *ctl); static int ocfs2_unblock_data(struct ocfs2_lock_res *lockres, @@ -120,7 +117,6 @@ static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb, */ struct ocfs2_lock_res_ops { void (*bast)(void *, int); - void (*unlock_ast)(void *, enum dlm_status); int (*unblock)(struct ocfs2_lock_res *, struct ocfs2_unblock_ctl *); void (*post_unlock)(struct ocfs2_super *, struct ocfs2_lock_res *); @@ -149,42 +145,36 @@ static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, static struct ocfs2_lock_res_ops ocfs2_inode_rw_lops = { .bast = ocfs2_inode_bast_func, - .unlock_ast = ocfs2_unlock_ast_func, .unblock = ocfs2_unblock_inode_lock, .flags = 0, }; static struct ocfs2_lock_res_ops ocfs2_inode_meta_lops = { .bast = ocfs2_inode_bast_func, - .unlock_ast = ocfs2_unlock_ast_func, .unblock = ocfs2_unblock_meta, .flags = LOCK_TYPE_REQUIRES_REFRESH, }; static struct ocfs2_lock_res_ops ocfs2_inode_data_lops = { .bast = ocfs2_inode_bast_func, - .unlock_ast = ocfs2_unlock_ast_func, .unblock = ocfs2_unblock_data, .flags = 0, }; static struct ocfs2_lock_res_ops ocfs2_super_lops = { .bast = ocfs2_super_bast_func, - .unlock_ast = ocfs2_unlock_ast_func, .unblock = ocfs2_unblock_osb_lock, .flags = LOCK_TYPE_REQUIRES_REFRESH, }; static struct ocfs2_lock_res_ops ocfs2_rename_lops = { .bast = ocfs2_rename_bast_func, - .unlock_ast = ocfs2_unlock_ast_func, .unblock = ocfs2_unblock_osb_lock, .flags = 0, }; static struct ocfs2_lock_res_ops ocfs2_dentry_lops = { .bast = ocfs2_dentry_bast_func, - .unlock_ast = ocfs2_unlock_ast_func, .unblock = ocfs2_unblock_dentry_lock, .post_unlock = ocfs2_dentry_post_unlock, .flags = 0, @@ -2221,7 +2211,7 @@ void ocfs2_dlm_shutdown(struct ocfs2_super *osb) mlog_exit_void(); } -static void ocfs2_unlock_ast_func(void *opaque, enum dlm_status status) +static void ocfs2_unlock_ast(void *opaque, enum dlm_status status) { struct ocfs2_lock_res *lockres = opaque; unsigned long flags; @@ -2345,7 +2335,7 @@ static int ocfs2_drop_lock(struct ocfs2_super *osb, mlog(0, "lock %s\n", lockres->l_name); status = dlmunlock(osb->dlm, &lockres->l_lksb, LKM_VALBLK, - lockres->l_ops->unlock_ast, lockres); + ocfs2_unlock_ast, lockres); if (status != DLM_NORMAL) { ocfs2_log_dlm_error("dlmunlock", status, lockres); mlog(ML_ERROR, "lockres flags: %lu\n", lockres->l_flags); @@ -2560,7 +2550,7 @@ static int ocfs2_cancel_convert(struct ocfs2_super *osb, status = dlmunlock(osb->dlm, &lockres->l_lksb, LKM_CANCEL, - lockres->l_ops->unlock_ast, + ocfs2_unlock_ast, lockres); if (status != DLM_NORMAL) { ocfs2_log_dlm_error("dlmunlock", status, lockres); -- cgit v1.2.3 From 54a7e7552e484c08db221e49c4519ccdeb8882d0 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Tue, 12 Sep 2006 21:49:13 -0700 Subject: ocfs2: Add ->get_osb() dlmglue locking operation Will be used to find the ocfs2_super structure from a given lockres. Signed-off-by: Mark Fasheh --- fs/ocfs2/dlmglue.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'fs/ocfs2/dlmglue.c') diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 7532f80b87b..2e4d43a5465 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -75,6 +75,8 @@ static void ocfs2_super_bast_func(void *opaque, int level); static void ocfs2_rename_bast_func(void *opaque, int level); +static struct ocfs2_super *ocfs2_get_dentry_osb(struct ocfs2_lock_res *lockres); +static struct ocfs2_super *ocfs2_get_inode_osb(struct ocfs2_lock_res *lockres); /* * Return value from ocfs2_convert_worker_t functions. @@ -116,6 +118,11 @@ static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb, * These fine tune the behavior of the generic dlmglue locking infrastructure. */ struct ocfs2_lock_res_ops { + /* + * Translate an ocfs2_lock_res * into an ocfs2_super *. Define + * this callback if ->l_priv is not an ocfs2_super pointer + */ + struct ocfs2_super * (*get_osb)(struct ocfs2_lock_res *); void (*bast)(void *, int); int (*unblock)(struct ocfs2_lock_res *, struct ocfs2_unblock_ctl *); void (*post_unlock)(struct ocfs2_super *, struct ocfs2_lock_res *); @@ -144,18 +151,21 @@ static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, ocfs2_convert_worker_t *worker); static struct ocfs2_lock_res_ops ocfs2_inode_rw_lops = { + .get_osb = ocfs2_get_inode_osb, .bast = ocfs2_inode_bast_func, .unblock = ocfs2_unblock_inode_lock, .flags = 0, }; static struct ocfs2_lock_res_ops ocfs2_inode_meta_lops = { + .get_osb = ocfs2_get_inode_osb, .bast = ocfs2_inode_bast_func, .unblock = ocfs2_unblock_meta, .flags = LOCK_TYPE_REQUIRES_REFRESH, }; static struct ocfs2_lock_res_ops ocfs2_inode_data_lops = { + .get_osb = ocfs2_get_inode_osb, .bast = ocfs2_inode_bast_func, .unblock = ocfs2_unblock_data, .flags = 0, @@ -174,6 +184,7 @@ static struct ocfs2_lock_res_ops ocfs2_rename_lops = { }; static struct ocfs2_lock_res_ops ocfs2_dentry_lops = { + .get_osb = ocfs2_get_dentry_osb, .bast = ocfs2_dentry_bast_func, .unblock = ocfs2_unblock_dentry_lock, .post_unlock = ocfs2_dentry_post_unlock, @@ -219,6 +230,14 @@ static inline struct ocfs2_dentry_lock *ocfs2_lock_res_dl(struct ocfs2_lock_res return (struct ocfs2_dentry_lock *)lockres->l_priv; } +static inline struct ocfs2_super *ocfs2_get_lockres_osb(struct ocfs2_lock_res *lockres) +{ + if (lockres->l_ops->get_osb) + return lockres->l_ops->get_osb(lockres); + + return (struct ocfs2_super *)lockres->l_priv; +} + static int ocfs2_lock_create(struct ocfs2_super *osb, struct ocfs2_lock_res *lockres, int level, @@ -352,6 +371,13 @@ void ocfs2_inode_lock_res_init(struct ocfs2_lock_res *res, ocfs2_lock_res_init_common(OCFS2_SB(inode->i_sb), res, type, ops, inode); } +static struct ocfs2_super *ocfs2_get_inode_osb(struct ocfs2_lock_res *lockres) +{ + struct inode *inode = ocfs2_lock_res_inode(lockres); + + return OCFS2_SB(inode->i_sb); +} + static __u64 ocfs2_get_dentry_lock_ino(struct ocfs2_lock_res *lockres) { __be64 inode_blkno_be; @@ -362,6 +388,13 @@ static __u64 ocfs2_get_dentry_lock_ino(struct ocfs2_lock_res *lockres) return be64_to_cpu(inode_blkno_be); } +static struct ocfs2_super *ocfs2_get_dentry_osb(struct ocfs2_lock_res *lockres) +{ + struct ocfs2_dentry_lock *dl = lockres->l_priv; + + return OCFS2_SB(dl->dl_inode->i_sb); +} + void ocfs2_dentry_lock_res_init(struct ocfs2_dentry_lock *dl, u64 parent, struct inode *inode) { -- cgit v1.2.3 From aa2623ad80577b37637914e809bafa36994ccdf1 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Tue, 12 Sep 2006 21:58:23 -0700 Subject: ocfs2: combine inode and generic blocking AST functions There is extremely little difference between the two now. We can remove the callback from ocfs2_lock_res_ops as well. Signed-off-by: Mark Fasheh --- fs/ocfs2/dlmglue.c | 123 +++++------------------------------------------------ 1 file changed, 11 insertions(+), 112 deletions(-) (limited to 'fs/ocfs2/dlmglue.c') diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 2e4d43a5465..3d5c6a0eb9e 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -67,14 +67,6 @@ struct ocfs2_mask_waiter { unsigned long mw_goal; }; -static void ocfs2_inode_bast_func(void *opaque, - int level); -static void ocfs2_dentry_bast_func(void *opaque, - int level); -static void ocfs2_super_bast_func(void *opaque, - int level); -static void ocfs2_rename_bast_func(void *opaque, - int level); static struct ocfs2_super *ocfs2_get_dentry_osb(struct ocfs2_lock_res *lockres); static struct ocfs2_super *ocfs2_get_inode_osb(struct ocfs2_lock_res *lockres); @@ -123,7 +115,6 @@ struct ocfs2_lock_res_ops { * this callback if ->l_priv is not an ocfs2_super pointer */ struct ocfs2_super * (*get_osb)(struct ocfs2_lock_res *); - void (*bast)(void *, int); int (*unblock)(struct ocfs2_lock_res *, struct ocfs2_unblock_ctl *); void (*post_unlock)(struct ocfs2_super *, struct ocfs2_lock_res *); @@ -152,40 +143,34 @@ static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, static struct ocfs2_lock_res_ops ocfs2_inode_rw_lops = { .get_osb = ocfs2_get_inode_osb, - .bast = ocfs2_inode_bast_func, .unblock = ocfs2_unblock_inode_lock, .flags = 0, }; static struct ocfs2_lock_res_ops ocfs2_inode_meta_lops = { .get_osb = ocfs2_get_inode_osb, - .bast = ocfs2_inode_bast_func, .unblock = ocfs2_unblock_meta, .flags = LOCK_TYPE_REQUIRES_REFRESH, }; static struct ocfs2_lock_res_ops ocfs2_inode_data_lops = { .get_osb = ocfs2_get_inode_osb, - .bast = ocfs2_inode_bast_func, .unblock = ocfs2_unblock_data, .flags = 0, }; static struct ocfs2_lock_res_ops ocfs2_super_lops = { - .bast = ocfs2_super_bast_func, .unblock = ocfs2_unblock_osb_lock, .flags = LOCK_TYPE_REQUIRES_REFRESH, }; static struct ocfs2_lock_res_ops ocfs2_rename_lops = { - .bast = ocfs2_rename_bast_func, .unblock = ocfs2_unblock_osb_lock, .flags = 0, }; static struct ocfs2_lock_res_ops ocfs2_dentry_lops = { .get_osb = ocfs2_get_dentry_osb, - .bast = ocfs2_dentry_bast_func, .unblock = ocfs2_unblock_dentry_lock, .post_unlock = ocfs2_dentry_post_unlock, .flags = 0, @@ -198,24 +183,6 @@ static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres) lockres->l_type == OCFS2_LOCK_TYPE_RW; } -static inline int ocfs2_is_super_lock(struct ocfs2_lock_res *lockres) -{ - return lockres->l_type == OCFS2_LOCK_TYPE_SUPER; -} - -static inline int ocfs2_is_rename_lock(struct ocfs2_lock_res *lockres) -{ - return lockres->l_type == OCFS2_LOCK_TYPE_RENAME; -} - -static inline struct ocfs2_super *ocfs2_lock_res_super(struct ocfs2_lock_res *lockres) -{ - BUG_ON(!ocfs2_is_super_lock(lockres) - && !ocfs2_is_rename_lock(lockres)); - - return (struct ocfs2_super *) lockres->l_priv; -} - static inline struct inode *ocfs2_lock_res_inode(struct ocfs2_lock_res *lockres) { BUG_ON(!ocfs2_is_inode_lock(lockres)); @@ -663,17 +630,19 @@ static int ocfs2_generic_handle_bast(struct ocfs2_lock_res *lockres, return needs_downconvert; } -static void ocfs2_generic_bast_func(struct ocfs2_super *osb, - struct ocfs2_lock_res *lockres, - int level) +static void ocfs2_blocking_ast(void *opaque, int level) { + struct ocfs2_lock_res *lockres = opaque; + struct ocfs2_super *osb = ocfs2_get_lockres_osb(lockres); int needs_downconvert; unsigned long flags; - mlog_entry_void(); - BUG_ON(level <= LKM_NLMODE); + mlog(0, "BAST fired for lockres %s, blocking %d, level %d type %s\n", + lockres->l_name, level, lockres->l_level, + ocfs2_lock_type_string(lockres->l_type)); + spin_lock_irqsave(&lockres->l_lock, flags); needs_downconvert = ocfs2_generic_handle_bast(lockres, level); if (needs_downconvert) @@ -683,30 +652,6 @@ static void ocfs2_generic_bast_func(struct ocfs2_super *osb, wake_up(&lockres->l_event); ocfs2_kick_vote_thread(osb); - - mlog_exit_void(); -} - -static void ocfs2_inode_bast_func(void *opaque, int level) -{ - struct ocfs2_lock_res *lockres = opaque; - struct inode *inode; - struct ocfs2_super *osb; - - mlog_entry_void(); - - BUG_ON(!ocfs2_is_inode_lock(lockres)); - - inode = ocfs2_lock_res_inode(lockres); - osb = OCFS2_SB(inode->i_sb); - - mlog(0, "BAST fired for inode %llu, blocking %d, level %d type %s\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, level, - lockres->l_level, ocfs2_lock_type_string(lockres->l_type)); - - ocfs2_generic_bast_func(osb, lockres, level); - - mlog_exit_void(); } static void ocfs2_locking_ast(void *opaque) @@ -751,52 +696,6 @@ static void ocfs2_locking_ast(void *opaque) spin_unlock_irqrestore(&lockres->l_lock, flags); } -static void ocfs2_super_bast_func(void *opaque, - int level) -{ - struct ocfs2_lock_res *lockres = opaque; - struct ocfs2_super *osb; - - mlog_entry_void(); - mlog(0, "Superblock BAST fired\n"); - - BUG_ON(!ocfs2_is_super_lock(lockres)); - osb = ocfs2_lock_res_super(lockres); - ocfs2_generic_bast_func(osb, lockres, level); - - mlog_exit_void(); -} - -static void ocfs2_rename_bast_func(void *opaque, - int level) -{ - struct ocfs2_lock_res *lockres = opaque; - struct ocfs2_super *osb; - - mlog_entry_void(); - - mlog(0, "Rename BAST fired\n"); - - BUG_ON(!ocfs2_is_rename_lock(lockres)); - - osb = ocfs2_lock_res_super(lockres); - ocfs2_generic_bast_func(osb, lockres, level); - - mlog_exit_void(); -} - -static void ocfs2_dentry_bast_func(void *opaque, int level) -{ - struct ocfs2_lock_res *lockres = opaque; - struct ocfs2_dentry_lock *dl = lockres->l_priv; - struct ocfs2_super *osb = OCFS2_SB(dl->dl_inode->i_sb); - - mlog(0, "Dentry bast: level: %d, name: %s\n", level, - lockres->l_name); - - ocfs2_generic_bast_func(osb, lockres, level); -} - static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres, int convert) { @@ -853,7 +752,7 @@ static int ocfs2_lock_create(struct ocfs2_super *osb, OCFS2_LOCK_ID_MAX_LEN - 1, ocfs2_locking_ast, lockres, - lockres->l_ops->bast); + ocfs2_blocking_ast); if (status != DLM_NORMAL) { ocfs2_log_dlm_error("dlmlock", status, lockres); ret = -EINVAL; @@ -1043,7 +942,7 @@ again: OCFS2_LOCK_ID_MAX_LEN - 1, ocfs2_locking_ast, lockres, - lockres->l_ops->bast); + ocfs2_blocking_ast); if (status != DLM_NORMAL) { if ((lkm_flags & LKM_NOQUEUE) && (status == DLM_NOTQUEUED)) @@ -2524,7 +2423,7 @@ static int ocfs2_downconvert_lock(struct ocfs2_super *osb, OCFS2_LOCK_ID_MAX_LEN - 1, ocfs2_locking_ast, lockres, - lockres->l_ops->bast); + ocfs2_blocking_ast); if (status != DLM_NORMAL) { ocfs2_log_dlm_error("dlmlock", status, lockres); ret = -EINVAL; @@ -3040,7 +2939,7 @@ static int ocfs2_unblock_osb_lock(struct ocfs2_lock_res *lockres, mlog(0, "Unblock lockres %s\n", lockres->l_name); - osb = ocfs2_lock_res_super(lockres); + osb = ocfs2_get_lockres_osb(lockres); status = ocfs2_generic_unblock_lock(osb, lockres, -- cgit v1.2.3 From b80fc012e03f8f207911b5eafe6916b000e03c8b Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Tue, 12 Sep 2006 22:08:14 -0700 Subject: ocfs2: don't unconditionally pass LVB flags Allow a lock type to specifiy whether it makes use of the LVB. The only type which does this right now is the meta data lock. This should save us some space on network messages since they won't have to needlessly transmit value blocks. Signed-off-by: Mark Fasheh --- fs/ocfs2/dlmglue.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'fs/ocfs2/dlmglue.c') diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 3d5c6a0eb9e..40562185088 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -135,6 +135,11 @@ struct ocfs2_lock_res_ops { */ #define LOCK_TYPE_REQUIRES_REFRESH 0x1 +/* + * Indicate that a lock type makes use of the lock value block. + */ +#define LOCK_TYPE_USES_LVB 0x2 + typedef int (ocfs2_convert_worker_t)(struct ocfs2_lock_res *, int); static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, struct ocfs2_lock_res *lockres, @@ -150,7 +155,7 @@ static struct ocfs2_lock_res_ops ocfs2_inode_rw_lops = { static struct ocfs2_lock_res_ops ocfs2_inode_meta_lops = { .get_osb = ocfs2_get_inode_osb, .unblock = ocfs2_unblock_meta, - .flags = LOCK_TYPE_REQUIRES_REFRESH, + .flags = LOCK_TYPE_REQUIRES_REFRESH|LOCK_TYPE_USES_LVB, }; static struct ocfs2_lock_res_ops ocfs2_inode_data_lops = { @@ -870,6 +875,9 @@ static int ocfs2_cluster_lock(struct ocfs2_super *osb, ocfs2_init_mask_waiter(&mw); + if (lockres->l_ops->flags & LOCK_TYPE_USES_LVB) + lkm_flags |= LKM_VALBLK; + again: wait = 0; @@ -937,7 +945,7 @@ again: status = dlmlock(osb->dlm, level, &lockres->l_lksb, - lkm_flags|LKM_CONVERT|LKM_VALBLK, + lkm_flags|LKM_CONVERT, lockres->l_name, OCFS2_LOCK_ID_MAX_LEN - 1, ocfs2_locking_ast, @@ -2212,11 +2220,15 @@ static int ocfs2_drop_lock(struct ocfs2_super *osb, { enum dlm_status status; unsigned long flags; + int lkm_flags = 0; /* We didn't get anywhere near actually using this lockres. */ if (!(lockres->l_flags & OCFS2_LOCK_INITIALIZED)) goto out; + if (lockres->l_ops->flags & LOCK_TYPE_USES_LVB) + lkm_flags |= LKM_VALBLK; + spin_lock_irqsave(&lockres->l_lock, flags); mlog_bug_on_msg(!(lockres->l_flags & OCFS2_LOCK_FREEING), @@ -2266,7 +2278,7 @@ static int ocfs2_drop_lock(struct ocfs2_super *osb, mlog(0, "lock %s\n", lockres->l_name); - status = dlmunlock(osb->dlm, &lockres->l_lksb, LKM_VALBLK, + status = dlmunlock(osb->dlm, &lockres->l_lksb, lkm_flags, ocfs2_unlock_ast, lockres); if (status != DLM_NORMAL) { ocfs2_log_dlm_error("dlmunlock", status, lockres); -- cgit v1.2.3 From f7fbfdd1fc91543253ba742a926a29c289f8e6ca Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Wed, 13 Sep 2006 21:02:29 -0700 Subject: ocfs2: Check for refreshing locks in generic unblock function Tidy up the exit path a bit too. Signed-off-by: Mark Fasheh --- fs/ocfs2/dlmglue.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'fs/ocfs2/dlmglue.c') diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 40562185088..ebc4a49801b 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -2640,22 +2640,22 @@ recheck: /* if we're blocking an exclusive and we have *any* holders, * then requeue. */ if ((lockres->l_blocking == LKM_EXMODE) - && (lockres->l_ex_holders || lockres->l_ro_holders)) { - spin_unlock_irqrestore(&lockres->l_lock, flags); - ctl->requeue = 1; - ret = 0; - goto leave; - } + && (lockres->l_ex_holders || lockres->l_ro_holders)) + goto leave_requeue; /* If it's a PR we're blocking, then only * requeue if we've got any EX holders */ if (lockres->l_blocking == LKM_PRMODE && - lockres->l_ex_holders) { - spin_unlock_irqrestore(&lockres->l_lock, flags); - ctl->requeue = 1; - ret = 0; - goto leave; - } + lockres->l_ex_holders) + goto leave_requeue; + + /* + * Can we get a lock in this state if the holder counts are + * zero? The meta data unblock code used to check this. + */ + if ((lockres->l_ops->flags & LOCK_TYPE_REQUIRES_REFRESH) + && (lockres->l_flags & OCFS2_LOCK_REFRESHING)) + goto leave_requeue; /* If we get here, then we know that there are no more * incompatible holders (and anyone asking for an incompatible @@ -2692,6 +2692,13 @@ downconvert: leave: mlog_exit(ret); return ret; + +leave_requeue: + spin_unlock_irqrestore(&lockres->l_lock, flags); + ctl->requeue = 1; + + mlog_exit(0); + return 0; } static int ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres, -- cgit v1.2.3 From 16d5b9567ad5241b5c6e0cc4778c1af6c04bb801 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Wed, 13 Sep 2006 21:10:12 -0700 Subject: ocfs2: Add ->check_downconvert callback in dlmglue This will allow lock types to force a requeue of a lock downconvert. Signed-off-by: Mark Fasheh --- fs/ocfs2/dlmglue.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'fs/ocfs2/dlmglue.c') diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index ebc4a49801b..9e8ed607173 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -118,6 +118,18 @@ struct ocfs2_lock_res_ops { int (*unblock)(struct ocfs2_lock_res *, struct ocfs2_unblock_ctl *); void (*post_unlock)(struct ocfs2_super *, struct ocfs2_lock_res *); + /* + * Allow a lock type to add checks to determine whether it is + * safe to downconvert a lock. Return 0 to re-queue the + * downconvert at a later time, nonzero to continue. + * + * For most locks, the default checks that there are no + * incompatible holders are sufficient. + * + * Called with the lockres spinlock held. + */ + int (*check_downconvert)(struct ocfs2_lock_res *, int); + /* * LOCK_TYPE_* flags which describe the specific requirements * of a lock type. Descriptions of each individual flag follow. @@ -2657,6 +2669,12 @@ recheck: && (lockres->l_flags & OCFS2_LOCK_REFRESHING)) goto leave_requeue; + new_level = ocfs2_highest_compat_lock_level(lockres->l_blocking); + + if (lockres->l_ops->check_downconvert + && !lockres->l_ops->check_downconvert(lockres, new_level)) + goto leave_requeue; + /* If we get here, then we know that there are no more * incompatible holders (and anyone asking for an incompatible * lock is blocked). We can now downconvert the lock */ @@ -2684,7 +2702,6 @@ recheck: downconvert: ctl->requeue = 0; - new_level = ocfs2_highest_compat_lock_level(lockres->l_blocking); ocfs2_prepare_downconvert(lockres, new_level); spin_unlock_irqrestore(&lockres->l_lock, flags); -- cgit v1.2.3 From 5ef0d4ea087740908f4fb57606f6c09e3b90c477 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Wed, 13 Sep 2006 21:21:52 -0700 Subject: ocfs2: Add ->set_lvb callback in dlmglue This allows a lock type to set the value block before downconvert. Signed-off-by: Mark Fasheh --- fs/ocfs2/dlmglue.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) (limited to 'fs/ocfs2/dlmglue.c') diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 9e8ed607173..faa6f57db70 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -130,6 +130,17 @@ struct ocfs2_lock_res_ops { */ int (*check_downconvert)(struct ocfs2_lock_res *, int); + /* + * Allows a lock type to populate the lock value block. This + * is called on downconvert, and when we drop a lock. + * + * Locks that want to use this should set LOCK_TYPE_USES_LVB + * in the flags field. + * + * Called with the lockres spinlock held. + */ + void (*set_lvb)(struct ocfs2_lock_res *); + /* * LOCK_TYPE_* flags which describe the specific requirements * of a lock type. Descriptions of each individual flag follow. @@ -148,7 +159,8 @@ struct ocfs2_lock_res_ops { #define LOCK_TYPE_REQUIRES_REFRESH 0x1 /* - * Indicate that a lock type makes use of the lock value block. + * Indicate that a lock type makes use of the lock value block. The + * ->set_lvb lock type callback must be defined. */ #define LOCK_TYPE_USES_LVB 0x2 @@ -2629,6 +2641,7 @@ static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, int blocking; int new_level; int ret = 0; + int set_lvb = 0; mlog_entry_void(); @@ -2703,9 +2716,23 @@ recheck: downconvert: ctl->requeue = 0; + if (lockres->l_ops->flags & LOCK_TYPE_USES_LVB) { + if (lockres->l_level == LKM_EXMODE) + set_lvb = 1; + + /* + * We only set the lvb if the lock has been fully + * refreshed - otherwise we risk setting stale + * data. Otherwise, there's no need to actually clear + * out the lvb here as it's value is still valid. + */ + if (set_lvb && !(lockres->l_flags & OCFS2_LOCK_NEEDS_REFRESH)) + lockres->l_ops->set_lvb(lockres); + } + ocfs2_prepare_downconvert(lockres, new_level); spin_unlock_irqrestore(&lockres->l_lock, flags); - ret = ocfs2_downconvert_lock(osb, lockres, new_level, 0); + ret = ocfs2_downconvert_lock(osb, lockres, new_level, set_lvb); leave: mlog_exit(ret); return ret; -- cgit v1.2.3 From 810d5aeba18825c754cf47db59eb83814a54bb27 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Wed, 13 Sep 2006 21:39:52 -0700 Subject: ocfs2: Have the metadata lock use generic dlmglue functions Fill in the ->check_downconvert and ->set_lvb callbacks with meta data specific operations and switch ocfs2_unblock_meta() to call ocfs2_generic_unblock_lock() Signed-off-by: Mark Fasheh --- fs/ocfs2/dlmglue.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) (limited to 'fs/ocfs2/dlmglue.c') diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index faa6f57db70..c8177d025d2 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -92,6 +92,10 @@ struct ocfs2_unblock_ctl { static int ocfs2_unblock_meta(struct ocfs2_lock_res *lockres, struct ocfs2_unblock_ctl *ctl); +static int ocfs2_check_meta_downconvert(struct ocfs2_lock_res *lockres, + int new_level); +static void ocfs2_set_meta_lvb(struct ocfs2_lock_res *lockres); + static int ocfs2_unblock_data(struct ocfs2_lock_res *lockres, struct ocfs2_unblock_ctl *ctl); static int ocfs2_unblock_inode_lock(struct ocfs2_lock_res *lockres, @@ -179,6 +183,8 @@ static struct ocfs2_lock_res_ops ocfs2_inode_rw_lops = { static struct ocfs2_lock_res_ops ocfs2_inode_meta_lops = { .get_osb = ocfs2_get_inode_osb, .unblock = ocfs2_unblock_meta, + .check_downconvert = ocfs2_check_meta_downconvert, + .set_lvb = ocfs2_set_meta_lvb, .flags = LOCK_TYPE_REQUIRES_REFRESH|LOCK_TYPE_USES_LVB, }; @@ -2822,6 +2828,29 @@ static int ocfs2_unblock_inode_lock(struct ocfs2_lock_res *lockres, return status; } +static int ocfs2_check_meta_downconvert(struct ocfs2_lock_res *lockres, + int new_level) +{ + struct inode *inode = ocfs2_lock_res_inode(lockres); + int checkpointed = ocfs2_inode_fully_checkpointed(inode); + + BUG_ON(new_level != LKM_NLMODE && new_level != LKM_PRMODE); + BUG_ON(lockres->l_level != LKM_EXMODE && !checkpointed); + + if (checkpointed) + return 1; + + ocfs2_start_checkpoint(OCFS2_SB(inode->i_sb)); + return 0; +} + +static void ocfs2_set_meta_lvb(struct ocfs2_lock_res *lockres) +{ + struct inode *inode = ocfs2_lock_res_inode(lockres); + + __ocfs2_stuff_meta_lvb(inode); +} + static int ocfs2_unblock_meta(struct ocfs2_lock_res *lockres, struct ocfs2_unblock_ctl *ctl) { @@ -2835,7 +2864,8 @@ static int ocfs2_unblock_meta(struct ocfs2_lock_res *lockres, mlog(0, "unblock inode %llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno); - status = ocfs2_do_unblock_meta(inode, &ctl->requeue); + status = ocfs2_generic_unblock_lock(OCFS2_SB(inode->i_sb), + lockres, ctl, NULL); if (status < 0) mlog_errno(status); -- cgit v1.2.3 From 08280f11de91beac2f5234ce5fc2ed246dfe6a86 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Wed, 13 Sep 2006 21:41:56 -0700 Subject: ocfs2: Remove unused dlmglue functions The meta data unblocking code no longer needs ocfs2_do_unblock_meta() or ocfs2_can_downconvert_meta_lock(), so remove them. Signed-off-by: Mark Fasheh --- fs/ocfs2/dlmglue.c | 103 ----------------------------------------------------- 1 file changed, 103 deletions(-) (limited to 'fs/ocfs2/dlmglue.c') diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index c8177d025d2..399d6e24b8d 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -268,9 +268,6 @@ static int ocfs2_meta_lock_update(struct inode *inode, struct buffer_head **bh); static void ocfs2_drop_osb_locks(struct ocfs2_super *osb); static inline int ocfs2_highest_compat_lock_level(int level); -static inline int ocfs2_can_downconvert_meta_lock(struct inode *inode, - struct ocfs2_lock_res *lockres, - int new_level); static void ocfs2_build_lock_name(enum ocfs2_lock_type type, u64 blkno, @@ -2538,106 +2535,6 @@ static int ocfs2_cancel_convert(struct ocfs2_super *osb, return ret; } -static inline int ocfs2_can_downconvert_meta_lock(struct inode *inode, - struct ocfs2_lock_res *lockres, - int new_level) -{ - int ret; - - mlog_entry_void(); - - BUG_ON(new_level != LKM_NLMODE && new_level != LKM_PRMODE); - - if (lockres->l_flags & OCFS2_LOCK_REFRESHING) { - ret = 0; - mlog(0, "lockres %s currently being refreshed -- backing " - "off!\n", lockres->l_name); - } else if (new_level == LKM_PRMODE) - ret = !lockres->l_ex_holders && - ocfs2_inode_fully_checkpointed(inode); - else /* Must be NLMODE we're converting to. */ - ret = !lockres->l_ro_holders && !lockres->l_ex_holders && - ocfs2_inode_fully_checkpointed(inode); - - mlog_exit(ret); - return ret; -} - -static int ocfs2_do_unblock_meta(struct inode *inode, - int *requeue) -{ - int new_level; - int set_lvb = 0; - int ret = 0; - struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_meta_lockres; - unsigned long flags; - - struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - - mlog_entry_void(); - - spin_lock_irqsave(&lockres->l_lock, flags); - - BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BLOCKED)); - - mlog(0, "l_level=%d, l_blocking=%d\n", lockres->l_level, - lockres->l_blocking); - - BUG_ON(lockres->l_level != LKM_EXMODE && - lockres->l_level != LKM_PRMODE); - - if (lockres->l_flags & OCFS2_LOCK_BUSY) { - *requeue = 1; - ret = ocfs2_prepare_cancel_convert(osb, lockres); - spin_unlock_irqrestore(&lockres->l_lock, flags); - if (ret) { - ret = ocfs2_cancel_convert(osb, lockres); - if (ret < 0) - mlog_errno(ret); - } - goto leave; - } - - new_level = ocfs2_highest_compat_lock_level(lockres->l_blocking); - - mlog(0, "l_level=%d, l_blocking=%d, new_level=%d\n", - lockres->l_level, lockres->l_blocking, new_level); - - if (ocfs2_can_downconvert_meta_lock(inode, lockres, new_level)) { - if (lockres->l_level == LKM_EXMODE) - set_lvb = 1; - - /* If the lock hasn't been refreshed yet (rare), then - * our memory inode values are old and we skip - * stuffing the lvb. There's no need to actually clear - * out the lvb here as it's value is still valid. */ - if (!(lockres->l_flags & OCFS2_LOCK_NEEDS_REFRESH)) { - if (set_lvb) - __ocfs2_stuff_meta_lvb(inode); - } else - mlog(0, "lockres %s: downconverting stale lock!\n", - lockres->l_name); - - mlog(0, "calling ocfs2_downconvert_lock with l_level=%d, " - "l_blocking=%d, new_level=%d\n", - lockres->l_level, lockres->l_blocking, new_level); - - ocfs2_prepare_downconvert(lockres, new_level); - spin_unlock_irqrestore(&lockres->l_lock, flags); - ret = ocfs2_downconvert_lock(osb, lockres, new_level, set_lvb); - goto leave; - } - if (!ocfs2_inode_fully_checkpointed(inode)) - ocfs2_start_checkpoint(osb); - - *requeue = 1; - spin_unlock_irqrestore(&lockres->l_lock, flags); - ret = 0; -leave: - mlog_exit(ret); - return ret; -} - static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, struct ocfs2_lock_res *lockres, struct ocfs2_unblock_ctl *ctl, -- cgit v1.2.3 From cc567d89b3af4294580c9c97610d2c1018032e33 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Wed, 13 Sep 2006 21:52:21 -0700 Subject: ocfs2: move downconvert worker to lockres ops This way lock types don't have to manually pass it to ocfs2_generic_unblock_lock(). Signed-off-by: Mark Fasheh --- fs/ocfs2/dlmglue.c | 50 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 18 deletions(-) (limited to 'fs/ocfs2/dlmglue.c') diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 399d6e24b8d..d92756dcd47 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -71,7 +71,7 @@ static struct ocfs2_super *ocfs2_get_dentry_osb(struct ocfs2_lock_res *lockres); static struct ocfs2_super *ocfs2_get_inode_osb(struct ocfs2_lock_res *lockres); /* - * Return value from ocfs2_convert_worker_t functions. + * Return value from ->downconvert_worker functions. * * These control the precise actions of ocfs2_generic_unblock_lock() * and ocfs2_process_blocked_lock() @@ -98,16 +98,23 @@ static void ocfs2_set_meta_lvb(struct ocfs2_lock_res *lockres); static int ocfs2_unblock_data(struct ocfs2_lock_res *lockres, struct ocfs2_unblock_ctl *ctl); +static int ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres, + int blocking); + static int ocfs2_unblock_inode_lock(struct ocfs2_lock_res *lockres, struct ocfs2_unblock_ctl *ctl); + static int ocfs2_unblock_dentry_lock(struct ocfs2_lock_res *lockres, struct ocfs2_unblock_ctl *ctl); -static int ocfs2_unblock_osb_lock(struct ocfs2_lock_res *lockres, - struct ocfs2_unblock_ctl *ctl); +static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres, + int blocking); static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb, struct ocfs2_lock_res *lockres); +static int ocfs2_unblock_osb_lock(struct ocfs2_lock_res *lockres, + struct ocfs2_unblock_ctl *ctl); + /* * OCFS2 Lock Resource Operations * @@ -145,6 +152,17 @@ struct ocfs2_lock_res_ops { */ void (*set_lvb)(struct ocfs2_lock_res *); + /* + * Called from the downconvert thread when it is determined + * that a lock will be downconverted. This is called without + * any locks held so the function can do work that might + * schedule (syncing out data, etc). + * + * This should return any one of the ocfs2_unblock_action + * values, depending on what it wants the thread to do. + */ + int (*downconvert_worker)(struct ocfs2_lock_res *, int); + /* * LOCK_TYPE_* flags which describe the specific requirements * of a lock type. Descriptions of each individual flag follow. @@ -168,11 +186,9 @@ struct ocfs2_lock_res_ops { */ #define LOCK_TYPE_USES_LVB 0x2 -typedef int (ocfs2_convert_worker_t)(struct ocfs2_lock_res *, int); static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, struct ocfs2_lock_res *lockres, - struct ocfs2_unblock_ctl *ctl, - ocfs2_convert_worker_t *worker); + struct ocfs2_unblock_ctl *ctl); static struct ocfs2_lock_res_ops ocfs2_inode_rw_lops = { .get_osb = ocfs2_get_inode_osb, @@ -191,6 +207,7 @@ static struct ocfs2_lock_res_ops ocfs2_inode_meta_lops = { static struct ocfs2_lock_res_ops ocfs2_inode_data_lops = { .get_osb = ocfs2_get_inode_osb, .unblock = ocfs2_unblock_data, + .downconvert_worker = ocfs2_data_convert_worker, .flags = 0, }; @@ -208,6 +225,7 @@ static struct ocfs2_lock_res_ops ocfs2_dentry_lops = { .get_osb = ocfs2_get_dentry_osb, .unblock = ocfs2_unblock_dentry_lock, .post_unlock = ocfs2_dentry_post_unlock, + .downconvert_worker = ocfs2_dentry_convert_worker, .flags = 0, }; @@ -2537,8 +2555,7 @@ static int ocfs2_cancel_convert(struct ocfs2_super *osb, static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, struct ocfs2_lock_res *lockres, - struct ocfs2_unblock_ctl *ctl, - ocfs2_convert_worker_t *worker) + struct ocfs2_unblock_ctl *ctl) { unsigned long flags; int blocking; @@ -2594,7 +2611,7 @@ recheck: /* If we get here, then we know that there are no more * incompatible holders (and anyone asking for an incompatible * lock is blocked). We can now downconvert the lock */ - if (!worker) + if (!lockres->l_ops->downconvert_worker) goto downconvert; /* Some lockres types want to do a bit of work before @@ -2604,7 +2621,7 @@ recheck: blocking = lockres->l_blocking; spin_unlock_irqrestore(&lockres->l_lock, flags); - ctl->unblock_action = worker(lockres, blocking); + ctl->unblock_action = lockres->l_ops->downconvert_worker(lockres, blocking); if (ctl->unblock_action == UNBLOCK_STOP_POST) goto leave; @@ -2692,8 +2709,7 @@ int ocfs2_unblock_data(struct ocfs2_lock_res *lockres, mlog(0, "unblock inode %llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno); - status = ocfs2_generic_unblock_lock(osb, lockres, ctl, - ocfs2_data_convert_worker); + status = ocfs2_generic_unblock_lock(osb, lockres, ctl); if (status < 0) mlog_errno(status); @@ -2717,7 +2733,7 @@ static int ocfs2_unblock_inode_lock(struct ocfs2_lock_res *lockres, inode = ocfs2_lock_res_inode(lockres); status = ocfs2_generic_unblock_lock(OCFS2_SB(inode->i_sb), - lockres, ctl, NULL); + lockres, ctl); if (status < 0) mlog_errno(status); @@ -2762,7 +2778,7 @@ static int ocfs2_unblock_meta(struct ocfs2_lock_res *lockres, (unsigned long long)OCFS2_I(inode)->ip_blkno); status = ocfs2_generic_unblock_lock(OCFS2_SB(inode->i_sb), - lockres, ctl, NULL); + lockres, ctl); if (status < 0) mlog_errno(status); @@ -2907,8 +2923,7 @@ static int ocfs2_unblock_dentry_lock(struct ocfs2_lock_res *lockres, ret = ocfs2_generic_unblock_lock(osb, lockres, - ctl, - ocfs2_dentry_convert_worker); + ctl); if (ret < 0) mlog_errno(ret); @@ -2933,8 +2948,7 @@ static int ocfs2_unblock_osb_lock(struct ocfs2_lock_res *lockres, status = ocfs2_generic_unblock_lock(osb, lockres, - ctl, - NULL); + ctl); if (status < 0) mlog_errno(status); -- cgit v1.2.3 From b5e500e23e532795fbf79a3cdbcb014f207fdb2a Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Wed, 13 Sep 2006 22:01:16 -0700 Subject: ocfs2: Remove ->unblock lockres operation Have ocfs2_process_blocked_lock() call ocfs2_generic_unblock_lock(), which gets to be ocfs2_unblock_lock() now that it's the only possible unblock function. Remove the ->unblock() callback from the structure, and all lock type specific unblock functions. Signed-off-by: Mark Fasheh --- fs/ocfs2/dlmglue.c | 152 +++-------------------------------------------------- 1 file changed, 6 insertions(+), 146 deletions(-) (limited to 'fs/ocfs2/dlmglue.c') diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index d92756dcd47..182ff2476cc 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -73,7 +73,7 @@ static struct ocfs2_super *ocfs2_get_inode_osb(struct ocfs2_lock_res *lockres); /* * Return value from ->downconvert_worker functions. * - * These control the precise actions of ocfs2_generic_unblock_lock() + * These control the precise actions of ocfs2_unblock_lock() * and ocfs2_process_blocked_lock() * */ @@ -90,31 +90,19 @@ struct ocfs2_unblock_ctl { enum ocfs2_unblock_action unblock_action; }; -static int ocfs2_unblock_meta(struct ocfs2_lock_res *lockres, - struct ocfs2_unblock_ctl *ctl); static int ocfs2_check_meta_downconvert(struct ocfs2_lock_res *lockres, int new_level); static void ocfs2_set_meta_lvb(struct ocfs2_lock_res *lockres); -static int ocfs2_unblock_data(struct ocfs2_lock_res *lockres, - struct ocfs2_unblock_ctl *ctl); static int ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres, int blocking); -static int ocfs2_unblock_inode_lock(struct ocfs2_lock_res *lockres, - struct ocfs2_unblock_ctl *ctl); - -static int ocfs2_unblock_dentry_lock(struct ocfs2_lock_res *lockres, - struct ocfs2_unblock_ctl *ctl); static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres, int blocking); static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb, struct ocfs2_lock_res *lockres); -static int ocfs2_unblock_osb_lock(struct ocfs2_lock_res *lockres, - struct ocfs2_unblock_ctl *ctl); - /* * OCFS2 Lock Resource Operations * @@ -126,7 +114,7 @@ struct ocfs2_lock_res_ops { * this callback if ->l_priv is not an ocfs2_super pointer */ struct ocfs2_super * (*get_osb)(struct ocfs2_lock_res *); - int (*unblock)(struct ocfs2_lock_res *, struct ocfs2_unblock_ctl *); + void (*post_unlock)(struct ocfs2_super *, struct ocfs2_lock_res *); /* @@ -186,19 +174,13 @@ struct ocfs2_lock_res_ops { */ #define LOCK_TYPE_USES_LVB 0x2 -static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, - struct ocfs2_lock_res *lockres, - struct ocfs2_unblock_ctl *ctl); - static struct ocfs2_lock_res_ops ocfs2_inode_rw_lops = { .get_osb = ocfs2_get_inode_osb, - .unblock = ocfs2_unblock_inode_lock, .flags = 0, }; static struct ocfs2_lock_res_ops ocfs2_inode_meta_lops = { .get_osb = ocfs2_get_inode_osb, - .unblock = ocfs2_unblock_meta, .check_downconvert = ocfs2_check_meta_downconvert, .set_lvb = ocfs2_set_meta_lvb, .flags = LOCK_TYPE_REQUIRES_REFRESH|LOCK_TYPE_USES_LVB, @@ -206,24 +188,20 @@ static struct ocfs2_lock_res_ops ocfs2_inode_meta_lops = { static struct ocfs2_lock_res_ops ocfs2_inode_data_lops = { .get_osb = ocfs2_get_inode_osb, - .unblock = ocfs2_unblock_data, .downconvert_worker = ocfs2_data_convert_worker, .flags = 0, }; static struct ocfs2_lock_res_ops ocfs2_super_lops = { - .unblock = ocfs2_unblock_osb_lock, .flags = LOCK_TYPE_REQUIRES_REFRESH, }; static struct ocfs2_lock_res_ops ocfs2_rename_lops = { - .unblock = ocfs2_unblock_osb_lock, .flags = 0, }; static struct ocfs2_lock_res_ops ocfs2_dentry_lops = { .get_osb = ocfs2_get_dentry_osb, - .unblock = ocfs2_unblock_dentry_lock, .post_unlock = ocfs2_dentry_post_unlock, .downconvert_worker = ocfs2_dentry_convert_worker, .flags = 0, @@ -2553,9 +2531,9 @@ static int ocfs2_cancel_convert(struct ocfs2_super *osb, return ret; } -static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, - struct ocfs2_lock_res *lockres, - struct ocfs2_unblock_ctl *ctl) +static int ocfs2_unblock_lock(struct ocfs2_super *osb, + struct ocfs2_lock_res *lockres, + struct ocfs2_unblock_ctl *ctl) { unsigned long flags; int blocking; @@ -2694,53 +2672,6 @@ static int ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres, return UNBLOCK_CONTINUE; } -int ocfs2_unblock_data(struct ocfs2_lock_res *lockres, - struct ocfs2_unblock_ctl *ctl) -{ - int status; - struct inode *inode; - struct ocfs2_super *osb; - - mlog_entry_void(); - - inode = ocfs2_lock_res_inode(lockres); - osb = OCFS2_SB(inode->i_sb); - - mlog(0, "unblock inode %llu\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno); - - status = ocfs2_generic_unblock_lock(osb, lockres, ctl); - if (status < 0) - mlog_errno(status); - - mlog(0, "inode %llu, requeue = %d\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, ctl->requeue); - - mlog_exit(status); - return status; -} - -static int ocfs2_unblock_inode_lock(struct ocfs2_lock_res *lockres, - struct ocfs2_unblock_ctl *ctl) -{ - int status; - struct inode *inode; - - mlog_entry_void(); - - mlog(0, "Unblock lockres %s\n", lockres->l_name); - - inode = ocfs2_lock_res_inode(lockres); - - status = ocfs2_generic_unblock_lock(OCFS2_SB(inode->i_sb), - lockres, ctl); - if (status < 0) - mlog_errno(status); - - mlog_exit(status); - return status; -} - static int ocfs2_check_meta_downconvert(struct ocfs2_lock_res *lockres, int new_level) { @@ -2764,31 +2695,6 @@ static void ocfs2_set_meta_lvb(struct ocfs2_lock_res *lockres) __ocfs2_stuff_meta_lvb(inode); } -static int ocfs2_unblock_meta(struct ocfs2_lock_res *lockres, - struct ocfs2_unblock_ctl *ctl) -{ - int status; - struct inode *inode; - - mlog_entry_void(); - - inode = ocfs2_lock_res_inode(lockres); - - mlog(0, "unblock inode %llu\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno); - - status = ocfs2_generic_unblock_lock(OCFS2_SB(inode->i_sb), - lockres, ctl); - if (status < 0) - mlog_errno(status); - - mlog(0, "inode %llu, requeue = %d\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, ctl->requeue); - - mlog_exit(status); - return status; -} - /* * Does the final reference drop on our dentry lock. Right now this * happens in the vote thread, but we could choose to simplify the @@ -2911,51 +2817,6 @@ static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres, return UNBLOCK_CONTINUE_POST; } -static int ocfs2_unblock_dentry_lock(struct ocfs2_lock_res *lockres, - struct ocfs2_unblock_ctl *ctl) -{ - int ret; - struct ocfs2_dentry_lock *dl = ocfs2_lock_res_dl(lockres); - struct ocfs2_super *osb = OCFS2_SB(dl->dl_inode->i_sb); - - mlog(0, "unblock dentry lock: %llu\n", - (unsigned long long)OCFS2_I(dl->dl_inode)->ip_blkno); - - ret = ocfs2_generic_unblock_lock(osb, - lockres, - ctl); - if (ret < 0) - mlog_errno(ret); - - mlog(0, "requeue = %d, post = %d\n", ctl->requeue, ctl->unblock_action); - - return ret; -} - -/* Generic unblock function for any lockres whose private data is an - * ocfs2_super pointer. */ -static int ocfs2_unblock_osb_lock(struct ocfs2_lock_res *lockres, - struct ocfs2_unblock_ctl *ctl) -{ - int status; - struct ocfs2_super *osb; - - mlog_entry_void(); - - mlog(0, "Unblock lockres %s\n", lockres->l_name); - - osb = ocfs2_get_lockres_osb(lockres); - - status = ocfs2_generic_unblock_lock(osb, - lockres, - ctl); - if (status < 0) - mlog_errno(status); - - mlog_exit(status); - return status; -} - void ocfs2_process_blocked_lock(struct ocfs2_super *osb, struct ocfs2_lock_res *lockres) { @@ -2971,7 +2832,6 @@ void ocfs2_process_blocked_lock(struct ocfs2_super *osb, BUG_ON(!lockres); BUG_ON(!lockres->l_ops); - BUG_ON(!lockres->l_ops->unblock); mlog(0, "lockres %s blocked.\n", lockres->l_name); @@ -2985,7 +2845,7 @@ void ocfs2_process_blocked_lock(struct ocfs2_super *osb, goto unqueue; spin_unlock_irqrestore(&lockres->l_lock, flags); - status = lockres->l_ops->unblock(lockres, &ctl); + status = ocfs2_unblock_lock(osb, lockres, &ctl); if (status < 0) mlog_errno(status); -- cgit v1.2.3 From 0d5dc6c2dd7a3cd2b2f505b0625c4ec9c0e5b4f0 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Thu, 14 Sep 2006 14:44:51 -0700 Subject: ocfs2: Teach ocfs2_drop_lock() to use ->set_lvb() callback With this, we don't need to pass an additional struct with function pointer. Now that the callbacks are fully used, comment the remaining API. Signed-off-by: Mark Fasheh --- fs/ocfs2/dlmglue.c | 59 ++++++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 31 deletions(-) (limited to 'fs/ocfs2/dlmglue.c') diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 182ff2476cc..de887063dcf 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -107,6 +107,14 @@ static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb, * OCFS2 Lock Resource Operations * * These fine tune the behavior of the generic dlmglue locking infrastructure. + * + * The most basic of lock types can point ->l_priv to their respective + * struct ocfs2_super and allow the default actions to manage things. + * + * Right now, each lock type also needs to implement an init function, + * and trivial lock/unlock wrappers. ocfs2_simple_drop_lockres() + * should be called when the lock is no longer needed (i.e., object + * destruction time). */ struct ocfs2_lock_res_ops { /* @@ -115,6 +123,15 @@ struct ocfs2_lock_res_ops { */ struct ocfs2_super * (*get_osb)(struct ocfs2_lock_res *); + /* + * Optionally called in the downconvert (or "vote") thread + * after a successful downconvert. The lockres will not be + * referenced after this callback is called, so it is safe to + * free memory, etc. + * + * The exact semantics of when this is called are controlled + * by ->downconvert_worker() + */ void (*post_unlock)(struct ocfs2_super *, struct ocfs2_lock_res *); /* @@ -2230,16 +2247,8 @@ complete_unlock: mlog_exit_void(); } -typedef void (ocfs2_pre_drop_cb_t)(struct ocfs2_lock_res *, void *); - -struct drop_lock_cb { - ocfs2_pre_drop_cb_t *drop_func; - void *drop_data; -}; - static int ocfs2_drop_lock(struct ocfs2_super *osb, - struct ocfs2_lock_res *lockres, - struct drop_lock_cb *dcb) + struct ocfs2_lock_res *lockres) { enum dlm_status status; unsigned long flags; @@ -2274,8 +2283,12 @@ static int ocfs2_drop_lock(struct ocfs2_super *osb, spin_lock_irqsave(&lockres->l_lock, flags); } - if (dcb) - dcb->drop_func(lockres, dcb->drop_data); + if (lockres->l_ops->flags & LOCK_TYPE_USES_LVB) { + if (lockres->l_flags & OCFS2_LOCK_ATTACHED && + lockres->l_level == LKM_EXMODE && + !(lockres->l_flags & OCFS2_LOCK_NEEDS_REFRESH)) + lockres->l_ops->set_lvb(lockres); + } if (lockres->l_flags & OCFS2_LOCK_BUSY) mlog(ML_ERROR, "destroying busy lock: \"%s\"\n", @@ -2355,7 +2368,7 @@ void ocfs2_simple_drop_lockres(struct ocfs2_super *osb, int ret; ocfs2_mark_lockres_freeing(lockres); - ret = ocfs2_drop_lock(osb, lockres, NULL); + ret = ocfs2_drop_lock(osb, lockres); if (ret) mlog_errno(ret); } @@ -2366,22 +2379,9 @@ static void ocfs2_drop_osb_locks(struct ocfs2_super *osb) ocfs2_simple_drop_lockres(osb, &osb->osb_rename_lockres); } -static void ocfs2_meta_pre_drop(struct ocfs2_lock_res *lockres, void *data) -{ - struct inode *inode = data; - - /* the metadata lock requires a bit more work as we have an - * LVB to worry about. */ - if (lockres->l_flags & OCFS2_LOCK_ATTACHED && - lockres->l_level == LKM_EXMODE && - !(lockres->l_flags & OCFS2_LOCK_NEEDS_REFRESH)) - __ocfs2_stuff_meta_lvb(inode); -} - int ocfs2_drop_inode_locks(struct inode *inode) { int status, err; - struct drop_lock_cb meta_dcb = { ocfs2_meta_pre_drop, inode, }; mlog_entry_void(); @@ -2389,24 +2389,21 @@ int ocfs2_drop_inode_locks(struct inode *inode) * ocfs2_clear_inode has done it for us. */ err = ocfs2_drop_lock(OCFS2_SB(inode->i_sb), - &OCFS2_I(inode)->ip_data_lockres, - NULL); + &OCFS2_I(inode)->ip_data_lockres); if (err < 0) mlog_errno(err); status = err; err = ocfs2_drop_lock(OCFS2_SB(inode->i_sb), - &OCFS2_I(inode)->ip_meta_lockres, - &meta_dcb); + &OCFS2_I(inode)->ip_meta_lockres); if (err < 0) mlog_errno(err); if (err < 0 && !status) status = err; err = ocfs2_drop_lock(OCFS2_SB(inode->i_sb), - &OCFS2_I(inode)->ip_rw_lockres, - NULL); + &OCFS2_I(inode)->ip_rw_lockres); if (err < 0) mlog_errno(err); if (err < 0 && !status) -- cgit v1.2.3