From: Shirish Pargaonkar <shirishpargaonkar@xxxxxxxxx> As observed and suggested by Tushar Gosavi... --------- readdir calls these function to send TRANS2_FIND_FIRST and TRANS2_FIND_NEXT command to the server. The current cifs module is not specifying CIFS_SEARCH_BACKUP_SEARCH flag while sending these command when backupuid/backupgid is specified. This can be resolved by specifying CIFS_SEARCH_BACKUP_SEARCH flag. --------- Reported-by: Tushar Gosavi <tugosavi@xxxxxxxxxx> Signed-off-by: Shirish Pargaonkar <shirishpargaonkar@xxxxxxxxx> --- fs/cifs/cifsproto.h | 6 ++++-- fs/cifs/cifssmb.c | 10 ++++------ fs/cifs/readdir.c | 15 +++++++++++++-- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 96192c1..97f5d03 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -192,11 +192,13 @@ extern int CIFSTCon(unsigned int xid, struct cifs_ses *ses, extern int CIFSFindFirst(const int xid, struct cifs_tcon *tcon, 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); 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, const __u16 search_handle); diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index da2f544..17c310a 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -4344,7 +4344,7 @@ int CIFSFindFirst(const int xid, struct cifs_tcon *tcon, const char *searchName, const struct nls_table *nls_codepage, - __u16 *pnetfid, + __u16 *pnetfid, __u16 search_flags, struct cifs_search_info *psrch_inf, int remap, const char dirsep) { /* level 257 SMB_ */ @@ -4416,8 +4416,7 @@ findFirstRetry: cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY); pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO)); - pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | - CIFS_SEARCH_RETURN_RESUME); + pSMB->SearchFlags = cpu_to_le16(search_flags); pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level); /* BB what should we set StorageType to? Does it matter? BB */ @@ -4487,7 +4486,7 @@ findFirstRetry: return rc; } -int CIFSFindNext(const int xid, struct cifs_tcon *tcon, +int CIFSFindNext(const int xid, struct cifs_tcon *tcon, __u16 search_flags, __u16 searchHandle, struct cifs_search_info *psrch_inf) { TRANSACTION2_FNEXT_REQ *pSMB = NULL; @@ -4531,8 +4530,7 @@ int CIFSFindNext(const int xid, struct cifs_tcon *tcon, cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO)); pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level); pSMB->ResumeKey = psrch_inf->resume_key; - pSMB->SearchFlags = - cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME); + pSMB->SearchFlags = cpu_to_le16(search_flags); name_len = psrch_inf->resume_name_len; params += name_len; diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index e2bbc68..297e432 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -219,6 +219,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) { + __u16 search_flags = 0; int rc = 0; char *full_path = NULL; struct cifsFileInfo *cifsFile; @@ -270,8 +271,12 @@ ffirst_retry: 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, - &cifsFile->netfid, &cifsFile->srch_inf, + &cifsFile->netfid, search_flags, &cifsFile->srch_inf, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb)); if (rc == 0) @@ -502,11 +507,13 @@ static int cifs_save_resume_key(const char *current_entry, static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon, struct file *file, char **ppCurrentEntry, int *num_to_ret) { + __u16 search_flags = 0; int rc = 0; int pos_in_buf = 0; loff_t first_entry_in_buffer; loff_t index_to_find = file->f_pos; 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 */ if ((cifsFile == NULL) || (ppCurrentEntry == NULL) || @@ -560,10 +567,14 @@ static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon, 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) && (rc == 0) && !cifsFile->srch_inf.endOfSearch) { cFYI(1, "calling findnext2"); - rc = CIFSFindNext(xid, pTcon, cifsFile->netfid, + rc = CIFSFindNext(xid, pTcon, cifsFile->netfid, search_flags, &cifsFile->srch_inf); /* FindFirst/Next set last_entry to NULL on malformed reply */ if (cifsFile->srch_inf.last_entry) -- 1.6.0.2 -- To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html