Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ec637e3f authored by Steve French's avatar Steve French
Browse files

[CIFS] Avoid extra large buffer allocation (and memcpy) in cifs_readpages



Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent c89a86bb
Loading
Loading
Loading
Loading
+19 −20
Original line number Diff line number Diff line
@@ -401,8 +401,8 @@ static read_proc_t ntlmv2_enabled_read;
static write_proc_t ntlmv2_enabled_write;
static read_proc_t packet_signing_enabled_read;
static write_proc_t packet_signing_enabled_write;
static read_proc_t quotaEnabled_read;
static write_proc_t quotaEnabled_write;
static read_proc_t experimEnabled_read;
static write_proc_t experimEnabled_write;
static read_proc_t linuxExtensionsEnabled_read;
static write_proc_t linuxExtensionsEnabled_write;

@@ -442,9 +442,9 @@ cifs_proc_init(void)
		pde->write_proc = oplockEnabled_write;

	pde = create_proc_read_entry("Experimental", 0, proc_fs_cifs,
				quotaEnabled_read, NULL);
				experimEnabled_read, NULL);
	if (pde)
		pde->write_proc = quotaEnabled_write;
		pde->write_proc = experimEnabled_write;

	pde = create_proc_read_entry("LinuxExtensionsEnabled", 0, proc_fs_cifs,
				linuxExtensionsEnabled_read, NULL);
@@ -586,14 +586,13 @@ oplockEnabled_write(struct file *file, const char __user *buffer,
}

static int
quotaEnabled_read(char *page, char **start, off_t off,
experimEnabled_read(char *page, char **start, off_t off,
                   int count, int *eof, void *data)
{
        int len;

        len = sprintf(page, "%d\n", experimEnabled);
/* could also check if quotas are enabled in kernel
	as a whole first */

        len -= off;
        *start = page + off;

@@ -608,7 +607,7 @@ quotaEnabled_read(char *page, char **start, off_t off,
        return len;
}
static int
quotaEnabled_write(struct file *file, const char __user *buffer,
experimEnabled_write(struct file *file, const char __user *buffer,
                    unsigned long count, void *data)
{
	char c;
@@ -621,6 +620,8 @@ quotaEnabled_write(struct file *file, const char __user *buffer,
		experimEnabled = 0;
	else if (c == '1' || c == 'y' || c == 'Y')
		experimEnabled = 1;
	else if (c == '2')
		experimEnabled = 2;

	return count;
}
@@ -632,8 +633,6 @@ linuxExtensionsEnabled_read(char *page, char **start, off_t off,
        int len;

        len = sprintf(page, "%d\n", linuxExtEnabled);
/* could also check if quotas are enabled in kernel
	as a whole first */
        len -= off;
        *start = page + off;

+3 −2
Original line number Diff line number Diff line
@@ -733,7 +733,7 @@ cifs_init_request_bufs(void)
		kmem_cache_destroy(cifs_req_cachep);
		return -ENOMEM;
	}
	/* 256 (MAX_CIFS_HDR_SIZE bytes is enough for most SMB responses and
	/* MAX_CIFS_SMALL_BUFFER_SIZE bytes is enough for most SMB responses and
	almost all handle based requests (but not write response, nor is it
	sufficient for path based requests).  A smaller size would have
	been more efficient (compacting multiple slab items on one 4k page) 
@@ -742,7 +742,8 @@ cifs_init_request_bufs(void)
	efficient to alloc 1 per page off the slab compared to 17K (5page) 
	alloc of large cifs buffers even when page debugging is on */
	cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq",
			MAX_CIFS_HDR_SIZE, 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
			MAX_CIFS_SMALL_BUFFER_SIZE, 0, SLAB_HWCACHE_ALIGN, 
			NULL, NULL);
	if (cifs_sm_req_cachep == NULL) {
		mempool_destroy(cifs_req_poolp);
		kmem_cache_destroy(cifs_req_cachep);
+7 −1
Original line number Diff line number Diff line
@@ -285,6 +285,7 @@ struct cifs_search_info {
	unsigned endOfSearch:1;
	unsigned emptyDir:1;
	unsigned unicode:1;
	unsigned smallBuf:1; /* so we know which buf_release function to call */
};

struct cifsFileInfo {
@@ -420,7 +421,12 @@ struct dir_notify_req {
#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 /* 112 byte response buffer instead of 4K */

/* Types of response buffer returned from SendReceive2 */
#define   CIFS_NO_BUFFER        0    /* Response buffer not returned */
#define   CIFS_SMALL_BUFFER     1
#define   CIFS_LARGE_BUFFER     2
#define   CIFS_IOVEC            4    /* array of response buffers */

/*
 *****************************************************************
+5 −1
Original line number Diff line number Diff line
@@ -80,7 +80,11 @@
#define NT_TRANSACT_GET_USER_QUOTA    0x07
#define NT_TRANSACT_SET_USER_QUOTA    0x08

#define MAX_CIFS_HDR_SIZE 256	/* is future chained NTCreateXReadX bigger? */
#define MAX_CIFS_SMALL_BUFFER_SIZE 448 /* big enough for most */
/* future chained NTCreateXReadX bigger, but for time being NTCreateX biggest */
/* among the requests (NTCreateX response is bigger with wct of 34) */
#define MAX_CIFS_HDR_SIZE 0x58 /* 4 len + 32 hdr + (2*24 wct) + 2 bct + 2 pad */
#define CIFS_SMALL_PATH 120 /* allows for (448-88)/3 */

/* internal cifs vfs structures */
/*****************************************************************
+8 −6
Original line number Diff line number Diff line
@@ -49,7 +49,7 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
			int * /* bytes returned */ , const int long_op);
extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
			struct kvec *, int /* nvec to send */, 
			int * /* bytes returned */ , const int long_op);
			int * /* type of buf returned */ , const int long_op);
extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
extern int is_valid_oplock_break(struct smb_hdr *smb);
@@ -94,7 +94,8 @@ extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,

extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
		const char *searchName, const struct nls_table *nls_codepage,
            __u16 *searchHandle, struct cifs_search_info * psrch_inf, int map, const char dirsep);
		__u16 *searchHandle, struct cifs_search_info * psrch_inf, 
		int map, const char dirsep);

extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
		__u16 searchHandle, struct cifs_search_info * psrch_inf);
@@ -231,7 +232,8 @@ extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,

extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
                        const int netfid, unsigned int count,
			const __u64 lseek, unsigned int *nbytes, char **buf);
                        const __u64 lseek, unsigned int *nbytes, char **buf,
			int * return_buf_type);
extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
			const int netfid, const unsigned int count,
			const __u64 lseek, unsigned int *nbytes,
Loading