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

Commit 1041e3f9 authored by Jeff Layton's avatar Jeff Layton
Browse files

cifs: keep a reusable kvec array for receives



Having to continually allocate a new kvec array is expensive. Allocate
one that's big enough, and only reallocate it as needed.

Reviewed-and-Tested-by: default avatarPavel Shilovsky <piastry@etersoft.ru>
Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
parent 42c4dfc2
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -292,6 +292,8 @@ struct TCP_Server_Info {
	bool	sec_kerberos;		/* supports plain Kerberos */
	bool	sec_mskerberos;		/* supports legacy MS Kerberos */
	struct delayed_work	echo; /* echo ping workqueue job */
	struct kvec *iov;	/* reusable kvec array for receives */
	unsigned int nr_iov;	/* number of kvecs in array */
#ifdef CONFIG_CIFS_FSCACHE
	struct fscache_cookie   *fscache; /* client index cache cookie */
#endif
+20 −2
Original line number Diff line number Diff line
@@ -410,6 +410,24 @@ kvec_array_init(struct kvec *new, struct kvec *iov, unsigned int nr_segs,
	return nr_segs;
}

static struct kvec *
get_server_iovec(struct TCP_Server_Info *server, unsigned int nr_segs)
{
	struct kvec *new_iov;

	if (server->iov && nr_segs <= server->nr_iov)
		return server->iov;

	/* not big enough -- allocate a new one and release the old */
	new_iov = kmalloc(sizeof(*new_iov) * nr_segs, GFP_NOFS);
	if (new_iov) {
		kfree(server->iov);
		server->iov = new_iov;
		server->nr_iov = nr_segs;
	}
	return new_iov;
}

static int
readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig,
		  unsigned int nr_segs, unsigned int to_read)
@@ -420,7 +438,7 @@ readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig,
	struct msghdr smb_msg;
	struct kvec *iov;

	iov = kmalloc(sizeof(*iov_orig) * nr_segs, GFP_NOFS);
	iov = get_server_iovec(server, nr_segs);
	if (!iov)
		return -ENOMEM;

@@ -464,7 +482,6 @@ readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig,
			break;
		}
	}
	kfree(iov);
	return total_read;
}

@@ -669,6 +686,7 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server)
	}

	kfree(server->hostname);
	kfree(server->iov);
	kfree(server);

	length = atomic_dec_return(&tcpSesAllocCount);