diff options
author | Shirish Pargaonkar <shirishpargaonkar@gmail.com> | 2012-05-15 11:19:16 -0400 |
---|---|---|
committer | Pavel Shilovsky <piastry@etersoft.ru> | 2012-05-17 05:07:49 -0400 |
commit | 2608bee744a92d60d15ff4e6e0b913d8b406aedd (patch) | |
tree | 3104d96b86e25c931b2bee199eb67842327aeaa1 /fs | |
parent | 7f92447aa7be605fd80d9f248efe0b8ac9379f11 (diff) |
cifs: Include backup intent search flags during searches {try #2)
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.
---------
Cc: <stable@kernel.org>
Reported-and-Tested-by: Tushar Gosavi <tugosavi@in.ibm.com>
Signed-off-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com>
Acked-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/cifsproto.h | 6 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 12 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 15 |
3 files changed, 22 insertions, 11 deletions
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index eeb789d8e855..0a3fa960b84d 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, | |||
192 | 192 | ||
193 | extern int CIFSFindFirst(const int xid, struct cifs_tcon *tcon, | 193 | extern int CIFSFindFirst(const int xid, struct cifs_tcon *tcon, |
194 | const char *searchName, const struct nls_table *nls_codepage, | 194 | const char *searchName, const struct nls_table *nls_codepage, |
195 | __u16 *searchHandle, struct cifs_search_info *psrch_inf, | 195 | __u16 *searchHandle, __u16 search_flags, |
196 | struct cifs_search_info *psrch_inf, | ||
196 | int map, const char dirsep); | 197 | int map, const char dirsep); |
197 | 198 | ||
198 | extern int CIFSFindNext(const int xid, struct cifs_tcon *tcon, | 199 | extern int CIFSFindNext(const int xid, struct cifs_tcon *tcon, |
199 | __u16 searchHandle, struct cifs_search_info *psrch_inf); | 200 | __u16 searchHandle, __u16 search_flags, |
201 | struct cifs_search_info *psrch_inf); | ||
200 | 202 | ||
201 | extern int CIFSFindClose(const int, struct cifs_tcon *tcon, | 203 | extern int CIFSFindClose(const int, struct cifs_tcon *tcon, |
202 | const __u16 search_handle); | 204 | const __u16 search_handle); |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 45633da461a8..3563c93d9f17 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -4238,7 +4238,7 @@ int | |||
4238 | CIFSFindFirst(const int xid, struct cifs_tcon *tcon, | 4238 | CIFSFindFirst(const int xid, struct cifs_tcon *tcon, |
4239 | const char *searchName, | 4239 | const char *searchName, |
4240 | const struct nls_table *nls_codepage, | 4240 | const struct nls_table *nls_codepage, |
4241 | __u16 *pnetfid, | 4241 | __u16 *pnetfid, __u16 search_flags, |
4242 | struct cifs_search_info *psrch_inf, int remap, const char dirsep) | 4242 | struct cifs_search_info *psrch_inf, int remap, const char dirsep) |
4243 | { | 4243 | { |
4244 | /* level 257 SMB_ */ | 4244 | /* level 257 SMB_ */ |
@@ -4310,8 +4310,7 @@ findFirstRetry: | |||
4310 | cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | | 4310 | cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | |
4311 | ATTR_DIRECTORY); | 4311 | ATTR_DIRECTORY); |
4312 | pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO)); | 4312 | pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO)); |
4313 | pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | | 4313 | pSMB->SearchFlags = cpu_to_le16(search_flags); |
4314 | CIFS_SEARCH_RETURN_RESUME); | ||
4315 | pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level); | 4314 | pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level); |
4316 | 4315 | ||
4317 | /* BB what should we set StorageType to? Does it matter? BB */ | 4316 | /* BB what should we set StorageType to? Does it matter? BB */ |
@@ -4381,8 +4380,8 @@ findFirstRetry: | |||
4381 | return rc; | 4380 | return rc; |
4382 | } | 4381 | } |
4383 | 4382 | ||
4384 | int CIFSFindNext(const int xid, struct cifs_tcon *tcon, | 4383 | int CIFSFindNext(const int xid, struct cifs_tcon *tcon, __u16 searchHandle, |
4385 | __u16 searchHandle, struct cifs_search_info *psrch_inf) | 4384 | __u16 search_flags, struct cifs_search_info *psrch_inf) |
4386 | { | 4385 | { |
4387 | TRANSACTION2_FNEXT_REQ *pSMB = NULL; | 4386 | TRANSACTION2_FNEXT_REQ *pSMB = NULL; |
4388 | TRANSACTION2_FNEXT_RSP *pSMBr = NULL; | 4387 | TRANSACTION2_FNEXT_RSP *pSMBr = NULL; |
@@ -4425,8 +4424,7 @@ int CIFSFindNext(const int xid, struct cifs_tcon *tcon, | |||
4425 | cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO)); | 4424 | cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO)); |
4426 | pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level); | 4425 | pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level); |
4427 | pSMB->ResumeKey = psrch_inf->resume_key; | 4426 | pSMB->ResumeKey = psrch_inf->resume_key; |
4428 | pSMB->SearchFlags = | 4427 | pSMB->SearchFlags = cpu_to_le16(search_flags); |
4429 | cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME); | ||
4430 | 4428 | ||
4431 | name_len = psrch_inf->resume_name_len; | 4429 | name_len = psrch_inf->resume_name_len; |
4432 | params += name_len; | 4430 | params += name_len; |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index e2bbc683e018..0a8224d1c4c5 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, | |||
219 | 219 | ||
220 | static int initiate_cifs_search(const int xid, struct file *file) | 220 | static int initiate_cifs_search(const int xid, struct file *file) |
221 | { | 221 | { |
222 | __u16 search_flags; | ||
222 | int rc = 0; | 223 | int rc = 0; |
223 | char *full_path = NULL; | 224 | char *full_path = NULL; |
224 | struct cifsFileInfo *cifsFile; | 225 | struct cifsFileInfo *cifsFile; |
@@ -270,8 +271,12 @@ ffirst_retry: | |||
270 | cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO; | 271 | cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO; |
271 | } | 272 | } |
272 | 273 | ||
274 | search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME; | ||
275 | if (backup_cred(cifs_sb)) | ||
276 | search_flags |= CIFS_SEARCH_BACKUP_SEARCH; | ||
277 | |||
273 | rc = CIFSFindFirst(xid, pTcon, full_path, cifs_sb->local_nls, | 278 | rc = CIFSFindFirst(xid, pTcon, full_path, cifs_sb->local_nls, |
274 | &cifsFile->netfid, &cifsFile->srch_inf, | 279 | &cifsFile->netfid, search_flags, &cifsFile->srch_inf, |
275 | cifs_sb->mnt_cifs_flags & | 280 | cifs_sb->mnt_cifs_flags & |
276 | CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb)); | 281 | CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb)); |
277 | if (rc == 0) | 282 | if (rc == 0) |
@@ -502,11 +507,13 @@ static int cifs_save_resume_key(const char *current_entry, | |||
502 | static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon, | 507 | static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon, |
503 | struct file *file, char **ppCurrentEntry, int *num_to_ret) | 508 | struct file *file, char **ppCurrentEntry, int *num_to_ret) |
504 | { | 509 | { |
510 | __u16 search_flags; | ||
505 | int rc = 0; | 511 | int rc = 0; |
506 | int pos_in_buf = 0; | 512 | int pos_in_buf = 0; |
507 | loff_t first_entry_in_buffer; | 513 | loff_t first_entry_in_buffer; |
508 | loff_t index_to_find = file->f_pos; | 514 | loff_t index_to_find = file->f_pos; |
509 | struct cifsFileInfo *cifsFile = file->private_data; | 515 | struct cifsFileInfo *cifsFile = file->private_data; |
516 | struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | ||
510 | /* check if index in the buffer */ | 517 | /* check if index in the buffer */ |
511 | 518 | ||
512 | if ((cifsFile == NULL) || (ppCurrentEntry == NULL) || | 519 | if ((cifsFile == NULL) || (ppCurrentEntry == NULL) || |
@@ -560,10 +567,14 @@ static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon, | |||
560 | cifsFile); | 567 | cifsFile); |
561 | } | 568 | } |
562 | 569 | ||
570 | search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME; | ||
571 | if (backup_cred(cifs_sb)) | ||
572 | search_flags |= CIFS_SEARCH_BACKUP_SEARCH; | ||
573 | |||
563 | while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) && | 574 | while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) && |
564 | (rc == 0) && !cifsFile->srch_inf.endOfSearch) { | 575 | (rc == 0) && !cifsFile->srch_inf.endOfSearch) { |
565 | cFYI(1, "calling findnext2"); | 576 | cFYI(1, "calling findnext2"); |
566 | rc = CIFSFindNext(xid, pTcon, cifsFile->netfid, | 577 | rc = CIFSFindNext(xid, pTcon, cifsFile->netfid, search_flags, |
567 | &cifsFile->srch_inf); | 578 | &cifsFile->srch_inf); |
568 | /* FindFirst/Next set last_entry to NULL on malformed reply */ | 579 | /* FindFirst/Next set last_entry to NULL on malformed reply */ |
569 | if (cifsFile->srch_inf.last_entry) | 580 | if (cifsFile->srch_inf.last_entry) |