Commit e28bc5b1 authored by Jeff Layton's avatar Jeff Layton

cifs: add cifs_async_readv

...which will allow cifs to do an asynchronous read call to the server.
The caller will allocate and set up cifs_readdata for each READ_AND_X
call that should be issued on the wire. The pages passed in are added
to the pagecache, but not placed on the LRU list yet (as we need the
page->lru to keep the pages on the list in the readdata).

When cifsd identifies the mid, it will see that there is a special
receive handler for the call, and use that to receive the rest of the
frame. cifs_readv_receive will then marshal up a kvec array with
kmapped pages from the pagecache, which eliminates one copy of the
data. Once the data is received, the pages are added to the LRU list,
set uptodate, and unlocked.
Reviewed-and-Tested-by: default avatarPavel Shilovsky <piastry@etersoft.ru>
Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
parent 2ab2593f
...@@ -154,6 +154,12 @@ extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *, ...@@ -154,6 +154,12 @@ extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *,
extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *, extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *,
const char *, int); const char *, int);
extern void dequeue_mid(struct mid_q_entry *mid, bool malformed);
extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
unsigned int to_read);
extern int cifs_readv_from_socket(struct TCP_Server_Info *server,
struct kvec *iov_orig, unsigned int nr_segs,
unsigned int to_read);
extern void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, extern void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
struct cifs_sb_info *cifs_sb); struct cifs_sb_info *cifs_sb);
extern int cifs_match_super(struct super_block *, void *); extern int cifs_match_super(struct super_block *, void *);
...@@ -443,6 +449,24 @@ extern int E_md4hash(const unsigned char *passwd, unsigned char *p16); ...@@ -443,6 +449,24 @@ extern int E_md4hash(const unsigned char *passwd, unsigned char *p16);
extern int SMBencrypt(unsigned char *passwd, const unsigned char *c8, extern int SMBencrypt(unsigned char *passwd, const unsigned char *c8,
unsigned char *p24); unsigned char *p24);
/* asynchronous read support */
struct cifs_readdata {
struct cifsFileInfo *cfile;
struct address_space *mapping;
__u64 offset;
unsigned int bytes;
pid_t pid;
int result;
struct list_head pages;
struct work_struct work;
unsigned int nr_iov;
struct kvec iov[1];
};
struct cifs_readdata *cifs_readdata_alloc(unsigned int nr_pages);
void cifs_readdata_free(struct cifs_readdata *rdata);
int cifs_async_readv(struct cifs_readdata *rdata);
/* asynchronous write support */ /* asynchronous write support */
struct cifs_writedata { struct cifs_writedata {
struct kref refcount; struct kref refcount;
......
This diff is collapsed.
...@@ -422,8 +422,8 @@ get_server_iovec(struct TCP_Server_Info *server, unsigned int nr_segs) ...@@ -422,8 +422,8 @@ get_server_iovec(struct TCP_Server_Info *server, unsigned int nr_segs)
return new_iov; return new_iov;
} }
static int int
readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig, cifs_readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig,
unsigned int nr_segs, unsigned int to_read) unsigned int nr_segs, unsigned int to_read)
{ {
int length = 0; int length = 0;
...@@ -479,8 +479,8 @@ readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig, ...@@ -479,8 +479,8 @@ readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig,
return total_read; return total_read;
} }
static int int
read_from_socket(struct TCP_Server_Info *server, char *buf, cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
unsigned int to_read) unsigned int to_read)
{ {
struct kvec iov; struct kvec iov;
...@@ -488,7 +488,7 @@ read_from_socket(struct TCP_Server_Info *server, char *buf, ...@@ -488,7 +488,7 @@ read_from_socket(struct TCP_Server_Info *server, char *buf,
iov.iov_base = buf; iov.iov_base = buf;
iov.iov_len = to_read; iov.iov_len = to_read;
return readv_from_socket(server, &iov, 1, to_read); return cifs_readv_from_socket(server, &iov, 1, to_read);
} }
static bool static bool
...@@ -553,8 +553,8 @@ find_mid(struct TCP_Server_Info *server, struct smb_hdr *buf) ...@@ -553,8 +553,8 @@ find_mid(struct TCP_Server_Info *server, struct smb_hdr *buf)
return NULL; return NULL;
} }
static void void
dequeue_mid(struct mid_q_entry *mid, int malformed) dequeue_mid(struct mid_q_entry *mid, bool malformed)
{ {
#ifdef CONFIG_CIFS_STATS2 #ifdef CONFIG_CIFS_STATS2
mid->when_received = jiffies; mid->when_received = jiffies;
...@@ -730,7 +730,7 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid) ...@@ -730,7 +730,7 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
} }
/* now read the rest */ /* now read the rest */
length = read_from_socket(server, length = cifs_read_from_socket(server,
buf + sizeof(struct smb_hdr) - 1, buf + sizeof(struct smb_hdr) - 1,
pdu_length - sizeof(struct smb_hdr) + 1 + 4); pdu_length - sizeof(struct smb_hdr) + 1 + 4);
if (length < 0) if (length < 0)
...@@ -791,7 +791,7 @@ cifs_demultiplex_thread(void *p) ...@@ -791,7 +791,7 @@ cifs_demultiplex_thread(void *p)
buf = server->smallbuf; buf = server->smallbuf;
pdu_length = 4; /* enough to get RFC1001 header */ pdu_length = 4; /* enough to get RFC1001 header */
length = read_from_socket(server, buf, pdu_length); length = cifs_read_from_socket(server, buf, pdu_length);
if (length < 0) if (length < 0)
continue; continue;
server->total_read = length; server->total_read = length;
...@@ -816,7 +816,7 @@ cifs_demultiplex_thread(void *p) ...@@ -816,7 +816,7 @@ cifs_demultiplex_thread(void *p)
} }
/* read down to the MID */ /* read down to the MID */
length = read_from_socket(server, buf + 4, length = cifs_read_from_socket(server, buf + 4,
sizeof(struct smb_hdr) - 1 - 4); sizeof(struct smb_hdr) - 1 - 4);
if (length < 0) if (length < 0)
continue; continue;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment