diff options
author | Steve French <sfrench@us.ibm.com> | 2010-04-22 15:21:55 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2010-04-22 15:21:55 -0400 |
commit | fa588e0c57048b3d4bfcd772d80dc0615f83fd35 (patch) | |
tree | a357298481dc4a8ab7f00998b065b9fee7e36d20 /fs/cifs | |
parent | 2c964d1f7c87eb71f7902111cd7c8fbba225e4b6 (diff) |
[CIFS] Allow null nd (as nfs server uses) on create
While creating a file on a server which supports unix extensions
such as Samba, if a file is being created which does not supply
nameidata (i.e. nd is null), cifs client can oops when calling
cifs_posix_open.
Signed-off-by: Shirish Pargaonkar <shirishp@us.ibm.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/cifsproto.h | 6 | ||||
-rw-r--r-- | fs/cifs/dir.c | 20 | ||||
-rw-r--r-- | fs/cifs/file.c | 11 |
3 files changed, 23 insertions, 14 deletions
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 32262e15be39..cc622a735f29 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -107,8 +107,10 @@ extern struct cifsFileInfo *cifs_new_fileinfo(struct inode *newinode, | |||
107 | __u16 fileHandle, struct file *file, | 107 | __u16 fileHandle, struct file *file, |
108 | struct vfsmount *mnt, unsigned int oflags); | 108 | struct vfsmount *mnt, unsigned int oflags); |
109 | extern int cifs_posix_open(char *full_path, struct inode **pinode, | 109 | extern int cifs_posix_open(char *full_path, struct inode **pinode, |
110 | struct vfsmount *mnt, int mode, int oflags, | 110 | struct vfsmount *mnt, |
111 | __u32 *poplock, __u16 *pnetfid, int xid); | 111 | struct super_block *sb, |
112 | int mode, int oflags, | ||
113 | __u32 *poplock, __u16 *pnetfid, int xid); | ||
112 | extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, | 114 | extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, |
113 | FILE_UNIX_BASIC_INFO *info, | 115 | FILE_UNIX_BASIC_INFO *info, |
114 | struct cifs_sb_info *cifs_sb); | 116 | struct cifs_sb_info *cifs_sb); |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 4aa2fe3f535f..d791d0763a9c 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -182,13 +182,14 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, | |||
182 | } | 182 | } |
183 | 183 | ||
184 | int cifs_posix_open(char *full_path, struct inode **pinode, | 184 | int cifs_posix_open(char *full_path, struct inode **pinode, |
185 | struct vfsmount *mnt, int mode, int oflags, | 185 | struct vfsmount *mnt, struct super_block *sb, |
186 | __u32 *poplock, __u16 *pnetfid, int xid) | 186 | int mode, int oflags, |
187 | __u32 *poplock, __u16 *pnetfid, int xid) | ||
187 | { | 188 | { |
188 | int rc; | 189 | int rc; |
189 | FILE_UNIX_BASIC_INFO *presp_data; | 190 | FILE_UNIX_BASIC_INFO *presp_data; |
190 | __u32 posix_flags = 0; | 191 | __u32 posix_flags = 0; |
191 | struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb); | 192 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
192 | struct cifs_fattr fattr; | 193 | struct cifs_fattr fattr; |
193 | 194 | ||
194 | cFYI(1, "posix open %s", full_path); | 195 | cFYI(1, "posix open %s", full_path); |
@@ -241,7 +242,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode, | |||
241 | 242 | ||
242 | /* get new inode and set it up */ | 243 | /* get new inode and set it up */ |
243 | if (*pinode == NULL) { | 244 | if (*pinode == NULL) { |
244 | *pinode = cifs_iget(mnt->mnt_sb, &fattr); | 245 | *pinode = cifs_iget(sb, &fattr); |
245 | if (!*pinode) { | 246 | if (!*pinode) { |
246 | rc = -ENOMEM; | 247 | rc = -ENOMEM; |
247 | goto posix_open_ret; | 248 | goto posix_open_ret; |
@@ -250,7 +251,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode, | |||
250 | cifs_fattr_to_inode(*pinode, &fattr); | 251 | cifs_fattr_to_inode(*pinode, &fattr); |
251 | } | 252 | } |
252 | 253 | ||
253 | cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt, oflags); | 254 | if (mnt) |
255 | cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt, oflags); | ||
254 | 256 | ||
255 | posix_open_ret: | 257 | posix_open_ret: |
256 | kfree(presp_data); | 258 | kfree(presp_data); |
@@ -314,13 +316,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
314 | if (nd && (nd->flags & LOOKUP_OPEN)) | 316 | if (nd && (nd->flags & LOOKUP_OPEN)) |
315 | oflags = nd->intent.open.flags; | 317 | oflags = nd->intent.open.flags; |
316 | else | 318 | else |
317 | oflags = FMODE_READ; | 319 | oflags = FMODE_READ | SMB_O_CREAT; |
318 | 320 | ||
319 | if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && | 321 | if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && |
320 | (CIFS_UNIX_POSIX_PATH_OPS_CAP & | 322 | (CIFS_UNIX_POSIX_PATH_OPS_CAP & |
321 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { | 323 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { |
322 | rc = cifs_posix_open(full_path, &newinode, nd->path.mnt, | 324 | rc = cifs_posix_open(full_path, &newinode, |
323 | mode, oflags, &oplock, &fileHandle, xid); | 325 | nd ? nd->path.mnt : NULL, |
326 | inode->i_sb, mode, oflags, &oplock, &fileHandle, xid); | ||
324 | /* EIO could indicate that (posix open) operation is not | 327 | /* EIO could indicate that (posix open) operation is not |
325 | supported, despite what server claimed in capability | 328 | supported, despite what server claimed in capability |
326 | negotation. EREMOTE indicates DFS junction, which is not | 329 | negotation. EREMOTE indicates DFS junction, which is not |
@@ -677,6 +680,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | |||
677 | (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open && | 680 | (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open && |
678 | (nd->intent.open.flags & O_CREAT)) { | 681 | (nd->intent.open.flags & O_CREAT)) { |
679 | rc = cifs_posix_open(full_path, &newInode, nd->path.mnt, | 682 | rc = cifs_posix_open(full_path, &newInode, nd->path.mnt, |
683 | parent_dir_inode->i_sb, | ||
680 | nd->intent.open.create_mode, | 684 | nd->intent.open.create_mode, |
681 | nd->intent.open.flags, &oplock, | 685 | nd->intent.open.flags, &oplock, |
682 | &fileHandle, xid); | 686 | &fileHandle, xid); |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 2ba4c41be972..5f1f7682256b 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -298,10 +298,12 @@ int cifs_open(struct inode *inode, struct file *file) | |||
298 | (CIFS_UNIX_POSIX_PATH_OPS_CAP & | 298 | (CIFS_UNIX_POSIX_PATH_OPS_CAP & |
299 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { | 299 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { |
300 | int oflags = (int) cifs_posix_convert_flags(file->f_flags); | 300 | int oflags = (int) cifs_posix_convert_flags(file->f_flags); |
301 | oflags |= SMB_O_CREAT; | ||
301 | /* can not refresh inode info since size could be stale */ | 302 | /* can not refresh inode info since size could be stale */ |
302 | rc = cifs_posix_open(full_path, &inode, file->f_path.mnt, | 303 | rc = cifs_posix_open(full_path, &inode, file->f_path.mnt, |
303 | cifs_sb->mnt_file_mode /* ignored */, | 304 | inode->i_sb, |
304 | oflags, &oplock, &netfid, xid); | 305 | cifs_sb->mnt_file_mode /* ignored */, |
306 | oflags, &oplock, &netfid, xid); | ||
305 | if (rc == 0) { | 307 | if (rc == 0) { |
306 | cFYI(1, "posix open succeeded"); | 308 | cFYI(1, "posix open succeeded"); |
307 | /* no need for special case handling of setting mode | 309 | /* no need for special case handling of setting mode |
@@ -513,8 +515,9 @@ reopen_error_exit: | |||
513 | int oflags = (int) cifs_posix_convert_flags(file->f_flags); | 515 | int oflags = (int) cifs_posix_convert_flags(file->f_flags); |
514 | /* can not refresh inode info since size could be stale */ | 516 | /* can not refresh inode info since size could be stale */ |
515 | rc = cifs_posix_open(full_path, NULL, file->f_path.mnt, | 517 | rc = cifs_posix_open(full_path, NULL, file->f_path.mnt, |
516 | cifs_sb->mnt_file_mode /* ignored */, | 518 | inode->i_sb, |
517 | oflags, &oplock, &netfid, xid); | 519 | cifs_sb->mnt_file_mode /* ignored */, |
520 | oflags, &oplock, &netfid, xid); | ||
518 | if (rc == 0) { | 521 | if (rc == 0) { |
519 | cFYI(1, "posix reopen succeeded"); | 522 | cFYI(1, "posix reopen succeeded"); |
520 | goto reopen_success; | 523 | goto reopen_success; |