2013-07-04 06:09:06 +08:00
|
|
|
/* Copyright (c) 2013 Coraid, Inc. See COPYING for GPL terms. */
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* aoecmd.c
|
|
|
|
* Filesystem request handling methods
|
|
|
|
*/
|
|
|
|
|
2009-04-02 03:42:24 +08:00
|
|
|
#include <linux/ata.h>
|
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h
percpu.h is included by sched.h and module.h and thus ends up being
included when building most .c files. percpu.h includes slab.h which
in turn includes gfp.h making everything defined by the two files
universally available and complicating inclusion dependencies.
percpu.h -> slab.h dependency is about to be removed. Prepare for
this change by updating users of gfp and slab facilities include those
headers directly instead of assuming availability. As this conversion
needs to touch large number of source files, the following script is
used as the basis of conversion.
http://userweb.kernel.org/~tj/misc/slabh-sweep.py
The script does the followings.
* Scan files for gfp and slab usages and update includes such that
only the necessary includes are there. ie. if only gfp is used,
gfp.h, if slab is used, slab.h.
* When the script inserts a new include, it looks at the include
blocks and try to put the new include such that its order conforms
to its surrounding. It's put in the include block which contains
core kernel includes, in the same order that the rest are ordered -
alphabetical, Christmas tree, rev-Xmas-tree or at the end if there
doesn't seem to be any matching order.
* If the script can't find a place to put a new include (mostly
because the file doesn't have fitting include block), it prints out
an error message indicating which .h file needs to be added to the
file.
The conversion was done in the following steps.
1. The initial automatic conversion of all .c files updated slightly
over 4000 files, deleting around 700 includes and adding ~480 gfp.h
and ~3000 slab.h inclusions. The script emitted errors for ~400
files.
2. Each error was manually checked. Some didn't need the inclusion,
some needed manual addition while adding it to implementation .h or
embedding .c file was more appropriate for others. This step added
inclusions to around 150 files.
3. The script was run again and the output was compared to the edits
from #2 to make sure no file was left behind.
4. Several build tests were done and a couple of problems were fixed.
e.g. lib/decompress_*.c used malloc/free() wrappers around slab
APIs requiring slab.h to be added manually.
5. The script was run on all .h files but without automatically
editing them as sprinkling gfp.h and slab.h inclusions around .h
files could easily lead to inclusion dependency hell. Most gfp.h
inclusion directives were ignored as stuff from gfp.h was usually
wildly available and often used in preprocessor macros. Each
slab.h inclusion directive was examined and added manually as
necessary.
6. percpu.h was updated not to include slab.h.
7. Build test were done on the following configurations and failures
were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my
distributed build env didn't work with gcov compiles) and a few
more options had to be turned off depending on archs to make things
build (like ipr on powerpc/64 which failed due to missing writeq).
* x86 and x86_64 UP and SMP allmodconfig and a custom test config.
* powerpc and powerpc64 SMP allmodconfig
* sparc and sparc64 SMP allmodconfig
* ia64 SMP allmodconfig
* s390 SMP allmodconfig
* alpha SMP allmodconfig
* um on x86_64 SMP allmodconfig
8. percpu.h modifications were reverted so that it could be applied as
a separate patch and serve as bisection point.
Given the fact that I had only a couple of failures from tests on step
6, I'm fairly confident about the coverage of this conversion patch.
If there is a breakage, it's likely to be something in one of the arch
headers which should be easily discoverable easily on most builds of
the specific arch.
Signed-off-by: Tejun Heo <tj@kernel.org>
Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
2010-03-24 16:04:11 +08:00
|
|
|
#include <linux/slab.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <linux/hdreg.h>
|
2018-10-13 00:03:14 +08:00
|
|
|
#include <linux/blk-mq.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <linux/skbuff.h>
|
|
|
|
#include <linux/netdevice.h>
|
2006-01-20 02:46:19 +08:00
|
|
|
#include <linux/genhd.h>
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
#include <linux/moduleparam.h>
|
2012-10-05 08:16:21 +08:00
|
|
|
#include <linux/workqueue.h>
|
|
|
|
#include <linux/kthread.h>
|
2007-09-18 02:56:21 +08:00
|
|
|
#include <net/net_namespace.h>
|
2005-09-30 00:47:40 +08:00
|
|
|
#include <asm/unaligned.h>
|
2012-10-05 08:16:21 +08:00
|
|
|
#include <linux/uio.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include "aoe.h"
|
|
|
|
|
2012-10-05 08:16:21 +08:00
|
|
|
#define MAXIOC (8192) /* default meant to avoid most soft lockups */
|
|
|
|
|
|
|
|
static void ktcomplete(struct frame *, struct sk_buff *);
|
2012-12-18 08:04:08 +08:00
|
|
|
static int count_targets(struct aoedev *d, int *untainted);
|
2012-10-05 08:16:21 +08:00
|
|
|
|
2012-10-05 08:16:23 +08:00
|
|
|
static struct buf *nextbuf(struct aoedev *);
|
|
|
|
|
2006-09-21 02:36:50 +08:00
|
|
|
static int aoe_deadsecs = 60 * 3;
|
|
|
|
module_param(aoe_deadsecs, int, 0644);
|
|
|
|
MODULE_PARM_DESC(aoe_deadsecs, "After aoe_deadsecs seconds, give up and fail dev.");
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2012-12-18 08:04:00 +08:00
|
|
|
static int aoe_maxout = 64;
|
2008-02-08 20:20:07 +08:00
|
|
|
module_param(aoe_maxout, int, 0644);
|
|
|
|
MODULE_PARM_DESC(aoe_maxout,
|
|
|
|
"Only aoe_maxout outstanding packets for every MAC on eX.Y.");
|
|
|
|
|
2013-07-04 06:09:05 +08:00
|
|
|
/* The number of online cpus during module initialization gives us a
|
|
|
|
* convenient heuristic cap on the parallelism used for ktio threads
|
|
|
|
* doing I/O completion. It is not important that the cap equal the
|
|
|
|
* actual number of running CPUs at any given time, but because of CPU
|
|
|
|
* hotplug, we take care to use ncpus instead of using
|
|
|
|
* num_online_cpus() after module initialization.
|
|
|
|
*/
|
|
|
|
static int ncpus;
|
|
|
|
|
|
|
|
/* mutex lock used for synchronization while thread spawning */
|
|
|
|
static DEFINE_MUTEX(ktio_spawn_lock);
|
|
|
|
|
|
|
|
static wait_queue_head_t *ktiowq;
|
|
|
|
static struct ktstate *kts;
|
2012-10-05 08:16:21 +08:00
|
|
|
|
|
|
|
/* io completion queue */
|
2013-07-04 06:09:05 +08:00
|
|
|
struct iocq_ktio {
|
2012-10-05 08:16:21 +08:00
|
|
|
struct list_head head;
|
|
|
|
spinlock_t lock;
|
2013-07-04 06:09:05 +08:00
|
|
|
};
|
|
|
|
static struct iocq_ktio *iocq;
|
2012-10-05 08:16:21 +08:00
|
|
|
|
2012-12-18 08:04:08 +08:00
|
|
|
static struct page *empty_page;
|
|
|
|
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
static struct sk_buff *
|
2006-09-21 02:36:49 +08:00
|
|
|
new_skb(ulong len)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct sk_buff *skb;
|
|
|
|
|
2013-03-28 02:28:41 +08:00
|
|
|
skb = alloc_skb(len + MAX_HEADER, GFP_ATOMIC);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (skb) {
|
2013-03-28 02:28:41 +08:00
|
|
|
skb_reserve(skb, MAX_HEADER);
|
2007-03-20 06:30:44 +08:00
|
|
|
skb_reset_mac_header(skb);
|
2007-04-11 11:45:18 +08:00
|
|
|
skb_reset_network_header(skb);
|
2005-04-17 06:20:36 +08:00
|
|
|
skb->protocol = __constant_htons(ETH_P_AOE);
|
2012-09-19 23:46:39 +08:00
|
|
|
skb_checksum_none_assert(skb);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
return skb;
|
|
|
|
}
|
|
|
|
|
2012-12-18 08:03:43 +08:00
|
|
|
static struct frame *
|
|
|
|
getframe_deferred(struct aoedev *d, u32 tag)
|
|
|
|
{
|
|
|
|
struct list_head *head, *pos, *nx;
|
|
|
|
struct frame *f;
|
|
|
|
|
|
|
|
head = &d->rexmitq;
|
|
|
|
list_for_each_safe(pos, nx, head) {
|
|
|
|
f = list_entry(pos, struct frame, head);
|
|
|
|
if (f->tag == tag) {
|
|
|
|
list_del(pos);
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
static struct frame *
|
2012-10-05 08:16:33 +08:00
|
|
|
getframe(struct aoedev *d, u32 tag)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2012-10-05 08:16:21 +08:00
|
|
|
struct frame *f;
|
|
|
|
struct list_head *head, *pos, *nx;
|
|
|
|
u32 n;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2012-10-05 08:16:21 +08:00
|
|
|
n = tag % NFACTIVE;
|
2012-10-05 08:16:33 +08:00
|
|
|
head = &d->factive[n];
|
2012-10-05 08:16:21 +08:00
|
|
|
list_for_each_safe(pos, nx, head) {
|
|
|
|
f = list_entry(pos, struct frame, head);
|
|
|
|
if (f->tag == tag) {
|
|
|
|
list_del(pos);
|
2005-04-17 06:20:36 +08:00
|
|
|
return f;
|
2012-10-05 08:16:21 +08:00
|
|
|
}
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Leave the top bit clear so we have tagspace for userland.
|
|
|
|
* The bottom 16 bits are the xmit tick for rexmit/rttavg processing.
|
|
|
|
* This driver reserves tag -1 to mean "unused frame."
|
|
|
|
*/
|
|
|
|
static int
|
2012-10-05 08:16:33 +08:00
|
|
|
newtag(struct aoedev *d)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
register ulong n;
|
|
|
|
|
|
|
|
n = jiffies & 0xffff;
|
2012-10-05 08:16:33 +08:00
|
|
|
return n |= (++d->lasttag & 0x7fff) << 16;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2012-10-05 08:16:21 +08:00
|
|
|
static u32
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
aoehdr_atainit(struct aoedev *d, struct aoetgt *t, struct aoe_hdr *h)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2012-10-05 08:16:33 +08:00
|
|
|
u32 host_tag = newtag(d);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
memcpy(h->src, t->ifp->nd->dev_addr, sizeof h->src);
|
|
|
|
memcpy(h->dst, t->addr, sizeof h->dst);
|
2005-04-19 13:00:20 +08:00
|
|
|
h->type = __constant_cpu_to_be16(ETH_P_AOE);
|
2005-04-17 06:20:36 +08:00
|
|
|
h->verfl = AOE_HVER;
|
2005-04-19 13:00:20 +08:00
|
|
|
h->major = cpu_to_be16(d->aoemajor);
|
2005-04-17 06:20:36 +08:00
|
|
|
h->minor = d->aoeminor;
|
|
|
|
h->cmd = AOECMD_ATA;
|
2005-04-19 13:00:20 +08:00
|
|
|
h->tag = cpu_to_be32(host_tag);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
return host_tag;
|
|
|
|
}
|
|
|
|
|
2006-09-21 02:36:49 +08:00
|
|
|
static inline void
|
|
|
|
put_lba(struct aoe_atahdr *ah, sector_t lba)
|
|
|
|
{
|
|
|
|
ah->lba0 = lba;
|
|
|
|
ah->lba1 = lba >>= 8;
|
|
|
|
ah->lba2 = lba >>= 8;
|
|
|
|
ah->lba3 = lba >>= 8;
|
|
|
|
ah->lba4 = lba >>= 8;
|
|
|
|
ah->lba5 = lba >>= 8;
|
|
|
|
}
|
|
|
|
|
2012-10-05 08:16:27 +08:00
|
|
|
static struct aoeif *
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
ifrotate(struct aoetgt *t)
|
|
|
|
{
|
2012-10-05 08:16:27 +08:00
|
|
|
struct aoeif *ifp;
|
|
|
|
|
|
|
|
ifp = t->ifp;
|
|
|
|
ifp++;
|
|
|
|
if (ifp >= &t->ifs[NAOEIFS] || ifp->nd == NULL)
|
|
|
|
ifp = t->ifs;
|
|
|
|
if (ifp->nd == NULL)
|
|
|
|
return NULL;
|
|
|
|
return t->ifp = ifp;
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
}
|
|
|
|
|
aoe: dynamically allocate a capped number of skbs when necessary
What this Patch Does
Even before this recent series of 12 patches to 2.6.22-rc4, the aoe
driver was reusing a small set of skbs that were allocated once and
were only used for outbound AoE commands.
The network layer cannot be allowed to put_page on the data that is
still associated with a bio we haven't returned to the block layer,
so the aoe driver (even before the patch under discussion) is still
the owner of skbs that have been handed to the network layer for
transmission. We need to keep track of these skbs so that we can
free them, but by tracking them, we can also easily re-use them.
The new patch was a response to the behavior of certain network
drivers. We cannot reuse an skb that the network driver still has
in its transmit ring. Network drivers can defer transmit ring
cleanup and then use the state in the skb to determine how many data
segments to clean up in its transmit ring. The tg3 driver is one
driver that behaves in this way.
When the network driver defers cleanup of its transmit ring, the aoe
driver can find itself in a situation where it would like to send an
AoE command, and the AoE target is ready for more work, but the
network driver still has all of the pre-allocated skbs. In that
case, the new patch just calls alloc_skb, as you'd expect.
We don't want to get carried away, though. We try not to do
excessive allocation in the write path, so we cap the number of skbs
we dynamically allocate.
Probably calling it a "dynamic pool" is misleading. We were already
trying to use a small fixed-size set of pre-allocated skbs before
this patch, and this patch just provides a little headroom (with a
ceiling, though) to accomodate network drivers that hang onto skbs,
by allocating when needed. The d->skbpool_hd list of allocated skbs
is necessary so that we can free them later.
We didn't notice the need for this headroom until AoE targets got
fast enough.
Alternatives
If the network layer never did a put_page on the pages in the bio's
we get from the block layer, then it would be possible for us to
hand skbs to the network layer and forget about them, allowing the
network layer to free skbs itself (and thereby calling our own
skb->destructor callback function if we needed that). In that case
we could get rid of the pre-allocated skbs and also the
d->skbpool_hd, instead just calling alloc_skb every time we wanted
to transmit a packet. The slab allocator would effectively maintain
the list of skbs.
Besides a loss of CPU cache locality, the main concern with that
approach the danger that it would increase the likelihood of
deadlock when VM is trying to free pages by writing dirty data from
the page cache through the aoe driver out to persistent storage on
an AoE device. Right now we have a situation where we have
pre-allocation that corresponds to how much we use, which seems
ideal.
Of course, there's still the separate issue of receiving the packets
that tell us that a write has successfully completed on the AoE
target. When memory is low and VM is using AoE to flush dirty data
to free up pages, it would be perfect if there were a way for us to
register a fast callback that could recognize write command
completion responses. But I don't think the current problems with
the receive side of the situation are a justification for
exacerbating the problem on the transmit side.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:05 +08:00
|
|
|
static void
|
|
|
|
skb_pool_put(struct aoedev *d, struct sk_buff *skb)
|
|
|
|
{
|
2008-09-22 13:36:49 +08:00
|
|
|
__skb_queue_tail(&d->skbpool, skb);
|
aoe: dynamically allocate a capped number of skbs when necessary
What this Patch Does
Even before this recent series of 12 patches to 2.6.22-rc4, the aoe
driver was reusing a small set of skbs that were allocated once and
were only used for outbound AoE commands.
The network layer cannot be allowed to put_page on the data that is
still associated with a bio we haven't returned to the block layer,
so the aoe driver (even before the patch under discussion) is still
the owner of skbs that have been handed to the network layer for
transmission. We need to keep track of these skbs so that we can
free them, but by tracking them, we can also easily re-use them.
The new patch was a response to the behavior of certain network
drivers. We cannot reuse an skb that the network driver still has
in its transmit ring. Network drivers can defer transmit ring
cleanup and then use the state in the skb to determine how many data
segments to clean up in its transmit ring. The tg3 driver is one
driver that behaves in this way.
When the network driver defers cleanup of its transmit ring, the aoe
driver can find itself in a situation where it would like to send an
AoE command, and the AoE target is ready for more work, but the
network driver still has all of the pre-allocated skbs. In that
case, the new patch just calls alloc_skb, as you'd expect.
We don't want to get carried away, though. We try not to do
excessive allocation in the write path, so we cap the number of skbs
we dynamically allocate.
Probably calling it a "dynamic pool" is misleading. We were already
trying to use a small fixed-size set of pre-allocated skbs before
this patch, and this patch just provides a little headroom (with a
ceiling, though) to accomodate network drivers that hang onto skbs,
by allocating when needed. The d->skbpool_hd list of allocated skbs
is necessary so that we can free them later.
We didn't notice the need for this headroom until AoE targets got
fast enough.
Alternatives
If the network layer never did a put_page on the pages in the bio's
we get from the block layer, then it would be possible for us to
hand skbs to the network layer and forget about them, allowing the
network layer to free skbs itself (and thereby calling our own
skb->destructor callback function if we needed that). In that case
we could get rid of the pre-allocated skbs and also the
d->skbpool_hd, instead just calling alloc_skb every time we wanted
to transmit a packet. The slab allocator would effectively maintain
the list of skbs.
Besides a loss of CPU cache locality, the main concern with that
approach the danger that it would increase the likelihood of
deadlock when VM is trying to free pages by writing dirty data from
the page cache through the aoe driver out to persistent storage on
an AoE device. Right now we have a situation where we have
pre-allocation that corresponds to how much we use, which seems
ideal.
Of course, there's still the separate issue of receiving the packets
that tell us that a write has successfully completed on the AoE
target. When memory is low and VM is using AoE to flush dirty data
to free up pages, it would be perfect if there were a way for us to
register a fast callback that could recognize write command
completion responses. But I don't think the current problems with
the receive side of the situation are a justification for
exacerbating the problem on the transmit side.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct sk_buff *
|
|
|
|
skb_pool_get(struct aoedev *d)
|
|
|
|
{
|
2008-09-22 13:36:49 +08:00
|
|
|
struct sk_buff *skb = skb_peek(&d->skbpool);
|
aoe: dynamically allocate a capped number of skbs when necessary
What this Patch Does
Even before this recent series of 12 patches to 2.6.22-rc4, the aoe
driver was reusing a small set of skbs that were allocated once and
were only used for outbound AoE commands.
The network layer cannot be allowed to put_page on the data that is
still associated with a bio we haven't returned to the block layer,
so the aoe driver (even before the patch under discussion) is still
the owner of skbs that have been handed to the network layer for
transmission. We need to keep track of these skbs so that we can
free them, but by tracking them, we can also easily re-use them.
The new patch was a response to the behavior of certain network
drivers. We cannot reuse an skb that the network driver still has
in its transmit ring. Network drivers can defer transmit ring
cleanup and then use the state in the skb to determine how many data
segments to clean up in its transmit ring. The tg3 driver is one
driver that behaves in this way.
When the network driver defers cleanup of its transmit ring, the aoe
driver can find itself in a situation where it would like to send an
AoE command, and the AoE target is ready for more work, but the
network driver still has all of the pre-allocated skbs. In that
case, the new patch just calls alloc_skb, as you'd expect.
We don't want to get carried away, though. We try not to do
excessive allocation in the write path, so we cap the number of skbs
we dynamically allocate.
Probably calling it a "dynamic pool" is misleading. We were already
trying to use a small fixed-size set of pre-allocated skbs before
this patch, and this patch just provides a little headroom (with a
ceiling, though) to accomodate network drivers that hang onto skbs,
by allocating when needed. The d->skbpool_hd list of allocated skbs
is necessary so that we can free them later.
We didn't notice the need for this headroom until AoE targets got
fast enough.
Alternatives
If the network layer never did a put_page on the pages in the bio's
we get from the block layer, then it would be possible for us to
hand skbs to the network layer and forget about them, allowing the
network layer to free skbs itself (and thereby calling our own
skb->destructor callback function if we needed that). In that case
we could get rid of the pre-allocated skbs and also the
d->skbpool_hd, instead just calling alloc_skb every time we wanted
to transmit a packet. The slab allocator would effectively maintain
the list of skbs.
Besides a loss of CPU cache locality, the main concern with that
approach the danger that it would increase the likelihood of
deadlock when VM is trying to free pages by writing dirty data from
the page cache through the aoe driver out to persistent storage on
an AoE device. Right now we have a situation where we have
pre-allocation that corresponds to how much we use, which seems
ideal.
Of course, there's still the separate issue of receiving the packets
that tell us that a write has successfully completed on the AoE
target. When memory is low and VM is using AoE to flush dirty data
to free up pages, it would be perfect if there were a way for us to
register a fast callback that could recognize write command
completion responses. But I don't think the current problems with
the receive side of the situation are a justification for
exacerbating the problem on the transmit side.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:05 +08:00
|
|
|
|
|
|
|
if (skb && atomic_read(&skb_shinfo(skb)->dataref) == 1) {
|
2008-09-22 13:36:49 +08:00
|
|
|
__skb_unlink(skb, &d->skbpool);
|
aoe: dynamically allocate a capped number of skbs when necessary
What this Patch Does
Even before this recent series of 12 patches to 2.6.22-rc4, the aoe
driver was reusing a small set of skbs that were allocated once and
were only used for outbound AoE commands.
The network layer cannot be allowed to put_page on the data that is
still associated with a bio we haven't returned to the block layer,
so the aoe driver (even before the patch under discussion) is still
the owner of skbs that have been handed to the network layer for
transmission. We need to keep track of these skbs so that we can
free them, but by tracking them, we can also easily re-use them.
The new patch was a response to the behavior of certain network
drivers. We cannot reuse an skb that the network driver still has
in its transmit ring. Network drivers can defer transmit ring
cleanup and then use the state in the skb to determine how many data
segments to clean up in its transmit ring. The tg3 driver is one
driver that behaves in this way.
When the network driver defers cleanup of its transmit ring, the aoe
driver can find itself in a situation where it would like to send an
AoE command, and the AoE target is ready for more work, but the
network driver still has all of the pre-allocated skbs. In that
case, the new patch just calls alloc_skb, as you'd expect.
We don't want to get carried away, though. We try not to do
excessive allocation in the write path, so we cap the number of skbs
we dynamically allocate.
Probably calling it a "dynamic pool" is misleading. We were already
trying to use a small fixed-size set of pre-allocated skbs before
this patch, and this patch just provides a little headroom (with a
ceiling, though) to accomodate network drivers that hang onto skbs,
by allocating when needed. The d->skbpool_hd list of allocated skbs
is necessary so that we can free them later.
We didn't notice the need for this headroom until AoE targets got
fast enough.
Alternatives
If the network layer never did a put_page on the pages in the bio's
we get from the block layer, then it would be possible for us to
hand skbs to the network layer and forget about them, allowing the
network layer to free skbs itself (and thereby calling our own
skb->destructor callback function if we needed that). In that case
we could get rid of the pre-allocated skbs and also the
d->skbpool_hd, instead just calling alloc_skb every time we wanted
to transmit a packet. The slab allocator would effectively maintain
the list of skbs.
Besides a loss of CPU cache locality, the main concern with that
approach the danger that it would increase the likelihood of
deadlock when VM is trying to free pages by writing dirty data from
the page cache through the aoe driver out to persistent storage on
an AoE device. Right now we have a situation where we have
pre-allocation that corresponds to how much we use, which seems
ideal.
Of course, there's still the separate issue of receiving the packets
that tell us that a write has successfully completed on the AoE
target. When memory is low and VM is using AoE to flush dirty data
to free up pages, it would be perfect if there were a way for us to
register a fast callback that could recognize write command
completion responses. But I don't think the current problems with
the receive side of the situation are a justification for
exacerbating the problem on the transmit side.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:05 +08:00
|
|
|
return skb;
|
|
|
|
}
|
2008-09-22 13:36:49 +08:00
|
|
|
if (skb_queue_len(&d->skbpool) < NSKBPOOLMAX &&
|
|
|
|
(skb = new_skb(ETH_ZLEN)))
|
aoe: dynamically allocate a capped number of skbs when necessary
What this Patch Does
Even before this recent series of 12 patches to 2.6.22-rc4, the aoe
driver was reusing a small set of skbs that were allocated once and
were only used for outbound AoE commands.
The network layer cannot be allowed to put_page on the data that is
still associated with a bio we haven't returned to the block layer,
so the aoe driver (even before the patch under discussion) is still
the owner of skbs that have been handed to the network layer for
transmission. We need to keep track of these skbs so that we can
free them, but by tracking them, we can also easily re-use them.
The new patch was a response to the behavior of certain network
drivers. We cannot reuse an skb that the network driver still has
in its transmit ring. Network drivers can defer transmit ring
cleanup and then use the state in the skb to determine how many data
segments to clean up in its transmit ring. The tg3 driver is one
driver that behaves in this way.
When the network driver defers cleanup of its transmit ring, the aoe
driver can find itself in a situation where it would like to send an
AoE command, and the AoE target is ready for more work, but the
network driver still has all of the pre-allocated skbs. In that
case, the new patch just calls alloc_skb, as you'd expect.
We don't want to get carried away, though. We try not to do
excessive allocation in the write path, so we cap the number of skbs
we dynamically allocate.
Probably calling it a "dynamic pool" is misleading. We were already
trying to use a small fixed-size set of pre-allocated skbs before
this patch, and this patch just provides a little headroom (with a
ceiling, though) to accomodate network drivers that hang onto skbs,
by allocating when needed. The d->skbpool_hd list of allocated skbs
is necessary so that we can free them later.
We didn't notice the need for this headroom until AoE targets got
fast enough.
Alternatives
If the network layer never did a put_page on the pages in the bio's
we get from the block layer, then it would be possible for us to
hand skbs to the network layer and forget about them, allowing the
network layer to free skbs itself (and thereby calling our own
skb->destructor callback function if we needed that). In that case
we could get rid of the pre-allocated skbs and also the
d->skbpool_hd, instead just calling alloc_skb every time we wanted
to transmit a packet. The slab allocator would effectively maintain
the list of skbs.
Besides a loss of CPU cache locality, the main concern with that
approach the danger that it would increase the likelihood of
deadlock when VM is trying to free pages by writing dirty data from
the page cache through the aoe driver out to persistent storage on
an AoE device. Right now we have a situation where we have
pre-allocation that corresponds to how much we use, which seems
ideal.
Of course, there's still the separate issue of receiving the packets
that tell us that a write has successfully completed on the AoE
target. When memory is low and VM is using AoE to flush dirty data
to free up pages, it would be perfect if there were a way for us to
register a fast callback that could recognize write command
completion responses. But I don't think the current problems with
the receive side of the situation are a justification for
exacerbating the problem on the transmit side.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:05 +08:00
|
|
|
return skb;
|
2008-09-22 13:36:49 +08:00
|
|
|
|
aoe: dynamically allocate a capped number of skbs when necessary
What this Patch Does
Even before this recent series of 12 patches to 2.6.22-rc4, the aoe
driver was reusing a small set of skbs that were allocated once and
were only used for outbound AoE commands.
The network layer cannot be allowed to put_page on the data that is
still associated with a bio we haven't returned to the block layer,
so the aoe driver (even before the patch under discussion) is still
the owner of skbs that have been handed to the network layer for
transmission. We need to keep track of these skbs so that we can
free them, but by tracking them, we can also easily re-use them.
The new patch was a response to the behavior of certain network
drivers. We cannot reuse an skb that the network driver still has
in its transmit ring. Network drivers can defer transmit ring
cleanup and then use the state in the skb to determine how many data
segments to clean up in its transmit ring. The tg3 driver is one
driver that behaves in this way.
When the network driver defers cleanup of its transmit ring, the aoe
driver can find itself in a situation where it would like to send an
AoE command, and the AoE target is ready for more work, but the
network driver still has all of the pre-allocated skbs. In that
case, the new patch just calls alloc_skb, as you'd expect.
We don't want to get carried away, though. We try not to do
excessive allocation in the write path, so we cap the number of skbs
we dynamically allocate.
Probably calling it a "dynamic pool" is misleading. We were already
trying to use a small fixed-size set of pre-allocated skbs before
this patch, and this patch just provides a little headroom (with a
ceiling, though) to accomodate network drivers that hang onto skbs,
by allocating when needed. The d->skbpool_hd list of allocated skbs
is necessary so that we can free them later.
We didn't notice the need for this headroom until AoE targets got
fast enough.
Alternatives
If the network layer never did a put_page on the pages in the bio's
we get from the block layer, then it would be possible for us to
hand skbs to the network layer and forget about them, allowing the
network layer to free skbs itself (and thereby calling our own
skb->destructor callback function if we needed that). In that case
we could get rid of the pre-allocated skbs and also the
d->skbpool_hd, instead just calling alloc_skb every time we wanted
to transmit a packet. The slab allocator would effectively maintain
the list of skbs.
Besides a loss of CPU cache locality, the main concern with that
approach the danger that it would increase the likelihood of
deadlock when VM is trying to free pages by writing dirty data from
the page cache through the aoe driver out to persistent storage on
an AoE device. Right now we have a situation where we have
pre-allocation that corresponds to how much we use, which seems
ideal.
Of course, there's still the separate issue of receiving the packets
that tell us that a write has successfully completed on the AoE
target. When memory is low and VM is using AoE to flush dirty data
to free up pages, it would be perfect if there were a way for us to
register a fast callback that could recognize write command
completion responses. But I don't think the current problems with
the receive side of the situation are a justification for
exacerbating the problem on the transmit side.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:05 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-10-05 08:16:21 +08:00
|
|
|
void
|
|
|
|
aoe_freetframe(struct frame *f)
|
|
|
|
{
|
|
|
|
struct aoetgt *t;
|
|
|
|
|
|
|
|
t = f->t;
|
|
|
|
f->buf = NULL;
|
2013-08-14 02:41:43 +08:00
|
|
|
memset(&f->iter, 0, sizeof(f->iter));
|
2012-10-05 08:16:21 +08:00
|
|
|
f->r_skb = NULL;
|
2012-12-18 08:04:08 +08:00
|
|
|
f->flags = 0;
|
2012-10-05 08:16:21 +08:00
|
|
|
list_add(&f->head, &t->ffree);
|
|
|
|
}
|
|
|
|
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
static struct frame *
|
2012-10-05 08:16:21 +08:00
|
|
|
newtframe(struct aoedev *d, struct aoetgt *t)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2012-10-05 08:16:21 +08:00
|
|
|
struct frame *f;
|
aoe: dynamically allocate a capped number of skbs when necessary
What this Patch Does
Even before this recent series of 12 patches to 2.6.22-rc4, the aoe
driver was reusing a small set of skbs that were allocated once and
were only used for outbound AoE commands.
The network layer cannot be allowed to put_page on the data that is
still associated with a bio we haven't returned to the block layer,
so the aoe driver (even before the patch under discussion) is still
the owner of skbs that have been handed to the network layer for
transmission. We need to keep track of these skbs so that we can
free them, but by tracking them, we can also easily re-use them.
The new patch was a response to the behavior of certain network
drivers. We cannot reuse an skb that the network driver still has
in its transmit ring. Network drivers can defer transmit ring
cleanup and then use the state in the skb to determine how many data
segments to clean up in its transmit ring. The tg3 driver is one
driver that behaves in this way.
When the network driver defers cleanup of its transmit ring, the aoe
driver can find itself in a situation where it would like to send an
AoE command, and the AoE target is ready for more work, but the
network driver still has all of the pre-allocated skbs. In that
case, the new patch just calls alloc_skb, as you'd expect.
We don't want to get carried away, though. We try not to do
excessive allocation in the write path, so we cap the number of skbs
we dynamically allocate.
Probably calling it a "dynamic pool" is misleading. We were already
trying to use a small fixed-size set of pre-allocated skbs before
this patch, and this patch just provides a little headroom (with a
ceiling, though) to accomodate network drivers that hang onto skbs,
by allocating when needed. The d->skbpool_hd list of allocated skbs
is necessary so that we can free them later.
We didn't notice the need for this headroom until AoE targets got
fast enough.
Alternatives
If the network layer never did a put_page on the pages in the bio's
we get from the block layer, then it would be possible for us to
hand skbs to the network layer and forget about them, allowing the
network layer to free skbs itself (and thereby calling our own
skb->destructor callback function if we needed that). In that case
we could get rid of the pre-allocated skbs and also the
d->skbpool_hd, instead just calling alloc_skb every time we wanted
to transmit a packet. The slab allocator would effectively maintain
the list of skbs.
Besides a loss of CPU cache locality, the main concern with that
approach the danger that it would increase the likelihood of
deadlock when VM is trying to free pages by writing dirty data from
the page cache through the aoe driver out to persistent storage on
an AoE device. Right now we have a situation where we have
pre-allocation that corresponds to how much we use, which seems
ideal.
Of course, there's still the separate issue of receiving the packets
that tell us that a write has successfully completed on the AoE
target. When memory is low and VM is using AoE to flush dirty data
to free up pages, it would be perfect if there were a way for us to
register a fast callback that could recognize write command
completion responses. But I don't think the current problems with
the receive side of the situation are a justification for
exacerbating the problem on the transmit side.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:05 +08:00
|
|
|
struct sk_buff *skb;
|
2012-10-05 08:16:21 +08:00
|
|
|
struct list_head *pos;
|
|
|
|
|
|
|
|
if (list_empty(&t->ffree)) {
|
|
|
|
if (t->falloc >= NSKBPOOLMAX*2)
|
|
|
|
return NULL;
|
|
|
|
f = kcalloc(1, sizeof(*f), GFP_ATOMIC);
|
|
|
|
if (f == NULL)
|
|
|
|
return NULL;
|
|
|
|
t->falloc++;
|
|
|
|
f->t = t;
|
|
|
|
} else {
|
|
|
|
pos = t->ffree.next;
|
|
|
|
list_del(pos);
|
|
|
|
f = list_entry(pos, struct frame, head);
|
|
|
|
}
|
|
|
|
|
|
|
|
skb = f->skb;
|
|
|
|
if (skb == NULL) {
|
|
|
|
f->skb = skb = new_skb(ETH_ZLEN);
|
|
|
|
if (!skb) {
|
|
|
|
bail: aoe_freetframe(f);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (atomic_read(&skb_shinfo(skb)->dataref) != 1) {
|
|
|
|
skb = skb_pool_get(d);
|
|
|
|
if (skb == NULL)
|
|
|
|
goto bail;
|
|
|
|
skb_pool_put(d, f->skb);
|
|
|
|
f->skb = skb;
|
|
|
|
}
|
|
|
|
|
|
|
|
skb->truesize -= skb->data_len;
|
|
|
|
skb_shinfo(skb)->nr_frags = skb->data_len = 0;
|
|
|
|
skb_trim(skb, 0);
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct frame *
|
|
|
|
newframe(struct aoedev *d)
|
|
|
|
{
|
|
|
|
struct frame *f;
|
|
|
|
struct aoetgt *t, **tt;
|
|
|
|
int totout = 0;
|
2012-12-18 08:04:08 +08:00
|
|
|
int use_tainted;
|
|
|
|
int has_untainted;
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
|
2012-12-18 08:04:11 +08:00
|
|
|
if (!d->targets || !d->targets[0]) {
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
printk(KERN_ERR "aoe: NULL TARGETS!\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
2012-10-05 08:16:21 +08:00
|
|
|
tt = d->tgt; /* last used target */
|
2012-12-18 08:04:08 +08:00
|
|
|
for (use_tainted = 0, has_untainted = 0;;) {
|
2012-10-05 08:16:21 +08:00
|
|
|
tt++;
|
2012-12-18 08:04:11 +08:00
|
|
|
if (tt >= &d->targets[d->ntargets] || !*tt)
|
2012-10-05 08:16:21 +08:00
|
|
|
tt = d->targets;
|
|
|
|
t = *tt;
|
2012-12-18 08:04:08 +08:00
|
|
|
if (!t->taint) {
|
|
|
|
has_untainted = 1;
|
|
|
|
totout += t->nout;
|
|
|
|
}
|
2012-10-05 08:16:21 +08:00
|
|
|
if (t->nout < t->maxout
|
2012-12-18 08:04:08 +08:00
|
|
|
&& (use_tainted || !t->taint)
|
2012-10-05 08:16:21 +08:00
|
|
|
&& t->ifp->nd) {
|
|
|
|
f = newtframe(d, t);
|
|
|
|
if (f) {
|
|
|
|
ifrotate(t);
|
2012-10-05 08:16:27 +08:00
|
|
|
d->tgt = tt;
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
return f;
|
|
|
|
}
|
|
|
|
}
|
2012-12-18 08:04:08 +08:00
|
|
|
if (tt == d->tgt) { /* we've looped and found nada */
|
|
|
|
if (!use_tainted && !has_untainted)
|
|
|
|
use_tainted = 1;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
2012-10-05 08:16:21 +08:00
|
|
|
}
|
|
|
|
if (totout == 0) {
|
|
|
|
d->kicked++;
|
|
|
|
d->flags |= DEVFL_KICKME;
|
aoe: dynamically allocate a capped number of skbs when necessary
What this Patch Does
Even before this recent series of 12 patches to 2.6.22-rc4, the aoe
driver was reusing a small set of skbs that were allocated once and
were only used for outbound AoE commands.
The network layer cannot be allowed to put_page on the data that is
still associated with a bio we haven't returned to the block layer,
so the aoe driver (even before the patch under discussion) is still
the owner of skbs that have been handed to the network layer for
transmission. We need to keep track of these skbs so that we can
free them, but by tracking them, we can also easily re-use them.
The new patch was a response to the behavior of certain network
drivers. We cannot reuse an skb that the network driver still has
in its transmit ring. Network drivers can defer transmit ring
cleanup and then use the state in the skb to determine how many data
segments to clean up in its transmit ring. The tg3 driver is one
driver that behaves in this way.
When the network driver defers cleanup of its transmit ring, the aoe
driver can find itself in a situation where it would like to send an
AoE command, and the AoE target is ready for more work, but the
network driver still has all of the pre-allocated skbs. In that
case, the new patch just calls alloc_skb, as you'd expect.
We don't want to get carried away, though. We try not to do
excessive allocation in the write path, so we cap the number of skbs
we dynamically allocate.
Probably calling it a "dynamic pool" is misleading. We were already
trying to use a small fixed-size set of pre-allocated skbs before
this patch, and this patch just provides a little headroom (with a
ceiling, though) to accomodate network drivers that hang onto skbs,
by allocating when needed. The d->skbpool_hd list of allocated skbs
is necessary so that we can free them later.
We didn't notice the need for this headroom until AoE targets got
fast enough.
Alternatives
If the network layer never did a put_page on the pages in the bio's
we get from the block layer, then it would be possible for us to
hand skbs to the network layer and forget about them, allowing the
network layer to free skbs itself (and thereby calling our own
skb->destructor callback function if we needed that). In that case
we could get rid of the pre-allocated skbs and also the
d->skbpool_hd, instead just calling alloc_skb every time we wanted
to transmit a packet. The slab allocator would effectively maintain
the list of skbs.
Besides a loss of CPU cache locality, the main concern with that
approach the danger that it would increase the likelihood of
deadlock when VM is trying to free pages by writing dirty data from
the page cache through the aoe driver out to persistent storage on
an AoE device. Right now we have a situation where we have
pre-allocation that corresponds to how much we use, which seems
ideal.
Of course, there's still the separate issue of receiving the packets
that tell us that a write has successfully completed on the AoE
target. When memory is low and VM is using AoE to flush dirty data
to free up pages, it would be perfect if there were a way for us to
register a fast callback that could recognize write command
completion responses. But I don't think the current problems with
the receive side of the situation are a justification for
exacerbating the problem on the transmit side.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:05 +08:00
|
|
|
}
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-10-05 08:16:20 +08:00
|
|
|
static void
|
2013-08-14 02:41:43 +08:00
|
|
|
skb_fillup(struct sk_buff *skb, struct bio *bio, struct bvec_iter iter)
|
2012-10-05 08:16:20 +08:00
|
|
|
{
|
|
|
|
int frag = 0;
|
2013-08-14 02:41:43 +08:00
|
|
|
struct bio_vec bv;
|
|
|
|
|
|
|
|
__bio_for_each_segment(bv, bio, iter, iter)
|
|
|
|
skb_fill_page_desc(skb, frag++, bv.bv_page,
|
|
|
|
bv.bv_offset, bv.bv_len);
|
2012-10-05 08:16:20 +08:00
|
|
|
}
|
|
|
|
|
2012-10-05 08:16:21 +08:00
|
|
|
static void
|
|
|
|
fhash(struct frame *f)
|
|
|
|
{
|
2012-10-05 08:16:33 +08:00
|
|
|
struct aoedev *d = f->t->d;
|
2012-10-05 08:16:21 +08:00
|
|
|
u32 n;
|
|
|
|
|
|
|
|
n = f->tag % NFACTIVE;
|
2012-10-05 08:16:33 +08:00
|
|
|
list_add_tail(&f->head, &d->factive[n]);
|
2012-10-05 08:16:21 +08:00
|
|
|
}
|
|
|
|
|
2012-12-18 08:04:08 +08:00
|
|
|
static void
|
|
|
|
ata_rw_frameinit(struct frame *f)
|
|
|
|
{
|
|
|
|
struct aoetgt *t;
|
|
|
|
struct aoe_hdr *h;
|
|
|
|
struct aoe_atahdr *ah;
|
|
|
|
struct sk_buff *skb;
|
|
|
|
char writebit, extbit;
|
|
|
|
|
|
|
|
skb = f->skb;
|
|
|
|
h = (struct aoe_hdr *) skb_mac_header(skb);
|
|
|
|
ah = (struct aoe_atahdr *) (h + 1);
|
|
|
|
skb_put(skb, sizeof(*h) + sizeof(*ah));
|
|
|
|
memset(h, 0, skb->len);
|
|
|
|
|
|
|
|
writebit = 0x10;
|
|
|
|
extbit = 0x4;
|
|
|
|
|
|
|
|
t = f->t;
|
|
|
|
f->tag = aoehdr_atainit(t->d, t, h);
|
|
|
|
fhash(f);
|
|
|
|
t->nout++;
|
|
|
|
f->waited = 0;
|
|
|
|
f->waited_total = 0;
|
|
|
|
|
|
|
|
/* set up ata header */
|
2013-08-14 02:41:43 +08:00
|
|
|
ah->scnt = f->iter.bi_size >> 9;
|
|
|
|
put_lba(ah, f->iter.bi_sector);
|
2012-12-18 08:04:08 +08:00
|
|
|
if (t->d->flags & DEVFL_EXT) {
|
|
|
|
ah->aflags |= AOEAFL_EXT;
|
|
|
|
} else {
|
|
|
|
extbit = 0;
|
|
|
|
ah->lba3 &= 0x0f;
|
|
|
|
ah->lba3 |= 0xe0; /* LBA bit + obsolete 0xa0 */
|
|
|
|
}
|
|
|
|
if (f->buf && bio_data_dir(f->buf->bio) == WRITE) {
|
2013-08-14 02:41:43 +08:00
|
|
|
skb_fillup(skb, f->buf->bio, f->iter);
|
2012-12-18 08:04:08 +08:00
|
|
|
ah->aflags |= AOEAFL_WRITE;
|
2013-08-14 02:41:43 +08:00
|
|
|
skb->len += f->iter.bi_size;
|
|
|
|
skb->data_len = f->iter.bi_size;
|
|
|
|
skb->truesize += f->iter.bi_size;
|
2012-12-18 08:04:08 +08:00
|
|
|
t->wpkts++;
|
|
|
|
} else {
|
|
|
|
t->rpkts++;
|
|
|
|
writebit = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ah->cmdstat = ATA_CMD_PIO_READ | writebit | extbit;
|
|
|
|
skb->dev = t->ifp->nd;
|
|
|
|
}
|
|
|
|
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
static int
|
|
|
|
aoecmd_ata_rw(struct aoedev *d)
|
|
|
|
{
|
|
|
|
struct frame *f;
|
2005-04-17 06:20:36 +08:00
|
|
|
struct buf *buf;
|
|
|
|
struct sk_buff *skb;
|
2012-10-05 08:16:23 +08:00
|
|
|
struct sk_buff_head queue;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2012-10-05 08:16:23 +08:00
|
|
|
buf = nextbuf(d);
|
|
|
|
if (buf == NULL)
|
|
|
|
return 0;
|
2012-10-05 08:16:21 +08:00
|
|
|
f = newframe(d);
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
if (f == NULL)
|
|
|
|
return 0;
|
2012-10-05 08:16:20 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/* initialize the headers & frame */
|
|
|
|
f->buf = buf;
|
2013-08-14 02:41:43 +08:00
|
|
|
f->iter = buf->iter;
|
|
|
|
f->iter.bi_size = min_t(unsigned long,
|
|
|
|
d->maxbcnt ?: DEFAULTBCNT,
|
|
|
|
f->iter.bi_size);
|
|
|
|
bio_advance_iter(buf->bio, &buf->iter, f->iter.bi_size);
|
|
|
|
|
|
|
|
if (!buf->iter.bi_size)
|
|
|
|
d->ip.buf = NULL;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/* mark all tracking fields and load out */
|
|
|
|
buf->nframesout += 1;
|
2013-08-14 02:41:43 +08:00
|
|
|
|
|
|
|
ata_rw_frameinit(f);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2012-12-18 08:04:08 +08:00
|
|
|
skb = skb_clone(f->skb, GFP_ATOMIC);
|
2012-10-05 08:16:23 +08:00
|
|
|
if (skb) {
|
2018-01-17 23:30:39 +08:00
|
|
|
f->sent = ktime_get();
|
2012-10-05 08:16:23 +08:00
|
|
|
__skb_queue_head_init(&queue);
|
|
|
|
__skb_queue_tail(&queue, skb);
|
|
|
|
aoenet_xmit(&queue);
|
|
|
|
}
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
return 1;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2006-01-20 02:46:19 +08:00
|
|
|
/* some callers cannot sleep, and they can call this function,
|
|
|
|
* transmitting the packets later, when interrupts are on
|
|
|
|
*/
|
2008-09-22 13:36:49 +08:00
|
|
|
static void
|
|
|
|
aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff_head *queue)
|
2006-01-20 02:46:19 +08:00
|
|
|
{
|
|
|
|
struct aoe_hdr *h;
|
|
|
|
struct aoe_cfghdr *ch;
|
2008-09-22 13:36:49 +08:00
|
|
|
struct sk_buff *skb;
|
2006-01-20 02:46:19 +08:00
|
|
|
struct net_device *ifp;
|
|
|
|
|
2010-10-29 09:15:29 +08:00
|
|
|
rcu_read_lock();
|
|
|
|
for_each_netdev_rcu(&init_net, ifp) {
|
2006-01-20 02:46:19 +08:00
|
|
|
dev_hold(ifp);
|
|
|
|
if (!is_aoe_netif(ifp))
|
2007-05-04 06:13:45 +08:00
|
|
|
goto cont;
|
2006-01-20 02:46:19 +08:00
|
|
|
|
2006-09-21 02:36:49 +08:00
|
|
|
skb = new_skb(sizeof *h + sizeof *ch);
|
2006-01-20 02:46:19 +08:00
|
|
|
if (skb == NULL) {
|
2006-09-21 02:36:51 +08:00
|
|
|
printk(KERN_INFO "aoe: skb alloc failure\n");
|
2007-05-04 06:13:45 +08:00
|
|
|
goto cont;
|
2006-01-20 02:46:19 +08:00
|
|
|
}
|
2006-12-22 17:09:21 +08:00
|
|
|
skb_put(skb, sizeof *h + sizeof *ch);
|
2006-09-21 02:36:49 +08:00
|
|
|
skb->dev = ifp;
|
2008-09-22 13:36:49 +08:00
|
|
|
__skb_queue_tail(queue, skb);
|
2007-10-17 14:27:03 +08:00
|
|
|
h = (struct aoe_hdr *) skb_mac_header(skb);
|
2006-01-20 02:46:19 +08:00
|
|
|
memset(h, 0, sizeof *h + sizeof *ch);
|
|
|
|
|
|
|
|
memset(h->dst, 0xff, sizeof h->dst);
|
|
|
|
memcpy(h->src, ifp->dev_addr, sizeof h->src);
|
|
|
|
h->type = __constant_cpu_to_be16(ETH_P_AOE);
|
|
|
|
h->verfl = AOE_HVER;
|
|
|
|
h->major = cpu_to_be16(aoemajor);
|
|
|
|
h->minor = aoeminor;
|
|
|
|
h->cmd = AOECMD_CFG;
|
|
|
|
|
2007-05-04 06:13:45 +08:00
|
|
|
cont:
|
|
|
|
dev_put(ifp);
|
2006-01-20 02:46:19 +08:00
|
|
|
}
|
2010-10-29 09:15:29 +08:00
|
|
|
rcu_read_unlock();
|
2006-01-20 02:46:19 +08:00
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
static void
|
2012-10-05 08:16:21 +08:00
|
|
|
resend(struct aoedev *d, struct frame *f)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct sk_buff *skb;
|
2012-10-05 08:16:23 +08:00
|
|
|
struct sk_buff_head queue;
|
2005-04-17 06:20:36 +08:00
|
|
|
struct aoe_hdr *h;
|
2012-10-05 08:16:21 +08:00
|
|
|
struct aoetgt *t;
|
2005-04-17 06:20:36 +08:00
|
|
|
char buf[128];
|
|
|
|
u32 n;
|
|
|
|
|
2012-10-05 08:16:21 +08:00
|
|
|
t = f->t;
|
2012-10-05 08:16:33 +08:00
|
|
|
n = newtag(d);
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
skb = f->skb;
|
2012-10-05 08:16:27 +08:00
|
|
|
if (ifrotate(t) == NULL) {
|
|
|
|
/* probably can't happen, but set it up to fail anyway */
|
|
|
|
pr_info("aoe: resend: no interfaces to rotate to.\n");
|
|
|
|
ktcomplete(f, NULL);
|
|
|
|
return;
|
|
|
|
}
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
h = (struct aoe_hdr *) skb_mac_header(skb);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2012-12-18 08:04:08 +08:00
|
|
|
if (!(f->flags & FFL_PROBE)) {
|
|
|
|
snprintf(buf, sizeof(buf),
|
|
|
|
"%15s e%ld.%d oldtag=%08x@%08lx newtag=%08x s=%pm d=%pm nout=%d\n",
|
|
|
|
"retransmit", d->aoemajor, d->aoeminor,
|
|
|
|
f->tag, jiffies, n,
|
|
|
|
h->src, h->dst, t->nout);
|
|
|
|
aoechr_error(buf);
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
f->tag = n;
|
2012-10-05 08:16:21 +08:00
|
|
|
fhash(f);
|
2005-04-19 13:00:20 +08:00
|
|
|
h->tag = cpu_to_be32(n);
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
memcpy(h->dst, t->addr, sizeof h->dst);
|
|
|
|
memcpy(h->src, t->ifp->nd->dev_addr, sizeof h->src);
|
|
|
|
|
|
|
|
skb->dev = t->ifp->nd;
|
2006-09-21 02:36:49 +08:00
|
|
|
skb = skb_clone(skb, GFP_ATOMIC);
|
|
|
|
if (skb == NULL)
|
|
|
|
return;
|
2018-01-17 23:30:39 +08:00
|
|
|
f->sent = ktime_get();
|
2012-10-05 08:16:23 +08:00
|
|
|
__skb_queue_head_init(&queue);
|
|
|
|
__skb_queue_tail(&queue, skb);
|
|
|
|
aoenet_xmit(&queue);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2012-12-18 08:03:49 +08:00
|
|
|
static int
|
|
|
|
tsince_hr(struct frame *f)
|
|
|
|
{
|
2018-01-17 23:30:39 +08:00
|
|
|
u64 delta = ktime_to_ns(ktime_sub(ktime_get(), f->sent));
|
2012-12-18 08:03:49 +08:00
|
|
|
|
2018-01-17 23:30:39 +08:00
|
|
|
/* delta is normally under 4.2 seconds, avoid 64-bit division */
|
|
|
|
if (likely(delta <= UINT_MAX))
|
|
|
|
return (u32)delta / NSEC_PER_USEC;
|
2012-12-18 08:03:49 +08:00
|
|
|
|
2018-01-17 23:30:39 +08:00
|
|
|
/* avoid overflow after 71 minutes */
|
|
|
|
if (delta > ((u64)INT_MAX * NSEC_PER_USEC))
|
|
|
|
return INT_MAX;
|
2012-12-18 08:03:49 +08:00
|
|
|
|
2018-01-17 23:30:39 +08:00
|
|
|
return div_u64(delta, NSEC_PER_USEC);
|
2012-12-18 08:03:49 +08:00
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
static int
|
2012-10-05 08:16:21 +08:00
|
|
|
tsince(u32 tag)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
int n;
|
|
|
|
|
|
|
|
n = jiffies & 0xffff;
|
|
|
|
n -= tag & 0xffff;
|
|
|
|
if (n < 0)
|
|
|
|
n += 1<<16;
|
2012-12-18 08:03:49 +08:00
|
|
|
return jiffies_to_usecs(n + 1);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
static struct aoeif *
|
|
|
|
getif(struct aoetgt *t, struct net_device *nd)
|
|
|
|
{
|
|
|
|
struct aoeif *p, *e;
|
|
|
|
|
|
|
|
p = t->ifs;
|
|
|
|
e = p + NAOEIFS;
|
|
|
|
for (; p < e; p++)
|
|
|
|
if (p->nd == nd)
|
|
|
|
return p;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
ejectif(struct aoetgt *t, struct aoeif *ifp)
|
|
|
|
{
|
|
|
|
struct aoeif *e;
|
2012-10-05 08:16:34 +08:00
|
|
|
struct net_device *nd;
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
ulong n;
|
|
|
|
|
2012-10-05 08:16:34 +08:00
|
|
|
nd = ifp->nd;
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
e = t->ifs + NAOEIFS - 1;
|
|
|
|
n = (e - ifp) * sizeof *ifp;
|
|
|
|
memmove(ifp, ifp+1, n);
|
|
|
|
e->nd = NULL;
|
2012-10-05 08:16:34 +08:00
|
|
|
dev_put(nd);
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
}
|
|
|
|
|
2012-12-18 08:03:51 +08:00
|
|
|
static struct frame *
|
2012-12-18 08:04:08 +08:00
|
|
|
reassign_frame(struct frame *f)
|
2012-12-18 08:03:51 +08:00
|
|
|
{
|
|
|
|
struct frame *nf;
|
|
|
|
struct sk_buff *skb;
|
|
|
|
|
|
|
|
nf = newframe(f->t->d);
|
|
|
|
if (!nf)
|
|
|
|
return NULL;
|
2012-12-18 08:04:08 +08:00
|
|
|
if (nf->t == f->t) {
|
|
|
|
aoe_freetframe(nf);
|
|
|
|
return NULL;
|
|
|
|
}
|
2012-12-18 08:03:51 +08:00
|
|
|
|
|
|
|
skb = nf->skb;
|
|
|
|
nf->skb = f->skb;
|
|
|
|
nf->buf = f->buf;
|
2013-08-14 02:41:43 +08:00
|
|
|
nf->iter = f->iter;
|
2012-12-18 08:03:51 +08:00
|
|
|
nf->waited = 0;
|
|
|
|
nf->waited_total = f->waited_total;
|
|
|
|
nf->sent = f->sent;
|
|
|
|
f->skb = skb;
|
|
|
|
|
|
|
|
return nf;
|
|
|
|
}
|
|
|
|
|
2012-12-18 08:04:08 +08:00
|
|
|
static void
|
|
|
|
probe(struct aoetgt *t)
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
{
|
2012-12-18 08:04:08 +08:00
|
|
|
struct aoedev *d;
|
|
|
|
struct frame *f;
|
|
|
|
struct sk_buff *skb;
|
|
|
|
struct sk_buff_head queue;
|
|
|
|
size_t n, m;
|
|
|
|
int frag;
|
2012-10-05 08:16:21 +08:00
|
|
|
|
2012-12-18 08:04:08 +08:00
|
|
|
d = t->d;
|
|
|
|
f = newtframe(d, t);
|
|
|
|
if (!f) {
|
|
|
|
pr_err("%s %pm for e%ld.%d: %s\n",
|
|
|
|
"aoe: cannot probe remote address",
|
|
|
|
t->addr,
|
|
|
|
(long) d->aoemajor, d->aoeminor,
|
|
|
|
"no frame available");
|
|
|
|
return;
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
}
|
2012-12-18 08:04:08 +08:00
|
|
|
f->flags |= FFL_PROBE;
|
|
|
|
ifrotate(t);
|
2013-08-14 02:41:43 +08:00
|
|
|
f->iter.bi_size = t->d->maxbcnt ? t->d->maxbcnt : DEFAULTBCNT;
|
2012-12-18 08:04:08 +08:00
|
|
|
ata_rw_frameinit(f);
|
|
|
|
skb = f->skb;
|
2013-08-14 02:41:43 +08:00
|
|
|
for (frag = 0, n = f->iter.bi_size; n > 0; ++frag, n -= m) {
|
2012-12-18 08:04:08 +08:00
|
|
|
if (n < PAGE_SIZE)
|
|
|
|
m = n;
|
|
|
|
else
|
|
|
|
m = PAGE_SIZE;
|
|
|
|
skb_fill_page_desc(skb, frag, empty_page, 0, m);
|
2012-12-18 08:03:51 +08:00
|
|
|
}
|
2013-08-14 02:41:43 +08:00
|
|
|
skb->len += f->iter.bi_size;
|
|
|
|
skb->data_len = f->iter.bi_size;
|
|
|
|
skb->truesize += f->iter.bi_size;
|
2012-12-18 08:04:08 +08:00
|
|
|
|
|
|
|
skb = skb_clone(f->skb, GFP_ATOMIC);
|
|
|
|
if (skb) {
|
2018-01-17 23:30:39 +08:00
|
|
|
f->sent = ktime_get();
|
2012-12-18 08:04:08 +08:00
|
|
|
__skb_queue_head_init(&queue);
|
|
|
|
__skb_queue_tail(&queue, skb);
|
|
|
|
aoenet_xmit(&queue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static long
|
|
|
|
rto(struct aoedev *d)
|
|
|
|
{
|
|
|
|
long t;
|
|
|
|
|
|
|
|
t = 2 * d->rttavg >> RTTSCALE;
|
|
|
|
t += 8 * d->rttdev >> RTTDSCALE;
|
|
|
|
if (t == 0)
|
|
|
|
t = 1;
|
|
|
|
|
|
|
|
return t;
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
}
|
|
|
|
|
2012-12-18 08:03:43 +08:00
|
|
|
static void
|
|
|
|
rexmit_deferred(struct aoedev *d)
|
|
|
|
{
|
|
|
|
struct aoetgt *t;
|
|
|
|
struct frame *f;
|
2012-12-18 08:04:08 +08:00
|
|
|
struct frame *nf;
|
2012-12-18 08:03:43 +08:00
|
|
|
struct list_head *pos, *nx, *head;
|
2012-12-18 08:03:51 +08:00
|
|
|
int since;
|
2012-12-18 08:04:08 +08:00
|
|
|
int untainted;
|
|
|
|
|
|
|
|
count_targets(d, &untainted);
|
2012-12-18 08:03:43 +08:00
|
|
|
|
|
|
|
head = &d->rexmitq;
|
|
|
|
list_for_each_safe(pos, nx, head) {
|
|
|
|
f = list_entry(pos, struct frame, head);
|
|
|
|
t = f->t;
|
2012-12-18 08:04:08 +08:00
|
|
|
if (t->taint) {
|
|
|
|
if (!(f->flags & FFL_PROBE)) {
|
|
|
|
nf = reassign_frame(f);
|
|
|
|
if (nf) {
|
|
|
|
if (t->nout_probes == 0
|
|
|
|
&& untainted > 0) {
|
|
|
|
probe(t);
|
|
|
|
t->nout_probes++;
|
|
|
|
}
|
|
|
|
list_replace(&f->head, &nf->head);
|
|
|
|
pos = &nf->head;
|
|
|
|
aoe_freetframe(f);
|
|
|
|
f = nf;
|
|
|
|
t = f->t;
|
|
|
|
}
|
|
|
|
} else if (untainted < 1) {
|
|
|
|
/* don't probe w/o other untainted aoetgts */
|
|
|
|
goto stop_probe;
|
|
|
|
} else if (tsince_hr(f) < t->taint * rto(d)) {
|
|
|
|
/* reprobe slowly when taint is high */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
} else if (f->flags & FFL_PROBE) {
|
|
|
|
stop_probe: /* don't probe untainted aoetgts */
|
|
|
|
list_del(pos);
|
|
|
|
aoe_freetframe(f);
|
|
|
|
/* leaving d->kicked, because this is routine */
|
|
|
|
f->t->d->flags |= DEVFL_KICKME;
|
|
|
|
continue;
|
|
|
|
}
|
2012-12-18 08:03:43 +08:00
|
|
|
if (t->nout >= t->maxout)
|
|
|
|
continue;
|
|
|
|
list_del(pos);
|
|
|
|
t->nout++;
|
2012-12-18 08:04:08 +08:00
|
|
|
if (f->flags & FFL_PROBE)
|
|
|
|
t->nout_probes++;
|
2012-12-18 08:03:51 +08:00
|
|
|
since = tsince_hr(f);
|
|
|
|
f->waited += since;
|
|
|
|
f->waited_total += since;
|
2012-12-18 08:03:43 +08:00
|
|
|
resend(d, f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-18 08:04:08 +08:00
|
|
|
/* An aoetgt accumulates demerits quickly, and successful
|
|
|
|
* probing redeems the aoetgt slowly.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
scorn(struct aoetgt *t)
|
|
|
|
{
|
|
|
|
int n;
|
|
|
|
|
|
|
|
n = t->taint++;
|
|
|
|
t->taint += t->taint * 2;
|
|
|
|
if (n > t->taint)
|
|
|
|
t->taint = n;
|
|
|
|
if (t->taint > MAX_TAINT)
|
|
|
|
t->taint = MAX_TAINT;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
count_targets(struct aoedev *d, int *untainted)
|
|
|
|
{
|
|
|
|
int i, good;
|
|
|
|
|
|
|
|
for (i = good = 0; i < d->ntargets && d->targets[i]; ++i)
|
|
|
|
if (d->targets[i]->taint == 0)
|
|
|
|
good++;
|
|
|
|
|
|
|
|
if (untainted)
|
|
|
|
*untainted = good;
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
static void
|
2017-10-06 07:13:54 +08:00
|
|
|
rexmit_timer(struct timer_list *timer)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct aoedev *d;
|
2012-12-18 08:03:43 +08:00
|
|
|
struct aoetgt *t;
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
struct aoeif *ifp;
|
2012-10-05 08:16:21 +08:00
|
|
|
struct frame *f;
|
|
|
|
struct list_head *head, *pos, *nx;
|
|
|
|
LIST_HEAD(flist);
|
2005-04-17 06:20:36 +08:00
|
|
|
register long timeout;
|
|
|
|
ulong flags, n;
|
2012-10-05 08:16:21 +08:00
|
|
|
int i;
|
2012-12-18 08:04:08 +08:00
|
|
|
int utgts; /* number of aoetgt descriptors (not slots) */
|
2012-12-18 08:03:51 +08:00
|
|
|
int since;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2017-10-06 07:13:54 +08:00
|
|
|
d = from_timer(d, timer, timer);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2012-12-18 08:03:47 +08:00
|
|
|
spin_lock_irqsave(&d->lock, flags);
|
|
|
|
|
2012-12-18 08:03:43 +08:00
|
|
|
/* timeout based on observed timings and variations */
|
2012-12-18 08:04:08 +08:00
|
|
|
timeout = rto(d);
|
|
|
|
|
|
|
|
utgts = count_targets(d, NULL);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
if (d->flags & DEVFL_TKILL) {
|
2006-01-26 02:54:44 +08:00
|
|
|
spin_unlock_irqrestore(&d->lock, flags);
|
2005-04-17 06:20:36 +08:00
|
|
|
return;
|
|
|
|
}
|
2012-10-05 08:16:21 +08:00
|
|
|
|
|
|
|
/* collect all frames to rexmit into flist */
|
2012-10-05 08:16:33 +08:00
|
|
|
for (i = 0; i < NFACTIVE; i++) {
|
|
|
|
head = &d->factive[i];
|
|
|
|
list_for_each_safe(pos, nx, head) {
|
|
|
|
f = list_entry(pos, struct frame, head);
|
2012-12-18 08:03:49 +08:00
|
|
|
if (tsince_hr(f) < timeout)
|
2012-10-05 08:16:33 +08:00
|
|
|
break; /* end of expired frames */
|
|
|
|
/* move to flist for later processing */
|
|
|
|
list_move_tail(pos, &flist);
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
}
|
2012-10-05 08:16:33 +08:00
|
|
|
}
|
2012-10-05 08:16:23 +08:00
|
|
|
|
2012-10-05 08:16:21 +08:00
|
|
|
/* process expired frames */
|
|
|
|
while (!list_empty(&flist)) {
|
|
|
|
pos = flist.next;
|
|
|
|
f = list_entry(pos, struct frame, head);
|
2012-12-18 08:03:51 +08:00
|
|
|
since = tsince_hr(f);
|
|
|
|
n = f->waited_total + since;
|
2012-12-18 08:03:49 +08:00
|
|
|
n /= USEC_PER_SEC;
|
2012-12-18 08:04:14 +08:00
|
|
|
if (aoe_deadsecs
|
|
|
|
&& n > aoe_deadsecs
|
|
|
|
&& !(f->flags & FFL_PROBE)) {
|
2012-10-05 08:16:21 +08:00
|
|
|
/* Waited too long. Device failure.
|
|
|
|
* Hang all frames on first hash bucket for downdev
|
|
|
|
* to clean up.
|
|
|
|
*/
|
2012-10-05 08:16:33 +08:00
|
|
|
list_splice(&flist, &d->factive[0]);
|
2012-10-05 08:16:21 +08:00
|
|
|
aoedev_downdev(d);
|
2012-12-18 08:03:43 +08:00
|
|
|
goto out;
|
2012-10-05 08:16:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
t = f->t;
|
2012-12-18 08:04:08 +08:00
|
|
|
n = f->waited + since;
|
|
|
|
n /= USEC_PER_SEC;
|
|
|
|
if (aoe_deadsecs && utgts > 0
|
|
|
|
&& (n > aoe_deadsecs / utgts || n > HARD_SCORN_SECS))
|
|
|
|
scorn(t); /* avoid this target */
|
2012-10-05 08:16:29 +08:00
|
|
|
|
2012-12-18 08:03:43 +08:00
|
|
|
if (t->maxout != 1) {
|
|
|
|
t->ssthresh = t->maxout / 2;
|
|
|
|
t->maxout = 1;
|
2012-10-05 08:16:21 +08:00
|
|
|
}
|
|
|
|
|
2012-12-18 08:04:08 +08:00
|
|
|
if (f->flags & FFL_PROBE) {
|
|
|
|
t->nout_probes--;
|
|
|
|
} else {
|
|
|
|
ifp = getif(t, f->skb->dev);
|
|
|
|
if (ifp && ++ifp->lost > (t->nframes << 1)
|
|
|
|
&& (ifp != t->ifs || t->ifs[1].nd)) {
|
|
|
|
ejectif(t, ifp);
|
|
|
|
ifp = NULL;
|
|
|
|
}
|
2012-10-05 08:16:21 +08:00
|
|
|
}
|
2012-12-18 08:03:43 +08:00
|
|
|
list_move_tail(pos, &d->rexmitq);
|
|
|
|
t->nout--;
|
2012-10-05 08:16:21 +08:00
|
|
|
}
|
2012-12-18 08:03:43 +08:00
|
|
|
rexmit_deferred(d);
|
2012-10-05 08:16:21 +08:00
|
|
|
|
2012-12-18 08:03:43 +08:00
|
|
|
out:
|
2012-12-18 08:04:08 +08:00
|
|
|
if ((d->flags & DEVFL_KICKME) && d->blkq) {
|
2006-09-21 02:36:49 +08:00
|
|
|
d->flags &= ~DEVFL_KICKME;
|
2018-10-13 00:03:14 +08:00
|
|
|
blk_mq_run_hw_queues(d->blkq, true);
|
2006-09-21 02:36:49 +08:00
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
d->timer.expires = jiffies + TIMERTICK;
|
|
|
|
add_timer(&d->timer);
|
|
|
|
|
|
|
|
spin_unlock_irqrestore(&d->lock, flags);
|
2012-10-05 08:16:23 +08:00
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2012-10-05 08:16:23 +08:00
|
|
|
static void
|
|
|
|
bufinit(struct buf *buf, struct request *rq, struct bio *bio)
|
|
|
|
{
|
|
|
|
memset(buf, 0, sizeof(*buf));
|
|
|
|
buf->rq = rq;
|
|
|
|
buf->bio = bio;
|
2013-08-14 02:41:43 +08:00
|
|
|
buf->iter = bio->bi_iter;
|
2012-10-05 08:16:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct buf *
|
|
|
|
nextbuf(struct aoedev *d)
|
|
|
|
{
|
|
|
|
struct request *rq;
|
|
|
|
struct request_queue *q;
|
2018-11-10 16:30:47 +08:00
|
|
|
struct aoe_req *req;
|
2012-10-05 08:16:23 +08:00
|
|
|
struct buf *buf;
|
|
|
|
struct bio *bio;
|
|
|
|
|
|
|
|
q = d->blkq;
|
|
|
|
if (q == NULL)
|
|
|
|
return NULL; /* initializing */
|
|
|
|
if (d->ip.buf)
|
|
|
|
return d->ip.buf;
|
|
|
|
rq = d->ip.rq;
|
|
|
|
if (rq == NULL) {
|
2018-10-13 00:03:14 +08:00
|
|
|
rq = list_first_entry_or_null(&d->rq_list, struct request,
|
|
|
|
queuelist);
|
2012-10-05 08:16:23 +08:00
|
|
|
if (rq == NULL)
|
|
|
|
return NULL;
|
2018-10-13 00:03:14 +08:00
|
|
|
list_del_init(&rq->queuelist);
|
|
|
|
blk_mq_start_request(rq);
|
2012-10-05 08:16:23 +08:00
|
|
|
d->ip.rq = rq;
|
|
|
|
d->ip.nxbio = rq->bio;
|
2018-11-10 16:30:47 +08:00
|
|
|
|
|
|
|
req = blk_mq_rq_to_pdu(rq);
|
|
|
|
req->nr_bios = 0;
|
|
|
|
__rq_for_each_bio(bio, rq)
|
|
|
|
req->nr_bios++;
|
2012-10-05 08:16:23 +08:00
|
|
|
}
|
|
|
|
buf = mempool_alloc(d->bufpool, GFP_ATOMIC);
|
|
|
|
if (buf == NULL) {
|
|
|
|
pr_err("aoe: nextbuf: unable to mempool_alloc!\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
bio = d->ip.nxbio;
|
|
|
|
bufinit(buf, rq, bio);
|
|
|
|
bio = bio->bi_next;
|
|
|
|
d->ip.nxbio = bio;
|
|
|
|
if (bio == NULL)
|
|
|
|
d->ip.rq = NULL;
|
|
|
|
return d->ip.buf = buf;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
/* enters with d->lock held */
|
|
|
|
void
|
|
|
|
aoecmd_work(struct aoedev *d)
|
|
|
|
{
|
2012-12-18 08:03:43 +08:00
|
|
|
rexmit_deferred(d);
|
2012-10-05 08:16:23 +08:00
|
|
|
while (aoecmd_ata_rw(d))
|
|
|
|
;
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
}
|
|
|
|
|
2006-01-20 02:46:19 +08:00
|
|
|
/* this function performs work that has been deferred until sleeping is OK
|
|
|
|
*/
|
|
|
|
void
|
2006-11-22 22:57:56 +08:00
|
|
|
aoecmd_sleepwork(struct work_struct *work)
|
2006-01-20 02:46:19 +08:00
|
|
|
{
|
2006-11-22 22:57:56 +08:00
|
|
|
struct aoedev *d = container_of(work, struct aoedev, work);
|
2012-10-05 08:16:35 +08:00
|
|
|
struct block_device *bd;
|
|
|
|
u64 ssize;
|
2006-01-20 02:46:19 +08:00
|
|
|
|
|
|
|
if (d->flags & DEVFL_GDALLOC)
|
|
|
|
aoeblk_gdalloc(d);
|
|
|
|
|
|
|
|
if (d->flags & DEVFL_NEWSIZE) {
|
2008-08-25 18:56:07 +08:00
|
|
|
ssize = get_capacity(d->gd);
|
2006-01-20 02:46:19 +08:00
|
|
|
bd = bdget_disk(d->gd, 0);
|
|
|
|
if (bd) {
|
2016-01-23 04:40:57 +08:00
|
|
|
inode_lock(bd->bd_inode);
|
2006-01-20 02:46:19 +08:00
|
|
|
i_size_write(bd->bd_inode, (loff_t)ssize<<9);
|
2016-01-23 04:40:57 +08:00
|
|
|
inode_unlock(bd->bd_inode);
|
2006-01-20 02:46:19 +08:00
|
|
|
bdput(bd);
|
|
|
|
}
|
2012-10-05 08:16:35 +08:00
|
|
|
spin_lock_irq(&d->lock);
|
2006-01-20 02:46:19 +08:00
|
|
|
d->flags |= DEVFL_UP;
|
|
|
|
d->flags &= ~DEVFL_NEWSIZE;
|
2012-10-05 08:16:35 +08:00
|
|
|
spin_unlock_irq(&d->lock);
|
2006-01-20 02:46:19 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-18 08:03:42 +08:00
|
|
|
static void
|
|
|
|
ata_ident_fixstring(u16 *id, int ns)
|
|
|
|
{
|
|
|
|
u16 s;
|
|
|
|
|
|
|
|
while (ns-- > 0) {
|
|
|
|
s = *id;
|
|
|
|
*id++ = s >> 8 | s << 8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
static void
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
u64 ssize;
|
|
|
|
u16 n;
|
|
|
|
|
|
|
|
/* word 83: command set supported */
|
2008-04-29 16:03:30 +08:00
|
|
|
n = get_unaligned_le16(&id[83 << 1]);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/* word 86: command set/feature enabled */
|
2008-04-29 16:03:30 +08:00
|
|
|
n |= get_unaligned_le16(&id[86 << 1]);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
if (n & (1<<10)) { /* bit 10: LBA 48 */
|
|
|
|
d->flags |= DEVFL_EXT;
|
|
|
|
|
|
|
|
/* word 100: number lba48 sectors */
|
2008-04-29 16:03:30 +08:00
|
|
|
ssize = get_unaligned_le64(&id[100 << 1]);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/* set as in ide-disk.c:init_idedisk_capacity */
|
|
|
|
d->geo.cylinders = ssize;
|
|
|
|
d->geo.cylinders /= (255 * 63);
|
|
|
|
d->geo.heads = 255;
|
|
|
|
d->geo.sectors = 63;
|
|
|
|
} else {
|
|
|
|
d->flags &= ~DEVFL_EXT;
|
|
|
|
|
|
|
|
/* number lba28 sectors */
|
2008-04-29 16:03:30 +08:00
|
|
|
ssize = get_unaligned_le32(&id[60 << 1]);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/* NOTE: obsolete in ATA 6 */
|
2008-04-29 16:03:30 +08:00
|
|
|
d->geo.cylinders = get_unaligned_le16(&id[54 << 1]);
|
|
|
|
d->geo.heads = get_unaligned_le16(&id[55 << 1]);
|
|
|
|
d->geo.sectors = get_unaligned_le16(&id[56 << 1]);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2006-01-20 02:46:19 +08:00
|
|
|
|
2012-12-18 08:03:42 +08:00
|
|
|
ata_ident_fixstring((u16 *) &id[10<<1], 10); /* serial */
|
|
|
|
ata_ident_fixstring((u16 *) &id[23<<1], 4); /* firmware */
|
|
|
|
ata_ident_fixstring((u16 *) &id[27<<1], 20); /* model */
|
|
|
|
memcpy(d->ident, id, sizeof(d->ident));
|
|
|
|
|
2006-01-20 02:46:19 +08:00
|
|
|
if (d->ssize != ssize)
|
2008-02-08 20:20:08 +08:00
|
|
|
printk(KERN_INFO
|
2008-11-25 16:40:37 +08:00
|
|
|
"aoe: %pm e%ld.%d v%04x has %llu sectors\n",
|
|
|
|
t->addr,
|
2006-01-20 02:46:19 +08:00
|
|
|
d->aoemajor, d->aoeminor,
|
|
|
|
d->fw_ver, (long long)ssize);
|
2005-04-17 06:20:36 +08:00
|
|
|
d->ssize = ssize;
|
|
|
|
d->geo.start = 0;
|
2008-02-08 20:20:06 +08:00
|
|
|
if (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE))
|
|
|
|
return;
|
2005-04-17 06:20:36 +08:00
|
|
|
if (d->gd != NULL) {
|
2008-08-25 18:56:07 +08:00
|
|
|
set_capacity(d->gd, ssize);
|
2006-01-20 02:46:19 +08:00
|
|
|
d->flags |= DEVFL_NEWSIZE;
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
} else
|
2006-01-20 02:46:19 +08:00
|
|
|
d->flags |= DEVFL_GDALLOC;
|
2005-04-17 06:20:36 +08:00
|
|
|
schedule_work(&d->work);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-12-18 08:03:43 +08:00
|
|
|
calc_rttavg(struct aoedev *d, struct aoetgt *t, int rtt)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
register long n;
|
|
|
|
|
|
|
|
n = rtt;
|
2012-12-18 08:03:43 +08:00
|
|
|
|
|
|
|
/* cf. Congestion Avoidance and Control, Jacobson & Karels, 1988 */
|
|
|
|
n -= d->rttavg >> RTTSCALE;
|
|
|
|
d->rttavg += n;
|
|
|
|
if (n < 0)
|
|
|
|
n = -n;
|
|
|
|
n -= d->rttdev >> RTTDSCALE;
|
|
|
|
d->rttdev += n;
|
|
|
|
|
|
|
|
if (!t || t->maxout >= t->nframes)
|
|
|
|
return;
|
|
|
|
if (t->maxout < t->ssthresh)
|
|
|
|
t->maxout += 1;
|
|
|
|
else if (t->nout == t->maxout && t->next_cwnd-- == 0) {
|
|
|
|
t->maxout += 1;
|
|
|
|
t->next_cwnd = t->maxout;
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
static struct aoetgt *
|
|
|
|
gettgt(struct aoedev *d, char *addr)
|
|
|
|
{
|
|
|
|
struct aoetgt **t, **e;
|
|
|
|
|
|
|
|
t = d->targets;
|
2012-12-18 08:04:11 +08:00
|
|
|
e = t + d->ntargets;
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
for (; t < e && *t; t++)
|
|
|
|
if (memcmp((*t)->addr, addr, sizeof((*t)->addr)) == 0)
|
|
|
|
return *t;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-10-05 08:16:20 +08:00
|
|
|
static void
|
2013-08-14 02:41:43 +08:00
|
|
|
bvcpy(struct sk_buff *skb, struct bio *bio, struct bvec_iter iter, long cnt)
|
2012-10-05 08:16:20 +08:00
|
|
|
{
|
|
|
|
int soff = 0;
|
2013-08-14 02:41:43 +08:00
|
|
|
struct bio_vec bv;
|
|
|
|
|
|
|
|
iter.bi_size = cnt;
|
|
|
|
|
|
|
|
__bio_for_each_segment(bv, bio, iter, iter) {
|
2018-05-09 21:59:46 +08:00
|
|
|
char *p = kmap_atomic(bv.bv_page) + bv.bv_offset;
|
2013-08-14 02:41:43 +08:00
|
|
|
skb_copy_bits(skb, soff, p, bv.bv_len);
|
2018-05-09 21:59:46 +08:00
|
|
|
kunmap_atomic(p);
|
2013-08-14 02:41:43 +08:00
|
|
|
soff += bv.bv_len;
|
|
|
|
}
|
2012-10-05 08:16:20 +08:00
|
|
|
}
|
|
|
|
|
2012-10-05 08:16:23 +08:00
|
|
|
void
|
|
|
|
aoe_end_request(struct aoedev *d, struct request *rq, int fastfail)
|
|
|
|
{
|
|
|
|
struct bio *bio;
|
|
|
|
int bok;
|
|
|
|
struct request_queue *q;
|
2018-10-13 00:03:14 +08:00
|
|
|
blk_status_t err = BLK_STS_OK;
|
2012-10-05 08:16:23 +08:00
|
|
|
|
|
|
|
q = d->blkq;
|
|
|
|
if (rq == d->ip.rq)
|
|
|
|
d->ip.rq = NULL;
|
|
|
|
do {
|
|
|
|
bio = rq->bio;
|
2017-06-03 15:38:06 +08:00
|
|
|
bok = !fastfail && !bio->bi_status;
|
2018-10-13 00:03:14 +08:00
|
|
|
if (!bok)
|
|
|
|
err = BLK_STS_IOERR;
|
|
|
|
} while (blk_update_request(rq, bok ? BLK_STS_OK : BLK_STS_IOERR, bio->bi_iter.bi_size));
|
|
|
|
|
|
|
|
__blk_mq_end_request(rq, err);
|
2012-10-05 08:16:23 +08:00
|
|
|
|
|
|
|
/* cf. http://lkml.org/lkml/2006/10/31/28 */
|
|
|
|
if (!fastfail)
|
2018-10-13 00:03:14 +08:00
|
|
|
blk_mq_run_hw_queues(q, true);
|
2012-10-05 08:16:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
aoe_end_buf(struct aoedev *d, struct buf *buf)
|
|
|
|
{
|
2018-11-10 16:30:47 +08:00
|
|
|
struct request *rq = buf->rq;
|
|
|
|
struct aoe_req *req = blk_mq_rq_to_pdu(rq);
|
2012-10-05 08:16:23 +08:00
|
|
|
|
|
|
|
if (buf == d->ip.buf)
|
|
|
|
d->ip.buf = NULL;
|
|
|
|
mempool_free(buf, d->bufpool);
|
2018-11-10 16:30:47 +08:00
|
|
|
if (--req->nr_bios == 0)
|
2012-10-05 08:16:23 +08:00
|
|
|
aoe_end_request(d, rq, 0);
|
|
|
|
}
|
|
|
|
|
2012-10-05 08:16:20 +08:00
|
|
|
static void
|
2012-10-05 08:16:21 +08:00
|
|
|
ktiocomplete(struct frame *f)
|
2012-10-05 08:16:20 +08:00
|
|
|
{
|
2012-10-05 08:16:21 +08:00
|
|
|
struct aoe_hdr *hin, *hout;
|
|
|
|
struct aoe_atahdr *ahin, *ahout;
|
|
|
|
struct buf *buf;
|
|
|
|
struct sk_buff *skb;
|
|
|
|
struct aoetgt *t;
|
|
|
|
struct aoeif *ifp;
|
|
|
|
struct aoedev *d;
|
|
|
|
long n;
|
2012-12-18 08:04:08 +08:00
|
|
|
int untainted;
|
2012-10-05 08:16:20 +08:00
|
|
|
|
2012-10-05 08:16:21 +08:00
|
|
|
if (f == NULL)
|
2012-10-05 08:16:20 +08:00
|
|
|
return;
|
2012-10-05 08:16:21 +08:00
|
|
|
|
|
|
|
t = f->t;
|
|
|
|
d = t->d;
|
2012-12-18 08:04:08 +08:00
|
|
|
skb = f->r_skb;
|
|
|
|
buf = f->buf;
|
|
|
|
if (f->flags & FFL_PROBE)
|
|
|
|
goto out;
|
|
|
|
if (!skb) /* just fail the buf. */
|
|
|
|
goto noskb;
|
2012-10-05 08:16:21 +08:00
|
|
|
|
|
|
|
hout = (struct aoe_hdr *) skb_mac_header(f->skb);
|
|
|
|
ahout = (struct aoe_atahdr *) (hout+1);
|
|
|
|
|
|
|
|
hin = (struct aoe_hdr *) skb->data;
|
|
|
|
skb_pull(skb, sizeof(*hin));
|
|
|
|
ahin = (struct aoe_atahdr *) skb->data;
|
|
|
|
skb_pull(skb, sizeof(*ahin));
|
|
|
|
if (ahin->cmdstat & 0xa9) { /* these bits cleared on success */
|
|
|
|
pr_err("aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%d\n",
|
|
|
|
ahout->cmdstat, ahin->cmdstat,
|
|
|
|
d->aoemajor, d->aoeminor);
|
2012-12-18 08:03:39 +08:00
|
|
|
noskb: if (buf)
|
2017-06-03 15:38:06 +08:00
|
|
|
buf->bio->bi_status = BLK_STS_IOERR;
|
2012-12-18 08:04:08 +08:00
|
|
|
goto out;
|
2012-10-05 08:16:20 +08:00
|
|
|
}
|
2012-10-05 08:16:21 +08:00
|
|
|
|
|
|
|
n = ahout->scnt << 9;
|
|
|
|
switch (ahout->cmdstat) {
|
|
|
|
case ATA_CMD_PIO_READ:
|
|
|
|
case ATA_CMD_PIO_READ_EXT:
|
|
|
|
if (skb->len < n) {
|
2012-12-18 08:04:17 +08:00
|
|
|
pr_err("%s e%ld.%d. skb->len=%d need=%ld\n",
|
|
|
|
"aoe: runt data size in read from",
|
|
|
|
(long) d->aoemajor, d->aoeminor,
|
|
|
|
skb->len, n);
|
2017-06-03 15:38:06 +08:00
|
|
|
buf->bio->bi_status = BLK_STS_IOERR;
|
2012-10-05 08:16:21 +08:00
|
|
|
break;
|
|
|
|
}
|
2013-08-14 02:41:43 +08:00
|
|
|
if (n > f->iter.bi_size) {
|
|
|
|
pr_err_ratelimited("%s e%ld.%d. bytes=%ld need=%u\n",
|
|
|
|
"aoe: too-large data size in read from",
|
|
|
|
(long) d->aoemajor, d->aoeminor,
|
|
|
|
n, f->iter.bi_size);
|
2017-06-03 15:38:06 +08:00
|
|
|
buf->bio->bi_status = BLK_STS_IOERR;
|
2013-08-14 02:41:43 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
bvcpy(skb, f->buf->bio, f->iter, n);
|
2018-08-02 06:30:20 +08:00
|
|
|
/* fall through */
|
2012-10-05 08:16:21 +08:00
|
|
|
case ATA_CMD_PIO_WRITE:
|
|
|
|
case ATA_CMD_PIO_WRITE_EXT:
|
|
|
|
spin_lock_irq(&d->lock);
|
|
|
|
ifp = getif(t, skb->dev);
|
2012-10-05 08:16:27 +08:00
|
|
|
if (ifp)
|
2012-10-05 08:16:21 +08:00
|
|
|
ifp->lost = 0;
|
|
|
|
spin_unlock_irq(&d->lock);
|
|
|
|
break;
|
|
|
|
case ATA_CMD_ID_ATA:
|
|
|
|
if (skb->len < 512) {
|
2012-12-18 08:04:17 +08:00
|
|
|
pr_info("%s e%ld.%d. skb->len=%d need=512\n",
|
|
|
|
"aoe: runt data size in ataid from",
|
|
|
|
(long) d->aoemajor, d->aoeminor,
|
2012-10-05 08:16:21 +08:00
|
|
|
skb->len);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (skb_linearize(skb))
|
|
|
|
break;
|
|
|
|
spin_lock_irq(&d->lock);
|
|
|
|
ataid_complete(d, t, skb->data);
|
|
|
|
spin_unlock_irq(&d->lock);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
pr_info("aoe: unrecognized ata command %2.2Xh for %d.%d\n",
|
|
|
|
ahout->cmdstat,
|
|
|
|
be16_to_cpu(get_unaligned(&hin->major)),
|
|
|
|
hin->minor);
|
|
|
|
}
|
2012-12-18 08:04:08 +08:00
|
|
|
out:
|
2012-10-05 08:16:21 +08:00
|
|
|
spin_lock_irq(&d->lock);
|
2012-12-18 08:04:08 +08:00
|
|
|
if (t->taint > 0
|
|
|
|
&& --t->taint > 0
|
|
|
|
&& t->nout_probes == 0) {
|
|
|
|
count_targets(d, &untainted);
|
|
|
|
if (untainted > 0) {
|
|
|
|
probe(t);
|
|
|
|
t->nout_probes++;
|
|
|
|
}
|
|
|
|
}
|
2012-10-05 08:16:21 +08:00
|
|
|
|
|
|
|
aoe_freetframe(f);
|
|
|
|
|
2013-08-14 02:41:43 +08:00
|
|
|
if (buf && --buf->nframesout == 0 && buf->iter.bi_size == 0)
|
2012-10-05 08:16:23 +08:00
|
|
|
aoe_end_buf(d, buf);
|
2012-10-05 08:16:21 +08:00
|
|
|
|
2012-10-05 08:16:23 +08:00
|
|
|
spin_unlock_irq(&d->lock);
|
|
|
|
aoedev_put(d);
|
2012-10-05 08:16:21 +08:00
|
|
|
dev_kfree_skb(skb);
|
2012-10-05 08:16:20 +08:00
|
|
|
}
|
|
|
|
|
2012-10-05 08:16:21 +08:00
|
|
|
/* Enters with iocq.lock held.
|
|
|
|
* Returns true iff responses needing processing remain.
|
|
|
|
*/
|
|
|
|
static int
|
2013-07-04 06:09:05 +08:00
|
|
|
ktio(int id)
|
2012-10-05 08:16:21 +08:00
|
|
|
{
|
|
|
|
struct frame *f;
|
|
|
|
struct list_head *pos;
|
|
|
|
int i;
|
2013-07-04 06:09:05 +08:00
|
|
|
int actual_id;
|
2012-10-05 08:16:21 +08:00
|
|
|
|
|
|
|
for (i = 0; ; ++i) {
|
|
|
|
if (i == MAXIOC)
|
|
|
|
return 1;
|
2013-07-04 06:09:05 +08:00
|
|
|
if (list_empty(&iocq[id].head))
|
2012-10-05 08:16:21 +08:00
|
|
|
return 0;
|
2013-07-04 06:09:05 +08:00
|
|
|
pos = iocq[id].head.next;
|
2012-10-05 08:16:21 +08:00
|
|
|
list_del(pos);
|
|
|
|
f = list_entry(pos, struct frame, head);
|
2013-07-04 06:09:05 +08:00
|
|
|
spin_unlock_irq(&iocq[id].lock);
|
2012-10-05 08:16:21 +08:00
|
|
|
ktiocomplete(f);
|
2013-07-04 06:09:05 +08:00
|
|
|
|
|
|
|
/* Figure out if extra threads are required. */
|
|
|
|
actual_id = f->t->d->aoeminor % ncpus;
|
|
|
|
|
|
|
|
if (!kts[actual_id].active) {
|
|
|
|
BUG_ON(id != 0);
|
|
|
|
mutex_lock(&ktio_spawn_lock);
|
|
|
|
if (!kts[actual_id].active
|
|
|
|
&& aoe_ktstart(&kts[actual_id]) == 0)
|
|
|
|
kts[actual_id].active = 1;
|
|
|
|
mutex_unlock(&ktio_spawn_lock);
|
|
|
|
}
|
|
|
|
spin_lock_irq(&iocq[id].lock);
|
2012-10-05 08:16:21 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
kthread(void *vp)
|
|
|
|
{
|
|
|
|
struct ktstate *k;
|
|
|
|
DECLARE_WAITQUEUE(wait, current);
|
|
|
|
int more;
|
|
|
|
|
|
|
|
k = vp;
|
|
|
|
current->flags |= PF_NOFREEZE;
|
|
|
|
set_user_nice(current, -10);
|
|
|
|
complete(&k->rendez); /* tell spawner we're running */
|
|
|
|
do {
|
|
|
|
spin_lock_irq(k->lock);
|
2013-07-04 06:09:05 +08:00
|
|
|
more = k->fn(k->id);
|
2012-10-05 08:16:21 +08:00
|
|
|
if (!more) {
|
|
|
|
add_wait_queue(k->waitq, &wait);
|
|
|
|
__set_current_state(TASK_INTERRUPTIBLE);
|
|
|
|
}
|
|
|
|
spin_unlock_irq(k->lock);
|
|
|
|
if (!more) {
|
|
|
|
schedule();
|
|
|
|
remove_wait_queue(k->waitq, &wait);
|
|
|
|
} else
|
|
|
|
cond_resched();
|
|
|
|
} while (!kthread_should_stop());
|
|
|
|
complete(&k->rendez); /* tell spawner we're stopping */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-10-05 08:16:25 +08:00
|
|
|
void
|
2012-10-05 08:16:21 +08:00
|
|
|
aoe_ktstop(struct ktstate *k)
|
|
|
|
{
|
|
|
|
kthread_stop(k->task);
|
|
|
|
wait_for_completion(&k->rendez);
|
|
|
|
}
|
|
|
|
|
2012-10-05 08:16:25 +08:00
|
|
|
int
|
2012-10-05 08:16:21 +08:00
|
|
|
aoe_ktstart(struct ktstate *k)
|
|
|
|
{
|
|
|
|
struct task_struct *task;
|
|
|
|
|
|
|
|
init_completion(&k->rendez);
|
2013-07-04 06:04:58 +08:00
|
|
|
task = kthread_run(kthread, k, "%s", k->name);
|
2012-10-05 08:16:21 +08:00
|
|
|
if (task == NULL || IS_ERR(task))
|
|
|
|
return -ENOMEM;
|
|
|
|
k->task = task;
|
|
|
|
wait_for_completion(&k->rendez); /* allow kthread to start */
|
|
|
|
init_completion(&k->rendez); /* for waiting for exit later */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* pass it off to kthreads for processing */
|
|
|
|
static void
|
|
|
|
ktcomplete(struct frame *f, struct sk_buff *skb)
|
|
|
|
{
|
2013-07-04 06:09:05 +08:00
|
|
|
int id;
|
2012-10-05 08:16:21 +08:00
|
|
|
ulong flags;
|
|
|
|
|
|
|
|
f->r_skb = skb;
|
2013-07-04 06:09:05 +08:00
|
|
|
id = f->t->d->aoeminor % ncpus;
|
|
|
|
spin_lock_irqsave(&iocq[id].lock, flags);
|
|
|
|
if (!kts[id].active) {
|
|
|
|
spin_unlock_irqrestore(&iocq[id].lock, flags);
|
|
|
|
/* The thread with id has not been spawned yet,
|
|
|
|
* so delegate the work to the main thread and
|
|
|
|
* try spawning a new thread.
|
|
|
|
*/
|
|
|
|
id = 0;
|
|
|
|
spin_lock_irqsave(&iocq[id].lock, flags);
|
|
|
|
}
|
|
|
|
list_add_tail(&f->head, &iocq[id].head);
|
|
|
|
spin_unlock_irqrestore(&iocq[id].lock, flags);
|
|
|
|
wake_up(&ktiowq[id]);
|
2012-10-05 08:16:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
struct sk_buff *
|
2005-04-17 06:20:36 +08:00
|
|
|
aoecmd_ata_rsp(struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
struct aoedev *d;
|
2012-10-05 08:16:21 +08:00
|
|
|
struct aoe_hdr *h;
|
2005-04-17 06:20:36 +08:00
|
|
|
struct frame *f;
|
2012-10-05 08:16:21 +08:00
|
|
|
u32 n;
|
2005-04-17 06:20:36 +08:00
|
|
|
ulong flags;
|
|
|
|
char ebuf[128];
|
2005-04-19 13:00:18 +08:00
|
|
|
u16 aoemajor;
|
|
|
|
|
2012-10-05 08:16:21 +08:00
|
|
|
h = (struct aoe_hdr *) skb->data;
|
|
|
|
aoemajor = be16_to_cpu(get_unaligned(&h->major));
|
2012-10-05 08:16:40 +08:00
|
|
|
d = aoedev_by_aoeaddr(aoemajor, h->minor, 0);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (d == NULL) {
|
|
|
|
snprintf(ebuf, sizeof ebuf, "aoecmd_ata_rsp: ata response "
|
|
|
|
"for unknown device %d.%d\n",
|
2012-10-05 08:16:21 +08:00
|
|
|
aoemajor, h->minor);
|
2005-04-17 06:20:36 +08:00
|
|
|
aoechr_error(ebuf);
|
2012-10-05 08:16:21 +08:00
|
|
|
return skb;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
spin_lock_irqsave(&d->lock, flags);
|
|
|
|
|
2012-10-05 08:16:21 +08:00
|
|
|
n = be32_to_cpu(get_unaligned(&h->tag));
|
2012-10-05 08:16:33 +08:00
|
|
|
f = getframe(d, n);
|
2012-12-18 08:03:43 +08:00
|
|
|
if (f) {
|
2012-12-18 08:03:49 +08:00
|
|
|
calc_rttavg(d, f->t, tsince_hr(f));
|
2012-12-18 08:03:43 +08:00
|
|
|
f->t->nout--;
|
2012-12-18 08:04:08 +08:00
|
|
|
if (f->flags & FFL_PROBE)
|
|
|
|
f->t->nout_probes--;
|
2012-12-18 08:03:43 +08:00
|
|
|
} else {
|
|
|
|
f = getframe_deferred(d, n);
|
|
|
|
if (f) {
|
2012-12-18 08:03:49 +08:00
|
|
|
calc_rttavg(d, NULL, tsince_hr(f));
|
2012-12-18 08:03:43 +08:00
|
|
|
} else {
|
|
|
|
calc_rttavg(d, NULL, tsince(n));
|
|
|
|
spin_unlock_irqrestore(&d->lock, flags);
|
|
|
|
aoedev_put(d);
|
|
|
|
snprintf(ebuf, sizeof(ebuf),
|
2012-12-18 08:03:45 +08:00
|
|
|
"%15s e%d.%d tag=%08x@%08lx s=%pm d=%pm\n",
|
2012-12-18 08:03:43 +08:00
|
|
|
"unexpected rsp",
|
|
|
|
get_unaligned_be16(&h->major),
|
|
|
|
h->minor,
|
|
|
|
get_unaligned_be32(&h->tag),
|
2012-12-18 08:03:45 +08:00
|
|
|
jiffies,
|
|
|
|
h->src,
|
|
|
|
h->dst);
|
2012-12-18 08:03:43 +08:00
|
|
|
aoechr_error(ebuf);
|
|
|
|
return skb;
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
aoecmd_work(d);
|
|
|
|
|
|
|
|
spin_unlock_irqrestore(&d->lock, flags);
|
2012-10-05 08:16:21 +08:00
|
|
|
|
|
|
|
ktcomplete(f, skb);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Note here that we do not perform an aoedev_put, as we are
|
|
|
|
* leaving this reference for the ktio to release.
|
|
|
|
*/
|
|
|
|
return NULL;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
aoecmd_cfg(ushort aoemajor, unsigned char aoeminor)
|
|
|
|
{
|
2008-09-22 13:36:49 +08:00
|
|
|
struct sk_buff_head queue;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2008-09-22 13:36:49 +08:00
|
|
|
__skb_queue_head_init(&queue);
|
|
|
|
aoecmd_cfg_pkts(aoemajor, aoeminor, &queue);
|
|
|
|
aoenet_xmit(&queue);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2012-12-18 08:03:39 +08:00
|
|
|
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
struct sk_buff *
|
2005-04-17 06:20:36 +08:00
|
|
|
aoecmd_ata_id(struct aoedev *d)
|
|
|
|
{
|
|
|
|
struct aoe_hdr *h;
|
|
|
|
struct aoe_atahdr *ah;
|
|
|
|
struct frame *f;
|
|
|
|
struct sk_buff *skb;
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
struct aoetgt *t;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2012-10-05 08:16:21 +08:00
|
|
|
f = newframe(d);
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
if (f == NULL)
|
2005-04-17 06:20:36 +08:00
|
|
|
return NULL;
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
|
|
|
|
t = *d->tgt;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/* initialize the headers & frame */
|
2006-09-21 02:36:49 +08:00
|
|
|
skb = f->skb;
|
2007-10-17 14:27:03 +08:00
|
|
|
h = (struct aoe_hdr *) skb_mac_header(skb);
|
2005-04-17 06:20:36 +08:00
|
|
|
ah = (struct aoe_atahdr *) (h+1);
|
2006-12-22 17:09:21 +08:00
|
|
|
skb_put(skb, sizeof *h + sizeof *ah);
|
|
|
|
memset(h, 0, skb->len);
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
f->tag = aoehdr_atainit(d, t, h);
|
2012-10-05 08:16:21 +08:00
|
|
|
fhash(f);
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
t->nout++;
|
2005-04-17 06:20:36 +08:00
|
|
|
f->waited = 0;
|
2012-12-18 08:03:51 +08:00
|
|
|
f->waited_total = 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/* set up ata header */
|
|
|
|
ah->scnt = 1;
|
2009-04-02 03:42:24 +08:00
|
|
|
ah->cmdstat = ATA_CMD_ID_ATA;
|
2005-04-17 06:20:36 +08:00
|
|
|
ah->lba3 = 0xa0;
|
|
|
|
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
skb->dev = t->ifp->nd;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2012-12-18 08:03:43 +08:00
|
|
|
d->rttavg = RTTAVG_INIT;
|
|
|
|
d->rttdev = RTTDEV_INIT;
|
2017-10-23 15:40:42 +08:00
|
|
|
d->timer.function = rexmit_timer;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2012-12-18 08:03:49 +08:00
|
|
|
skb = skb_clone(skb, GFP_ATOMIC);
|
2018-01-17 23:30:39 +08:00
|
|
|
if (skb)
|
|
|
|
f->sent = ktime_get();
|
2012-12-18 08:03:49 +08:00
|
|
|
|
|
|
|
return skb;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2012-12-18 08:03:39 +08:00
|
|
|
|
2012-12-18 08:04:11 +08:00
|
|
|
static struct aoetgt **
|
|
|
|
grow_targets(struct aoedev *d)
|
|
|
|
{
|
|
|
|
ulong oldn, newn;
|
|
|
|
struct aoetgt **tt;
|
|
|
|
|
|
|
|
oldn = d->ntargets;
|
|
|
|
newn = oldn * 2;
|
|
|
|
tt = kcalloc(newn, sizeof(*d->targets), GFP_ATOMIC);
|
|
|
|
if (!tt)
|
|
|
|
return NULL;
|
|
|
|
memmove(tt, d->targets, sizeof(*d->targets) * oldn);
|
|
|
|
d->tgt = tt + (d->tgt - d->targets);
|
|
|
|
kfree(d->targets);
|
|
|
|
d->targets = tt;
|
|
|
|
d->ntargets = newn;
|
|
|
|
|
|
|
|
return &d->targets[oldn];
|
|
|
|
}
|
|
|
|
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
static struct aoetgt *
|
|
|
|
addtgt(struct aoedev *d, char *addr, ulong nframes)
|
|
|
|
{
|
|
|
|
struct aoetgt *t, **tt, **te;
|
|
|
|
|
|
|
|
tt = d->targets;
|
2012-12-18 08:04:11 +08:00
|
|
|
te = tt + d->ntargets;
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
for (; tt < te && *tt; tt++)
|
|
|
|
;
|
|
|
|
|
2008-02-08 20:20:09 +08:00
|
|
|
if (tt == te) {
|
2012-12-18 08:04:11 +08:00
|
|
|
tt = grow_targets(d);
|
|
|
|
if (!tt)
|
|
|
|
goto nomem;
|
2008-02-08 20:20:09 +08:00
|
|
|
}
|
2012-10-05 08:16:21 +08:00
|
|
|
t = kzalloc(sizeof(*t), GFP_ATOMIC);
|
2012-12-18 08:04:11 +08:00
|
|
|
if (!t)
|
|
|
|
goto nomem;
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
t->nframes = nframes;
|
2012-10-05 08:16:21 +08:00
|
|
|
t->d = d;
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
memcpy(t->addr, addr, sizeof t->addr);
|
|
|
|
t->ifp = t->ifs;
|
2012-12-18 08:03:43 +08:00
|
|
|
aoecmd_wreset(t);
|
2012-12-18 08:04:08 +08:00
|
|
|
t->maxout = t->nframes / 2;
|
2012-10-05 08:16:21 +08:00
|
|
|
INIT_LIST_HEAD(&t->ffree);
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
return *tt = t;
|
2012-12-18 08:04:11 +08:00
|
|
|
|
|
|
|
nomem:
|
|
|
|
pr_info("aoe: cannot allocate memory to add target\n");
|
|
|
|
return NULL;
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
}
|
|
|
|
|
2012-10-05 08:16:27 +08:00
|
|
|
static void
|
|
|
|
setdbcnt(struct aoedev *d)
|
|
|
|
{
|
|
|
|
struct aoetgt **t, **e;
|
|
|
|
int bcnt = 0;
|
|
|
|
|
|
|
|
t = d->targets;
|
2012-12-18 08:04:11 +08:00
|
|
|
e = t + d->ntargets;
|
2012-10-05 08:16:27 +08:00
|
|
|
for (; t < e && *t; t++)
|
|
|
|
if (bcnt == 0 || bcnt > (*t)->minbcnt)
|
|
|
|
bcnt = (*t)->minbcnt;
|
|
|
|
if (bcnt != d->maxbcnt) {
|
|
|
|
d->maxbcnt = bcnt;
|
|
|
|
pr_info("aoe: e%ld.%d: setting %d byte data frames\n",
|
|
|
|
d->aoemajor, d->aoeminor, bcnt);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
setifbcnt(struct aoetgt *t, struct net_device *nd, int bcnt)
|
|
|
|
{
|
|
|
|
struct aoedev *d;
|
|
|
|
struct aoeif *p, *e;
|
|
|
|
int minbcnt;
|
|
|
|
|
|
|
|
d = t->d;
|
|
|
|
minbcnt = bcnt;
|
|
|
|
p = t->ifs;
|
|
|
|
e = p + NAOEIFS;
|
|
|
|
for (; p < e; p++) {
|
|
|
|
if (p->nd == NULL)
|
|
|
|
break; /* end of the valid interfaces */
|
|
|
|
if (p->nd == nd) {
|
|
|
|
p->bcnt = bcnt; /* we're updating */
|
|
|
|
nd = NULL;
|
|
|
|
} else if (minbcnt > p->bcnt)
|
|
|
|
minbcnt = p->bcnt; /* find the min interface */
|
|
|
|
}
|
|
|
|
if (nd) {
|
|
|
|
if (p == e) {
|
|
|
|
pr_err("aoe: device setifbcnt failure; too many interfaces.\n");
|
|
|
|
return;
|
|
|
|
}
|
2012-10-05 08:16:34 +08:00
|
|
|
dev_hold(nd);
|
2012-10-05 08:16:27 +08:00
|
|
|
p->nd = nd;
|
|
|
|
p->bcnt = bcnt;
|
|
|
|
}
|
|
|
|
t->minbcnt = minbcnt;
|
|
|
|
setdbcnt(d);
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
void
|
|
|
|
aoecmd_cfg_rsp(struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
struct aoedev *d;
|
|
|
|
struct aoe_hdr *h;
|
|
|
|
struct aoe_cfghdr *ch;
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
struct aoetgt *t;
|
2012-10-05 08:16:40 +08:00
|
|
|
ulong flags, aoemajor;
|
2005-04-17 06:20:36 +08:00
|
|
|
struct sk_buff *sl;
|
2012-10-05 08:16:23 +08:00
|
|
|
struct sk_buff_head queue;
|
2006-09-21 02:36:49 +08:00
|
|
|
u16 n;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2012-10-05 08:16:23 +08:00
|
|
|
sl = NULL;
|
2007-10-17 14:27:03 +08:00
|
|
|
h = (struct aoe_hdr *) skb_mac_header(skb);
|
2005-04-17 06:20:36 +08:00
|
|
|
ch = (struct aoe_cfghdr *) (h+1);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Enough people have their dip switches set backwards to
|
|
|
|
* warrant a loud message for this special case.
|
|
|
|
*/
|
2008-07-04 15:28:32 +08:00
|
|
|
aoemajor = get_unaligned_be16(&h->major);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (aoemajor == 0xfff) {
|
2006-09-21 02:36:51 +08:00
|
|
|
printk(KERN_ERR "aoe: Warning: shelf address is all ones. "
|
2006-09-21 02:36:49 +08:00
|
|
|
"Check shelf dip switches.\n");
|
2005-04-17 06:20:36 +08:00
|
|
|
return;
|
|
|
|
}
|
2012-10-05 08:16:44 +08:00
|
|
|
if (aoemajor == 0xffff) {
|
|
|
|
pr_info("aoe: e%ld.%d: broadcast shelf number invalid\n",
|
2012-10-05 08:16:40 +08:00
|
|
|
aoemajor, (int) h->minor);
|
2012-10-05 08:16:32 +08:00
|
|
|
return;
|
|
|
|
}
|
2012-10-05 08:16:44 +08:00
|
|
|
if (h->minor == 0xff) {
|
|
|
|
pr_info("aoe: e%ld.%d: broadcast slot number invalid\n",
|
|
|
|
aoemajor, (int) h->minor);
|
2005-04-17 06:20:36 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-09-21 02:36:49 +08:00
|
|
|
n = be16_to_cpu(ch->bufcnt);
|
2008-02-08 20:20:07 +08:00
|
|
|
if (n > aoe_maxout) /* keep it reasonable */
|
|
|
|
n = aoe_maxout;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2012-10-05 08:16:44 +08:00
|
|
|
d = aoedev_by_aoeaddr(aoemajor, h->minor, 1);
|
|
|
|
if (d == NULL) {
|
|
|
|
pr_info("aoe: device allocation failure\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
spin_lock_irqsave(&d->lock, flags);
|
|
|
|
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
t = gettgt(d, h->src);
|
2012-12-18 08:03:29 +08:00
|
|
|
if (t) {
|
|
|
|
t->nframes = n;
|
|
|
|
if (n < t->maxout)
|
2012-12-18 08:03:43 +08:00
|
|
|
aoecmd_wreset(t);
|
2012-12-18 08:03:29 +08:00
|
|
|
} else {
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
t = addtgt(d, h->src, n);
|
2012-10-05 08:16:23 +08:00
|
|
|
if (!t)
|
|
|
|
goto bail;
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
}
|
2012-10-05 08:16:27 +08:00
|
|
|
n = skb->dev->mtu;
|
|
|
|
n -= sizeof(struct aoe_hdr) + sizeof(struct aoe_atahdr);
|
|
|
|
n /= 512;
|
|
|
|
if (n > ch->scnt)
|
|
|
|
n = ch->scnt;
|
|
|
|
n = n ? n * 512 : DEFAULTBCNT;
|
|
|
|
setifbcnt(t, skb->dev, n);
|
2006-01-20 02:46:19 +08:00
|
|
|
|
|
|
|
/* don't change users' perspective */
|
2012-10-05 08:16:23 +08:00
|
|
|
if (d->nopen == 0) {
|
|
|
|
d->fw_ver = be16_to_cpu(ch->fwver);
|
|
|
|
sl = aoecmd_ata_id(d);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2012-10-05 08:16:23 +08:00
|
|
|
bail:
|
2005-04-17 06:20:36 +08:00
|
|
|
spin_unlock_irqrestore(&d->lock, flags);
|
2012-10-05 08:16:23 +08:00
|
|
|
aoedev_put(d);
|
2008-09-22 13:36:49 +08:00
|
|
|
if (sl) {
|
|
|
|
__skb_queue_head_init(&queue);
|
|
|
|
__skb_queue_tail(&queue, sl);
|
|
|
|
aoenet_xmit(&queue);
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2012-12-18 08:03:43 +08:00
|
|
|
void
|
|
|
|
aoecmd_wreset(struct aoetgt *t)
|
|
|
|
{
|
|
|
|
t->maxout = 1;
|
|
|
|
t->ssthresh = t->nframes / 2;
|
|
|
|
t->next_cwnd = t->nframes;
|
|
|
|
}
|
|
|
|
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
void
|
|
|
|
aoecmd_cleanslate(struct aoedev *d)
|
|
|
|
{
|
|
|
|
struct aoetgt **t, **te;
|
|
|
|
|
2012-12-18 08:03:43 +08:00
|
|
|
d->rttavg = RTTAVG_INIT;
|
|
|
|
d->rttdev = RTTDEV_INIT;
|
2012-10-05 08:16:27 +08:00
|
|
|
d->maxbcnt = 0;
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
|
|
|
|
t = d->targets;
|
2012-12-18 08:04:11 +08:00
|
|
|
te = t + d->ntargets;
|
2012-10-05 08:16:27 +08:00
|
|
|
for (; t < te && *t; t++)
|
2012-12-18 08:03:43 +08:00
|
|
|
aoecmd_wreset(*t);
|
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by
an AoE shelf number and an AoE slot number. Such a device might have more
than one network interface, and it might be reachable by more than one local
network interface. This patch tracks the available network paths available to
each AoE device, allowing them to be used more efficiently.
Andrew Morton asked about the call to msleep_interruptible in the revalidate
function. Yes, if a signal is pending, then msleep_interruptible will not
return 0. That means we will not loop but will call aoenet_xmit with a NULL
skb, which is a noop. If the system is too low on memory or the aoe driver is
too low on frames, then the user can hit control-C to interrupt the attempt to
do a revalidate. I have added a comment to the code summarizing that.
Andrew Morton asked whether the allocation performed inside addtgt could use a
more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev
lock has been locked with spin_lock_irqsave. It would be nice to allocate the
memory under fewer restrictions, but targets are only added when the device is
being discovered, and if the target can't be added right now, we can try again
in a minute when then next AoE config query broadcast goes out.
Andrew Morton pointed out that the "too many targets" message could be printed
for failing GFP_ATOMIC allocations. The last patch in this series makes the
messages more specific.
Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-02-08 20:20:00 +08:00
|
|
|
}
|
2012-10-05 08:16:21 +08:00
|
|
|
|
2012-10-05 08:16:23 +08:00
|
|
|
void
|
|
|
|
aoe_failbuf(struct aoedev *d, struct buf *buf)
|
|
|
|
{
|
|
|
|
if (buf == NULL)
|
|
|
|
return;
|
2013-08-14 02:41:43 +08:00
|
|
|
buf->iter.bi_size = 0;
|
2017-06-03 15:38:06 +08:00
|
|
|
buf->bio->bi_status = BLK_STS_IOERR;
|
2012-10-05 08:16:23 +08:00
|
|
|
if (buf->nframesout == 0)
|
|
|
|
aoe_end_buf(d, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
aoe_flush_iocq(void)
|
2013-07-04 06:09:05 +08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ncpus; i++) {
|
|
|
|
if (kts[i].active)
|
|
|
|
aoe_flush_iocq_by_index(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
aoe_flush_iocq_by_index(int id)
|
2012-10-05 08:16:21 +08:00
|
|
|
{
|
|
|
|
struct frame *f;
|
|
|
|
struct aoedev *d;
|
|
|
|
LIST_HEAD(flist);
|
|
|
|
struct list_head *pos;
|
|
|
|
struct sk_buff *skb;
|
|
|
|
ulong flags;
|
|
|
|
|
2013-07-04 06:09:05 +08:00
|
|
|
spin_lock_irqsave(&iocq[id].lock, flags);
|
|
|
|
list_splice_init(&iocq[id].head, &flist);
|
|
|
|
spin_unlock_irqrestore(&iocq[id].lock, flags);
|
2012-10-05 08:16:21 +08:00
|
|
|
while (!list_empty(&flist)) {
|
|
|
|
pos = flist.next;
|
|
|
|
list_del(pos);
|
|
|
|
f = list_entry(pos, struct frame, head);
|
|
|
|
d = f->t->d;
|
|
|
|
skb = f->r_skb;
|
|
|
|
spin_lock_irqsave(&d->lock, flags);
|
|
|
|
if (f->buf) {
|
|
|
|
f->buf->nframesout--;
|
|
|
|
aoe_failbuf(d, f->buf);
|
|
|
|
}
|
|
|
|
aoe_freetframe(f);
|
|
|
|
spin_unlock_irqrestore(&d->lock, flags);
|
|
|
|
dev_kfree_skb(skb);
|
2012-10-05 08:16:23 +08:00
|
|
|
aoedev_put(d);
|
2012-10-05 08:16:21 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int __init
|
|
|
|
aoecmd_init(void)
|
|
|
|
{
|
2012-12-18 08:04:08 +08:00
|
|
|
void *p;
|
2013-07-04 06:09:05 +08:00
|
|
|
int i;
|
|
|
|
int ret;
|
2012-12-18 08:04:08 +08:00
|
|
|
|
|
|
|
/* get_zeroed_page returns page with ref count 1 */
|
2016-06-25 05:48:47 +08:00
|
|
|
p = (void *) get_zeroed_page(GFP_KERNEL);
|
2012-12-18 08:04:08 +08:00
|
|
|
if (!p)
|
|
|
|
return -ENOMEM;
|
|
|
|
empty_page = virt_to_page(p);
|
|
|
|
|
2013-07-04 06:09:05 +08:00
|
|
|
ncpus = num_online_cpus();
|
|
|
|
|
|
|
|
iocq = kcalloc(ncpus, sizeof(struct iocq_ktio), GFP_KERNEL);
|
|
|
|
if (!iocq)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
kts = kcalloc(ncpus, sizeof(struct ktstate), GFP_KERNEL);
|
|
|
|
if (!kts) {
|
|
|
|
ret = -ENOMEM;
|
|
|
|
goto kts_fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
ktiowq = kcalloc(ncpus, sizeof(wait_queue_head_t), GFP_KERNEL);
|
|
|
|
if (!ktiowq) {
|
|
|
|
ret = -ENOMEM;
|
|
|
|
goto ktiowq_fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
mutex_init(&ktio_spawn_lock);
|
|
|
|
|
|
|
|
for (i = 0; i < ncpus; i++) {
|
|
|
|
INIT_LIST_HEAD(&iocq[i].head);
|
|
|
|
spin_lock_init(&iocq[i].lock);
|
|
|
|
init_waitqueue_head(&ktiowq[i]);
|
|
|
|
snprintf(kts[i].name, sizeof(kts[i].name), "aoe_ktio%d", i);
|
|
|
|
kts[i].fn = ktio;
|
|
|
|
kts[i].waitq = &ktiowq[i];
|
|
|
|
kts[i].lock = &iocq[i].lock;
|
|
|
|
kts[i].id = i;
|
|
|
|
kts[i].active = 0;
|
|
|
|
}
|
|
|
|
kts[0].active = 1;
|
|
|
|
if (aoe_ktstart(&kts[0])) {
|
|
|
|
ret = -ENOMEM;
|
|
|
|
goto ktstart_fail;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
ktstart_fail:
|
|
|
|
kfree(ktiowq);
|
|
|
|
ktiowq_fail:
|
|
|
|
kfree(kts);
|
|
|
|
kts_fail:
|
|
|
|
kfree(iocq);
|
|
|
|
|
|
|
|
return ret;
|
2012-10-05 08:16:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
aoecmd_exit(void)
|
|
|
|
{
|
2013-07-04 06:09:05 +08:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ncpus; i++)
|
|
|
|
if (kts[i].active)
|
|
|
|
aoe_ktstop(&kts[i]);
|
|
|
|
|
2012-10-05 08:16:23 +08:00
|
|
|
aoe_flush_iocq();
|
2012-12-18 08:04:08 +08:00
|
|
|
|
2013-07-04 06:09:05 +08:00
|
|
|
/* Free up the iocq and thread speicific configuration
|
|
|
|
* allocated during startup.
|
|
|
|
*/
|
|
|
|
kfree(iocq);
|
|
|
|
kfree(kts);
|
|
|
|
kfree(ktiowq);
|
|
|
|
|
2012-12-18 08:04:08 +08:00
|
|
|
free_page((unsigned long) page_address(empty_page));
|
|
|
|
empty_page = NULL;
|
2012-10-05 08:16:21 +08:00
|
|
|
}
|