Commit 71b98beb authored by Petr Vandrovec's avatar Petr Vandrovec

Use search for fileset instead of search for one item in ncpfs. It is much faster

as you usually read whole directory in one request when using TCP transport, instead
of using one request for each directory entry.
parent 39228ed9
......@@ -687,6 +687,9 @@ ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
struct nw_search_sequence seq;
struct ncp_entry_info entry;
int err;
void* buf;
int more;
size_t bufsize;
DPRINTK("ncp_do_readdir: %s/%s, fpos=%ld\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
......@@ -700,16 +703,56 @@ ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
DPRINTK("ncp_do_readdir: init failed, err=%d\n", err);
return;
}
#ifdef USE_OLD_SLOW_DIRECTORY_LISTING
for (;;) {
err = ncp_search_for_file_or_subdir(server, &seq, &entry.i);
if (err) {
DPRINTK("ncp_do_readdir: search failed, err=%d\n", err);
return;
break;
}
entry.volume = entry.i.volNumber;
if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry))
return;
break;
}
#else
/* We MUST NOT use server->buffer_size handshaked with server if we are
using UDP, as for UDP server uses max. buffer size determined by
MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes).
So we use 128KB, just to be sure, as there is no way how to know
this value in advance. */
bufsize = 131072;
buf = vmalloc(bufsize);
if (!buf)
return;
do {
int cnt;
char* rpl;
size_t rpls;
err = ncp_search_for_fileset(server, &seq, &more, &cnt, buf, bufsize, &rpl, &rpls);
if (err) /* Error */
break;
if (!cnt) /* prevent endless loop */
break;
while (cnt--) {
size_t onerpl;
if (rpls < offsetof(struct nw_info_struct, entryName))
break; /* short packet */
ncp_extract_file_info(rpl, &entry.i);
onerpl = offsetof(struct nw_info_struct, entryName) + entry.i.nameLen;
if (rpls < onerpl)
break; /* short packet */
rpl += onerpl;
rpls -= onerpl;
entry.volume = entry.i.volNumber;
if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry))
break;
}
} while (more);
vfree(buf);
#endif
return;
}
int ncp_conn_logged_in(struct super_block *sb)
......
......@@ -89,12 +89,22 @@ static inline char *
return &(server->packet[sizeof(struct ncp_reply_header) + offset]);
}
static inline __u8 BVAL(void* data)
{
return get_unaligned((__u8*)data);
}
static __u8
ncp_reply_byte(struct ncp_server *server, int offset)
{
return get_unaligned((__u8 *) ncp_reply_data(server, offset));
}
static inline __u16 WVAL_LH(void* data)
{
return le16_to_cpu(get_unaligned((__u16*)data));
}
static __u16
ncp_reply_word(struct ncp_server *server, int offset)
{
......@@ -311,7 +321,7 @@ int ncp_dirhandle_free(struct ncp_server* server, __u8 dirhandle) {
return result;
}
static void ncp_extract_file_info(void *structure, struct nw_info_struct *target)
void ncp_extract_file_info(void *structure, struct nw_info_struct *target)
{
__u8 *name_len;
const int info_struct_size = offsetof(struct nw_info_struct, nameLen);
......@@ -736,6 +746,54 @@ int ncp_search_for_file_or_subdir(struct ncp_server *server,
return result;
}
int ncp_search_for_fileset(struct ncp_server *server,
struct nw_search_sequence *seq,
int* more,
int* cnt,
char* buffer,
size_t bufsize,
char** rbuf,
size_t* rsize)
{
int result;
ncp_init_request(server);
ncp_add_byte(server, 20);
ncp_add_byte(server, server->name_space[seq->volNumber]);
ncp_add_byte(server, 0); /* datastream */
ncp_add_word(server, htons(0x0680));
ncp_add_dword(server, RIM_ALL);
ncp_add_word(server, 32767); /* max returned items */
ncp_add_mem(server, seq, 9);
#ifdef CONFIG_NCPFS_NFS_NS
if (server->name_space[seq->volNumber] == NW_NS_NFS) {
ncp_add_byte(server, 0); /* 0 byte pattern */
} else
#endif
{
ncp_add_byte(server, 2); /* 2 byte pattern */
ncp_add_byte(server, 0xff); /* following is a wildcard */
ncp_add_byte(server, '*');
}
result = ncp_request2(server, 87, buffer, bufsize);
if (result) {
ncp_unlock_server(server);
return result;
}
if (server->ncp_reply_size < 12) {
ncp_unlock_server(server);
return 0xFF;
}
*rsize = server->ncp_reply_size - 12;
ncp_unlock_server(server);
buffer = buffer + sizeof(struct ncp_reply_header);
*rbuf = buffer + 12;
*cnt = WVAL_LH(buffer + 10);
*more = BVAL(buffer + 9);
memcpy(seq, buffer, 9);
return 0;
}
int
ncp_RenameNSEntry(struct ncp_server *server,
struct inode *old_dir, char *old_name, int old_type,
......
......@@ -66,6 +66,7 @@ static inline void ncp_inode_close(struct inode *inode) {
atomic_dec(&NCP_FINFO(inode)->opened);
}
void ncp_extract_file_info(void* src, struct nw_info_struct* target);
int ncp_obtain_info(struct ncp_server *server, struct inode *, char *,
struct nw_info_struct *target);
int ncp_lookup_volume(struct ncp_server *, char *, struct nw_info_struct *);
......@@ -84,6 +85,11 @@ int ncp_initialize_search(struct ncp_server *, struct inode *,
int ncp_search_for_file_or_subdir(struct ncp_server *server,
struct nw_search_sequence *seq,
struct nw_info_struct *target);
int ncp_search_for_fileset(struct ncp_server *server,
struct nw_search_sequence *seq,
int* more, int* cnt,
char* buffer, size_t bufsize,
char** rbuf, size_t* rsize);
int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
struct inode *, char *, struct inode *, char *);
......
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