diff options
Diffstat (limited to 'fs/cifs/dir.c')
| -rw-r--r-- | fs/cifs/dir.c | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 914239d53634..66b825ade3e1 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
| @@ -46,7 +46,8 @@ char * | |||
| 46 | build_path_from_dentry(struct dentry *direntry) | 46 | build_path_from_dentry(struct dentry *direntry) |
| 47 | { | 47 | { |
| 48 | struct dentry *temp; | 48 | struct dentry *temp; |
| 49 | int namelen = 0; | 49 | int namelen; |
| 50 | int pplen; | ||
| 50 | char *full_path; | 51 | char *full_path; |
| 51 | char dirsep; | 52 | char dirsep; |
| 52 | 53 | ||
| @@ -56,7 +57,9 @@ build_path_from_dentry(struct dentry *direntry) | |||
| 56 | when the server crashed */ | 57 | when the server crashed */ |
| 57 | 58 | ||
| 58 | dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb)); | 59 | dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb)); |
| 60 | pplen = CIFS_SB(direntry->d_sb)->prepathlen; | ||
| 59 | cifs_bp_rename_retry: | 61 | cifs_bp_rename_retry: |
| 62 | namelen = pplen; | ||
| 60 | for (temp = direntry; !IS_ROOT(temp);) { | 63 | for (temp = direntry; !IS_ROOT(temp);) { |
| 61 | namelen += (1 + temp->d_name.len); | 64 | namelen += (1 + temp->d_name.len); |
| 62 | temp = temp->d_parent; | 65 | temp = temp->d_parent; |
| @@ -70,7 +73,6 @@ cifs_bp_rename_retry: | |||
| 70 | if(full_path == NULL) | 73 | if(full_path == NULL) |
| 71 | return full_path; | 74 | return full_path; |
| 72 | full_path[namelen] = 0; /* trailing null */ | 75 | full_path[namelen] = 0; /* trailing null */ |
| 73 | |||
| 74 | for (temp = direntry; !IS_ROOT(temp);) { | 76 | for (temp = direntry; !IS_ROOT(temp);) { |
| 75 | namelen -= 1 + temp->d_name.len; | 77 | namelen -= 1 + temp->d_name.len; |
| 76 | if (namelen < 0) { | 78 | if (namelen < 0) { |
| @@ -79,7 +81,7 @@ cifs_bp_rename_retry: | |||
| 79 | full_path[namelen] = dirsep; | 81 | full_path[namelen] = dirsep; |
| 80 | strncpy(full_path + namelen + 1, temp->d_name.name, | 82 | strncpy(full_path + namelen + 1, temp->d_name.name, |
| 81 | temp->d_name.len); | 83 | temp->d_name.len); |
| 82 | cFYI(0, (" name: %s ", full_path + namelen)); | 84 | cFYI(0, ("name: %s", full_path + namelen)); |
| 83 | } | 85 | } |
| 84 | temp = temp->d_parent; | 86 | temp = temp->d_parent; |
| 85 | if(temp == NULL) { | 87 | if(temp == NULL) { |
| @@ -88,18 +90,23 @@ cifs_bp_rename_retry: | |||
| 88 | return NULL; | 90 | return NULL; |
| 89 | } | 91 | } |
| 90 | } | 92 | } |
| 91 | if (namelen != 0) { | 93 | if (namelen != pplen) { |
| 92 | cERROR(1, | 94 | cERROR(1, |
| 93 | ("We did not end path lookup where we expected namelen is %d", | 95 | ("did not end path lookup where expected namelen is %d", |
| 94 | namelen)); | 96 | namelen)); |
| 95 | /* presumably this is only possible if we were racing with a rename | 97 | /* presumably this is only possible if racing with a rename |
| 96 | of one of the parent directories (we can not lock the dentries | 98 | of one of the parent directories (we can not lock the dentries |
| 97 | above us to prevent this, but retrying should be harmless) */ | 99 | above us to prevent this, but retrying should be harmless) */ |
| 98 | kfree(full_path); | 100 | kfree(full_path); |
| 99 | namelen = 0; | ||
| 100 | goto cifs_bp_rename_retry; | 101 | goto cifs_bp_rename_retry; |
| 101 | } | 102 | } |
| 102 | 103 | /* DIR_SEP already set for byte 0 / vs \ but not for | |
| 104 | subsequent slashes in prepath which currently must | ||
| 105 | be entered the right way - not sure if there is an alternative | ||
| 106 | since the '\' is a valid posix character so we can not switch | ||
| 107 | those safely to '/' if any are found in the middle of the prepath */ | ||
| 108 | /* BB test paths to Windows with '/' in the midst of prepath */ | ||
| 109 | strncpy(full_path,CIFS_SB(direntry->d_sb)->prepath,pplen); | ||
| 103 | return full_path; | 110 | return full_path; |
| 104 | } | 111 | } |
| 105 | 112 | ||
