aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2010-04-22 15:21:55 -0400
committerSteve French <sfrench@us.ibm.com>2010-04-22 15:21:55 -0400
commitfa588e0c57048b3d4bfcd772d80dc0615f83fd35 (patch)
treea357298481dc4a8ab7f00998b065b9fee7e36d20 /fs/cifs
parent2c964d1f7c87eb71f7902111cd7c8fbba225e4b6 (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.h6
-rw-r--r--fs/cifs/dir.c20
-rw-r--r--fs/cifs/file.c11
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);
109extern int cifs_posix_open(char *full_path, struct inode **pinode, 109extern 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);
112extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, 114extern 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
184int cifs_posix_open(char *full_path, struct inode **pinode, 184int 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
255posix_open_ret: 257posix_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;