+static int gdlm_plock(void *lockspace, struct lm_lockname *name,
+ struct file *file, int cmd, struct file_lock *fl)
+{
+ struct gdlm_ls *ls = lockspace;
+ return dlm_posix_lock(ls->dlm_lockspace, name->ln_number, file, cmd, fl);
+}
+
+static int gdlm_punlock(void *lockspace, struct lm_lockname *name,
+ struct file *file, struct file_lock *fl)
+{
+ struct gdlm_ls *ls = lockspace;
+ return dlm_posix_unlock(ls->dlm_lockspace, name->ln_number, file, fl);
+}
+
+static int gdlm_plock_get(void *lockspace, struct lm_lockname *name,
+ struct file *file, struct file_lock *fl)
+{
+ struct gdlm_ls *ls = lockspace;
+ return dlm_posix_get(ls->dlm_lockspace, name->ln_number, file, fl);
+}
+
const struct lm_lockops gdlm_ops = {
.lm_proto_name = "lock_dlm",
.lm_mount = gdlm_mount,
diff --git a/fs/gfs2/locking/dlm/plock.c b/fs/gfs2/locking/dlm/plock.c
deleted file mode 100644
index 2ebd374..0000000
--- a/fs/gfs2/locking/dlm/plock.c
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
- * Copyright (C) 2005 Red Hat, Inc. All rights reserved.
- *
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU General Public License version 2.
- */
-
-#include <linux/miscdevice.h>
-#include <linux/lock_dlm_plock.h>
-#include <linux/poll.h>
-
-#include "lock_dlm.h"
-
-
-static spinlock_t ops_lock;
-static struct list_head send_list;
-static struct list_head recv_list;
-static wait_queue_head_t send_wq;
-static wait_queue_head_t recv_wq;
-
-struct plock_op {
- struct list_head list;
- int done;
- struct gdlm_plock_info info;
-};
-
-struct plock_xop {
- struct plock_op xop;
- void *callback;
- void *fl;
- void *file;
- struct file_lock flc;
-};
-
-
-static inline void set_version(struct gdlm_plock_info *info)
-{
- info->version[0] = GDLM_PLOCK_VERSION_MAJOR;
- info->version[1] = GDLM_PLOCK_VERSION_MINOR;
- info->version[2] = GDLM_PLOCK_VERSION_PATCH;
-}
-
-static int check_version(struct gdlm_plock_info *info)
-{
- if ((GDLM_PLOCK_VERSION_MAJOR != info->version[0]) ||
- (GDLM_PLOCK_VERSION_MINOR < info->version[1])) {
- log_error("plock device version mismatch: "
- "kernel (%u.%u.%u), user (%u.%u.%u)",
- GDLM_PLOCK_VERSION_MAJOR,
- GDLM_PLOCK_VERSION_MINOR,
- GDLM_PLOCK_VERSION_PATCH,
- info->version[0],
- info->version[1],
- info->version[2]);
- return -EINVAL;
- }
- return 0;
-}
-
-static void send_op(struct plock_op *op)
-{
- set_version(&op->info);
- INIT_LIST_HEAD(&op->list);
- spin_lock(&ops_lock);
- list_add_tail(&op->list, &send_list);
- spin_unlock(&ops_lock);
- wake_up(&send_wq);
-}
-
-int gdlm_plock(void *lockspace, struct lm_lockname *name,
- struct file *file, int cmd, struct file_lock *fl)
-{
- struct gdlm_ls *ls = lockspace;
- struct plock_op *op;
- struct plock_xop *xop;
- int rv;
-
- xop = kzalloc(sizeof(*xop), GFP_KERNEL);
- if (!xop)
- return -ENOMEM;
-
- op = &xop->xop;
- op->info.optype = GDLM_PLOCK_OP_LOCK;
- op->info.pid = fl->fl_pid;
- op->info.ex = (fl->fl_type == F_WRLCK);
- op->info.wait = IS_SETLKW(cmd);
- op->info.fsid = ls->id;
- op->info.number = name->ln_number;
- op->info.start = fl->fl_start;
- op->info.end = fl->fl_end;
- if (fl->fl_lmops && fl->fl_lmops->fl_grant) {
- /* fl_owner is lockd which doesn't distinguish
- processes on the nfs client */
- op->info.owner = (__u64) fl->fl_pid;
- xop->callback = fl->fl_lmops->fl_grant;
- locks_init_lock(&xop->flc);
- locks_copy_lock(&xop->flc, fl);
- xop->fl = fl;
- xop->file = file;
- } else {
- op->info.owner = (__u64)(long) fl->fl_owner;
- xop->callback = NULL;
- }
-
- send_op(op);
-
- if (xop->callback == NULL)
- wait_event(recv_wq, (op->done != 0));
- else
- return -EINPROGRESS;
-
- spin_lock(&ops_lock);
- if (!list_empty(&op->list)) {
- printk(KERN_INFO "plock op on list
");
- list_del(&op->list);
- }
- spin_unlock(&ops_lock);
-
- rv = op->info.rv;
-
- if (!rv) {
- if (posix_lock_file_wait(file, fl) < 0)
- log_error("gdlm_plock: vfs lock error %x,%llx",
- name->ln_type,
- (unsigned long long)name->ln_number);
- }
-
- kfree(xop);
- return rv;
-}
-
-/* Returns failure iff a succesful lock operation should be canceled */
-static int gdlm_plock_callback(struct plock_op *op)
-{
- struct file *file;
- struct file_lock *fl;
- struct file_lock *flc;
- int (*notify)(void *, void *, int) = NULL;
- struct plock_xop *xop = (struct plock_xop *)op;
- int rv = 0;
-
- spin_lock(&ops_lock);
- if (!list_empty(&op->list)) {
- printk(KERN_INFO "plock op on list
");
- list_del(&op->list);
- }
- spin_unlock(&ops_lock);
-
- /* check if the following 2 are still valid or make a copy */
- file = xop->file;
- flc = &xop->flc;
- fl = xop->fl;
- notify = xop->callback;
-
- if (op->info.rv) {
- notify(flc, NULL, op->info.rv);
- goto out;
- }
-
- /* got fs lock; bookkeep locally as well: */
- flc->fl_flags &= ~FL_SLEEP;
- if (posix_lock_file(file, flc, NULL)) {
- /*
- * This can only happen in the case of kmalloc() failure.
- * The filesystem's own lock is the authoritative lock,
- * so a failure to get the lock locally is not a disaster.
- * As long as GFS cannot reliably cancel locks (especially
- * in a low-memory situation), we're better off ignoring
- * this failure than trying to recover.
- */
- log_error("gdlm_plock: vfs lock error file %p fl %p",
- file, fl);
- }
-
- rv = notify(flc, NULL, 0);
- if (rv) {
- /* XXX: We need to cancel the fs lock here: */
- printk("gfs2 lock granted after lock request failed;"
- " dangling lock!
");
- goto out;
- }
-
-out:
- kfree(xop);
- return rv;
-}
-
-int gdlm_punlock(void *lockspace, struct lm_lockname *name,
- struct file *file, struct file_lock *fl)
-{
- struct gdlm_ls *ls = lockspace;
- struct plock_op *op;
- int rv;
-
- op = kzalloc(sizeof(*op), GFP_KERNEL);
- if (!op)
- return -ENOMEM;
-
- if (posix_lock_file_wait(file, fl) < 0)
- log_error("gdlm_punlock: vfs unlock error %x,%llx",
- name->ln_type, (unsigned long long)name->ln_number);
-
- op->info.optype = GDLM_PLOCK_OP_UNLOCK;
- op->info.pid = fl->fl_pid;
- op->info.fsid = ls->id;
- op->info.number = name->ln_number;
- op->info.start = fl->fl_start;
- op->info.end = fl->fl_end;
- if (fl->fl_lmops && fl->fl_lmops->fl_grant)
- op->info.owner = (__u64) fl->fl_pid;
- else
- op->info.owner = (__u64)(long) fl->fl_owner;
-
- send_op(op);
- wait_event(recv_wq, (op->done != 0));
-
- spin_lock(&ops_lock);
- if (!list_empty(&op->list)) {
- printk(KERN_INFO "punlock op on list
");
- list_del(&op->list);
- }
- spin_unlock(&ops_lock);
-
- rv = op->info.rv;
-
- if (rv == -ENOENT)
- rv = 0;
-
- kfree(op);
- return rv;
-}
-
-int gdlm_plock_get(void *lockspace, struct lm_lockname *name,
- struct file *file, struct file_lock *fl)
-{
- struct gdlm_ls *ls = lockspace;
- struct plock_op *op;
- int rv;
-
- op = kzalloc(sizeof(*op), GFP_KERNEL);
- if (!op)
- return -ENOMEM;
-
- op->info.optype = GDLM_PLOCK_OP_GET;
- op->info.pid = fl->fl_pid;
- op->info.ex = (fl->fl_type == F_WRLCK);
- op->info.fsid = ls->id;
- op->info.number = name->ln_number;
- op->info.start = fl->fl_start;
- op->info.end = fl->fl_end;
- if (fl->fl_lmops && fl->fl_lmops->fl_grant)
- op->info.owner = (__u64) fl->fl_pid;
- else
- op->info.owner = (__u64)(long) fl->fl_owner;
-
- send_op(op);
- wait_event(recv_wq, (op->done != 0));
-
- spin_lock(&ops_lock);
- if (!list_empty(&op->list)) {
- printk(KERN_INFO "plock_get op on list
");
- list_del(&op->list);
- }
- spin_unlock(&ops_lock);
-
- /* info.rv from userspace is 1 for conflict, 0 for no-conflict,
- -ENOENT if there are no locks on the file */
-
- rv = op->info.rv;
-
- fl->fl_type = F_UNLCK;
- if (rv == -ENOENT)
- rv = 0;
- else if (rv > 0) {
- fl->fl_type = (op->info.ex) ? F_WRLCK : F_RDLCK;
- fl->fl_pid = op->info.pid;
- fl->fl_start = op->info.start;
- fl->fl_end = op->info.end;
- rv = 0;
- }
-
- kfree(op);
- return rv;
-}
-
-/* a read copies out one plock request from the send list */
-static ssize_t dev_read(struct file *file, char __user *u, size_t count,
- loff_t *ppos)
-{
- struct gdlm_plock_info info;
- struct plock_op *op = NULL;
-
- if (count < sizeof(info))
- return -EINVAL;
-
- spin_lock(&ops_lock);
- if (!list_empty(&send_list)) {
- op = list_entry(send_list.next, struct plock_op, list);
- list_move(&op->list, &recv_list);
- memcpy(&info, &op->info, sizeof(info));
- }
- spin_unlock(&ops_lock);
-
- if (!op)
- return -EAGAIN;
-
- if (copy_to_user(u, &info, sizeof(info)))
- return -EFAULT;
- return sizeof(info);
-}
-
-/* a write copies in one plock result that should match a plock_op
- on the recv list */
-static ssize_t dev_write(struct file *file, const char __user *u, size_t count,
- loff_t *ppos)
-{
- struct gdlm_plock_info info;
- struct plock_op *op;
- int found = 0;
-
- if (count != sizeof(info))
- return -EINVAL;
-
- if (copy_from_user(&info, u, sizeof(info)))
- return -EFAULT;
-
- if (check_version(&info))
- return -EINVAL;
-
- spin_lock(&ops_lock);
- list_for_each_entry(op, &recv_list, list) {
- if (op->info.fsid == info.fsid && op->info.number == info.number &&
- op->info.owner == info.owner) {
- list_del_init(&op->list);
- found = 1;
- op->done = 1;
- memcpy(&op->info, &info, sizeof(info));
- break;
- }
- }
- spin_unlock(&ops_lock);
-
- if (found) {
- struct plock_xop *xop;
- xop = (struct plock_xop *)op;
- if (xop->callback)
- count = gdlm_plock_callback(op);
- else
- wake_up(&recv_wq);
- } else
- printk(KERN_INFO "gdlm dev_write no op %x %llx
", info.fsid,
- (unsigned long long)info.number);
- return count;
-}
-
-static unsigned int dev_poll(struct file *file, poll_table *wait)
-{
- unsigned int mask = 0;
-
- poll_wait(file, &send_wq, wait);
-
- spin_lock(&ops_lock);
- if (!list_empty(&send_list))
- mask = POLLIN | POLLRDNORM;
- spin_unlock(&ops_lock);
-
- return mask;
-}
-
-static const struct file_operations dev_fops = {
- .read = dev_read,
- .write = dev_write,
- .poll = dev_poll,
- .owner = THIS_MODULE
-};
-
-static struct miscdevice plock_dev_misc = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = GDLM_PLOCK_MISC_NAME,
- .fops = &dev_fops
-};
-
-int gdlm_plock_init(void)
-{
- int rv;
-
- spin_lock_init(&ops_lock);
- INIT_LIST_HEAD(&send_list);
- INIT_LIST_HEAD(&recv_list);
- init_waitqueue_head(&send_wq);
- init_waitqueue_head(&recv_wq);
-
- rv = misc_register(&plock_dev_misc);
- if (rv)
- printk(KERN_INFO "gdlm_plock_init: misc_register failed %d",
- rv);
- return rv;
-}
-
-void gdlm_plock_exit(void)
-{
- if (misc_deregister(&plock_dev_misc) < 0)
- printk(KERN_INFO "gdlm_plock_exit: misc_deregister failed");
-}
-
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 9cdd12a..7fd04ba 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -99,7 +99,7 @@ header-y += ixjuser.h
header-y += jffs2.h
header-y += keyctl.h
header-y += limits.h
-header-y += lock_dlm_plock.h
+header-y += dlm_plock.h
header-y += magic.h
header-y += major.h
header-y += matroxfb.h
diff --git a/include/linux/dlm_plock.h b/include/linux/dlm_plock.h
new file mode 100644
index 0000000..18d5fdb
--- /dev/null
+++ b/include/linux/dlm_plock.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ */
+
+#ifndef __DLM_PLOCK_DOT_H__
+#define __DLM_PLOCK_DOT_H__
+
+#define DLM_PLOCK_MISC_NAME "dlm_plock"
+
+#define DLM_PLOCK_VERSION_MAJOR 1
+#define DLM_PLOCK_VERSION_MINOR 1
+#define DLM_PLOCK_VERSION_PATCH 0
+
+enum {
+ DLM_PLOCK_OP_LOCK = 1,
+ DLM_PLOCK_OP_UNLOCK,
+ DLM_PLOCK_OP_GET,
+};
+
+struct dlm_plock_info {
+ __u32 version[3];
+ __u8 optype;
+ __u8 ex;
+ __u8 wait;
+ __u8 pad;
+ __u32 pid;
+ __s32 nodeid;
+ __s32 rv;
+ __u32 fsid;
+ __u64 number;
+ __u64 start;
+ __u64 end;
+ __u64 owner;
+};
+
+#ifdef __KERNEL__
+int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
+ int cmd, struct file_lock *fl);
+int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
+ struct file_lock *fl);
+int dlm_posix_get(dlm_lockspace_t *lockspace, u64 number, struct file *file,
+ struct file_lock *fl);
+#endif /* __KERNEL__ */
+
+#endif
+
diff --git a/include/linux/lock_dlm_plock.h b/include/linux/lock_dlm_plock.h
deleted file mode 100644
index fc34151..0000000
--- a/include/linux/lock_dlm_plock.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2005 Red Hat, Inc. All rights reserved.
- *
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU General Public License v.2.
- */
-
-#ifndef __LOCK_DLM_PLOCK_DOT_H__
-#define __LOCK_DLM_PLOCK_DOT_H__
-
-#define GDLM_PLOCK_MISC_NAME "lock_dlm_plock"
-
-#define GDLM_PLOCK_VERSION_MAJOR 1
-#define GDLM_PLOCK_VERSION_MINOR 1
-#define GDLM_PLOCK_VERSION_PATCH 0
-
-enum {
- GDLM_PLOCK_OP_LOCK = 1,
- GDLM_PLOCK_OP_UNLOCK,
- GDLM_PLOCK_OP_GET,
-};
-
-struct gdlm_plock_info {
- __u32 version[3];
- __u8 optype;
- __u8 ex;
- __u8 wait;
- __u8 pad;
- __u32 pid;
- __s32 nodeid;
- __s32 rv;
- __u32 fsid;
- __u64 number;
- __u64 start;
- __u64 end;
- __u64 owner;
-};
-
-#endif
-
--
1.5.3.3
04-15-2008, 09:16 PM
David Teigland
dlm: move plock code from gfs2
On Tue, Apr 15, 2008 at 04:02:26PM -0500, David Teigland wrote:
> Move the code that handles cluster posix locks from gfs2 into the dlm
> so that it can be used by both gfs2 and ocfs2.
Attached is a patch to gfs_controld in STABLE2 to adapt to this change.
Since the cluster STABLE2 branch is meant to run on the latest released
kernel, this won't be commited until 2.6.26 is released.
Dave
04-16-2008, 03:53 AM
"Fabio M. Di Nitto"
dlm: move plock code from gfs2
On Tue, 15 Apr 2008, David Teigland wrote:
On Tue, Apr 15, 2008 at 04:02:26PM -0500, David Teigland wrote:
Move the code that handles cluster posix locks from gfs2 into the dlm
so that it can be used by both gfs2 and ocfs2.
Attached is a patch to gfs_controld in STABLE2 to adapt to this change.
Since the cluster STABLE2 branch is meant to run on the latest released
kernel, this won't be commited until 2.6.26 is released.
Looks like the patch is empty.
Fabio
--
I'm going to make him an offer he can't refuse.
04-16-2008, 01:35 PM
David Teigland
dlm: move plock code from gfs2
On Wed, Apr 16, 2008 at 05:53:43AM +0200, Fabio M. Di Nitto wrote:
> On Tue, 15 Apr 2008, David Teigland wrote:
>
> >On Tue, Apr 15, 2008 at 04:02:26PM -0500, David Teigland wrote:
> >>Move the code that handles cluster posix locks from gfs2 into the dlm
> >>so that it can be used by both gfs2 and ocfs2.
> >
> >Attached is a patch to gfs_controld in STABLE2 to adapt to this change.
> >Since the cluster STABLE2 branch is meant to run on the latest released
> >kernel, this won't be commited until 2.6.26 is released.
>
> Looks like the patch is empty.
thanks, second attempt
04-16-2008, 01:42 PM
David Teigland
dlm: move plock code from gfs2
On Wed, Apr 16, 2008 at 08:35:57AM -0500, David Teigland wrote:
> On Wed, Apr 16, 2008 at 05:53:43AM +0200, Fabio M. Di Nitto wrote:
> > On Tue, 15 Apr 2008, David Teigland wrote:
> >
> > >On Tue, Apr 15, 2008 at 04:02:26PM -0500, David Teigland wrote:
> > >>Move the code that handles cluster posix locks from gfs2 into the dlm
> > >>so that it can be used by both gfs2 and ocfs2.
> > >
> > >Attached is a patch to gfs_controld in STABLE2 to adapt to this change.
> > >Since the cluster STABLE2 branch is meant to run on the latest released
> > >kernel, this won't be commited until 2.6.26 is released.
> >
> > Looks like the patch is empty.
>
> thanks, second attempt
That attachment is empty too, baffling, here it is in the body,
04-16-2008, 01:44 PM
"Fabio M. Di Nitto"
dlm: move plock code from gfs2
On Wed, 16 Apr 2008, David Teigland wrote:
On Wed, Apr 16, 2008 at 05:53:43AM +0200, Fabio M. Di Nitto wrote:
On Tue, 15 Apr 2008, David Teigland wrote:
On Tue, Apr 15, 2008 at 04:02:26PM -0500, David Teigland wrote:
Move the code that handles cluster posix locks from gfs2 into the dlm
so that it can be used by both gfs2 and ocfs2.
Attached is a patch to gfs_controld in STABLE2 to adapt to this change.
Since the cluster STABLE2 branch is meant to run on the latest released
kernel, this won't be commited until 2.6.26 is released.
Looks like the patch is empty.
thanks, second attempt
Looks like a problem with the mailing list. The copy in CC to me had the
patch. The one to the mailing list not.
Am I the only one?
Fabio
--
I'm going to make him an offer he can't refuse.
04-16-2008, 01:54 PM
David Teigland
dlm: move plock code from gfs2
On Wed, Apr 16, 2008 at 08:42:11AM -0500, David Teigland wrote:
> On Wed, Apr 16, 2008 at 08:35:57AM -0500, David Teigland wrote:
> > On Wed, Apr 16, 2008 at 05:53:43AM +0200, Fabio M. Di Nitto wrote:
> > > On Tue, 15 Apr 2008, David Teigland wrote:
> > >
> > > >On Tue, Apr 15, 2008 at 04:02:26PM -0500, David Teigland wrote:
> > > >>Move the code that handles cluster posix locks from gfs2 into the dlm
> > > >>so that it can be used by both gfs2 and ocfs2.
> > > >
> > > >Attached is a patch to gfs_controld in STABLE2 to adapt to this change.
> > > >Since the cluster STABLE2 branch is meant to run on the latest released
> > > >kernel, this won't be commited until 2.6.26 is released.
> > >
> > > Looks like the patch is empty.
> >
> > thanks, second attempt
>
> That attachment is empty too, baffling, here it is in the body,
Looks like the patch headers confused the mailing list. Took them off
this time...
In kernels before 2.6.26, cluster posix lock ops are passed to user
space through the gfs-specific lock_dlm module. In 2.6.26, the same
ops are passed to user space through the dlm module. Update gfs_controld
to read the plock ops from either module, depending on the kernel.
- if (!control_device_number(&major, &minor)) {
- log_error("Is dlm missing from kernel?");
+ if (!control_device_number(plock_misc_name, &major, &minor))
return -1;
- }
if (!control_exists(control, major, minor) &&
!create_control(control, major, minor)) {
- log_error("Failure to communicate with kernel lock_dlm");
+ log_error("Failure to create device file %s", control);
return -1;
}
control_fd = open(control, O_RDWR);
if (control_fd < 0) {
- log_error("Failure to communicate with kernel lock_dlm: %s",
+ log_error("Failure to open device %s: %s", control,
strerror(errno));
return -1;
}
@@ -308,6 +310,16 @@ static int open_control(void)
return 0;
}
+/*
+ * In kernels before 2.6.26, plocks came from gfs2's lock_dlm module.
+ * Reading plocks from there as well should allow us to use cluster3
+ * on old (RHEL5) kernels. In this case, the fsid we read in plock_info
+ * structs is the mountgroup id, which we need to translate to the ls id.
+ */
+
+#define OLD_CONTROL_NAME "lock_dlm_plock"
+#define OLD_PLOCK_MISC_NAME "lock_dlm_plock"
+
int setup_plocks(void)
{
SaAisErrorT err;
@@ -330,14 +342,29 @@ int setup_plocks(void)
log_error("ckpt init error %d - plocks unavailable", err);
control:
- rv = open_control();
- if (rv)
- return rv;
+ need_fsid_translation = 1;
+
+ rv = open_control(CONTROL_NAME, DLM_PLOCK_MISC_NAME);
+ if (rv) {
+ log_debug("setup_plocks trying old lock_dlm interface");
+ rv = open_control(OLD_CONTROL_NAME, OLD_PLOCK_MISC_NAME);
+ if (rv) {
+ log_error("Is dlm missing from kernel? No control device.");
+ return rv;
+ }
+
+ /* the fsid from the kernel is the mountgroup id in old
+ kernels, which we can use to look up the mg directly
+ without translation */
+
+ need_fsid_translation = 0;
+ }
/* if we've already sent an own message for this resource,
(pending list is not empty), then we shouldn't send another */
@@ -1090,7 +1120,7 @@ static void send_own(struct mountgroup *mg, struct resource *r, int owner)
memset(&info, 0, sizeof(info));
info.number = r->number;
@@ -1139,7 +1169,7 @@ static void send_drop(struct mountgroup *mg, struct resource *r)
so the op is saved on the pending list until the r owner is established */