Commit f03c86f7 authored by Pavel Shilovsky's avatar Pavel Shilovsky

Update 3.2 sources from stable (v3.2.27)

parent b8fbf88f
...@@ -706,7 +706,7 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin) ...@@ -706,7 +706,7 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
* origin == SEEK_END || SEEK_DATA || SEEK_HOLE => we must revalidate * origin == SEEK_END || SEEK_DATA || SEEK_HOLE => we must revalidate
* the cached file length * the cached file length
*/ */
if (origin != SEEK_SET || origin != SEEK_CUR) { if (origin != SEEK_SET && origin != SEEK_CUR) {
int rc; int rc;
struct inode *inode = file->f_path.dentry->d_inode; struct inode *inode = file->f_path.dentry->d_inode;
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#define CIFS_MIN_RCV_POOL 4 #define CIFS_MIN_RCV_POOL 4
#define MAX_REOPEN_ATT 5 /* these many maximum attempts to reopen a file */
/* /*
* default attribute cache timeout (jiffies) * default attribute cache timeout (jiffies)
*/ */
......
...@@ -184,11 +184,13 @@ extern int CIFSTCon(unsigned int xid, struct cifs_ses *ses, ...@@ -184,11 +184,13 @@ extern int CIFSTCon(unsigned int xid, struct cifs_ses *ses,
extern int CIFSFindFirst(const int xid, struct cifs_tcon *tcon, extern int CIFSFindFirst(const int xid, struct cifs_tcon *tcon,
const char *searchName, const struct nls_table *nls_codepage, const char *searchName, const struct nls_table *nls_codepage,
__u16 *searchHandle, struct cifs_search_info *psrch_inf, __u16 *searchHandle, __u16 search_flags,
struct cifs_search_info *psrch_inf,
int map, const char dirsep); int map, const char dirsep);
extern int CIFSFindNext(const int xid, struct cifs_tcon *tcon, extern int CIFSFindNext(const int xid, struct cifs_tcon *tcon,
__u16 searchHandle, struct cifs_search_info *psrch_inf); __u16 searchHandle, __u16 search_flags,
struct cifs_search_info *psrch_inf);
extern int CIFSFindClose(const int, struct cifs_tcon *tcon, extern int CIFSFindClose(const int, struct cifs_tcon *tcon,
const __u16 search_handle); const __u16 search_handle);
......
...@@ -89,6 +89,32 @@ static struct { ...@@ -89,6 +89,32 @@ static struct {
/* Forward declarations */ /* Forward declarations */
static void cifs_readv_complete(struct work_struct *work); static void cifs_readv_complete(struct work_struct *work);
#ifdef CONFIG_HIGHMEM
/*
* On arches that have high memory, kmap address space is limited. By
* serializing the kmap operations on those arches, we ensure that we don't
* end up with a bunch of threads in writeback with partially mapped page
* arrays, stuck waiting for kmap to come back. That situation prevents
* progress and can deadlock.
*/
static DEFINE_MUTEX(cifs_kmap_mutex);
static inline void
cifs_kmap_lock(void)
{
mutex_lock(&cifs_kmap_mutex);
}
static inline void
cifs_kmap_unlock(void)
{
mutex_unlock(&cifs_kmap_mutex);
}
#else /* !CONFIG_HIGHMEM */
#define cifs_kmap_lock() do { ; } while(0)
#define cifs_kmap_unlock() do { ; } while(0)
#endif /* CONFIG_HIGHMEM */
/* Mark as invalid, all open files on tree connections since they /* Mark as invalid, all open files on tree connections since they
were closed when session to server was lost */ were closed when session to server was lost */
static void mark_open_files_invalid(struct cifs_tcon *pTcon) static void mark_open_files_invalid(struct cifs_tcon *pTcon)
...@@ -1547,6 +1573,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) ...@@ -1547,6 +1573,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0; eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0;
cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index); cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index);
cifs_kmap_lock();
list_for_each_entry_safe(page, tpage, &rdata->pages, lru) { list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
if (remaining >= PAGE_CACHE_SIZE) { if (remaining >= PAGE_CACHE_SIZE) {
/* enough data to fill the page */ /* enough data to fill the page */
...@@ -1596,6 +1623,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) ...@@ -1596,6 +1623,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
page_cache_release(page); page_cache_release(page);
} }
} }
cifs_kmap_unlock();
/* issue the read if we have any iovecs left to fill */ /* issue the read if we have any iovecs left to fill */
if (rdata->nr_iov > 1) { if (rdata->nr_iov > 1) {
...@@ -2178,6 +2206,7 @@ cifs_async_writev(struct cifs_writedata *wdata) ...@@ -2178,6 +2206,7 @@ cifs_async_writev(struct cifs_writedata *wdata)
iov[0].iov_base = smb; iov[0].iov_base = smb;
/* marshal up the pages into iov array */ /* marshal up the pages into iov array */
cifs_kmap_lock();
wdata->bytes = 0; wdata->bytes = 0;
for (i = 0; i < wdata->nr_pages; i++) { for (i = 0; i < wdata->nr_pages; i++) {
iov[i + 1].iov_len = min(inode->i_size - iov[i + 1].iov_len = min(inode->i_size -
...@@ -2186,6 +2215,7 @@ cifs_async_writev(struct cifs_writedata *wdata) ...@@ -2186,6 +2215,7 @@ cifs_async_writev(struct cifs_writedata *wdata)
iov[i + 1].iov_base = kmap(wdata->pages[i]); iov[i + 1].iov_base = kmap(wdata->pages[i]);
wdata->bytes += iov[i + 1].iov_len; wdata->bytes += iov[i + 1].iov_len;
} }
cifs_kmap_unlock();
cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes); cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
...@@ -4334,7 +4364,7 @@ int ...@@ -4334,7 +4364,7 @@ int
CIFSFindFirst(const int xid, struct cifs_tcon *tcon, CIFSFindFirst(const int xid, struct cifs_tcon *tcon,
const char *searchName, const char *searchName,
const struct nls_table *nls_codepage, const struct nls_table *nls_codepage,
__u16 *pnetfid, __u16 *pnetfid, __u16 search_flags,
struct cifs_search_info *psrch_inf, int remap, const char dirsep) struct cifs_search_info *psrch_inf, int remap, const char dirsep)
{ {
/* level 257 SMB_ */ /* level 257 SMB_ */
...@@ -4406,8 +4436,7 @@ findFirstRetry: ...@@ -4406,8 +4436,7 @@ findFirstRetry:
cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
ATTR_DIRECTORY); ATTR_DIRECTORY);
pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO)); pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | pSMB->SearchFlags = cpu_to_le16(search_flags);
CIFS_SEARCH_RETURN_RESUME);
pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level); pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
/* BB what should we set StorageType to? Does it matter? BB */ /* BB what should we set StorageType to? Does it matter? BB */
...@@ -4477,8 +4506,8 @@ findFirstRetry: ...@@ -4477,8 +4506,8 @@ findFirstRetry:
return rc; return rc;
} }
int CIFSFindNext(const int xid, struct cifs_tcon *tcon, int CIFSFindNext(const int xid, struct cifs_tcon *tcon, __u16 searchHandle,
__u16 searchHandle, struct cifs_search_info *psrch_inf) __u16 search_flags, struct cifs_search_info *psrch_inf)
{ {
TRANSACTION2_FNEXT_REQ *pSMB = NULL; TRANSACTION2_FNEXT_REQ *pSMB = NULL;
TRANSACTION2_FNEXT_RSP *pSMBr = NULL; TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
...@@ -4521,8 +4550,7 @@ int CIFSFindNext(const int xid, struct cifs_tcon *tcon, ...@@ -4521,8 +4550,7 @@ int CIFSFindNext(const int xid, struct cifs_tcon *tcon,
cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO)); cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level); pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
pSMB->ResumeKey = psrch_inf->resume_key; pSMB->ResumeKey = psrch_inf->resume_key;
pSMB->SearchFlags = pSMB->SearchFlags = cpu_to_le16(search_flags);
cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
name_len = psrch_inf->resume_name_len; name_len = psrch_inf->resume_name_len;
params += name_len; params += name_len;
...@@ -4833,8 +4861,12 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, ...@@ -4833,8 +4861,12 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
max_len = data_end - temp; max_len = data_end - temp;
node->node_name = cifs_strndup_from_ucs(temp, max_len, node->node_name = cifs_strndup_from_ucs(temp, max_len,
is_unicode, nls_codepage); is_unicode, nls_codepage);
if (!node->node_name) if (!node->node_name) {
rc = -ENOMEM; rc = -ENOMEM;
goto parse_DFS_referrals_exit;
}
ref++;
} }
parse_DFS_referrals_exit: parse_DFS_referrals_exit:
......
...@@ -2929,6 +2929,18 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, ...@@ -2929,6 +2929,18 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
#define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024) #define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024)
#define CIFS_DEFAULT_NON_POSIX_WSIZE (65536) #define CIFS_DEFAULT_NON_POSIX_WSIZE (65536)
/*
* On hosts with high memory, we can't currently support wsize/rsize that are
* larger than we can kmap at once. Cap the rsize/wsize at
* LAST_PKMAP * PAGE_SIZE. We'll never be able to fill a read or write request
* larger than that anyway.
*/
#ifdef CONFIG_HIGHMEM
#define CIFS_KMAP_SIZE_LIMIT (LAST_PKMAP * PAGE_CACHE_SIZE)
#else /* CONFIG_HIGHMEM */
#define CIFS_KMAP_SIZE_LIMIT (1<<24)
#endif /* CONFIG_HIGHMEM */
static unsigned int static unsigned int
cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info) cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
{ {
...@@ -2959,6 +2971,9 @@ cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info) ...@@ -2959,6 +2971,9 @@ cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
wsize = min_t(unsigned int, wsize, wsize = min_t(unsigned int, wsize,
server->maxBuf - sizeof(WRITE_REQ) + 4); server->maxBuf - sizeof(WRITE_REQ) + 4);
/* limit to the amount that we can kmap at once */
wsize = min_t(unsigned int, wsize, CIFS_KMAP_SIZE_LIMIT);
/* hard limit of CIFS_MAX_WSIZE */ /* hard limit of CIFS_MAX_WSIZE */
wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE); wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
...@@ -2979,18 +2994,15 @@ cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info) ...@@ -2979,18 +2994,15 @@ cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
* MS-CIFS indicates that servers are only limited by the client's * MS-CIFS indicates that servers are only limited by the client's
* bufsize for reads, testing against win98se shows that it throws * bufsize for reads, testing against win98se shows that it throws
* INVALID_PARAMETER errors if you try to request too large a read. * INVALID_PARAMETER errors if you try to request too large a read.
* OS/2 just sends back short reads.
* *
* If the server advertises a MaxBufferSize of less than one page, * If the server doesn't advertise CAP_LARGE_READ_X, then assume that
* assume that it also can't satisfy reads larger than that either. * it can't handle a read request larger than its MaxBufferSize either.
*
* FIXME: Is there a better heuristic for this?
*/ */
if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_READ_CAP)) if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_READ_CAP))
defsize = CIFS_DEFAULT_IOSIZE; defsize = CIFS_DEFAULT_IOSIZE;
else if (server->capabilities & CAP_LARGE_READ_X) else if (server->capabilities & CAP_LARGE_READ_X)
defsize = CIFS_DEFAULT_NON_POSIX_RSIZE; defsize = CIFS_DEFAULT_NON_POSIX_RSIZE;
else if (server->maxBuf >= PAGE_CACHE_SIZE)
defsize = CIFSMaxBufSize;
else else
defsize = server->maxBuf - sizeof(READ_RSP); defsize = server->maxBuf - sizeof(READ_RSP);
...@@ -3003,6 +3015,9 @@ cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info) ...@@ -3003,6 +3015,9 @@ cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
if (!(server->capabilities & CAP_LARGE_READ_X)) if (!(server->capabilities & CAP_LARGE_READ_X))
rsize = min_t(unsigned int, CIFSMaxBufSize, rsize); rsize = min_t(unsigned int, CIFSMaxBufSize, rsize);
/* limit to the amount that we can kmap at once */
rsize = min_t(unsigned int, rsize, CIFS_KMAP_SIZE_LIMIT);
/* hard limit of CIFS_MAX_RSIZE */ /* hard limit of CIFS_MAX_RSIZE */
rsize = min_t(unsigned int, rsize, CIFS_MAX_RSIZE); rsize = min_t(unsigned int, rsize, CIFS_MAX_RSIZE);
......
...@@ -841,13 +841,21 @@ cifs_posix_lock_set(struct file *file, struct file_lock *flock) ...@@ -841,13 +841,21 @@ cifs_posix_lock_set(struct file *file, struct file_lock *flock)
if ((flock->fl_flags & FL_POSIX) == 0) if ((flock->fl_flags & FL_POSIX) == 0)
return rc; return rc;
try_again:
mutex_lock(&cinode->lock_mutex); mutex_lock(&cinode->lock_mutex);
if (!cinode->can_cache_brlcks) { if (!cinode->can_cache_brlcks) {
mutex_unlock(&cinode->lock_mutex); mutex_unlock(&cinode->lock_mutex);
return rc; return rc;
} }
rc = posix_lock_file_wait(file, flock);
rc = posix_lock_file(file, flock, NULL);
mutex_unlock(&cinode->lock_mutex); mutex_unlock(&cinode->lock_mutex);
if (rc == FILE_LOCK_DEFERRED) {
rc = wait_event_interruptible(flock->fl_wait, !flock->fl_next);
if (!rc)
goto try_again;
locks_delete_block(flock);
}
return rc; return rc;
} }
...@@ -1532,10 +1540,11 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode, ...@@ -1532,10 +1540,11 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode, struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
bool fsuid_only) bool fsuid_only)
{ {
struct cifsFileInfo *open_file; struct cifsFileInfo *open_file, *inv_file = NULL;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
bool any_available = false; bool any_available = false;
int rc; int rc;
unsigned int refind = 0;
/* Having a null inode here (because mapping->host was set to zero by /* Having a null inode here (because mapping->host was set to zero by
the VFS or MM) should not happen but we had reports of on oops (due to the VFS or MM) should not happen but we had reports of on oops (due to
...@@ -1555,40 +1564,25 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode, ...@@ -1555,40 +1564,25 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
spin_lock(&cifs_file_list_lock); spin_lock(&cifs_file_list_lock);
refind_writable: refind_writable:
if (refind > MAX_REOPEN_ATT) {
spin_unlock(&cifs_file_list_lock);
return NULL;
}
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
if (!any_available && open_file->pid != current->tgid) if (!any_available && open_file->pid != current->tgid)
continue; continue;
if (fsuid_only && open_file->uid != current_fsuid()) if (fsuid_only && open_file->uid != current_fsuid())
continue; continue;
if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
cifsFileInfo_get(open_file);
if (!open_file->invalidHandle) { if (!open_file->invalidHandle) {
/* found a good writable file */ /* found a good writable file */
cifsFileInfo_get(open_file);
spin_unlock(&cifs_file_list_lock); spin_unlock(&cifs_file_list_lock);
return open_file; return open_file;
} else {
if (!inv_file)
inv_file = open_file;
} }
spin_unlock(&cifs_file_list_lock);
/* Had to unlock since following call can block */
rc = cifs_reopen_file(open_file, false);
if (!rc)
return open_file;
/* if it fails, try another handle if possible */
cFYI(1, "wp failed on reopen file");
cifsFileInfo_put(open_file);
spin_lock(&cifs_file_list_lock);
/* else we simply continue to the next entry. Thus
we do not loop on reopen errors. If we
can not reopen the file, for example if we
reconnected to a server with another client
racing to delete or lock the file we would not
make progress if we restarted before the beginning
of the loop here. */
} }
} }
/* couldn't find useable FH with same pid, try any available */ /* couldn't find useable FH with same pid, try any available */
...@@ -1596,7 +1590,30 @@ refind_writable: ...@@ -1596,7 +1590,30 @@ refind_writable:
any_available = true; any_available = true;
goto refind_writable; goto refind_writable;
} }
if (inv_file) {
any_available = false;
cifsFileInfo_get(inv_file);
}
spin_unlock(&cifs_file_list_lock); spin_unlock(&cifs_file_list_lock);
if (inv_file) {
rc = cifs_reopen_file(inv_file, false);
if (!rc)
return inv_file;
else {
spin_lock(&cifs_file_list_lock);
list_move_tail(&inv_file->flist,
&cifs_inode->openFileList);
spin_unlock(&cifs_file_list_lock);
cifsFileInfo_put(inv_file);
spin_lock(&cifs_file_list_lock);
++refind;
goto refind_writable;
}
}
return NULL; return NULL;
} }
......
...@@ -86,9 +86,12 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name, ...@@ -86,9 +86,12 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name,
dentry = d_lookup(parent, name); dentry = d_lookup(parent, name);
if (dentry) { if (dentry) {
/* FIXME: check for inode number changes? */ inode = dentry->d_inode;
if (dentry->d_inode != NULL) /* update inode in place if i_ino didn't change */
if (inode && CIFS_I(inode)->uniqueid == fattr->cf_uniqueid) {
cifs_fattr_to_inode(inode, fattr);
return dentry; return dentry;
}
d_drop(dentry); d_drop(dentry);
dput(dentry); dput(dentry);
} }
...@@ -219,6 +222,7 @@ int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb, ...@@ -219,6 +222,7 @@ int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb,
static int initiate_cifs_search(const int xid, struct file *file) static int initiate_cifs_search(const int xid, struct file *file)
{ {
__u16 search_flags;
int rc = 0; int rc = 0;
char *full_path = NULL; char *full_path = NULL;
struct cifsFileInfo *cifsFile; struct cifsFileInfo *cifsFile;
...@@ -270,8 +274,12 @@ ffirst_retry: ...@@ -270,8 +274,12 @@ ffirst_retry:
cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO; cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
} }
search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME;
if (backup_cred(cifs_sb))
search_flags |= CIFS_SEARCH_BACKUP_SEARCH;
rc = CIFSFindFirst(xid, pTcon, full_path, cifs_sb->local_nls, rc = CIFSFindFirst(xid, pTcon, full_path, cifs_sb->local_nls,
&cifsFile->netfid, &cifsFile->srch_inf, &cifsFile->netfid, search_flags, &cifsFile->srch_inf,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb)); CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
if (rc == 0) if (rc == 0)
...@@ -502,11 +510,13 @@ static int cifs_save_resume_key(const char *current_entry, ...@@ -502,11 +510,13 @@ static int cifs_save_resume_key(const char *current_entry,
static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon, static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon,
struct file *file, char **ppCurrentEntry, int *num_to_ret) struct file *file, char **ppCurrentEntry, int *num_to_ret)
{ {
__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 *cifsFile = file->private_data;
struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
/* check if index in the buffer */ /* check if index in the buffer */
if ((cifsFile == NULL) || (ppCurrentEntry == NULL) || if ((cifsFile == NULL) || (ppCurrentEntry == NULL) ||
...@@ -560,10 +570,14 @@ static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon, ...@@ -560,10 +570,14 @@ static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon,
cifsFile); cifsFile);
} }
search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME;
if (backup_cred(cifs_sb))
search_flags |= CIFS_SEARCH_BACKUP_SEARCH;
while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) && while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) &&
(rc == 0) && !cifsFile->srch_inf.endOfSearch) { (rc == 0) && !cifsFile->srch_inf.endOfSearch) {
cFYI(1, "calling findnext2"); cFYI(1, "calling findnext2");
rc = CIFSFindNext(xid, pTcon, cifsFile->netfid, rc = CIFSFindNext(xid, pTcon, cifsFile->netfid, search_flags,
&cifsFile->srch_inf); &cifsFile->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 (cifsFile->srch_inf.last_entry)
......
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