diff options
Diffstat (limited to 'fs/cifs/dir.c')
-rw-r--r-- | fs/cifs/dir.c | 91 |
1 files changed, 59 insertions, 32 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index e9f7ecc2714b..391816b461ca 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -73,7 +73,7 @@ cifs_bp_rename_retry: | |||
73 | namelen += (1 + temp->d_name.len); | 73 | namelen += (1 + temp->d_name.len); |
74 | temp = temp->d_parent; | 74 | temp = temp->d_parent; |
75 | if (temp == NULL) { | 75 | if (temp == NULL) { |
76 | cERROR(1, ("corrupt dentry")); | 76 | cERROR(1, "corrupt dentry"); |
77 | return NULL; | 77 | return NULL; |
78 | } | 78 | } |
79 | } | 79 | } |
@@ -90,19 +90,18 @@ cifs_bp_rename_retry: | |||
90 | full_path[namelen] = dirsep; | 90 | full_path[namelen] = dirsep; |
91 | strncpy(full_path + namelen + 1, temp->d_name.name, | 91 | strncpy(full_path + namelen + 1, temp->d_name.name, |
92 | temp->d_name.len); | 92 | temp->d_name.len); |
93 | cFYI(0, ("name: %s", full_path + namelen)); | 93 | cFYI(0, "name: %s", full_path + namelen); |
94 | } | 94 | } |
95 | temp = temp->d_parent; | 95 | temp = temp->d_parent; |
96 | if (temp == NULL) { | 96 | if (temp == NULL) { |
97 | cERROR(1, ("corrupt dentry")); | 97 | cERROR(1, "corrupt dentry"); |
98 | kfree(full_path); | 98 | kfree(full_path); |
99 | return NULL; | 99 | return NULL; |
100 | } | 100 | } |
101 | } | 101 | } |
102 | if (namelen != pplen + dfsplen) { | 102 | if (namelen != pplen + dfsplen) { |
103 | cERROR(1, | 103 | cERROR(1, "did not end path lookup where expected namelen is %d", |
104 | ("did not end path lookup where expected namelen is %d", | 104 | namelen); |
105 | namelen)); | ||
106 | /* presumably this is only possible if racing with a rename | 105 | /* presumably this is only possible if racing with a rename |
107 | of one of the parent directories (we can not lock the dentries | 106 | of one of the parent directories (we can not lock the dentries |
108 | above us to prevent this, but retrying should be harmless) */ | 107 | above us to prevent this, but retrying should be harmless) */ |
@@ -130,6 +129,12 @@ cifs_bp_rename_retry: | |||
130 | return full_path; | 129 | return full_path; |
131 | } | 130 | } |
132 | 131 | ||
132 | /* | ||
133 | * When called with struct file pointer set to NULL, there is no way we could | ||
134 | * update file->private_data, but getting it stuck on openFileList provides a | ||
135 | * way to access it from cifs_fill_filedata and thereby set file->private_data | ||
136 | * from cifs_open. | ||
137 | */ | ||
133 | struct cifsFileInfo * | 138 | struct cifsFileInfo * |
134 | cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, | 139 | cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, |
135 | struct file *file, struct vfsmount *mnt, unsigned int oflags) | 140 | struct file *file, struct vfsmount *mnt, unsigned int oflags) |
@@ -173,7 +178,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, | |||
173 | if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { | 178 | if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { |
174 | pCifsInode->clientCanCacheAll = true; | 179 | pCifsInode->clientCanCacheAll = true; |
175 | pCifsInode->clientCanCacheRead = true; | 180 | pCifsInode->clientCanCacheRead = true; |
176 | cFYI(1, ("Exclusive Oplock inode %p", newinode)); | 181 | cFYI(1, "Exclusive Oplock inode %p", newinode); |
177 | } else if ((oplock & 0xF) == OPLOCK_READ) | 182 | } else if ((oplock & 0xF) == OPLOCK_READ) |
178 | pCifsInode->clientCanCacheRead = true; | 183 | pCifsInode->clientCanCacheRead = true; |
179 | } | 184 | } |
@@ -183,16 +188,17 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, | |||
183 | } | 188 | } |
184 | 189 | ||
185 | int cifs_posix_open(char *full_path, struct inode **pinode, | 190 | int cifs_posix_open(char *full_path, struct inode **pinode, |
186 | struct vfsmount *mnt, int mode, int oflags, | 191 | struct vfsmount *mnt, struct super_block *sb, |
187 | __u32 *poplock, __u16 *pnetfid, int xid) | 192 | int mode, int oflags, |
193 | __u32 *poplock, __u16 *pnetfid, int xid) | ||
188 | { | 194 | { |
189 | int rc; | 195 | int rc; |
190 | FILE_UNIX_BASIC_INFO *presp_data; | 196 | FILE_UNIX_BASIC_INFO *presp_data; |
191 | __u32 posix_flags = 0; | 197 | __u32 posix_flags = 0; |
192 | struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb); | 198 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
193 | struct cifs_fattr fattr; | 199 | struct cifs_fattr fattr; |
194 | 200 | ||
195 | cFYI(1, ("posix open %s", full_path)); | 201 | cFYI(1, "posix open %s", full_path); |
196 | 202 | ||
197 | presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL); | 203 | presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL); |
198 | if (presp_data == NULL) | 204 | if (presp_data == NULL) |
@@ -242,7 +248,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode, | |||
242 | 248 | ||
243 | /* get new inode and set it up */ | 249 | /* get new inode and set it up */ |
244 | if (*pinode == NULL) { | 250 | if (*pinode == NULL) { |
245 | *pinode = cifs_iget(mnt->mnt_sb, &fattr); | 251 | cifs_fill_uniqueid(sb, &fattr); |
252 | *pinode = cifs_iget(sb, &fattr); | ||
246 | if (!*pinode) { | 253 | if (!*pinode) { |
247 | rc = -ENOMEM; | 254 | rc = -ENOMEM; |
248 | goto posix_open_ret; | 255 | goto posix_open_ret; |
@@ -251,7 +258,18 @@ int cifs_posix_open(char *full_path, struct inode **pinode, | |||
251 | cifs_fattr_to_inode(*pinode, &fattr); | 258 | cifs_fattr_to_inode(*pinode, &fattr); |
252 | } | 259 | } |
253 | 260 | ||
254 | cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt, oflags); | 261 | /* |
262 | * cifs_fill_filedata() takes care of setting cifsFileInfo pointer to | ||
263 | * file->private_data. | ||
264 | */ | ||
265 | if (mnt) { | ||
266 | struct cifsFileInfo *pfile_info; | ||
267 | |||
268 | pfile_info = cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt, | ||
269 | oflags); | ||
270 | if (pfile_info == NULL) | ||
271 | rc = -ENOMEM; | ||
272 | } | ||
255 | 273 | ||
256 | posix_open_ret: | 274 | posix_open_ret: |
257 | kfree(presp_data); | 275 | kfree(presp_data); |
@@ -315,13 +333,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
315 | if (nd && (nd->flags & LOOKUP_OPEN)) | 333 | if (nd && (nd->flags & LOOKUP_OPEN)) |
316 | oflags = nd->intent.open.flags; | 334 | oflags = nd->intent.open.flags; |
317 | else | 335 | else |
318 | oflags = FMODE_READ; | 336 | oflags = FMODE_READ | SMB_O_CREAT; |
319 | 337 | ||
320 | if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && | 338 | if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && |
321 | (CIFS_UNIX_POSIX_PATH_OPS_CAP & | 339 | (CIFS_UNIX_POSIX_PATH_OPS_CAP & |
322 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { | 340 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { |
323 | rc = cifs_posix_open(full_path, &newinode, nd->path.mnt, | 341 | rc = cifs_posix_open(full_path, &newinode, |
324 | mode, oflags, &oplock, &fileHandle, xid); | 342 | nd ? nd->path.mnt : NULL, |
343 | inode->i_sb, mode, oflags, &oplock, &fileHandle, xid); | ||
325 | /* EIO could indicate that (posix open) operation is not | 344 | /* EIO could indicate that (posix open) operation is not |
326 | supported, despite what server claimed in capability | 345 | supported, despite what server claimed in capability |
327 | negotation. EREMOTE indicates DFS junction, which is not | 346 | negotation. EREMOTE indicates DFS junction, which is not |
@@ -358,7 +377,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
358 | else if ((oflags & O_CREAT) == O_CREAT) | 377 | else if ((oflags & O_CREAT) == O_CREAT) |
359 | disposition = FILE_OPEN_IF; | 378 | disposition = FILE_OPEN_IF; |
360 | else | 379 | else |
361 | cFYI(1, ("Create flag not set in create function")); | 380 | cFYI(1, "Create flag not set in create function"); |
362 | } | 381 | } |
363 | 382 | ||
364 | /* BB add processing to set equivalent of mode - e.g. via CreateX with | 383 | /* BB add processing to set equivalent of mode - e.g. via CreateX with |
@@ -394,7 +413,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
394 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 413 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
395 | } | 414 | } |
396 | if (rc) { | 415 | if (rc) { |
397 | cFYI(1, ("cifs_create returned 0x%x", rc)); | 416 | cFYI(1, "cifs_create returned 0x%x", rc); |
398 | goto cifs_create_out; | 417 | goto cifs_create_out; |
399 | } | 418 | } |
400 | 419 | ||
@@ -457,15 +476,22 @@ cifs_create_set_dentry: | |||
457 | if (rc == 0) | 476 | if (rc == 0) |
458 | setup_cifs_dentry(tcon, direntry, newinode); | 477 | setup_cifs_dentry(tcon, direntry, newinode); |
459 | else | 478 | else |
460 | cFYI(1, ("Create worked, get_inode_info failed rc = %d", rc)); | 479 | cFYI(1, "Create worked, get_inode_info failed rc = %d", rc); |
461 | 480 | ||
462 | /* nfsd case - nfs srv does not set nd */ | 481 | /* nfsd case - nfs srv does not set nd */ |
463 | if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) { | 482 | if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) { |
464 | /* mknod case - do not leave file open */ | 483 | /* mknod case - do not leave file open */ |
465 | CIFSSMBClose(xid, tcon, fileHandle); | 484 | CIFSSMBClose(xid, tcon, fileHandle); |
466 | } else if (!(posix_create) && (newinode)) { | 485 | } else if (!(posix_create) && (newinode)) { |
467 | cifs_new_fileinfo(newinode, fileHandle, NULL, | 486 | struct cifsFileInfo *pfile_info; |
468 | nd->path.mnt, oflags); | 487 | /* |
488 | * cifs_fill_filedata() takes care of setting cifsFileInfo | ||
489 | * pointer to file->private_data. | ||
490 | */ | ||
491 | pfile_info = cifs_new_fileinfo(newinode, fileHandle, NULL, | ||
492 | nd->path.mnt, oflags); | ||
493 | if (pfile_info == NULL) | ||
494 | rc = -ENOMEM; | ||
469 | } | 495 | } |
470 | cifs_create_out: | 496 | cifs_create_out: |
471 | kfree(buf); | 497 | kfree(buf); |
@@ -531,7 +557,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | |||
531 | u16 fileHandle; | 557 | u16 fileHandle; |
532 | FILE_ALL_INFO *buf; | 558 | FILE_ALL_INFO *buf; |
533 | 559 | ||
534 | cFYI(1, ("sfu compat create special file")); | 560 | cFYI(1, "sfu compat create special file"); |
535 | 561 | ||
536 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); | 562 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); |
537 | if (buf == NULL) { | 563 | if (buf == NULL) { |
@@ -616,8 +642,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | |||
616 | 642 | ||
617 | xid = GetXid(); | 643 | xid = GetXid(); |
618 | 644 | ||
619 | cFYI(1, ("parent inode = 0x%p name is: %s and dentry = 0x%p", | 645 | cFYI(1, "parent inode = 0x%p name is: %s and dentry = 0x%p", |
620 | parent_dir_inode, direntry->d_name.name, direntry)); | 646 | parent_dir_inode, direntry->d_name.name, direntry); |
621 | 647 | ||
622 | /* check whether path exists */ | 648 | /* check whether path exists */ |
623 | 649 | ||
@@ -632,7 +658,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | |||
632 | int i; | 658 | int i; |
633 | for (i = 0; i < direntry->d_name.len; i++) | 659 | for (i = 0; i < direntry->d_name.len; i++) |
634 | if (direntry->d_name.name[i] == '\\') { | 660 | if (direntry->d_name.name[i] == '\\') { |
635 | cFYI(1, ("Invalid file name")); | 661 | cFYI(1, "Invalid file name"); |
636 | FreeXid(xid); | 662 | FreeXid(xid); |
637 | return ERR_PTR(-EINVAL); | 663 | return ERR_PTR(-EINVAL); |
638 | } | 664 | } |
@@ -657,11 +683,11 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | |||
657 | } | 683 | } |
658 | 684 | ||
659 | if (direntry->d_inode != NULL) { | 685 | if (direntry->d_inode != NULL) { |
660 | cFYI(1, ("non-NULL inode in lookup")); | 686 | cFYI(1, "non-NULL inode in lookup"); |
661 | } else { | 687 | } else { |
662 | cFYI(1, ("NULL inode in lookup")); | 688 | cFYI(1, "NULL inode in lookup"); |
663 | } | 689 | } |
664 | cFYI(1, ("Full path: %s inode = 0x%p", full_path, direntry->d_inode)); | 690 | cFYI(1, "Full path: %s inode = 0x%p", full_path, direntry->d_inode); |
665 | 691 | ||
666 | /* Posix open is only called (at lookup time) for file create now. | 692 | /* Posix open is only called (at lookup time) for file create now. |
667 | * For opens (rather than creates), because we do not know if it | 693 | * For opens (rather than creates), because we do not know if it |
@@ -678,6 +704,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | |||
678 | (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open && | 704 | (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open && |
679 | (nd->intent.open.flags & O_CREAT)) { | 705 | (nd->intent.open.flags & O_CREAT)) { |
680 | rc = cifs_posix_open(full_path, &newInode, nd->path.mnt, | 706 | rc = cifs_posix_open(full_path, &newInode, nd->path.mnt, |
707 | parent_dir_inode->i_sb, | ||
681 | nd->intent.open.create_mode, | 708 | nd->intent.open.create_mode, |
682 | nd->intent.open.flags, &oplock, | 709 | nd->intent.open.flags, &oplock, |
683 | &fileHandle, xid); | 710 | &fileHandle, xid); |
@@ -723,7 +750,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | |||
723 | /* if it was once a directory (but how can we tell?) we could do | 750 | /* if it was once a directory (but how can we tell?) we could do |
724 | shrink_dcache_parent(direntry); */ | 751 | shrink_dcache_parent(direntry); */ |
725 | } else if (rc != -EACCES) { | 752 | } else if (rc != -EACCES) { |
726 | cERROR(1, ("Unexpected lookup error %d", rc)); | 753 | cERROR(1, "Unexpected lookup error %d", rc); |
727 | /* We special case check for Access Denied - since that | 754 | /* We special case check for Access Denied - since that |
728 | is a common return code */ | 755 | is a common return code */ |
729 | } | 756 | } |
@@ -742,8 +769,8 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) | |||
742 | if (cifs_revalidate_dentry(direntry)) | 769 | if (cifs_revalidate_dentry(direntry)) |
743 | return 0; | 770 | return 0; |
744 | } else { | 771 | } else { |
745 | cFYI(1, ("neg dentry 0x%p name = %s", | 772 | cFYI(1, "neg dentry 0x%p name = %s", |
746 | direntry, direntry->d_name.name)); | 773 | direntry, direntry->d_name.name); |
747 | if (time_after(jiffies, direntry->d_time + HZ) || | 774 | if (time_after(jiffies, direntry->d_time + HZ) || |
748 | !lookupCacheEnabled) { | 775 | !lookupCacheEnabled) { |
749 | d_drop(direntry); | 776 | d_drop(direntry); |
@@ -758,7 +785,7 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) | |||
758 | { | 785 | { |
759 | int rc = 0; | 786 | int rc = 0; |
760 | 787 | ||
761 | cFYI(1, ("In cifs d_delete, name = %s", direntry->d_name.name)); | 788 | cFYI(1, "In cifs d_delete, name = %s", direntry->d_name.name); |
762 | 789 | ||
763 | return rc; | 790 | return rc; |
764 | } */ | 791 | } */ |