diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-05-11 08:44:27 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-05-11 08:44:31 -0400 |
commit | 41fb454ebe6024f5c1e3b3cbc0abc0da762e7b51 (patch) | |
tree | 51c50bcb67a5039448ddfa1869d7948cab1217e9 /fs/cifs/readdir.c | |
parent | 19c1a6f5764d787113fa323ffb18be7991208f82 (diff) | |
parent | 091bf7624d1c90cec9e578a18529f615213ff847 (diff) |
Merge commit 'v2.6.30-rc5' into core/iommu
Merge reason: core/iommu was on an .30-rc1 base,
update it to .30-rc5 to refresh.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'fs/cifs/readdir.c')
-rw-r--r-- | fs/cifs/readdir.c | 78 |
1 files changed, 58 insertions, 20 deletions
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index c2c01ff4c32c..964e097c8203 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -31,6 +31,13 @@ | |||
31 | #include "cifs_fs_sb.h" | 31 | #include "cifs_fs_sb.h" |
32 | #include "cifsfs.h" | 32 | #include "cifsfs.h" |
33 | 33 | ||
34 | /* | ||
35 | * To be safe - for UCS to UTF-8 with strings loaded with the rare long | ||
36 | * characters alloc more to account for such multibyte target UTF-8 | ||
37 | * characters. | ||
38 | */ | ||
39 | #define UNICODE_NAME_MAX ((4 * NAME_MAX) + 2) | ||
40 | |||
34 | #ifdef CONFIG_CIFS_DEBUG2 | 41 | #ifdef CONFIG_CIFS_DEBUG2 |
35 | static void dump_cifs_file_struct(struct file *file, char *label) | 42 | static void dump_cifs_file_struct(struct file *file, char *label) |
36 | { | 43 | { |
@@ -239,6 +246,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, | |||
239 | if (atomic_read(&cifsInfo->inUse) == 0) | 246 | if (atomic_read(&cifsInfo->inUse) == 0) |
240 | atomic_set(&cifsInfo->inUse, 1); | 247 | atomic_set(&cifsInfo->inUse, 1); |
241 | 248 | ||
249 | cifsInfo->server_eof = end_of_file; | ||
242 | spin_lock(&tmp_inode->i_lock); | 250 | spin_lock(&tmp_inode->i_lock); |
243 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { | 251 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { |
244 | /* can not safely change the file size here if the | 252 | /* can not safely change the file size here if the |
@@ -375,6 +383,7 @@ static void unix_fill_in_inode(struct inode *tmp_inode, | |||
375 | tmp_inode->i_gid = le64_to_cpu(pfindData->Gid); | 383 | tmp_inode->i_gid = le64_to_cpu(pfindData->Gid); |
376 | tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks); | 384 | tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks); |
377 | 385 | ||
386 | cifsInfo->server_eof = end_of_file; | ||
378 | spin_lock(&tmp_inode->i_lock); | 387 | spin_lock(&tmp_inode->i_lock); |
379 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { | 388 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { |
380 | /* can not safely change the file size here if the | 389 | /* can not safely change the file size here if the |
@@ -436,6 +445,38 @@ static void unix_fill_in_inode(struct inode *tmp_inode, | |||
436 | } | 445 | } |
437 | } | 446 | } |
438 | 447 | ||
448 | /* BB eventually need to add the following helper function to | ||
449 | resolve NT_STATUS_STOPPED_ON_SYMLINK return code when | ||
450 | we try to do FindFirst on (NTFS) directory symlinks */ | ||
451 | /* | ||
452 | int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb, | ||
453 | int xid) | ||
454 | { | ||
455 | __u16 fid; | ||
456 | int len; | ||
457 | int oplock = 0; | ||
458 | int rc; | ||
459 | struct cifsTconInfo *ptcon = cifs_sb->tcon; | ||
460 | char *tmpbuffer; | ||
461 | |||
462 | rc = CIFSSMBOpen(xid, ptcon, full_path, FILE_OPEN, GENERIC_READ, | ||
463 | OPEN_REPARSE_POINT, &fid, &oplock, NULL, | ||
464 | cifs_sb->local_nls, | ||
465 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
466 | if (!rc) { | ||
467 | tmpbuffer = kmalloc(maxpath); | ||
468 | rc = CIFSSMBQueryReparseLinkInfo(xid, ptcon, full_path, | ||
469 | tmpbuffer, | ||
470 | maxpath -1, | ||
471 | fid, | ||
472 | cifs_sb->local_nls); | ||
473 | if (CIFSSMBClose(xid, ptcon, fid)) { | ||
474 | cFYI(1, ("Error closing temporary reparsepoint open)")); | ||
475 | } | ||
476 | } | ||
477 | } | ||
478 | */ | ||
479 | |||
439 | static int initiate_cifs_search(const int xid, struct file *file) | 480 | static int initiate_cifs_search(const int xid, struct file *file) |
440 | { | 481 | { |
441 | int rc = 0; | 482 | int rc = 0; |
@@ -491,7 +532,10 @@ ffirst_retry: | |||
491 | CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb)); | 532 | CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb)); |
492 | if (rc == 0) | 533 | if (rc == 0) |
493 | cifsFile->invalidHandle = false; | 534 | cifsFile->invalidHandle = false; |
494 | if ((rc == -EOPNOTSUPP) && | 535 | /* BB add following call to handle readdir on new NTFS symlink errors |
536 | else if STATUS_STOPPED_ON_SYMLINK | ||
537 | call get_symlink_reparse_path and retry with new path */ | ||
538 | else if ((rc == -EOPNOTSUPP) && | ||
495 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { | 539 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { |
496 | cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; | 540 | cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; |
497 | goto ffirst_retry; | 541 | goto ffirst_retry; |
@@ -820,7 +864,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, | |||
820 | /* inode num, inode type and filename returned */ | 864 | /* inode num, inode type and filename returned */ |
821 | static int cifs_get_name_from_search_buf(struct qstr *pqst, | 865 | static int cifs_get_name_from_search_buf(struct qstr *pqst, |
822 | char *current_entry, __u16 level, unsigned int unicode, | 866 | char *current_entry, __u16 level, unsigned int unicode, |
823 | struct cifs_sb_info *cifs_sb, int max_len, __u64 *pinum) | 867 | struct cifs_sb_info *cifs_sb, unsigned int max_len, __u64 *pinum) |
824 | { | 868 | { |
825 | int rc = 0; | 869 | int rc = 0; |
826 | unsigned int len = 0; | 870 | unsigned int len = 0; |
@@ -840,7 +884,7 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst, | |||
840 | len = strnlen(filename, PATH_MAX); | 884 | len = strnlen(filename, PATH_MAX); |
841 | } | 885 | } |
842 | 886 | ||
843 | *pinum = pFindData->UniqueId; | 887 | *pinum = le64_to_cpu(pFindData->UniqueId); |
844 | } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { | 888 | } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { |
845 | FILE_DIRECTORY_INFO *pFindData = | 889 | FILE_DIRECTORY_INFO *pFindData = |
846 | (FILE_DIRECTORY_INFO *)current_entry; | 890 | (FILE_DIRECTORY_INFO *)current_entry; |
@@ -856,7 +900,7 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst, | |||
856 | (SEARCH_ID_FULL_DIR_INFO *)current_entry; | 900 | (SEARCH_ID_FULL_DIR_INFO *)current_entry; |
857 | filename = &pFindData->FileName[0]; | 901 | filename = &pFindData->FileName[0]; |
858 | len = le32_to_cpu(pFindData->FileNameLength); | 902 | len = le32_to_cpu(pFindData->FileNameLength); |
859 | *pinum = pFindData->UniqueId; | 903 | *pinum = le64_to_cpu(pFindData->UniqueId); |
860 | } else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) { | 904 | } else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) { |
861 | FILE_BOTH_DIRECTORY_INFO *pFindData = | 905 | FILE_BOTH_DIRECTORY_INFO *pFindData = |
862 | (FILE_BOTH_DIRECTORY_INFO *)current_entry; | 906 | (FILE_BOTH_DIRECTORY_INFO *)current_entry; |
@@ -879,14 +923,12 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst, | |||
879 | } | 923 | } |
880 | 924 | ||
881 | if (unicode) { | 925 | if (unicode) { |
882 | /* BB fixme - test with long names */ | 926 | pqst->len = cifs_from_ucs2((char *) pqst->name, |
883 | /* Note converted filename can be longer than in unicode */ | 927 | (__le16 *) filename, |
884 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) | 928 | UNICODE_NAME_MAX, |
885 | pqst->len = cifs_convertUCSpath((char *)pqst->name, | 929 | min(len, max_len), nlt, |
886 | (__le16 *)filename, len/2, nlt); | 930 | cifs_sb->mnt_cifs_flags & |
887 | else | 931 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
888 | pqst->len = cifs_strfromUCS_le((char *)pqst->name, | ||
889 | (__le16 *)filename, len/2, nlt); | ||
890 | } else { | 932 | } else { |
891 | pqst->name = filename; | 933 | pqst->name = filename; |
892 | pqst->len = len; | 934 | pqst->len = len; |
@@ -896,8 +938,8 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst, | |||
896 | return rc; | 938 | return rc; |
897 | } | 939 | } |
898 | 940 | ||
899 | static int cifs_filldir(char *pfindEntry, struct file *file, | 941 | static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, |
900 | filldir_t filldir, void *direntry, char *scratch_buf, int max_len) | 942 | void *direntry, char *scratch_buf, unsigned int max_len) |
901 | { | 943 | { |
902 | int rc = 0; | 944 | int rc = 0; |
903 | struct qstr qstring; | 945 | struct qstr qstring; |
@@ -994,7 +1036,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) | |||
994 | int num_to_fill = 0; | 1036 | int num_to_fill = 0; |
995 | char *tmp_buf = NULL; | 1037 | char *tmp_buf = NULL; |
996 | char *end_of_smb; | 1038 | char *end_of_smb; |
997 | int max_len; | 1039 | unsigned int max_len; |
998 | 1040 | ||
999 | xid = GetXid(); | 1041 | xid = GetXid(); |
1000 | 1042 | ||
@@ -1068,11 +1110,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) | |||
1068 | cifsFile->srch_inf.ntwrk_buf_start); | 1110 | cifsFile->srch_inf.ntwrk_buf_start); |
1069 | end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; | 1111 | end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; |
1070 | 1112 | ||
1071 | /* To be safe - for UCS to UTF-8 with strings loaded | 1113 | tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL); |
1072 | with the rare long characters alloc more to account for | ||
1073 | such multibyte target UTF-8 characters. cifs_unicode.c, | ||
1074 | which actually does the conversion, has the same limit */ | ||
1075 | tmp_buf = kmalloc((2 * NAME_MAX) + 4, GFP_KERNEL); | ||
1076 | for (i = 0; (i < num_to_fill) && (rc == 0); i++) { | 1114 | for (i = 0; (i < num_to_fill) && (rc == 0); i++) { |
1077 | if (current_entry == NULL) { | 1115 | if (current_entry == NULL) { |
1078 | /* evaluate whether this case is an error */ | 1116 | /* evaluate whether this case is an error */ |