[readdir] convert cifs
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
9b5d5a1707
commit
be4ccdcc25
|
@ -968,7 +968,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct file_operations cifs_dir_ops = {
|
const struct file_operations cifs_dir_ops = {
|
||||||
.readdir = cifs_readdir,
|
.iterate = cifs_readdir,
|
||||||
.release = cifs_closedir,
|
.release = cifs_closedir,
|
||||||
.read = generic_read_dir,
|
.read = generic_read_dir,
|
||||||
.unlocked_ioctl = cifs_ioctl,
|
.unlocked_ioctl = cifs_ioctl,
|
||||||
|
|
|
@ -101,7 +101,7 @@ extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
|
||||||
extern int cifs_file_strict_mmap(struct file * , struct vm_area_struct *);
|
extern int cifs_file_strict_mmap(struct file * , struct vm_area_struct *);
|
||||||
extern const struct file_operations cifs_dir_ops;
|
extern const struct file_operations cifs_dir_ops;
|
||||||
extern int cifs_dir_open(struct inode *inode, struct file *file);
|
extern int cifs_dir_open(struct inode *inode, struct file *file);
|
||||||
extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir);
|
extern int cifs_readdir(struct file *file, struct dir_context *ctx);
|
||||||
|
|
||||||
/* Functions related to dir entries */
|
/* Functions related to dir entries */
|
||||||
extern const struct dentry_operations cifs_dentry_ops;
|
extern const struct dentry_operations cifs_dentry_ops;
|
||||||
|
|
|
@ -537,14 +537,14 @@ static int cifs_save_resume_key(const char *current_entry,
|
||||||
* every entry (do not increment for . or .. entry).
|
* every entry (do not increment for . or .. entry).
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon,
|
find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
|
||||||
struct file *file, char **current_entry, int *num_to_ret)
|
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 = pos;
|
||||||
struct cifsFileInfo *cfile = 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;
|
struct TCP_Server_Info *server = tcon->ses->server;
|
||||||
|
@ -659,8 +659,9 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
|
static int cifs_filldir(char *find_entry, struct file *file,
|
||||||
void *dirent, char *scratch_buf, unsigned int max_len)
|
struct dir_context *ctx,
|
||||||
|
char *scratch_buf, unsigned int max_len)
|
||||||
{
|
{
|
||||||
struct cifsFileInfo *file_info = file->private_data;
|
struct cifsFileInfo *file_info = file->private_data;
|
||||||
struct super_block *sb = file->f_path.dentry->d_sb;
|
struct super_block *sb = file->f_path.dentry->d_sb;
|
||||||
|
@ -740,13 +741,11 @@ static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
|
||||||
cifs_prime_dcache(file->f_dentry, &name, &fattr);
|
cifs_prime_dcache(file->f_dentry, &name, &fattr);
|
||||||
|
|
||||||
ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
|
ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
|
||||||
rc = filldir(dirent, name.name, name.len, file->f_pos, ino,
|
return !dir_emit(ctx, name.name, name.len, ino, fattr.cf_dtype);
|
||||||
fattr.cf_dtype);
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
|
int cifs_readdir(struct file *file, struct dir_context *ctx)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
unsigned int xid;
|
unsigned int xid;
|
||||||
|
@ -772,103 +771,86 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
|
||||||
goto rddir2_exit;
|
goto rddir2_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ((int) file->f_pos) {
|
if (!dir_emit_dots(file, ctx))
|
||||||
case 0:
|
goto rddir2_exit;
|
||||||
if (filldir(direntry, ".", 1, file->f_pos,
|
|
||||||
file_inode(file)->i_ino, DT_DIR) < 0) {
|
/* 1) If search is active,
|
||||||
cifs_dbg(VFS, "Filldir for current dir failed\n");
|
is in current search buffer?
|
||||||
rc = -ENOMEM;
|
if it before then restart search
|
||||||
|
if after then keep searching till find it */
|
||||||
|
|
||||||
|
if (file->private_data == NULL) {
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto rddir2_exit;
|
||||||
|
}
|
||||||
|
cifsFile = file->private_data;
|
||||||
|
if (cifsFile->srch_inf.endOfSearch) {
|
||||||
|
if (cifsFile->srch_inf.emptyDir) {
|
||||||
|
cifs_dbg(FYI, "End of search, empty dir\n");
|
||||||
|
rc = 0;
|
||||||
|
goto rddir2_exit;
|
||||||
|
}
|
||||||
|
} /* else {
|
||||||
|
cifsFile->invalidHandle = true;
|
||||||
|
tcon->ses->server->close(xid, tcon, &cifsFile->fid);
|
||||||
|
} */
|
||||||
|
|
||||||
|
tcon = tlink_tcon(cifsFile->tlink);
|
||||||
|
rc = find_cifs_entry(xid, tcon, ctx->pos, file, ¤t_entry,
|
||||||
|
&num_to_fill);
|
||||||
|
if (rc) {
|
||||||
|
cifs_dbg(FYI, "fce error %d\n", rc);
|
||||||
|
goto rddir2_exit;
|
||||||
|
} else if (current_entry != NULL) {
|
||||||
|
cifs_dbg(FYI, "entry %lld found\n", ctx->pos);
|
||||||
|
} else {
|
||||||
|
cifs_dbg(FYI, "could not find entry\n");
|
||||||
|
goto rddir2_exit;
|
||||||
|
}
|
||||||
|
cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n",
|
||||||
|
num_to_fill, cifsFile->srch_inf.ntwrk_buf_start);
|
||||||
|
max_len = tcon->ses->server->ops->calc_smb_size(
|
||||||
|
cifsFile->srch_inf.ntwrk_buf_start);
|
||||||
|
end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
|
||||||
|
|
||||||
|
tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL);
|
||||||
|
if (tmp_buf == NULL) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto rddir2_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < num_to_fill; i++) {
|
||||||
|
if (current_entry == NULL) {
|
||||||
|
/* evaluate whether this case is an error */
|
||||||
|
cifs_dbg(VFS, "past SMB end, num to fill %d i %d\n",
|
||||||
|
num_to_fill, i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
file->f_pos++;
|
/*
|
||||||
case 1:
|
* if buggy server returns . and .. late do we want to
|
||||||
if (filldir(direntry, "..", 2, file->f_pos,
|
* check for that here?
|
||||||
parent_ino(file->f_path.dentry), DT_DIR) < 0) {
|
*/
|
||||||
cifs_dbg(VFS, "Filldir for parent dir failed\n");
|
rc = cifs_filldir(current_entry, file, ctx,
|
||||||
rc = -ENOMEM;
|
tmp_buf, max_len);
|
||||||
break;
|
|
||||||
}
|
|
||||||
file->f_pos++;
|
|
||||||
default:
|
|
||||||
/* 1) If search is active,
|
|
||||||
is in current search buffer?
|
|
||||||
if it before then restart search
|
|
||||||
if after then keep searching till find it */
|
|
||||||
|
|
||||||
if (file->private_data == NULL) {
|
|
||||||
rc = -EINVAL;
|
|
||||||
free_xid(xid);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
cifsFile = file->private_data;
|
|
||||||
if (cifsFile->srch_inf.endOfSearch) {
|
|
||||||
if (cifsFile->srch_inf.emptyDir) {
|
|
||||||
cifs_dbg(FYI, "End of search, empty dir\n");
|
|
||||||
rc = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} /* else {
|
|
||||||
cifsFile->invalidHandle = true;
|
|
||||||
tcon->ses->server->close(xid, tcon, &cifsFile->fid);
|
|
||||||
} */
|
|
||||||
|
|
||||||
tcon = tlink_tcon(cifsFile->tlink);
|
|
||||||
rc = find_cifs_entry(xid, tcon, file, ¤t_entry,
|
|
||||||
&num_to_fill);
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cifs_dbg(FYI, "fce error %d\n", rc);
|
if (rc > 0)
|
||||||
goto rddir2_exit;
|
rc = 0;
|
||||||
} else if (current_entry != NULL) {
|
|
||||||
cifs_dbg(FYI, "entry %lld found\n", file->f_pos);
|
|
||||||
} else {
|
|
||||||
cifs_dbg(FYI, "could not find entry\n");
|
|
||||||
goto rddir2_exit;
|
|
||||||
}
|
|
||||||
cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n",
|
|
||||||
num_to_fill, cifsFile->srch_inf.ntwrk_buf_start);
|
|
||||||
max_len = tcon->ses->server->ops->calc_smb_size(
|
|
||||||
cifsFile->srch_inf.ntwrk_buf_start);
|
|
||||||
end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
|
|
||||||
|
|
||||||
tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL);
|
|
||||||
if (tmp_buf == NULL) {
|
|
||||||
rc = -ENOMEM;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; (i < num_to_fill) && (rc == 0); i++) {
|
ctx->pos++;
|
||||||
if (current_entry == NULL) {
|
if (ctx->pos ==
|
||||||
/* evaluate whether this case is an error */
|
cifsFile->srch_inf.index_of_last_entry) {
|
||||||
cifs_dbg(VFS, "past SMB end, num to fill %d i %d\n",
|
cifs_dbg(FYI, "last entry in buf at pos %lld %s\n",
|
||||||
num_to_fill, i);
|
ctx->pos, tmp_buf);
|
||||||
break;
|
cifs_save_resume_key(current_entry, cifsFile);
|
||||||
}
|
break;
|
||||||
/*
|
} else
|
||||||
* if buggy server returns . and .. late do we want to
|
current_entry =
|
||||||
* check for that here?
|
nxt_dir_entry(current_entry, end_of_smb,
|
||||||
*/
|
cifsFile->srch_inf.info_level);
|
||||||
rc = cifs_filldir(current_entry, file, filldir,
|
}
|
||||||
direntry, tmp_buf, max_len);
|
kfree(tmp_buf);
|
||||||
if (rc == -EOVERFLOW) {
|
|
||||||
rc = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
file->f_pos++;
|
|
||||||
if (file->f_pos ==
|
|
||||||
cifsFile->srch_inf.index_of_last_entry) {
|
|
||||||
cifs_dbg(FYI, "last entry in buf at pos %lld %s\n",
|
|
||||||
file->f_pos, tmp_buf);
|
|
||||||
cifs_save_resume_key(current_entry, cifsFile);
|
|
||||||
break;
|
|
||||||
} else
|
|
||||||
current_entry =
|
|
||||||
nxt_dir_entry(current_entry, end_of_smb,
|
|
||||||
cifsFile->srch_inf.info_level);
|
|
||||||
}
|
|
||||||
kfree(tmp_buf);
|
|
||||||
break;
|
|
||||||
} /* end switch */
|
|
||||||
|
|
||||||
rddir2_exit:
|
rddir2_exit:
|
||||||
free_xid(xid);
|
free_xid(xid);
|
||||||
|
|
Loading…
Reference in New Issue