Skip to content

Commit

Permalink
aoe: kernel thread handles I/O completions for simple locking
Browse files Browse the repository at this point in the history
Make the frames the aoe driver uses to track the relationship between bios
and packets more flexible and detached, so that they can be passed to an
"aoe_ktio" thread for completion of I/O.

The frames are handled much like skbs, with a capped amount of
preallocation so that real-world use cases are likely to run smoothly and
degenerate gracefully even under memory pressure.

Decoupling I/O completion from the receive path and serializing it in a
process makes it easier to think about the correctness of the locking in
the driver, especially in the case of a remote MAC address becoming
unusable.

[dan.carpenter@oracle.com: cleanup an allocation a bit]
Signed-off-by: Ed Cashin <ecashin@coraid.com>
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Ed Cashin authored and Linus Torvalds committed Oct 5, 2012
1 parent 3d5b060 commit 896831f
Show file tree
Hide file tree
Showing 6 changed files with 560 additions and 306 deletions.
33 changes: 27 additions & 6 deletions drivers/block/aoe/aoe.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ enum {
NTARGETS = 8,
NAOEIFS = 8,
NSKBPOOLMAX = 128,
NFACTIVE = 17,

TIMERTICK = HZ / 10,
MINTIMER = HZ >> 2,
Expand All @@ -112,13 +113,16 @@ struct buf {
};

struct frame {
int tag;
struct list_head head;
u32 tag;
ulong waited;
struct buf *buf;
struct aoetgt *t; /* parent target I belong to */
char *bufaddr;
ulong bcnt;
sector_t lba;
struct sk_buff *skb;
struct sk_buff *skb; /* command skb freed on module exit */
struct sk_buff *r_skb; /* response skb for async processing */
struct bio_vec *bv;
ulong bv_off;
};
Expand All @@ -133,16 +137,18 @@ struct aoeif {
struct aoetgt {
unsigned char addr[6];
ushort nframes;
struct frame *frames;
struct aoedev *d; /* parent device I belong to */
struct list_head factive[NFACTIVE]; /* hash of active frames */
struct list_head ffree; /* list of free frames */
struct aoeif ifs[NAOEIFS];
struct aoeif *ifp; /* current aoeif in use */
ushort nout;
ushort maxout;
u16 lasttag; /* last tag sent */
u16 useme;
ulong falloc;
ulong lastwadj; /* last window adjustment */
int wpkts, rpkts;
int dataref;
};

struct aoedev {
Expand All @@ -169,9 +175,20 @@ struct aoedev {
struct buf *inprocess; /* the one we're currently working on */
struct aoetgt *targets[NTARGETS];
struct aoetgt **tgt; /* target in use when working */
struct aoetgt **htgt; /* target needing rexmit assistance */
struct aoetgt *htgt; /* target needing rexmit assistance */
ulong ntargets;
ulong kicked;
};

/* kthread tracking */
struct ktstate {
struct completion rendez;
struct task_struct *task;
wait_queue_head_t *waitq;
int (*fn) (void);
char *name;
spinlock_t *lock;
};

int aoeblk_init(void);
void aoeblk_exit(void);
Expand All @@ -184,18 +201,22 @@ void aoechr_error(char *);

void aoecmd_work(struct aoedev *d);
void aoecmd_cfg(ushort aoemajor, unsigned char aoeminor);
void aoecmd_ata_rsp(struct sk_buff *);
struct sk_buff *aoecmd_ata_rsp(struct sk_buff *);
void aoecmd_cfg_rsp(struct sk_buff *);
void aoecmd_sleepwork(struct work_struct *);
void aoecmd_cleanslate(struct aoedev *);
void aoecmd_exit(void);
int aoecmd_init(void);
struct sk_buff *aoecmd_ata_id(struct aoedev *);
void aoe_freetframe(struct frame *);

int aoedev_init(void);
void aoedev_exit(void);
struct aoedev *aoedev_by_aoeaddr(int maj, int min);
struct aoedev *aoedev_by_sysminor_m(ulong sysminor);
void aoedev_downdev(struct aoedev *d);
int aoedev_flush(const char __user *str, size_t size);
void aoe_failbuf(struct aoedev *d, struct buf *buf);

int aoenet_init(void);
void aoenet_exit(void);
Expand Down
3 changes: 1 addition & 2 deletions drivers/block/aoe/aoechr.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,9 @@ revalidate(const char __user *str, size_t size)
if (copy_from_user(buf, str, size))
return -EFAULT;

/* should be e%d.%d format */
n = sscanf(buf, "e%d.%d", &major, &minor);
if (n != 2) {
printk(KERN_ERR "aoe: invalid device specification\n");
pr_err("aoe: invalid device specification %s\n", buf);
return -EINVAL;
}
d = aoedev_by_aoeaddr(major, minor);
Expand Down
Loading

0 comments on commit 896831f

Please sign in to comment.