CIFS: Move readdir code to ops struct
Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org> Signed-off-by: Steve French <smfrench@gmail.com>
This commit is contained in:
parent
1feeaac753
commit
92fc65a74a
6 changed files with 172 additions and 102 deletions
|
@ -177,6 +177,7 @@ struct cifs_fid;
|
||||||
struct cifs_readdata;
|
struct cifs_readdata;
|
||||||
struct cifs_writedata;
|
struct cifs_writedata;
|
||||||
struct cifs_io_parms;
|
struct cifs_io_parms;
|
||||||
|
struct cifs_search_info;
|
||||||
|
|
||||||
struct smb_version_operations {
|
struct smb_version_operations {
|
||||||
int (*send_cancel)(struct TCP_Server_Info *, void *,
|
int (*send_cancel)(struct TCP_Server_Info *, void *,
|
||||||
|
@ -313,6 +314,20 @@ struct smb_version_operations {
|
||||||
int (*sync_write)(const unsigned int, struct cifsFileInfo *,
|
int (*sync_write)(const unsigned int, struct cifsFileInfo *,
|
||||||
struct cifs_io_parms *, unsigned int *, struct kvec *,
|
struct cifs_io_parms *, unsigned int *, struct kvec *,
|
||||||
unsigned long);
|
unsigned long);
|
||||||
|
/* open dir, start readdir */
|
||||||
|
int (*query_dir_first)(const unsigned int, struct cifs_tcon *,
|
||||||
|
const char *, struct cifs_sb_info *,
|
||||||
|
struct cifs_fid *, __u16,
|
||||||
|
struct cifs_search_info *);
|
||||||
|
/* continue readdir */
|
||||||
|
int (*query_dir_next)(const unsigned int, struct cifs_tcon *,
|
||||||
|
struct cifs_fid *,
|
||||||
|
__u16, struct cifs_search_info *srch_inf);
|
||||||
|
/* close dir */
|
||||||
|
int (*close_dir)(const unsigned int, struct cifs_tcon *,
|
||||||
|
struct cifs_fid *);
|
||||||
|
/* calculate a size of SMB message */
|
||||||
|
unsigned int (*calc_smb_size)(void *);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct smb_version_values {
|
struct smb_version_values {
|
||||||
|
|
|
@ -100,7 +100,7 @@ extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
|
||||||
unsigned int bytes_written);
|
unsigned int bytes_written);
|
||||||
extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool);
|
extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool);
|
||||||
extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool);
|
extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool);
|
||||||
extern unsigned int smbCalcSize(struct smb_hdr *ptr);
|
extern unsigned int smbCalcSize(void *buf);
|
||||||
extern int decode_negTokenInit(unsigned char *security_blob, int length,
|
extern int decode_negTokenInit(unsigned char *security_blob, int length,
|
||||||
struct TCP_Server_Info *server);
|
struct TCP_Server_Info *server);
|
||||||
extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len);
|
extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len);
|
||||||
|
|
|
@ -618,39 +618,47 @@ int cifs_closedir(struct inode *inode, struct file *file)
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
unsigned int xid;
|
unsigned int xid;
|
||||||
struct cifsFileInfo *cfile = file->private_data;
|
struct cifsFileInfo *cfile = file->private_data;
|
||||||
char *tmp;
|
struct cifs_tcon *tcon;
|
||||||
|
struct TCP_Server_Info *server;
|
||||||
|
char *buf;
|
||||||
|
|
||||||
cFYI(1, "Closedir inode = 0x%p", inode);
|
cFYI(1, "Closedir inode = 0x%p", inode);
|
||||||
|
|
||||||
xid = get_xid();
|
if (cfile == NULL)
|
||||||
|
return rc;
|
||||||
|
|
||||||
if (cfile) {
|
xid = get_xid();
|
||||||
struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
|
tcon = tlink_tcon(cfile->tlink);
|
||||||
|
server = tcon->ses->server;
|
||||||
|
|
||||||
cFYI(1, "Freeing private data in close dir");
|
cFYI(1, "Freeing private data in close dir");
|
||||||
spin_lock(&cifs_file_list_lock);
|
spin_lock(&cifs_file_list_lock);
|
||||||
if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) {
|
if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) {
|
||||||
cfile->invalidHandle = true;
|
cfile->invalidHandle = true;
|
||||||
spin_unlock(&cifs_file_list_lock);
|
spin_unlock(&cifs_file_list_lock);
|
||||||
rc = CIFSFindClose(xid, tcon, cfile->fid.netfid);
|
if (server->ops->close_dir)
|
||||||
|
rc = server->ops->close_dir(xid, tcon, &cfile->fid);
|
||||||
|
else
|
||||||
|
rc = -ENOSYS;
|
||||||
cFYI(1, "Closing uncompleted readdir with rc %d", rc);
|
cFYI(1, "Closing uncompleted readdir with rc %d", rc);
|
||||||
/* not much we can do if it fails anyway, ignore rc */
|
/* not much we can do if it fails anyway, ignore rc */
|
||||||
rc = 0;
|
rc = 0;
|
||||||
} else
|
} else
|
||||||
spin_unlock(&cifs_file_list_lock);
|
spin_unlock(&cifs_file_list_lock);
|
||||||
tmp = cfile->srch_inf.ntwrk_buf_start;
|
|
||||||
if (tmp) {
|
buf = cfile->srch_inf.ntwrk_buf_start;
|
||||||
|
if (buf) {
|
||||||
cFYI(1, "closedir free smb buf in srch struct");
|
cFYI(1, "closedir free smb buf in srch struct");
|
||||||
cfile->srch_inf.ntwrk_buf_start = NULL;
|
cfile->srch_inf.ntwrk_buf_start = NULL;
|
||||||
if (cfile->srch_inf.smallBuf)
|
if (cfile->srch_inf.smallBuf)
|
||||||
cifs_small_buf_release(tmp);
|
cifs_small_buf_release(buf);
|
||||||
else
|
else
|
||||||
cifs_buf_release(tmp);
|
cifs_buf_release(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
cifs_put_tlink(cfile->tlink);
|
cifs_put_tlink(cfile->tlink);
|
||||||
kfree(file->private_data);
|
kfree(file->private_data);
|
||||||
file->private_data = NULL;
|
file->private_data = NULL;
|
||||||
}
|
|
||||||
/* BB can we lock the filestruct while this is going on? */
|
/* BB can we lock the filestruct while this is going on? */
|
||||||
free_xid(xid);
|
free_xid(xid);
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -913,8 +913,9 @@ map_smb_to_linux_error(char *buf, bool logErr)
|
||||||
* portion, the number of word parameters and the data portion of the message
|
* portion, the number of word parameters and the data portion of the message
|
||||||
*/
|
*/
|
||||||
unsigned int
|
unsigned int
|
||||||
smbCalcSize(struct smb_hdr *ptr)
|
smbCalcSize(void *buf)
|
||||||
{
|
{
|
||||||
|
struct smb_hdr *ptr = (struct smb_hdr *)buf;
|
||||||
return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) +
|
return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) +
|
||||||
2 /* size of the bcc field */ + get_bcc(ptr));
|
2 /* size of the bcc field */ + get_bcc(ptr));
|
||||||
}
|
}
|
||||||
|
|
|
@ -220,7 +220,8 @@ int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb,
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int initiate_cifs_search(const unsigned int xid, struct file *file)
|
static int
|
||||||
|
initiate_cifs_search(const unsigned int xid, struct file *file)
|
||||||
{
|
{
|
||||||
__u16 search_flags;
|
__u16 search_flags;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
@ -229,6 +230,7 @@ static int initiate_cifs_search(const unsigned int xid, struct file *file)
|
||||||
struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
|
struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
|
||||||
struct tcon_link *tlink = NULL;
|
struct tcon_link *tlink = NULL;
|
||||||
struct cifs_tcon *tcon;
|
struct cifs_tcon *tcon;
|
||||||
|
struct TCP_Server_Info *server;
|
||||||
|
|
||||||
if (file->private_data == NULL) {
|
if (file->private_data == NULL) {
|
||||||
tlink = cifs_sb_tlink(cifs_sb);
|
tlink = cifs_sb_tlink(cifs_sb);
|
||||||
|
@ -248,6 +250,13 @@ static int initiate_cifs_search(const unsigned int xid, struct file *file)
|
||||||
tcon = tlink_tcon(cifsFile->tlink);
|
tcon = tlink_tcon(cifsFile->tlink);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
server = tcon->ses->server;
|
||||||
|
|
||||||
|
if (!server->ops->query_dir_first) {
|
||||||
|
rc = -ENOSYS;
|
||||||
|
goto error_exit;
|
||||||
|
}
|
||||||
|
|
||||||
cifsFile->invalidHandle = true;
|
cifsFile->invalidHandle = true;
|
||||||
cifsFile->srch_inf.endOfSearch = false;
|
cifsFile->srch_inf.endOfSearch = false;
|
||||||
|
|
||||||
|
@ -278,10 +287,10 @@ ffirst_retry:
|
||||||
if (backup_cred(cifs_sb))
|
if (backup_cred(cifs_sb))
|
||||||
search_flags |= CIFS_SEARCH_BACKUP_SEARCH;
|
search_flags |= CIFS_SEARCH_BACKUP_SEARCH;
|
||||||
|
|
||||||
rc = CIFSFindFirst(xid, tcon, full_path, cifs_sb->local_nls,
|
rc = server->ops->query_dir_first(xid, tcon, full_path, cifs_sb,
|
||||||
&cifsFile->fid.netfid, search_flags, &cifsFile->srch_inf,
|
&cifsFile->fid, search_flags,
|
||||||
cifs_sb->mnt_cifs_flags &
|
&cifsFile->srch_inf);
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
|
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
cifsFile->invalidHandle = false;
|
cifsFile->invalidHandle = false;
|
||||||
/* BB add following call to handle readdir on new NTFS symlink errors
|
/* BB add following call to handle readdir on new NTFS symlink errors
|
||||||
|
@ -501,62 +510,67 @@ static int cifs_save_resume_key(const char *current_entry,
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find the corresponding entry in the search */
|
/*
|
||||||
/* Note that the SMB server returns search entries for . and .. which
|
* Find the corresponding entry in the search. Note that the SMB server returns
|
||||||
complicates logic here if we choose to parse for them and we do not
|
* search entries for . and .. which complicates logic here if we choose to
|
||||||
assume that they are located in the findfirst return buffer.*/
|
* parse for them and we do not assume that they are located in the findfirst
|
||||||
/* We start counting in the buffer with entry 2 and increment for every
|
* return buffer. We start counting in the buffer with entry 2 and increment for
|
||||||
entry (do not increment for . or .. entry) */
|
* every entry (do not increment for . or .. entry).
|
||||||
static int find_cifs_entry(const unsigned int xid, struct cifs_tcon *pTcon,
|
*/
|
||||||
struct file *file, char **ppCurrentEntry, int *num_to_ret)
|
static int
|
||||||
|
find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
|
struct file *file, char **current_entry, int *num_to_ret)
|
||||||
{
|
{
|
||||||
__u16 search_flags;
|
__u16 search_flags;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int pos_in_buf = 0;
|
int pos_in_buf = 0;
|
||||||
loff_t first_entry_in_buffer;
|
loff_t first_entry_in_buffer;
|
||||||
loff_t index_to_find = file->f_pos;
|
loff_t index_to_find = file->f_pos;
|
||||||
struct cifsFileInfo *cifsFile = file->private_data;
|
struct cifsFileInfo *cfile = file->private_data;
|
||||||
struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
|
struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
|
||||||
|
struct TCP_Server_Info *server = tcon->ses->server;
|
||||||
/* check if index in the buffer */
|
/* check if index in the buffer */
|
||||||
|
|
||||||
if ((cifsFile == NULL) || (ppCurrentEntry == NULL) ||
|
if (!server->ops->query_dir_first || !server->ops->query_dir_next)
|
||||||
(num_to_ret == NULL))
|
return -ENOSYS;
|
||||||
|
|
||||||
|
if ((cfile == NULL) || (current_entry == NULL) || (num_to_ret == NULL))
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
*ppCurrentEntry = NULL;
|
*current_entry = NULL;
|
||||||
first_entry_in_buffer =
|
first_entry_in_buffer = cfile->srch_inf.index_of_last_entry -
|
||||||
cifsFile->srch_inf.index_of_last_entry -
|
cfile->srch_inf.entries_in_buffer;
|
||||||
cifsFile->srch_inf.entries_in_buffer;
|
|
||||||
|
|
||||||
/* if first entry in buf is zero then is first buffer
|
/*
|
||||||
in search response data which means it is likely . and ..
|
* If first entry in buf is zero then is first buffer
|
||||||
will be in this buffer, although some servers do not return
|
* in search response data which means it is likely . and ..
|
||||||
. and .. for the root of a drive and for those we need
|
* will be in this buffer, although some servers do not return
|
||||||
to start two entries earlier */
|
* . and .. for the root of a drive and for those we need
|
||||||
|
* to start two entries earlier.
|
||||||
|
*/
|
||||||
|
|
||||||
dump_cifs_file_struct(file, "In fce ");
|
dump_cifs_file_struct(file, "In fce ");
|
||||||
if (((index_to_find < cifsFile->srch_inf.index_of_last_entry) &&
|
if (((index_to_find < cfile->srch_inf.index_of_last_entry) &&
|
||||||
is_dir_changed(file)) ||
|
is_dir_changed(file)) || (index_to_find < first_entry_in_buffer)) {
|
||||||
(index_to_find < first_entry_in_buffer)) {
|
|
||||||
/* close and restart search */
|
/* close and restart search */
|
||||||
cFYI(1, "search backing up - close and restart search");
|
cFYI(1, "search backing up - close and restart search");
|
||||||
spin_lock(&cifs_file_list_lock);
|
spin_lock(&cifs_file_list_lock);
|
||||||
if (!cifsFile->srch_inf.endOfSearch &&
|
if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) {
|
||||||
!cifsFile->invalidHandle) {
|
cfile->invalidHandle = true;
|
||||||
cifsFile->invalidHandle = true;
|
|
||||||
spin_unlock(&cifs_file_list_lock);
|
spin_unlock(&cifs_file_list_lock);
|
||||||
CIFSFindClose(xid, pTcon, cifsFile->fid.netfid);
|
if (server->ops->close)
|
||||||
|
server->ops->close(xid, tcon, &cfile->fid);
|
||||||
} else
|
} else
|
||||||
spin_unlock(&cifs_file_list_lock);
|
spin_unlock(&cifs_file_list_lock);
|
||||||
if (cifsFile->srch_inf.ntwrk_buf_start) {
|
if (cfile->srch_inf.ntwrk_buf_start) {
|
||||||
cFYI(1, "freeing SMB ff cache buf on search rewind");
|
cFYI(1, "freeing SMB ff cache buf on search rewind");
|
||||||
if (cifsFile->srch_inf.smallBuf)
|
if (cfile->srch_inf.smallBuf)
|
||||||
cifs_small_buf_release(cifsFile->srch_inf.
|
cifs_small_buf_release(cfile->srch_inf.
|
||||||
ntwrk_buf_start);
|
ntwrk_buf_start);
|
||||||
else
|
else
|
||||||
cifs_buf_release(cifsFile->srch_inf.
|
cifs_buf_release(cfile->srch_inf.
|
||||||
ntwrk_buf_start);
|
ntwrk_buf_start);
|
||||||
cifsFile->srch_inf.ntwrk_buf_start = NULL;
|
cfile->srch_inf.ntwrk_buf_start = NULL;
|
||||||
}
|
}
|
||||||
rc = initiate_cifs_search(xid, file);
|
rc = initiate_cifs_search(xid, file);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
|
@ -565,65 +579,64 @@ static int find_cifs_entry(const unsigned int xid, struct cifs_tcon *pTcon,
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
/* FindFirst/Next set last_entry to NULL on malformed reply */
|
/* FindFirst/Next set last_entry to NULL on malformed reply */
|
||||||
if (cifsFile->srch_inf.last_entry)
|
if (cfile->srch_inf.last_entry)
|
||||||
cifs_save_resume_key(cifsFile->srch_inf.last_entry,
|
cifs_save_resume_key(cfile->srch_inf.last_entry, cfile);
|
||||||
cifsFile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME;
|
search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME;
|
||||||
if (backup_cred(cifs_sb))
|
if (backup_cred(cifs_sb))
|
||||||
search_flags |= CIFS_SEARCH_BACKUP_SEARCH;
|
search_flags |= CIFS_SEARCH_BACKUP_SEARCH;
|
||||||
|
|
||||||
while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) &&
|
while ((index_to_find >= cfile->srch_inf.index_of_last_entry) &&
|
||||||
(rc == 0) && !cifsFile->srch_inf.endOfSearch) {
|
(rc == 0) && !cfile->srch_inf.endOfSearch) {
|
||||||
cFYI(1, "calling findnext2");
|
cFYI(1, "calling findnext2");
|
||||||
rc = CIFSFindNext(xid, pTcon, cifsFile->fid.netfid,
|
rc = server->ops->query_dir_next(xid, tcon, &cfile->fid,
|
||||||
search_flags, &cifsFile->srch_inf);
|
search_flags,
|
||||||
|
&cfile->srch_inf);
|
||||||
/* FindFirst/Next set last_entry to NULL on malformed reply */
|
/* FindFirst/Next set last_entry to NULL on malformed reply */
|
||||||
if (cifsFile->srch_inf.last_entry)
|
if (cfile->srch_inf.last_entry)
|
||||||
cifs_save_resume_key(cifsFile->srch_inf.last_entry,
|
cifs_save_resume_key(cfile->srch_inf.last_entry, cfile);
|
||||||
cifsFile);
|
|
||||||
if (rc)
|
if (rc)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
if (index_to_find < cifsFile->srch_inf.index_of_last_entry) {
|
if (index_to_find < cfile->srch_inf.index_of_last_entry) {
|
||||||
/* we found the buffer that contains the entry */
|
/* we found the buffer that contains the entry */
|
||||||
/* scan and find it */
|
/* scan and find it */
|
||||||
int i;
|
int i;
|
||||||
char *current_entry;
|
char *cur_ent;
|
||||||
char *end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
|
char *end_of_smb = cfile->srch_inf.ntwrk_buf_start +
|
||||||
smbCalcSize((struct smb_hdr *)
|
server->ops->calc_smb_size(
|
||||||
cifsFile->srch_inf.ntwrk_buf_start);
|
cfile->srch_inf.ntwrk_buf_start);
|
||||||
|
|
||||||
current_entry = cifsFile->srch_inf.srch_entries_start;
|
cur_ent = cfile->srch_inf.srch_entries_start;
|
||||||
first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry
|
first_entry_in_buffer = cfile->srch_inf.index_of_last_entry
|
||||||
- cifsFile->srch_inf.entries_in_buffer;
|
- cfile->srch_inf.entries_in_buffer;
|
||||||
pos_in_buf = index_to_find - first_entry_in_buffer;
|
pos_in_buf = index_to_find - first_entry_in_buffer;
|
||||||
cFYI(1, "found entry - pos_in_buf %d", pos_in_buf);
|
cFYI(1, "found entry - pos_in_buf %d", pos_in_buf);
|
||||||
|
|
||||||
for (i = 0; (i < (pos_in_buf)) && (current_entry != NULL); i++) {
|
for (i = 0; (i < (pos_in_buf)) && (cur_ent != NULL); i++) {
|
||||||
/* go entry by entry figuring out which is first */
|
/* go entry by entry figuring out which is first */
|
||||||
current_entry = nxt_dir_entry(current_entry, end_of_smb,
|
cur_ent = nxt_dir_entry(cur_ent, end_of_smb,
|
||||||
cifsFile->srch_inf.info_level);
|
cfile->srch_inf.info_level);
|
||||||
}
|
}
|
||||||
if ((current_entry == NULL) && (i < pos_in_buf)) {
|
if ((cur_ent == NULL) && (i < pos_in_buf)) {
|
||||||
/* BB fixme - check if we should flag this error */
|
/* BB fixme - check if we should flag this error */
|
||||||
cERROR(1, "reached end of buf searching for pos in buf"
|
cERROR(1, "reached end of buf searching for pos in buf"
|
||||||
" %d index to find %lld rc %d",
|
" %d index to find %lld rc %d", pos_in_buf,
|
||||||
pos_in_buf, index_to_find, rc);
|
index_to_find, rc);
|
||||||
}
|
}
|
||||||
rc = 0;
|
rc = 0;
|
||||||
*ppCurrentEntry = current_entry;
|
*current_entry = cur_ent;
|
||||||
} else {
|
} else {
|
||||||
cFYI(1, "index not in buffer - could not findnext into it");
|
cFYI(1, "index not in buffer - could not findnext into it");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) {
|
if (pos_in_buf >= cfile->srch_inf.entries_in_buffer) {
|
||||||
cFYI(1, "can not return entries pos_in_buf beyond last");
|
cFYI(1, "can not return entries pos_in_buf beyond last");
|
||||||
*num_to_ret = 0;
|
*num_to_ret = 0;
|
||||||
} else
|
} else
|
||||||
*num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf;
|
*num_to_ret = cfile->srch_inf.entries_in_buffer - pos_in_buf;
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -723,7 +736,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
unsigned int xid;
|
unsigned int xid;
|
||||||
int i;
|
int i;
|
||||||
struct cifs_tcon *pTcon;
|
struct cifs_tcon *tcon;
|
||||||
struct cifsFileInfo *cifsFile = NULL;
|
struct cifsFileInfo *cifsFile = NULL;
|
||||||
char *current_entry;
|
char *current_entry;
|
||||||
int num_to_fill = 0;
|
int num_to_fill = 0;
|
||||||
|
@ -781,12 +794,12 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
|
||||||
}
|
}
|
||||||
} /* else {
|
} /* else {
|
||||||
cifsFile->invalidHandle = true;
|
cifsFile->invalidHandle = true;
|
||||||
CIFSFindClose(xid, pTcon, cifsFile->fid.netfid);
|
tcon->ses->server->close(xid, tcon, &cifsFile->fid);
|
||||||
} */
|
} */
|
||||||
|
|
||||||
pTcon = tlink_tcon(cifsFile->tlink);
|
tcon = tlink_tcon(cifsFile->tlink);
|
||||||
rc = find_cifs_entry(xid, pTcon, file,
|
rc = find_cifs_entry(xid, tcon, file, ¤t_entry,
|
||||||
¤t_entry, &num_to_fill);
|
&num_to_fill);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cFYI(1, "fce error %d", rc);
|
cFYI(1, "fce error %d", rc);
|
||||||
goto rddir2_exit;
|
goto rddir2_exit;
|
||||||
|
@ -798,7 +811,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
|
||||||
}
|
}
|
||||||
cFYI(1, "loop through %d times filling dir for net buf %p",
|
cFYI(1, "loop through %d times filling dir for net buf %p",
|
||||||
num_to_fill, cifsFile->srch_inf.ntwrk_buf_start);
|
num_to_fill, cifsFile->srch_inf.ntwrk_buf_start);
|
||||||
max_len = smbCalcSize((struct smb_hdr *)
|
max_len = tcon->ses->server->ops->calc_smb_size(
|
||||||
cifsFile->srch_inf.ntwrk_buf_start);
|
cifsFile->srch_inf.ntwrk_buf_start);
|
||||||
end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
|
end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
|
||||||
|
|
||||||
|
@ -815,10 +828,12 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
|
||||||
num_to_fill, i);
|
num_to_fill, i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* if buggy server returns . and .. late do
|
/*
|
||||||
we want to check for that here? */
|
* if buggy server returns . and .. late do we want to
|
||||||
rc = cifs_filldir(current_entry, file,
|
* check for that here?
|
||||||
filldir, direntry, tmp_buf, max_len);
|
*/
|
||||||
|
rc = cifs_filldir(current_entry, file, filldir,
|
||||||
|
direntry, tmp_buf, max_len);
|
||||||
if (rc == -EOVERFLOW) {
|
if (rc == -EOVERFLOW) {
|
||||||
rc = 0;
|
rc = 0;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -836,6 +836,33 @@ out:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cifs_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
|
const char *path, struct cifs_sb_info *cifs_sb,
|
||||||
|
struct cifs_fid *fid, __u16 search_flags,
|
||||||
|
struct cifs_search_info *srch_inf)
|
||||||
|
{
|
||||||
|
return CIFSFindFirst(xid, tcon, path, cifs_sb->local_nls,
|
||||||
|
&fid->netfid, search_flags, srch_inf,
|
||||||
|
cifs_sb->mnt_cifs_flags &
|
||||||
|
CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cifs_query_dir_next(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
|
struct cifs_fid *fid, __u16 search_flags,
|
||||||
|
struct cifs_search_info *srch_inf)
|
||||||
|
{
|
||||||
|
return CIFSFindNext(xid, tcon, fid->netfid, search_flags, srch_inf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cifs_close_dir(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
|
struct cifs_fid *fid)
|
||||||
|
{
|
||||||
|
return CIFSFindClose(xid, tcon, fid->netfid);
|
||||||
|
}
|
||||||
|
|
||||||
struct smb_version_operations smb1_operations = {
|
struct smb_version_operations smb1_operations = {
|
||||||
.send_cancel = send_nt_cancel,
|
.send_cancel = send_nt_cancel,
|
||||||
.compare_fids = cifs_compare_fids,
|
.compare_fids = cifs_compare_fids,
|
||||||
|
@ -891,6 +918,10 @@ struct smb_version_operations smb1_operations = {
|
||||||
.async_writev = cifs_async_writev,
|
.async_writev = cifs_async_writev,
|
||||||
.sync_read = cifs_sync_read,
|
.sync_read = cifs_sync_read,
|
||||||
.sync_write = cifs_sync_write,
|
.sync_write = cifs_sync_write,
|
||||||
|
.query_dir_first = cifs_query_dir_first,
|
||||||
|
.query_dir_next = cifs_query_dir_next,
|
||||||
|
.close_dir = cifs_close_dir,
|
||||||
|
.calc_smb_size = smbCalcSize,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct smb_version_values smb1_values = {
|
struct smb_version_values smb1_values = {
|
||||||
|
|
Loading…
Reference in a new issue