Commit cad2376e authored by Steve French's avatar Steve French Committed by Steve French

Fix check of filldir return code during readdir to avoid incomplete search...

Fix check of filldir return code during readdir to avoid incomplete search results displayed on very large directories. Fix cleanup of proc entries.  Add config parm to allow disabling negotiating Linux extensions 
parent db62a2bd
......@@ -223,6 +223,8 @@ 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 linuxExtensionsEnabled_read;
static write_proc_t linuxExtensionsEnabled_write;
void
cifs_proc_init(void)
......@@ -235,62 +237,67 @@ cifs_proc_init(void)
proc_fs_cifs->owner = THIS_MODULE;
create_proc_read_entry("DebugData", 0, proc_fs_cifs,
cifs_debug_data_read, 0);
cifs_debug_data_read, 0);
create_proc_read_entry("SimultaneousOps", 0, proc_fs_cifs,
cifs_total_xid_read, 0);
cifs_total_xid_read, 0);
create_proc_read_entry("Stats", 0, proc_fs_cifs,
cifs_stats_read, 0);
cifs_stats_read, 0);
pde = create_proc_read_entry("cifsFYI", 0, proc_fs_cifs,
cifsFYI_read, 0);
cifsFYI_read, 0);
if (pde)
pde->write_proc = cifsFYI_write;
pde =
create_proc_read_entry("traceSMB", 0, proc_fs_cifs,
traceSMB_read, 0);
traceSMB_read, 0);
if (pde)
pde->write_proc = traceSMB_write;
pde = create_proc_read_entry("OplockEnabled", 0, proc_fs_cifs,
oplockEnabled_read, 0);
oplockEnabled_read, 0);
if (pde)
pde->write_proc = oplockEnabled_write;
pde = create_proc_read_entry("QuotaEnabled", 0, proc_fs_cifs,
quotaEnabled_read, 0);
if (pde)
pde->write_proc = quotaEnabled_write;
pde = create_proc_read_entry("QuotaEnabled", 0, proc_fs_cifs,
quotaEnabled_read, 0);
if (pde)
pde->write_proc = quotaEnabled_write;
pde = create_proc_read_entry("LinuxExtensionsEnabled", 0, proc_fs_cifs,
linuxExtensionsEnabled_read, 0);
if (pde)
pde->write_proc = linuxExtensionsEnabled_write;
pde =
create_proc_read_entry("MultiuserMount", 0, proc_fs_cifs,
multiuser_mount_read, 0);
multiuser_mount_read, 0);
if (pde)
pde->write_proc = multiuser_mount_write;
pde =
create_proc_read_entry("ExtendedSecurity", 0, proc_fs_cifs,
extended_security_read, 0);
extended_security_read, 0);
if (pde)
pde->write_proc = extended_security_write;
pde =
create_proc_read_entry("LookupCacheEnable", 0, proc_fs_cifs,
lookupFlag_read, 0);
create_proc_read_entry("LookupCacheEnabled", 0, proc_fs_cifs,
lookupFlag_read, 0);
if (pde)
pde->write_proc = lookupFlag_write;
pde =
create_proc_read_entry("NTLMV2Enabled", 0, proc_fs_cifs,
ntlmv2_enabled_read, 0);
ntlmv2_enabled_read, 0);
if (pde)
pde->write_proc = ntlmv2_enabled_write;
pde =
create_proc_read_entry("PacketSigningEnabled", 0, proc_fs_cifs,
packet_signing_enabled_read, 0);
packet_signing_enabled_read, 0);
if (pde)
pde->write_proc = packet_signing_enabled_write;
}
......@@ -305,12 +312,15 @@ cifs_proc_clean(void)
remove_proc_entry("cifsFYI", proc_fs_cifs);
remove_proc_entry("TraceSMB", proc_fs_cifs);
remove_proc_entry("SimultaneousOps", proc_fs_cifs);
remove_proc_entry("TotalOps", proc_fs_cifs);
remove_proc_entry("Stats", proc_fs_cifs);
remove_proc_entry("MultiuserMount", proc_fs_cifs);
remove_proc_entry("OplockEnabled", proc_fs_cifs);
remove_proc_entry("NTLMV2Enabled",proc_fs_cifs);
remove_proc_entry("ExtendedSecurity",proc_fs_cifs);
remove_proc_entry("PacketSigningEnabled",proc_fs_cifs);
remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs);
remove_proc_entry("QuotaEnabled",proc_fs_cifs);
remove_proc_entry("LookupCacheEnabled",proc_fs_cifs);
remove_proc_entry("cifs", proc_root_fs);
}
......@@ -432,6 +442,46 @@ quotaEnabled_write(struct file *file, const char *buffer,
return count;
}
static int
linuxExtensionsEnabled_read(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
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;
if (len > count)
len = count;
else
*eof = 1;
if (len < 0)
len = 0;
return len;
}
static int
linuxExtensionsEnabled_write(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char c;
int rc;
rc = get_user(c, buffer);
if (rc)
return rc;
if (c == '0' || c == 'n' || c == 'N')
linuxExtEnabled = 0;
else if (c == '1' || c == 'y' || c == 'Y')
linuxExtEnabled = 1;
return count;
}
static int
lookupFlag_read(char *page, char **start, off_t off,
......
......@@ -52,6 +52,7 @@ int cifsERROR = 1;
int traceSMB = 0;
unsigned int oplockEnabled = 1;
unsigned int quotaEnabled = 0;
unsigned int linuxExtEnabled = 1;
unsigned int lookupCacheEnabled = 1;
unsigned int multiuser_mount = 0;
unsigned int extended_security = 0;
......
......@@ -384,4 +384,6 @@ GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent
with more secure ntlmssp2 challenge/resp */
GLOBAL_EXTERN unsigned int ntlmv2_support; /* better optional password hash */
GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */
GLOBAL_EXTERN unsigned int linuxExtEnabled; /* enable Linux/Unix CIFS extensions */
......@@ -1216,7 +1216,7 @@ unix_fill_in_inode(struct inode *tmp_inode,
}
}
void
static void
construct_dentry(struct qstr *qstring, struct file *file,
struct inode **ptmp_inode, struct dentry **pnew_dentry)
{
......@@ -1252,13 +1252,36 @@ construct_dentry(struct qstr *qstring, struct file *file,
*pnew_dentry = tmp_dentry;
}
void
static void reset_resume_key(struct file * dir_file,
unsigned char * filename,
unsigned int len) {
struct cifsFileInfo *cifsFile;
cifsFile = (struct cifsFileInfo *)dir_file->private_data;
if(cifsFile == NULL)
return;
if(cifsFile->search_resume_name) {
kfree(cifsFile->search_resume_name);
}
cifsFile->resume_name_length = len;
cifsFile->search_resume_name =
kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
memcpy(cifsFile->search_resume_name, filename,
cifsFile->resume_name_length);
cFYI(1,("Reset resume key to: %s",filename));
return;
}
static int
cifs_filldir(struct qstr *pqstring, FILE_DIRECTORY_INFO * pfindData,
struct file *file, filldir_t filldir, void *direntry)
{
struct inode *tmp_inode;
struct dentry *tmp_dentry;
int object_type;
int object_type,rc;
pqstring->name = pfindData->FileName;
pqstring->len = pfindData->FileNameLength;
......@@ -1266,19 +1289,26 @@ cifs_filldir(struct qstr *pqstring, FILE_DIRECTORY_INFO * pfindData,
construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
fill_in_inode(tmp_inode, pfindData, &object_type);
filldir(direntry, pfindData->FileName, pqstring->len, file->f_pos,
rc = filldir(direntry, pfindData->FileName, pqstring->len, file->f_pos,
tmp_inode->i_ino, object_type);
if(rc) {
/* due to readdir error we need to recalculate resume
key so next readdir will restart on right entry */
reset_resume_key(file, pfindData->FileName, pqstring->len);
cFYI(1,("Error %d on filldir of %s",rc ,pfindData->FileName));
}
dput(tmp_dentry);
return rc;
}
void
static int
cifs_filldir_unix(struct qstr *pqstring,
FILE_UNIX_INFO * pUnixFindData, struct file *file,
filldir_t filldir, void *direntry)
{
struct inode *tmp_inode;
struct dentry *tmp_dentry;
int object_type;
int object_type, rc;
pqstring->name = pUnixFindData->FileName;
pqstring->len = strnlen(pUnixFindData->FileName, MAX_PATHCONF);
......@@ -1286,9 +1316,16 @@ cifs_filldir_unix(struct qstr *pqstring,
construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
unix_fill_in_inode(tmp_inode, pUnixFindData, &object_type);
filldir(direntry, pUnixFindData->FileName, pqstring->len,
rc = filldir(direntry, pUnixFindData->FileName, pqstring->len,
file->f_pos, tmp_inode->i_ino, object_type);
if(rc) {
/* due to readdir error we need to recalculate resume
key so next readdir will restart on right entry */
reset_resume_key(file, pUnixFindData->FileName,pqstring->len);
cFYI(1,("Error %d on filldir of %s",rc ,pUnixFindData->FileName));
}
dput(tmp_dentry);
return rc;
}
int
......@@ -1468,10 +1505,16 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
FileName[0] != '.')
|| (pfindData->
FileName[1] != '.'))) {
cifs_filldir(&qstring,
if(cifs_filldir(&qstring,
pfindData,
file, filldir,
direntry);
direntry)) {
/* do not end search if
kernel not ready to take
remaining entries yet */
findParms.EndofSearch = 0;
break;
}
file->f_pos++;
}
} else { /* UnixSearch */
......@@ -1498,11 +1541,17 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
FileName[0] != '.')
|| (pfindDataUnix->
FileName[1] != '.'))) {
cifs_filldir_unix(&qstring,
if(cifs_filldir_unix(&qstring,
pfindDataUnix,
file,
filldir,
direntry);
direntry)) {
/* do not end search if
kernel not ready to take
remaining entries yet */
findParms.EndofSearch = 0;
break;
}
file->f_pos++;
}
}
......@@ -1570,6 +1619,11 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
rc = -ENOMEM;
break;
}
/* Free the memory allocated by previous findfirst
or findnext call - we can not reuse the memory since
the resume name may not be same string length */
if(cifsFile->search_resume_name)
kfree(cifsFile->search_resume_name);
cifsFile->search_resume_name =
kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
cFYI(1,("Last file: %s with name %d bytes long",
......@@ -1600,6 +1654,11 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
rc = -ENOMEM;
break;
}
/* Free the memory allocated by previous findfirst
or findnext call - we can not reuse the memory since
the resume name may not be same string length */
if(cifsFile->search_resume_name)
kfree(cifsFile->search_resume_name);
cifsFile->search_resume_name =
kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
cFYI(1,("fnext last file: %s with name %d bytes long",
......@@ -1631,11 +1690,17 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
|| (pfindData->FileName[0] != '.')
|| (pfindData->FileName[1] !=
'.'))) {
cifs_filldir
if(cifs_filldir
(&qstring,
pfindData,
file, filldir,
direntry);
direntry)) {
/* do not end search if
kernel not ready to take
remaining entries yet */
findNextParms.EndofSearch = 0;
break;
}
file->f_pos++;
}
} else { /* UnixSearch */
......@@ -1665,11 +1730,17 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
|| (pfindDataUnix->
FileName[1] !=
'.'))) {
cifs_filldir_unix
if(cifs_filldir_unix
(&qstring,
pfindDataUnix,
file, filldir,
direntry);
direntry)) {
/* do not end search if
kernel not ready to take
remaining entries yet */
findNextParms.EndofSearch = 0;
break;
}
file->f_pos++;
}
}
......
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