diff options
Diffstat (limited to 'fs/cifs/dir.c')
-rw-r--r-- | fs/cifs/dir.c | 172 |
1 files changed, 87 insertions, 85 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index e5210519ac4b..eeab602c6e0a 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * fs/cifs/dir.c | 2 | * fs/cifs/dir.c |
3 | * | 3 | * |
4 | * vfs operations that deal with dentries | 4 | * vfs operations that deal with dentries |
5 | * | 5 | * |
6 | * Copyright (C) International Business Machines Corp., 2002,2005 | 6 | * Copyright (C) International Business Machines Corp., 2002,2005 |
7 | * Author(s): Steve French (sfrench@us.ibm.com) | 7 | * Author(s): Steve French (sfrench@us.ibm.com) |
8 | * | 8 | * |
@@ -34,11 +34,12 @@ | |||
34 | static void | 34 | static void |
35 | renew_parental_timestamps(struct dentry *direntry) | 35 | renew_parental_timestamps(struct dentry *direntry) |
36 | { | 36 | { |
37 | /* BB check if there is a way to get the kernel to do this or if we really need this */ | 37 | /* BB check if there is a way to get the kernel to do this or if we |
38 | really need this */ | ||
38 | do { | 39 | do { |
39 | direntry->d_time = jiffies; | 40 | direntry->d_time = jiffies; |
40 | direntry = direntry->d_parent; | 41 | direntry = direntry->d_parent; |
41 | } while (!IS_ROOT(direntry)); | 42 | } while (!IS_ROOT(direntry)); |
42 | } | 43 | } |
43 | 44 | ||
44 | /* Note: caller must free return buffer */ | 45 | /* Note: caller must free return buffer */ |
@@ -51,7 +52,7 @@ build_path_from_dentry(struct dentry *direntry) | |||
51 | char *full_path; | 52 | char *full_path; |
52 | char dirsep; | 53 | char dirsep; |
53 | 54 | ||
54 | if(direntry == NULL) | 55 | if (direntry == NULL) |
55 | return NULL; /* not much we can do if dentry is freed and | 56 | return NULL; /* not much we can do if dentry is freed and |
56 | we need to reopen the file after it was closed implicitly | 57 | we need to reopen the file after it was closed implicitly |
57 | when the server crashed */ | 58 | when the server crashed */ |
@@ -59,18 +60,18 @@ build_path_from_dentry(struct dentry *direntry) | |||
59 | dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb)); | 60 | dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb)); |
60 | pplen = CIFS_SB(direntry->d_sb)->prepathlen; | 61 | pplen = CIFS_SB(direntry->d_sb)->prepathlen; |
61 | cifs_bp_rename_retry: | 62 | cifs_bp_rename_retry: |
62 | namelen = pplen; | 63 | namelen = pplen; |
63 | for (temp = direntry; !IS_ROOT(temp);) { | 64 | for (temp = direntry; !IS_ROOT(temp);) { |
64 | namelen += (1 + temp->d_name.len); | 65 | namelen += (1 + temp->d_name.len); |
65 | temp = temp->d_parent; | 66 | temp = temp->d_parent; |
66 | if(temp == NULL) { | 67 | if (temp == NULL) { |
67 | cERROR(1,("corrupt dentry")); | 68 | cERROR(1, ("corrupt dentry")); |
68 | return NULL; | 69 | return NULL; |
69 | } | 70 | } |
70 | } | 71 | } |
71 | 72 | ||
72 | full_path = kmalloc(namelen+1, GFP_KERNEL); | 73 | full_path = kmalloc(namelen+1, GFP_KERNEL); |
73 | if(full_path == NULL) | 74 | if (full_path == NULL) |
74 | return full_path; | 75 | return full_path; |
75 | full_path[namelen] = 0; /* trailing null */ | 76 | full_path[namelen] = 0; /* trailing null */ |
76 | for (temp = direntry; !IS_ROOT(temp);) { | 77 | for (temp = direntry; !IS_ROOT(temp);) { |
@@ -84,8 +85,8 @@ cifs_bp_rename_retry: | |||
84 | cFYI(0, ("name: %s", full_path + namelen)); | 85 | cFYI(0, ("name: %s", full_path + namelen)); |
85 | } | 86 | } |
86 | temp = temp->d_parent; | 87 | temp = temp->d_parent; |
87 | if(temp == NULL) { | 88 | if (temp == NULL) { |
88 | cERROR(1,("corrupt dentry")); | 89 | cERROR(1, ("corrupt dentry")); |
89 | kfree(full_path); | 90 | kfree(full_path); |
90 | return NULL; | 91 | return NULL; |
91 | } | 92 | } |
@@ -94,7 +95,7 @@ cifs_bp_rename_retry: | |||
94 | cERROR(1, | 95 | cERROR(1, |
95 | ("did not end path lookup where expected namelen is %d", | 96 | ("did not end path lookup where expected namelen is %d", |
96 | namelen)); | 97 | namelen)); |
97 | /* presumably this is only possible if racing with a rename | 98 | /* presumably this is only possible if racing with a rename |
98 | of one of the parent directories (we can not lock the dentries | 99 | of one of the parent directories (we can not lock the dentries |
99 | above us to prevent this, but retrying should be harmless) */ | 100 | above us to prevent this, but retrying should be harmless) */ |
100 | kfree(full_path); | 101 | kfree(full_path); |
@@ -106,7 +107,7 @@ cifs_bp_rename_retry: | |||
106 | since the '\' is a valid posix character so we can not switch | 107 | 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 | 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 | /* BB test paths to Windows with '/' in the midst of prepath */ |
109 | strncpy(full_path,CIFS_SB(direntry->d_sb)->prepath,pplen); | 110 | strncpy(full_path, CIFS_SB(direntry->d_sb)->prepath, pplen); |
110 | return full_path; | 111 | return full_path; |
111 | } | 112 | } |
112 | 113 | ||
@@ -147,12 +148,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
147 | pTcon = cifs_sb->tcon; | 148 | pTcon = cifs_sb->tcon; |
148 | 149 | ||
149 | full_path = build_path_from_dentry(direntry); | 150 | full_path = build_path_from_dentry(direntry); |
150 | if(full_path == NULL) { | 151 | if (full_path == NULL) { |
151 | FreeXid(xid); | 152 | FreeXid(xid); |
152 | return -ENOMEM; | 153 | return -ENOMEM; |
153 | } | 154 | } |
154 | 155 | ||
155 | if(nd && (nd->flags & LOOKUP_OPEN)) { | 156 | if (nd && (nd->flags & LOOKUP_OPEN)) { |
156 | int oflags = nd->intent.open.flags; | 157 | int oflags = nd->intent.open.flags; |
157 | 158 | ||
158 | desiredAccess = 0; | 159 | desiredAccess = 0; |
@@ -164,28 +165,29 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
164 | write_only = TRUE; | 165 | write_only = TRUE; |
165 | } | 166 | } |
166 | 167 | ||
167 | if((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) | 168 | if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) |
168 | disposition = FILE_CREATE; | 169 | disposition = FILE_CREATE; |
169 | else if((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC)) | 170 | else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC)) |
170 | disposition = FILE_OVERWRITE_IF; | 171 | disposition = FILE_OVERWRITE_IF; |
171 | else if((oflags & O_CREAT) == O_CREAT) | 172 | else if ((oflags & O_CREAT) == O_CREAT) |
172 | disposition = FILE_OPEN_IF; | 173 | disposition = FILE_OPEN_IF; |
173 | else { | 174 | else { |
174 | cFYI(1,("Create flag not set in create function")); | 175 | cFYI(1, ("Create flag not set in create function")); |
175 | } | 176 | } |
176 | } | 177 | } |
177 | 178 | ||
178 | /* BB add processing to set equivalent of mode - e.g. via CreateX with ACLs */ | 179 | /* BB add processing to set equivalent of mode - e.g. via CreateX with |
180 | ACLs */ | ||
179 | if (oplockEnabled) | 181 | if (oplockEnabled) |
180 | oplock = REQ_OPLOCK; | 182 | oplock = REQ_OPLOCK; |
181 | 183 | ||
182 | buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL); | 184 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); |
183 | if(buf == NULL) { | 185 | if (buf == NULL) { |
184 | kfree(full_path); | 186 | kfree(full_path); |
185 | FreeXid(xid); | 187 | FreeXid(xid); |
186 | return -ENOMEM; | 188 | return -ENOMEM; |
187 | } | 189 | } |
188 | if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) | 190 | if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) |
189 | rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, | 191 | rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, |
190 | desiredAccess, CREATE_NOT_DIR, | 192 | desiredAccess, CREATE_NOT_DIR, |
191 | &fileHandle, &oplock, buf, cifs_sb->local_nls, | 193 | &fileHandle, &oplock, buf, cifs_sb->local_nls, |
@@ -193,13 +195,13 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
193 | else | 195 | else |
194 | rc = -EIO; /* no NT SMB support fall into legacy open below */ | 196 | rc = -EIO; /* no NT SMB support fall into legacy open below */ |
195 | 197 | ||
196 | if(rc == -EIO) { | 198 | if (rc == -EIO) { |
197 | /* old server, retry the open legacy style */ | 199 | /* old server, retry the open legacy style */ |
198 | rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, | 200 | rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, |
199 | desiredAccess, CREATE_NOT_DIR, | 201 | desiredAccess, CREATE_NOT_DIR, |
200 | &fileHandle, &oplock, buf, cifs_sb->local_nls, | 202 | &fileHandle, &oplock, buf, cifs_sb->local_nls, |
201 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 203 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
202 | } | 204 | } |
203 | if (rc) { | 205 | if (rc) { |
204 | cFYI(1, ("cifs_create returned 0x%x", rc)); | 206 | cFYI(1, ("cifs_create returned 0x%x", rc)); |
205 | } else { | 207 | } else { |
@@ -207,13 +209,13 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
207 | then we now have to set the mode if possible */ | 209 | then we now have to set the mode if possible */ |
208 | if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) && | 210 | if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) && |
209 | (oplock & CIFS_CREATE_ACTION)) | 211 | (oplock & CIFS_CREATE_ACTION)) |
210 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { | 212 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { |
211 | CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, | 213 | CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, |
212 | (__u64)current->fsuid, | 214 | (__u64)current->fsuid, |
213 | (__u64)current->fsgid, | 215 | (__u64)current->fsgid, |
214 | 0 /* dev */, | 216 | 0 /* dev */, |
215 | cifs_sb->local_nls, | 217 | cifs_sb->local_nls, |
216 | cifs_sb->mnt_cifs_flags & | 218 | cifs_sb->mnt_cifs_flags & |
217 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 219 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
218 | } else { | 220 | } else { |
219 | CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, | 221 | CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, |
@@ -221,26 +223,28 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
221 | (__u64)-1, | 223 | (__u64)-1, |
222 | 0 /* dev */, | 224 | 0 /* dev */, |
223 | cifs_sb->local_nls, | 225 | cifs_sb->local_nls, |
224 | cifs_sb->mnt_cifs_flags & | 226 | cifs_sb->mnt_cifs_flags & |
225 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 227 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
226 | } | 228 | } |
227 | else { | 229 | else { |
228 | /* BB implement mode setting via Windows security descriptors */ | 230 | /* BB implement mode setting via Windows security |
229 | /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/ | 231 | descriptors e.g. */ |
230 | /* could set r/o dos attribute if mode & 0222 == 0 */ | 232 | /* CIFSSMBWinSetPerms(xid,pTcon,path,mode,-1,-1,nls);*/ |
233 | |||
234 | /* Could set r/o dos attribute if mode & 0222 == 0 */ | ||
231 | } | 235 | } |
232 | 236 | ||
233 | /* BB server might mask mode so we have to query for Unix case*/ | 237 | /* BB server might mask mode so we have to query for Unix case*/ |
234 | if (pTcon->ses->capabilities & CAP_UNIX) | 238 | if (pTcon->ses->capabilities & CAP_UNIX) |
235 | rc = cifs_get_inode_info_unix(&newinode, full_path, | 239 | rc = cifs_get_inode_info_unix(&newinode, full_path, |
236 | inode->i_sb,xid); | 240 | inode->i_sb, xid); |
237 | else { | 241 | else { |
238 | rc = cifs_get_inode_info(&newinode, full_path, | 242 | rc = cifs_get_inode_info(&newinode, full_path, |
239 | buf, inode->i_sb,xid); | 243 | buf, inode->i_sb, xid); |
240 | if(newinode) { | 244 | if (newinode) { |
241 | newinode->i_mode = mode; | 245 | newinode->i_mode = mode; |
242 | if((oplock & CIFS_CREATE_ACTION) && | 246 | if ((oplock & CIFS_CREATE_ACTION) && |
243 | (cifs_sb->mnt_cifs_flags & | 247 | (cifs_sb->mnt_cifs_flags & |
244 | CIFS_MOUNT_SET_UID)) { | 248 | CIFS_MOUNT_SET_UID)) { |
245 | newinode->i_uid = current->fsuid; | 249 | newinode->i_uid = current->fsuid; |
246 | newinode->i_gid = current->fsgid; | 250 | newinode->i_gid = current->fsgid; |
@@ -259,14 +263,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
259 | direntry->d_op = &cifs_dentry_ops; | 263 | direntry->d_op = &cifs_dentry_ops; |
260 | d_instantiate(direntry, newinode); | 264 | d_instantiate(direntry, newinode); |
261 | } | 265 | } |
262 | if((nd->flags & LOOKUP_OPEN) == FALSE) { | 266 | if ((nd->flags & LOOKUP_OPEN) == FALSE) { |
263 | /* mknod case - do not leave file open */ | 267 | /* mknod case - do not leave file open */ |
264 | CIFSSMBClose(xid, pTcon, fileHandle); | 268 | CIFSSMBClose(xid, pTcon, fileHandle); |
265 | } else if(newinode) { | 269 | } else if (newinode) { |
266 | pCifsFile = | 270 | pCifsFile = |
267 | kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); | 271 | kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); |
268 | 272 | ||
269 | if(pCifsFile == NULL) | 273 | if (pCifsFile == NULL) |
270 | goto cifs_create_out; | 274 | goto cifs_create_out; |
271 | pCifsFile->netfid = fileHandle; | 275 | pCifsFile->netfid = fileHandle; |
272 | pCifsFile->pid = current->tgid; | 276 | pCifsFile->pid = current->tgid; |
@@ -276,33 +280,33 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
276 | init_MUTEX(&pCifsFile->fh_sem); | 280 | init_MUTEX(&pCifsFile->fh_sem); |
277 | mutex_init(&pCifsFile->lock_mutex); | 281 | mutex_init(&pCifsFile->lock_mutex); |
278 | INIT_LIST_HEAD(&pCifsFile->llist); | 282 | INIT_LIST_HEAD(&pCifsFile->llist); |
279 | atomic_set(&pCifsFile->wrtPending,0); | 283 | atomic_set(&pCifsFile->wrtPending, 0); |
280 | 284 | ||
281 | /* set the following in open now | 285 | /* set the following in open now |
282 | pCifsFile->pfile = file; */ | 286 | pCifsFile->pfile = file; */ |
283 | write_lock(&GlobalSMBSeslock); | 287 | write_lock(&GlobalSMBSeslock); |
284 | list_add(&pCifsFile->tlist,&pTcon->openFileList); | 288 | list_add(&pCifsFile->tlist, &pTcon->openFileList); |
285 | pCifsInode = CIFS_I(newinode); | 289 | pCifsInode = CIFS_I(newinode); |
286 | if(pCifsInode) { | 290 | if (pCifsInode) { |
287 | /* if readable file instance put first in list*/ | 291 | /* if readable file instance put first in list*/ |
288 | if (write_only == TRUE) { | 292 | if (write_only == TRUE) { |
289 | list_add_tail(&pCifsFile->flist, | 293 | list_add_tail(&pCifsFile->flist, |
290 | &pCifsInode->openFileList); | 294 | &pCifsInode->openFileList); |
291 | } else { | 295 | } else { |
292 | list_add(&pCifsFile->flist, | 296 | list_add(&pCifsFile->flist, |
293 | &pCifsInode->openFileList); | 297 | &pCifsInode->openFileList); |
294 | } | 298 | } |
295 | if((oplock & 0xF) == OPLOCK_EXCLUSIVE) { | 299 | if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { |
296 | pCifsInode->clientCanCacheAll = TRUE; | 300 | pCifsInode->clientCanCacheAll = TRUE; |
297 | pCifsInode->clientCanCacheRead = TRUE; | 301 | pCifsInode->clientCanCacheRead = TRUE; |
298 | cFYI(1,("Exclusive Oplock for inode %p", | 302 | cFYI(1,("Exclusive Oplock for inode %p", |
299 | newinode)); | 303 | newinode)); |
300 | } else if((oplock & 0xF) == OPLOCK_READ) | 304 | } else if ((oplock & 0xF) == OPLOCK_READ) |
301 | pCifsInode->clientCanCacheRead = TRUE; | 305 | pCifsInode->clientCanCacheRead = TRUE; |
302 | } | 306 | } |
303 | write_unlock(&GlobalSMBSeslock); | 307 | write_unlock(&GlobalSMBSeslock); |
304 | } | 308 | } |
305 | } | 309 | } |
306 | cifs_create_out: | 310 | cifs_create_out: |
307 | kfree(buf); | 311 | kfree(buf); |
308 | kfree(full_path); | 312 | kfree(full_path); |
@@ -310,8 +314,8 @@ cifs_create_out: | |||
310 | return rc; | 314 | return rc; |
311 | } | 315 | } |
312 | 316 | ||
313 | int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | 317 | int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, |
314 | dev_t device_number) | 318 | dev_t device_number) |
315 | { | 319 | { |
316 | int rc = -EPERM; | 320 | int rc = -EPERM; |
317 | int xid; | 321 | int xid; |
@@ -329,43 +333,44 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | |||
329 | pTcon = cifs_sb->tcon; | 333 | pTcon = cifs_sb->tcon; |
330 | 334 | ||
331 | full_path = build_path_from_dentry(direntry); | 335 | full_path = build_path_from_dentry(direntry); |
332 | if(full_path == NULL) | 336 | if (full_path == NULL) |
333 | rc = -ENOMEM; | 337 | rc = -ENOMEM; |
334 | else if (pTcon->ses->capabilities & CAP_UNIX) { | 338 | else if (pTcon->ses->capabilities & CAP_UNIX) { |
335 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { | 339 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { |
336 | rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, | 340 | rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, |
337 | mode,(__u64)current->fsuid,(__u64)current->fsgid, | 341 | mode, (__u64)current->fsuid, |
342 | (__u64)current->fsgid, | ||
338 | device_number, cifs_sb->local_nls, | 343 | device_number, cifs_sb->local_nls, |
339 | cifs_sb->mnt_cifs_flags & | 344 | cifs_sb->mnt_cifs_flags & |
340 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 345 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
341 | } else { | 346 | } else { |
342 | rc = CIFSSMBUnixSetPerms(xid, pTcon, | 347 | rc = CIFSSMBUnixSetPerms(xid, pTcon, |
343 | full_path, mode, (__u64)-1, (__u64)-1, | 348 | full_path, mode, (__u64)-1, (__u64)-1, |
344 | device_number, cifs_sb->local_nls, | 349 | device_number, cifs_sb->local_nls, |
345 | cifs_sb->mnt_cifs_flags & | 350 | cifs_sb->mnt_cifs_flags & |
346 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 351 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
347 | } | 352 | } |
348 | 353 | ||
349 | if(!rc) { | 354 | if (!rc) { |
350 | rc = cifs_get_inode_info_unix(&newinode, full_path, | 355 | rc = cifs_get_inode_info_unix(&newinode, full_path, |
351 | inode->i_sb,xid); | 356 | inode->i_sb, xid); |
352 | if (pTcon->nocase) | 357 | if (pTcon->nocase) |
353 | direntry->d_op = &cifs_ci_dentry_ops; | 358 | direntry->d_op = &cifs_ci_dentry_ops; |
354 | else | 359 | else |
355 | direntry->d_op = &cifs_dentry_ops; | 360 | direntry->d_op = &cifs_dentry_ops; |
356 | if(rc == 0) | 361 | if (rc == 0) |
357 | d_instantiate(direntry, newinode); | 362 | d_instantiate(direntry, newinode); |
358 | } | 363 | } |
359 | } else { | 364 | } else { |
360 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { | 365 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { |
361 | int oplock = 0; | 366 | int oplock = 0; |
362 | u16 fileHandle; | 367 | u16 fileHandle; |
363 | FILE_ALL_INFO * buf; | 368 | FILE_ALL_INFO * buf; |
364 | 369 | ||
365 | cFYI(1,("sfu compat create special file")); | 370 | cFYI(1, ("sfu compat create special file")); |
366 | 371 | ||
367 | buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL); | 372 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); |
368 | if(buf == NULL) { | 373 | if (buf == NULL) { |
369 | kfree(full_path); | 374 | kfree(full_path); |
370 | FreeXid(xid); | 375 | FreeXid(xid); |
371 | return -ENOMEM; | 376 | return -ENOMEM; |
@@ -373,39 +378,38 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | |||
373 | 378 | ||
374 | rc = CIFSSMBOpen(xid, pTcon, full_path, | 379 | rc = CIFSSMBOpen(xid, pTcon, full_path, |
375 | FILE_CREATE, /* fail if exists */ | 380 | FILE_CREATE, /* fail if exists */ |
376 | GENERIC_WRITE /* BB would | 381 | GENERIC_WRITE /* BB would |
377 | WRITE_OWNER | WRITE_DAC be better? */, | 382 | WRITE_OWNER | WRITE_DAC be better? */, |
378 | /* Create a file and set the | 383 | /* Create a file and set the |
379 | file attribute to SYSTEM */ | 384 | file attribute to SYSTEM */ |
380 | CREATE_NOT_DIR | CREATE_OPTION_SPECIAL, | 385 | CREATE_NOT_DIR | CREATE_OPTION_SPECIAL, |
381 | &fileHandle, &oplock, buf, | 386 | &fileHandle, &oplock, buf, |
382 | cifs_sb->local_nls, | 387 | cifs_sb->local_nls, |
383 | cifs_sb->mnt_cifs_flags & | 388 | cifs_sb->mnt_cifs_flags & |
384 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 389 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
385 | 390 | ||
386 | /* BB FIXME - add handling for backlevel servers | 391 | /* BB FIXME - add handling for backlevel servers |
387 | which need legacy open and check for all | 392 | which need legacy open and check for all |
388 | calls to SMBOpen for fallback to | 393 | calls to SMBOpen for fallback to SMBLeagcyOpen */ |
389 | SMBLeagcyOpen */ | 394 | if (!rc) { |
390 | if(!rc) { | ||
391 | /* BB Do not bother to decode buf since no | 395 | /* BB Do not bother to decode buf since no |
392 | local inode yet to put timestamps in, | 396 | local inode yet to put timestamps in, |
393 | but we can reuse it safely */ | 397 | but we can reuse it safely */ |
394 | int bytes_written; | 398 | int bytes_written; |
395 | struct win_dev *pdev; | 399 | struct win_dev *pdev; |
396 | pdev = (struct win_dev *)buf; | 400 | pdev = (struct win_dev *)buf; |
397 | if(S_ISCHR(mode)) { | 401 | if (S_ISCHR(mode)) { |
398 | memcpy(pdev->type, "IntxCHR", 8); | 402 | memcpy(pdev->type, "IntxCHR", 8); |
399 | pdev->major = | 403 | pdev->major = |
400 | cpu_to_le64(MAJOR(device_number)); | 404 | cpu_to_le64(MAJOR(device_number)); |
401 | pdev->minor = | 405 | pdev->minor = |
402 | cpu_to_le64(MINOR(device_number)); | 406 | cpu_to_le64(MINOR(device_number)); |
403 | rc = CIFSSMBWrite(xid, pTcon, | 407 | rc = CIFSSMBWrite(xid, pTcon, |
404 | fileHandle, | 408 | fileHandle, |
405 | sizeof(struct win_dev), | 409 | sizeof(struct win_dev), |
406 | 0, &bytes_written, (char *)pdev, | 410 | 0, &bytes_written, (char *)pdev, |
407 | NULL, 0); | 411 | NULL, 0); |
408 | } else if(S_ISBLK(mode)) { | 412 | } else if (S_ISBLK(mode)) { |
409 | memcpy(pdev->type, "IntxBLK", 8); | 413 | memcpy(pdev->type, "IntxBLK", 8); |
410 | pdev->major = | 414 | pdev->major = |
411 | cpu_to_le64(MAJOR(device_number)); | 415 | cpu_to_le64(MAJOR(device_number)); |
@@ -432,7 +436,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | |||
432 | 436 | ||
433 | 437 | ||
434 | struct dentry * | 438 | struct dentry * |
435 | cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct nameidata *nd) | 439 | cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, |
440 | struct nameidata *nd) | ||
436 | { | 441 | { |
437 | int xid; | 442 | int xid; |
438 | int rc = 0; /* to get around spurious gcc warning, set to zero here */ | 443 | int rc = 0; /* to get around spurious gcc warning, set to zero here */ |
@@ -447,8 +452,6 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name | |||
447 | (" parent inode = 0x%p name is: %s and dentry = 0x%p", | 452 | (" parent inode = 0x%p name is: %s and dentry = 0x%p", |
448 | parent_dir_inode, direntry->d_name.name, direntry)); | 453 | parent_dir_inode, direntry->d_name.name, direntry)); |
449 | 454 | ||
450 | /* BB Add check of incoming data - e.g. frame not longer than maximum SMB - let server check the namelen BB */ | ||
451 | |||
452 | /* check whether path exists */ | 455 | /* check whether path exists */ |
453 | 456 | ||
454 | cifs_sb = CIFS_SB(parent_dir_inode->i_sb); | 457 | cifs_sb = CIFS_SB(parent_dir_inode->i_sb); |
@@ -472,7 +475,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name | |||
472 | deadlock in the cases (beginning of sys_rename itself) | 475 | deadlock in the cases (beginning of sys_rename itself) |
473 | in which we already have the sb rename sem */ | 476 | in which we already have the sb rename sem */ |
474 | full_path = build_path_from_dentry(direntry); | 477 | full_path = build_path_from_dentry(direntry); |
475 | if(full_path == NULL) { | 478 | if (full_path == NULL) { |
476 | FreeXid(xid); | 479 | FreeXid(xid); |
477 | return ERR_PTR(-ENOMEM); | 480 | return ERR_PTR(-ENOMEM); |
478 | } | 481 | } |
@@ -487,10 +490,10 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name | |||
487 | 490 | ||
488 | if (pTcon->ses->capabilities & CAP_UNIX) | 491 | if (pTcon->ses->capabilities & CAP_UNIX) |
489 | rc = cifs_get_inode_info_unix(&newInode, full_path, | 492 | rc = cifs_get_inode_info_unix(&newInode, full_path, |
490 | parent_dir_inode->i_sb,xid); | 493 | parent_dir_inode->i_sb, xid); |
491 | else | 494 | else |
492 | rc = cifs_get_inode_info(&newInode, full_path, NULL, | 495 | rc = cifs_get_inode_info(&newInode, full_path, NULL, |
493 | parent_dir_inode->i_sb,xid); | 496 | parent_dir_inode->i_sb, xid); |
494 | 497 | ||
495 | if ((rc == 0) && (newInode != NULL)) { | 498 | if ((rc == 0) && (newInode != NULL)) { |
496 | if (pTcon->nocase) | 499 | if (pTcon->nocase) |
@@ -499,7 +502,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name | |||
499 | direntry->d_op = &cifs_dentry_ops; | 502 | direntry->d_op = &cifs_dentry_ops; |
500 | d_add(direntry, newInode); | 503 | d_add(direntry, newInode); |
501 | 504 | ||
502 | /* since paths are not looked up by component - the parent | 505 | /* since paths are not looked up by component - the parent |
503 | directories are presumed to be good here */ | 506 | directories are presumed to be good here */ |
504 | renew_parental_timestamps(direntry); | 507 | renew_parental_timestamps(direntry); |
505 | 508 | ||
@@ -511,13 +514,13 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name | |||
511 | else | 514 | else |
512 | direntry->d_op = &cifs_dentry_ops; | 515 | direntry->d_op = &cifs_dentry_ops; |
513 | d_add(direntry, NULL); | 516 | d_add(direntry, NULL); |
514 | /* if it was once a directory (but how can we tell?) we could do | 517 | /* if it was once a directory (but how can we tell?) we could do |
515 | shrink_dcache_parent(direntry); */ | 518 | shrink_dcache_parent(direntry); */ |
516 | } else { | 519 | } else { |
517 | cERROR(1,("Error 0x%x on cifs_get_inode_info in lookup of %s", | 520 | cERROR(1,("Error 0x%x on cifs_get_inode_info in lookup of %s", |
518 | rc,full_path)); | 521 | rc, full_path)); |
519 | /* BB special case check for Access Denied - watch security | 522 | /* BB special case check for Access Denied - watch security |
520 | exposure of returning dir info implicitly via different rc | 523 | exposure of returning dir info implicitly via different rc |
521 | if file exists or not but no access BB */ | 524 | if file exists or not but no access BB */ |
522 | } | 525 | } |
523 | 526 | ||
@@ -538,11 +541,11 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) | |||
538 | } else { | 541 | } else { |
539 | cFYI(1, ("neg dentry 0x%p name = %s", | 542 | cFYI(1, ("neg dentry 0x%p name = %s", |
540 | direntry, direntry->d_name.name)); | 543 | direntry, direntry->d_name.name)); |
541 | if(time_after(jiffies, direntry->d_time + HZ) || | 544 | if (time_after(jiffies, direntry->d_time + HZ) || |
542 | !lookupCacheEnabled) { | 545 | !lookupCacheEnabled) { |
543 | d_drop(direntry); | 546 | d_drop(direntry); |
544 | isValid = 0; | 547 | isValid = 0; |
545 | } | 548 | } |
546 | } | 549 | } |
547 | 550 | ||
548 | return isValid; | 551 | return isValid; |
@@ -559,8 +562,7 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) | |||
559 | 562 | ||
560 | struct dentry_operations cifs_dentry_ops = { | 563 | struct dentry_operations cifs_dentry_ops = { |
561 | .d_revalidate = cifs_d_revalidate, | 564 | .d_revalidate = cifs_d_revalidate, |
562 | /* d_delete: cifs_d_delete, *//* not needed except for debugging */ | 565 | /* d_delete: cifs_d_delete, */ /* not needed except for debugging */ |
563 | /* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */ | ||
564 | }; | 566 | }; |
565 | 567 | ||
566 | static int cifs_ci_hash(struct dentry *dentry, struct qstr *q) | 568 | static int cifs_ci_hash(struct dentry *dentry, struct qstr *q) |