Commit 1904babb authored by Steve French's avatar Steve French Committed by Steve French

[CIFS] fix size of cifs small buffers to just barely fit within slab limit

(which appears to be 116 bytes), otherwise they take 1 page each.
Add them to cifs debug counters and optionally use them for SMBClose.

Signed-off-by: Steve French (sfrench@us.ibm.com)
parent 31c90511
......@@ -202,6 +202,13 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
bufAllocCount.counter);
length += item_length;
buf += item_length;
#ifdef CONFIG_CIFS_EXPERIMENTAL
item_length =
sprintf(buf,"SMB Small Req/Resp Buffer: %d\n",
smBufAllocCount.counter);
length += item_length;
buf += item_length;
#endif /* CIFS_EXPERIMENTAL */
item_length =
sprintf(buf,"Operations (MIDs): %d\n",
midCount.counter);
......
......@@ -207,7 +207,7 @@ static kmem_cache_t *cifs_inode_cachep;
static kmem_cache_t *cifs_req_cachep;
static kmem_cache_t *cifs_mid_cachep;
kmem_cache_t *cifs_oplock_cachep;
#ifdef CIFS_EXPERIMENTAL
#ifdef CONFIG_CIFS_EXPERIMENTAL
static kmem_cache_t *cifs_sm_req_cachep;
mempool_t *cifs_sm_req_poolp;
#endif /* CIFS_EXPERIMENTAL */
......@@ -608,15 +608,16 @@ cifs_init_request_bufs(void)
kmem_cache_destroy(cifs_req_cachep);
return -ENOMEM;
}
#ifdef CIFS_EXPERIMENTAL
#ifdef CONFIG_CIFS_EXPERIMENTAL
/* 120 bytes is enough for most SMB responses and handle
based requests (but not write response, nor is it
sufficient for path based requests). 120 bytes is 83
more than sizeof(struct smb_hdr) and smaller than 128 byte
cutoff which should make it easy to alloc off the slab
compared to 17K (5page) alloc of large cifs buffers */
sufficient for path based requests). 112 bytes is 75 more than
sizeof(struct smb_hdr) but still (with slab hdr) just smaller than
128 byte cutoff which should make it easy to alloc off the slab
compared to 17K (5page) alloc of large cifs buffers and not
so large as to force a single page alloc for each slab entry */
cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq",
120, 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
112, 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
if (cifs_sm_req_cachep == NULL) {
mempool_destroy(cifs_req_poolp);
kmem_cache_destroy(cifs_req_cachep);
......@@ -646,7 +647,7 @@ cifs_destroy_request_bufs(void)
if (kmem_cache_destroy(cifs_req_cachep))
printk(KERN_WARNING
"cifs_destroy_request_cache: error not all structures were freed\n");
#ifdef CIFS_EXPERIMENTAL
#ifdef CONFIG_CIFS_EXPERIMENTAL
mempool_destroy(cifs_sm_req_poolp);
if (kmem_cache_destroy(cifs_sm_req_cachep))
printk(KERN_WARNING
......
......@@ -90,5 +90,5 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *,
size_t, int);
extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
#define CIFS_VERSION "1.25"
#define CIFS_VERSION "1.26"
#endif /* _CIFSFS_H */
......@@ -330,7 +330,7 @@ struct oplock_q_entry {
#define MID_RESPONSE_RECEIVED 4
#define MID_RETRY_NEEDED 8 /* session closed while this request out */
#define MID_NO_RESP_NEEDED 0x10
#define MID_SMALL_BUFFER 0x20 /* 120 byte response buffer instead of 4K */
#define MID_SMALL_BUFFER 0x20 /* 112 byte response buffer instead of 4K */
/*
*****************************************************************
......@@ -413,6 +413,9 @@ GLOBAL_EXTERN atomic_t tconInfoReconnectCount;
/* Various Debug counters to remove someday (BB) */
GLOBAL_EXTERN atomic_t bufAllocCount;
#ifdef CONFIG_CIFS_EXPERIMENTAL
GLOBAL_EXTERN atomic_t smBufAllocCount;
#endif /* CIFS_EXPERIMENTAL */
GLOBAL_EXTERN atomic_t midCount;
/* Misc globals */
......
/*
* fs/cifs/cifsproto.h
*
* Copyright (c) International Business Machines Corp., 2002
* Copyright (c) International Business Machines Corp., 2002,2004
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
......@@ -32,6 +32,10 @@ struct statfs;
extern struct smb_hdr *cifs_buf_get(void);
extern void cifs_buf_release(void *);
#ifdef CONFIG_CIFS_EXPERIMENTAL
extern struct smb_hdr *cifs_small_buf_get(void);
extern void cifs_small_buf_release(void *);
#endif /* CIFS_EXPERIMENTAL */
extern int smb_send(struct socket *, struct smb_hdr *,
unsigned int /* length */ , struct sockaddr *);
extern unsigned int _GetXid(void);
......
......@@ -78,6 +78,99 @@ static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
/* BB Add call to invalidate_inodes(sb) for all superblocks mounted to this tcon */
}
#ifdef CONFIG_CIFS_EXPERIMENTAL
static int
small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
void **request_buf /* returned */)
{
int rc = 0;
/* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
check for tcp and smb session status done differently
for those three - in the calling routine */
if(tcon) {
if((tcon->ses) && (tcon->ses->server)){
struct nls_table *nls_codepage;
/* Give Demultiplex thread up to 10 seconds to
reconnect, should be greater than cifs socket
timeout which is 7 seconds */
while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
wait_event_interruptible_timeout(tcon->ses->server->response_q,
(tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
/* on "soft" mounts we wait once */
if((tcon->retry == FALSE) ||
(tcon->ses->status == CifsExiting)) {
cFYI(1,("gave up waiting on reconnect in smb_init"));
return -EHOSTDOWN;
} /* else "hard" mount - keep retrying until
process is killed or server comes back up */
} else /* TCP session is reestablished now */
break;
}
nls_codepage = load_nls_default();
/* need to prevent multiple threads trying to
simultaneously reconnect the same SMB session */
down(&tcon->ses->sesSem);
if(tcon->ses->status == CifsNeedReconnect)
rc = cifs_setup_session(0, tcon->ses, nls_codepage);
if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
mark_open_files_invalid(tcon);
rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
nls_codepage);
up(&tcon->ses->sesSem);
if(rc == 0)
atomic_inc(&tconInfoReconnectCount);
cFYI(1, ("reconnect tcon rc = %d", rc));
/* Removed call to reopen open files here -
it is safer (and faster) to reopen files
one at a time as needed in read and write */
/* Check if handle based operation so we
know whether we can continue or not without
returning to caller to reset file handle */
switch(smb_command) {
case SMB_COM_READ_ANDX:
case SMB_COM_WRITE_ANDX:
case SMB_COM_CLOSE:
case SMB_COM_FIND_CLOSE2:
case SMB_COM_LOCKING_ANDX: {
unload_nls(nls_codepage);
return -EAGAIN;
}
}
} else {
up(&tcon->ses->sesSem);
}
unload_nls(nls_codepage);
} else {
return -EIO;
}
}
if(rc)
return rc;
*request_buf = cifs_small_buf_get();
if (*request_buf == 0) {
/* BB should we add a retry in here if not a writepage? */
return -ENOMEM;
}
header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
#ifdef CONFIG_CIFS_STATS
if(tcon != NULL) {
atomic_inc(&tcon->num_smbs_sent);
}
#endif /* CONFIG_CIFS_STATS */
return rc;
}
#endif /* CIFS_EXPERIMENTAL */
static int
smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
void **request_buf /* returned */ ,
......@@ -172,9 +265,10 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
if(tcon != NULL) {
atomic_inc(&tcon->num_smbs_sent);
}
#endif
#endif /* CONFIG_CIFS_STATS */
return rc;
}
static int validate_t2(struct smb_t2_rsp * pSMB)
{
int rc = -EINVAL;
......@@ -893,8 +987,13 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
cFYI(1, ("In CIFSSMBClose"));
/* do not retry on dead session on close */
#ifdef CONFIG_CIFS_EXPERIMENTAL
rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
#else
rc = smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB,
(void **) &pSMBr);
#endif /* CIFS_EXPERIMENTAL */
if(rc == -EAGAIN)
return 0;
if (rc)
......@@ -911,8 +1010,14 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
cERROR(1, ("Send error in Close = %d", rc));
}
}
#ifdef CONFIG_CIFS_EXPERIMENTAL
if (pSMB)
cifs_small_buf_release(pSMB);
#else
if (pSMB)
cifs_buf_release(pSMB);
#endif /* CIFS_EXPERIMENTAL */
/* Since session is dead, file will be closed on server already */
if(rc == -EAGAIN)
......@@ -2053,7 +2158,7 @@ CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
return rc;
}
#ifdef CIFS_EXPERIMENTAL /* function unused at present */
#ifdef CONFIG_CIFS_EXPERIMENTAL /* function unused at present */
int
CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
const char *searchName, FILE_ALL_INFO * findData,
......@@ -2635,7 +2740,7 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle
return rc;
}
#ifdef CIFS_EXPERIMENTAL
#ifdef CONFIG_CIFS_EXPERIMENTAL
int
CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
......
......@@ -29,7 +29,7 @@
#include "smberr.h"
#include "nterr.h"
#ifdef CIFS_EXPERIMENTAL
#ifdef CONFIG_CIFS_EXPERIMENTAL
extern mempool_t *cifs_sm_req_poolp;
#endif /* CIFS_EXPERIMENTAL */
extern mempool_t *cifs_req_poolp;
......@@ -187,7 +187,7 @@ cifs_buf_release(void *buf_to_free)
return;
}
#ifdef CIFS_EXPERIMENTAL
#ifdef CONFIG_CIFS_EXPERIMENTAL
struct smb_hdr *
cifs_small_buf_get(void)
{
......
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