On Mon, 2 May 2011 10:04:26 -0400 Jeff Layton <jlayton@xxxxxxxxxx> wrote: > Add the ability for CIFS to do an asynchronous write. The kernel will > set the frame up as it would for a "normal" SMBWrite2 request, and use > cifs_call_async to send it. The mid callback will then be configured to > handle the result. > > Reviewed-by: Pavel Shilovsky <piastry@xxxxxxxxxxx> > Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx> > --- > fs/cifs/cifsproto.h | 18 ++++ > fs/cifs/cifssmb.c | 238 +++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 256 insertions(+), 0 deletions(-) > > diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h > index c621b45..d35019b 100644 > --- a/fs/cifs/cifsproto.h > +++ b/fs/cifs/cifsproto.h > @@ -433,4 +433,22 @@ extern int mdfour(unsigned char *, unsigned char *, int); > extern int E_md4hash(const unsigned char *passwd, unsigned char *p16); > extern int SMBencrypt(unsigned char *passwd, const unsigned char *c8, > unsigned char *p24); > + > +/* asynchronous write support */ > +struct cifs_writedata { > + struct kref refcount; > + enum writeback_sync_modes sync_mode; > + struct work_struct work; > + struct cifsFileInfo *cfile; > + __u64 offset; > + unsigned int bytes; > + int result; > + unsigned int nr_pages; > + struct page *pages[1]; > +}; > + > +int cifs_async_writev(struct cifs_writedata *wdata); > +struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages); > +void cifs_writedata_release(struct kref *refcount); > + > #endif /* _CIFSPROTO_H */ > diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c > index d4698b9..6ff9b0a 100644 > --- a/fs/cifs/cifssmb.c > +++ b/fs/cifs/cifssmb.c > @@ -32,6 +32,7 @@ > #include <linux/vfs.h> > #include <linux/slab.h> > #include <linux/posix_acl_xattr.h> > +#include <linux/pagemap.h> > #include <asm/uaccess.h> > #include "cifspdu.h" > #include "cifsglob.h" > @@ -1604,6 +1605,243 @@ CIFSSMBWrite(const int xid, struct cifs_tcon *tcon, > return rc; > } > > +void > +cifs_writedata_release(struct kref *refcount) > +{ > + struct cifs_writedata *wdata = container_of(refcount, > + struct cifs_writedata, refcount); > + > + if (wdata->cfile) > + cifsFileInfo_put(wdata->cfile); > + > + kfree(wdata); > +} > + > +/* > + * Write failed with a retryable error. Resend the write request. It's also > + * possible that the page was redirtied so re-clean the page. > + */ > +static void > +cifs_writev_requeue(struct cifs_writedata *wdata) > +{ > + int i, rc; > + struct inode *inode = wdata->cfile->dentry->d_inode; > + > + for (i = 0; i < wdata->nr_pages; i++) { > + lock_page(wdata->pages[i]); > + clear_page_dirty_for_io(wdata->pages[i]); > + } > + > + do { > + rc = cifs_async_writev(wdata); > + } while(rc != -EAGAIN); > + <forehead slap> The above should be == -EAGAIN... -- Jeff Layton <jlayton@xxxxxxxxxx> -- To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html