From 2dbcb3c79338dc4f4c45c21e4bf62e61e455ae19 Mon Sep 17 00:00:00 2001 From: Vikas Gorur Date: Fri, 27 Feb 2009 02:14:15 +0530 Subject: reverting nested locks in posix-locks for inodelk Signed-off-by: Anand V. Avati --- xlators/features/locks/src/common.c | 90 ++++---- xlators/features/locks/src/common.h | 9 +- xlators/features/locks/src/internal.c | 381 +++++++++++++++++++++------------- xlators/features/locks/src/locks.h | 8 +- xlators/features/locks/src/posix.c | 8 +- 5 files changed, 290 insertions(+), 206 deletions(-) (limited to 'xlators/features/locks') diff --git a/xlators/features/locks/src/common.c b/xlators/features/locks/src/common.c index bdabb1511..d87aec229 100644 --- a/xlators/features/locks/src/common.c +++ b/xlators/features/locks/src/common.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2006-2009 Z RESEARCH, Inc. + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. This file is part of GlusterFS. GlusterFS is free software; you can redistribute it and/or modify @@ -37,53 +37,51 @@ #include "locks.h" -int -pl_is_lock_grantable (pl_inode_t *pl_inode, posix_lock_t *lock, - gf_lk_domain_t dom); +static int +__is_lock_grantable (pl_inode_t *pl_inode, posix_lock_t *lock, + gf_lk_domain_t dom); static void __insert_and_merge (pl_inode_t *pl_inode, posix_lock_t *lock, gf_lk_domain_t dom); +#define DOMAIN_HEAD(pl_inode, dom) (dom == GF_LOCK_POSIX \ + ? &pl_inode->ext_list \ + : &pl_inode->int_list) pl_inode_t * pl_inode_get (xlator_t *this, inode_t *inode) { - pl_inode_t *pl_inode = NULL; - mode_t st_mode = 0; - uint64_t tmp_pl_inode = 0; - int ret = 0; - - LOCK (&inode->lock); - { - ret = inode_ctx_get (inode, this, &tmp_pl_inode); - if (ret == 0) { - pl_inode = (pl_inode_t *)(long)tmp_pl_inode; - goto out; - } + pl_inode_t *pl_inode = NULL; + mode_t st_mode = 0; + int ret = 0; + + ret = inode_ctx_get (inode, this, + (uint64_t *)(&pl_inode)); + if (ret == 0) + goto out; + + pl_inode = CALLOC (1, sizeof (*pl_inode)); + if (!pl_inode) { + gf_log (this->name, GF_LOG_ERROR, + "out of memory :("); + goto out; + } - pl_inode = CALLOC (1, sizeof (*pl_inode)); - if (!pl_inode) { - gf_log (this->name, GF_LOG_ERROR, - "out of memory :("); - goto out; - } + st_mode = inode->st_mode; + if ((st_mode & S_ISGID) && !(st_mode & S_IXGRP)) + pl_inode->mandatory = 1; - st_mode = inode->st_mode; - if ((st_mode & S_ISGID) && !(st_mode & S_IXGRP)) - pl_inode->mandatory = 1; + pthread_mutex_init (&pl_inode->mutex, NULL); - pthread_mutex_init (&pl_inode->mutex, NULL); - - INIT_LIST_HEAD (&pl_inode->dir_list); - INIT_LIST_HEAD (&pl_inode->ext_list); - INIT_LIST_HEAD (&pl_inode->int_list); - INIT_LIST_HEAD (&pl_inode->rw_list); + INIT_LIST_HEAD (&pl_inode->dir_list); + INIT_LIST_HEAD (&pl_inode->ext_list); + INIT_LIST_HEAD (&pl_inode->int_list); + INIT_LIST_HEAD (&pl_inode->rw_list); + + ret = inode_ctx_put (inode, this, (uint64_t)(long)(pl_inode)); - ret = inode_ctx_put (inode, this, (uint64_t)(long)pl_inode); - } out: - UNLOCK (&inode->lock); return pl_inode; } @@ -148,8 +146,8 @@ posix_lock_to_flock (posix_lock_t *lock, struct flock *flock) /* Insert the lock into the inode's lock list */ -void -pl_insert_lock (pl_inode_t *pl_inode, posix_lock_t *lock, gf_lk_domain_t dom) +static void +__insert_lock (pl_inode_t *pl_inode, posix_lock_t *lock, gf_lk_domain_t dom) { list_add_tail (&lock->list, DOMAIN_HEAD (pl_inode, dom)); @@ -305,9 +303,9 @@ first_overlap (pl_inode_t *pl_inode, posix_lock_t *lock, /* Return true if lock is grantable */ -int -pl_is_lock_grantable (pl_inode_t *pl_inode, posix_lock_t *lock, - gf_lk_domain_t dom) +static int +__is_lock_grantable (pl_inode_t *pl_inode, posix_lock_t *lock, + gf_lk_domain_t dom) { posix_lock_t *l = NULL; int ret = 1; @@ -398,14 +396,14 @@ __insert_and_merge (pl_inode_t *pl_inode, posix_lock_t *lock, } if ((conf->fl_type == F_RDLCK) && (lock->fl_type == F_RDLCK)) { - pl_insert_lock (pl_inode, lock, dom); + __insert_lock (pl_inode, lock, dom); return; } } /* no conflicts, so just insert */ if (lock->fl_type != F_UNLCK) { - pl_insert_lock (pl_inode, lock, dom); + __insert_lock (pl_inode, lock, dom); } else { __destroy_lock (lock); } @@ -437,12 +435,12 @@ __grant_blocked_locks (xlator_t *this, pl_inode_t *pl_inode, list_for_each_entry_safe (l, tmp, &tmp_list, list) { list_del_init (&l->list); - if (pl_is_lock_grantable (pl_inode, l, dom)) { + if (__is_lock_grantable (pl_inode, l, dom)) { conf = CALLOC (1, sizeof (*conf)); if (!conf) { l->blocked = 1; - pl_insert_lock (pl_inode, l, dom); + __insert_lock (pl_inode, l, dom); continue; } @@ -463,7 +461,7 @@ __grant_blocked_locks (xlator_t *this, pl_inode_t *pl_inode, list_add (&conf->list, granted); } else { l->blocked = 1; - pl_insert_lock (pl_inode, l, dom); + __insert_lock (pl_inode, l, dom); } } } @@ -506,7 +504,7 @@ pl_setlk (xlator_t *this, pl_inode_t *pl_inode, posix_lock_t *lock, pthread_mutex_lock (&pl_inode->mutex); { - if (pl_is_lock_grantable (pl_inode, lock, dom)) { + if (__is_lock_grantable (pl_inode, lock, dom)) { gf_log (this->name, GF_LOG_DEBUG, "%s (pid=%d) %"PRId64" - %"PRId64" => OK", lock->fl_type == F_UNLCK ? "Unlock" : "Lock", @@ -522,7 +520,7 @@ pl_setlk (xlator_t *this, pl_inode_t *pl_inode, posix_lock_t *lock, lock->user_flock.l_start, lock->user_flock.l_len); lock->blocked = 1; - pl_insert_lock (pl_inode, lock, dom); + __insert_lock (pl_inode, lock, dom); ret = -1; } else { gf_log (this->name, GF_LOG_DEBUG, diff --git a/xlators/features/locks/src/common.h b/xlators/features/locks/src/common.h index 45d0670e9..ee17b0087 100644 --- a/xlators/features/locks/src/common.h +++ b/xlators/features/locks/src/common.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2006-2009 Z RESEARCH, Inc. + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. This file is part of GlusterFS. GlusterFS is free software; you can redistribute it and/or modify @@ -33,13 +33,6 @@ int pl_setlk (xlator_t *this, pl_inode_t *inode, posix_lock_t *lock, int can_block, gf_lk_domain_t domain); -int -pl_is_lock_grantable (pl_inode_t *pl_inode, posix_lock_t *lock, - gf_lk_domain_t dom); - -void -pl_insert_lock (pl_inode_t *pl_inode, posix_lock_t *lock, gf_lk_domain_t dom); - void grant_blocked_locks (xlator_t *this, pl_inode_t *inode, gf_lk_domain_t domain); diff --git a/xlators/features/locks/src/internal.c b/xlators/features/locks/src/internal.c index eb3862fe9..985762fb9 100644 --- a/xlators/features/locks/src/internal.c +++ b/xlators/features/locks/src/internal.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2006-2009 Z RESEARCH, Inc. + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. This file is part of GlusterFS. GlusterFS is free software; you can redistribute it and/or modify @@ -52,24 +52,6 @@ delete_locks_of_transport (pl_inode_t *pinode, transport_t *trans) } -static posix_lock_t * -__find_exact_matching_lock (pl_inode_t *pinode, posix_lock_t *lock) -{ - posix_lock_t *l = NULL; - posix_lock_t *match = NULL; - - list_for_each_entry (l, DOMAIN_HEAD (pinode, GF_LOCK_INTERNAL), list) { - if (same_owner (l, lock) - && (l->fl_start == lock->fl_start) - && (l->fl_end == lock->fl_end)) { - match = l; - break; - } - } - - return match; -} - /** * pl_inodelk: * @@ -78,26 +60,23 @@ __find_exact_matching_lock (pl_inode_t *pinode, posix_lock_t *lock) * from those held by applications. This fop is for the use of AFR. */ - -static int -pl_inodelk_common (call_frame_t *frame, xlator_t *this, - inode_t *inode, int32_t cmd, struct flock *flock) +int +pl_inodelk (call_frame_t *frame, xlator_t *this, + loc_t *loc, int32_t cmd, struct flock *flock) { int32_t op_ret = -1; int32_t op_errno = 0; + int ret = -1; int can_block = 0; - posix_locks_private_t * priv = NULL; transport_t * transport = NULL; pid_t client_pid = -1; pl_inode_t * pinode = NULL; - posix_lock_t * reqlock = NULL; - posix_lock_t * matchlock = NULL; /* steady, fire! */ - VALIDATE_OR_GOTO (frame, unwind); - VALIDATE_OR_GOTO (inode, unwind); - VALIDATE_OR_GOTO (flock, unwind); + VALIDATE_OR_GOTO (frame, out); + VALIDATE_OR_GOTO (loc, out); + VALIDATE_OR_GOTO (flock, out); if ((flock->l_start < 0) || (flock->l_len < 0)) { op_errno = EINVAL; @@ -109,9 +88,9 @@ pl_inodelk_common (call_frame_t *frame, xlator_t *this, priv = (posix_locks_private_t *) this->private; - VALIDATE_OR_GOTO (priv, unwind); + VALIDATE_OR_GOTO (priv, out); - pinode = pl_inode_get (this, inode); + pinode = pl_inode_get (this, loc->inode); if (!pinode) { gf_log (this->name, GF_LOG_ERROR, "out of memory :("); @@ -124,7 +103,6 @@ pl_inodelk_common (call_frame_t *frame, xlator_t *this, special case: this means release all locks from this transport */ - gf_log (this->name, GF_LOG_DEBUG, "releasing all locks from transport %p", transport); @@ -141,117 +119,145 @@ pl_inodelk_common (call_frame_t *frame, xlator_t *this, goto unwind; } - pthread_mutex_lock (&pinode->mutex); - { - switch (cmd) { - case F_SETLKW: - can_block = 1; - reqlock->frame = frame; - reqlock->this = this; - - /* fall through */ - - case F_SETLK: - memcpy (&reqlock->user_flock, flock, sizeof (struct flock)); - - switch (flock->l_type) { - - case F_WRLCK: - if (!pl_is_lock_grantable (pinode, reqlock, GF_LOCK_INTERNAL)) { - if (can_block) { - gf_log (this->name, GF_LOG_DEBUG, - "%s (pid=%d) %"PRId64" - %"PRId64" => blocked", - reqlock->fl_type == F_UNLCK ? "unlock" : "lock", - reqlock->client_pid, - reqlock->user_flock.l_start, - reqlock->user_flock.l_len); - pl_insert_lock (pinode, reqlock, GF_LOCK_INTERNAL); - - goto unlock; - } - - __destroy_lock (reqlock); - - - gf_log (this->name, GF_LOG_DEBUG, - "%s (pid=%d) %"PRId64" - %"PRId64" => NOK", - reqlock->fl_type == F_UNLCK ? "unlock" : "lock", - reqlock->client_pid, reqlock->user_flock.l_start, - reqlock->user_flock.l_len); - op_errno = EAGAIN; - - goto unlock; - } - - gf_log (this->name, GF_LOG_DEBUG, - "%s (pid=%d) %"PRId64" - %"PRId64" => OK", - reqlock->fl_type == F_UNLCK ? "unlock" : "lock", - reqlock->client_pid, - reqlock->user_flock.l_start, - reqlock->user_flock.l_len); - pl_insert_lock (pinode, reqlock, GF_LOCK_INTERNAL); - - break; - - case F_UNLCK: - matchlock = __find_exact_matching_lock (pinode, reqlock); - - __destroy_lock (reqlock); - if (!matchlock) { - op_errno = EINVAL; - goto unlock; - } - - __delete_lock (pinode, matchlock); - __destroy_lock (matchlock); - - break; - - default: - op_errno = ENOTSUP; - gf_log (this->name, GF_LOG_ERROR, - "lock type %d not supported for [F]INODELK", - flock->l_type); - goto unlock; - } - - - break; - - default: - op_errno = ENOTSUP; - gf_log (this->name, GF_LOG_ERROR, - "lock command F_GETLK not supported for [F]INODELK (cmd=%d)", - cmd); - goto unlock; + switch (cmd) { + case F_SETLKW: + can_block = 1; + reqlock->frame = frame; + reqlock->this = this; + + /* fall through */ + + case F_SETLK: + memcpy (&reqlock->user_flock, flock, sizeof (struct flock)); + ret = pl_setlk (this, pinode, reqlock, + can_block, GF_LOCK_INTERNAL); + + if (ret == -1) { + if (can_block) + goto out; + + gf_log (this->name, GF_LOG_DEBUG, "returning EAGAIN"); + op_errno = EAGAIN; + __destroy_lock (reqlock); + goto unwind; } - - op_ret = 0; - - unlock: - if (pinode) - pthread_mutex_unlock (&pinode->mutex); + break; + + default: + op_errno = ENOTSUP; + gf_log (this->name, GF_LOG_ERROR, + "lock command F_GETLK not supported for GF_FILE_LK (cmd=%d)", + cmd); + goto unwind; } -unwind: + op_ret = 0; + +unwind: STACK_UNWIND (frame, op_ret, op_errno); +out: return 0; } -int -pl_inodelk (call_frame_t *frame, xlator_t *this, - loc_t *loc, int32_t cmd, struct flock *flock) -{ - return pl_inodelk_common (frame, this, loc->inode, cmd, flock); -} - - int pl_finodelk (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t cmd, struct flock *flock) { - return pl_inodelk_common (frame, this, fd->inode, cmd, flock); + int32_t op_ret = -1; + int32_t op_errno = 0; + int ret = -1; + int can_block = 0; + posix_locks_private_t * priv = NULL; + transport_t * transport = NULL; + pid_t client_pid = -1; + pl_inode_t * pinode = NULL; + posix_lock_t * reqlock = NULL; + + VALIDATE_OR_GOTO (frame, out); + VALIDATE_OR_GOTO (fd, out); + VALIDATE_OR_GOTO (flock, out); + + if ((flock->l_start < 0) || (flock->l_len < 0)) { + op_errno = EINVAL; + goto unwind; + } + + transport = frame->root->trans; + client_pid = frame->root->pid; + + priv = (posix_locks_private_t *) this->private; + + VALIDATE_OR_GOTO (priv, out); + + pinode = pl_inode_get (this, fd->inode); + if (!pinode) { + gf_log (this->name, GF_LOG_ERROR, + "out of memory :("); + op_errno = ENOMEM; + goto unwind; + } + + if (client_pid == 0) { + /* + special case: this means release all locks + from this transport + */ + gf_log (this->name, GF_LOG_DEBUG, + "releasing all locks from transport %p", transport); + + delete_locks_of_transport (pinode, transport); + goto unwind; + } + + reqlock = new_posix_lock (flock, transport, client_pid); + if (!reqlock) { + gf_log (this->name, GF_LOG_ERROR, + "out of memory :("); + op_ret = -1; + op_errno = ENOMEM; + goto unwind; + } + + switch (cmd) { + case F_SETLKW: + can_block = 1; + reqlock->frame = frame; + reqlock->this = this; + reqlock->fd = fd; + + /* fall through */ + + case F_SETLK: + memcpy (&reqlock->user_flock, flock, sizeof (struct flock)); + ret = pl_setlk (this, pinode, reqlock, + can_block, GF_LOCK_INTERNAL); + + if (ret == -1) { + if (can_block) + goto out; + + gf_log (this->name, GF_LOG_DEBUG, "returning EAGAIN"); + op_errno = EAGAIN; + __destroy_lock (reqlock); + goto unwind; + } + break; + + default: + op_errno = ENOTSUP; + gf_log (this->name, GF_LOG_ERROR, + "lock command F_GETLK not supported for GF_FILE_LK (cmd=%d)", + cmd); + goto unwind; + } + + op_ret = 0; + +unwind: + STACK_UNWIND (frame, op_ret, op_errno); +out: + return 0; } @@ -642,9 +648,9 @@ unlock: */ int -pl_entrylk_common (call_frame_t *frame, xlator_t *this, - inode_t *inode, const char *basename, - entrylk_cmd cmd, entrylk_type type) +pl_entrylk (call_frame_t *frame, xlator_t *this, + loc_t *loc, const char *basename, + entrylk_cmd cmd, entrylk_type type) { int32_t op_ret = -1; int32_t op_errno = 0; @@ -657,7 +663,8 @@ pl_entrylk_common (call_frame_t *frame, xlator_t *this, pl_entry_lock_t *unlocked = NULL; char unwind = 1; - pinode = pl_inode_get (this, inode); + + pinode = pl_inode_get (this, loc->inode); if (!pinode) { gf_log (this->name, GF_LOG_ERROR, "out of memory :("); @@ -744,19 +751,105 @@ out: } -int -pl_entrylk (call_frame_t *frame, xlator_t *this, - loc_t *loc, const char *basename, - entrylk_cmd cmd, entrylk_type type) -{ - return pl_entrylk_common (frame, this, loc->inode, basename, cmd, type); -} - +/** + * pl_entrylk: + * + * Locking on names (directory entries) + */ int pl_fentrylk (call_frame_t *frame, xlator_t *this, fd_t *fd, const char *basename, entrylk_cmd cmd, entrylk_type type) { - return pl_entrylk_common (frame, this, fd->inode, basename, cmd, type); + int32_t op_ret = -1; + int32_t op_errno = 0; + + transport_t * transport = NULL; + pid_t pid = -1; + + pl_inode_t * pinode = NULL; + int ret = -1; + pl_entry_lock_t *unlocked = NULL; + char unwind = 1; + + pinode = pl_inode_get (this, fd->inode); + if (!pinode) { + gf_log (this->name, GF_LOG_ERROR, + "out of memory :("); + goto out; + } + + pid = frame->root->pid; + transport = frame->root->trans; + + if (pid == 0) { + /* + this is a special case that means release + all locks from this transport + */ + + gf_log (this->name, GF_LOG_DEBUG, + "releasing locks for transport %p", transport); + + release_entry_locks_for_transport (this, pinode, transport); + op_ret = 0; + goto out; + } + + switch (cmd) { + case ENTRYLK_LOCK: + pthread_mutex_lock (&pinode->mutex); + { + ret = __lock_name (pinode, basename, type, + frame, this, 0); + } + pthread_mutex_unlock (&pinode->mutex); + + if (ret < 0) { + if (ret == -EAGAIN) + unwind = 0; + op_errno = -ret; + goto out; + } + break; + + case ENTRYLK_LOCK_NB: + pthread_mutex_lock (&pinode->mutex); + { + ret = __lock_name (pinode, basename, type, + frame, this, 1); + } + pthread_mutex_unlock (&pinode->mutex); + + if (ret < 0) { + op_errno = -ret; + goto out; + } + break; + + case ENTRYLK_UNLOCK: + pthread_mutex_lock (&pinode->mutex); + { + unlocked = __unlock_name (pinode, basename, type); + } + pthread_mutex_unlock (&pinode->mutex); + + if (unlocked) + grant_blocked_entry_locks (this, pinode, unlocked); + break; + + default: + gf_log (this->name, GF_LOG_ERROR, + "unexpected case!"); + goto out; + } + + op_ret = 0; +out: + if (unwind) { + STACK_UNWIND (frame, op_ret, op_errno); + } + + return 0; } diff --git a/xlators/features/locks/src/locks.h b/xlators/features/locks/src/locks.h index b62b13a71..5a834657d 100644 --- a/xlators/features/locks/src/locks.h +++ b/xlators/features/locks/src/locks.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2006-2009 Z RESEARCH, Inc. + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. This file is part of GlusterFS. GlusterFS is free software; you can redistribute it and/or modify @@ -92,10 +92,10 @@ struct __pl_inode { }; typedef struct __pl_inode pl_inode_t; -#define DOMAIN_HEAD(pl_inode, dom) (dom == GF_LOCK_POSIX \ - ? &pl_inode->ext_list \ - : &pl_inode->int_list) +#define LOCKS_FOR_DOMAIN(inode,domain) (domain == GF_LOCK_POSIX \ + ? inode->fcntl_locks \ + : inode->inodelk_locks) struct __pl_fd { gf_boolean_t nonblocking; /* whether O_NONBLOCK has been set */ diff --git a/xlators/features/locks/src/posix.c b/xlators/features/locks/src/posix.c index c2fee4d58..46d2cb9a0 100644 --- a/xlators/features/locks/src/posix.c +++ b/xlators/features/locks/src/posix.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2006-2009 Z RESEARCH, Inc. + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. This file is part of GlusterFS. GlusterFS is free software; you can redistribute it and/or modify @@ -277,6 +277,7 @@ pl_flush (call_frame_t *frame, xlator_t *this, priv = this->private; pl_inode = pl_inode_get (this, fd->inode); + if (!pl_inode) { gf_log (this->name, GF_LOG_ERROR, "returning EBADFD"); STACK_UNWIND (frame, -1, EBADFD); @@ -443,7 +444,6 @@ pl_readv (call_frame_t *frame, xlator_t *this, priv = this->private; - pl_inode = pl_inode_get (this, fd->inode); if (priv->mandatory && pl_inode->mandatory) { @@ -537,8 +537,8 @@ pl_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, priv = this->private; - pl_inode = pl_inode_get (this, fd->inode); + if (priv->mandatory && pl_inode->mandatory) { region.fl_start = offset; region.fl_end = offset + iov_length (vector, count) - 1; @@ -719,7 +719,7 @@ pl_forget (xlator_t *this, "Pending entry locks found!"); } - FREE (pl_inode); + FREE (pl_inode); return 0; } -- cgit