Commit 5d9ac7fd authored by Jeff Layton's avatar Jeff Layton Committed by Steve French

cifs: clean up error handling in cifs_mknod

Get rid of some nesting and add a label we can goto on error.
Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent da5cabf8
...@@ -496,6 +496,11 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, ...@@ -496,6 +496,11 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
char *full_path = NULL; char *full_path = NULL;
struct inode *newinode = NULL; struct inode *newinode = NULL;
int oplock = 0;
u16 fileHandle;
FILE_ALL_INFO *buf = NULL;
unsigned int bytes_written;
struct win_dev *pdev;
if (!old_valid_dev(device_number)) if (!old_valid_dev(device_number))
return -EINVAL; return -EINVAL;
...@@ -506,9 +511,12 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, ...@@ -506,9 +511,12 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if (full_path == NULL) if (full_path == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
else if (pTcon->unix_ext) { goto mknod_out;
}
if (pTcon->unix_ext) {
struct cifs_unix_set_info_args args = { struct cifs_unix_set_info_args args = {
.mode = mode & ~current_umask(), .mode = mode & ~current_umask(),
.ctime = NO_CHANGE_64, .ctime = NO_CHANGE_64,
...@@ -527,87 +535,78 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, ...@@ -527,87 +535,78 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc)
goto mknod_out;
if (!rc) { rc = cifs_get_inode_info_unix(&newinode, full_path,
rc = cifs_get_inode_info_unix(&newinode, full_path,
inode->i_sb, xid); inode->i_sb, xid);
if (pTcon->nocase) if (pTcon->nocase)
direntry->d_op = &cifs_ci_dentry_ops; direntry->d_op = &cifs_ci_dentry_ops;
else else
direntry->d_op = &cifs_dentry_ops; direntry->d_op = &cifs_dentry_ops;
if (rc == 0)
d_instantiate(direntry, newinode);
}
} else {
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
int oplock = 0;
u16 fileHandle;
FILE_ALL_INFO *buf;
cFYI(1, "sfu compat create special file"); if (rc == 0)
d_instantiate(direntry, newinode);
goto mknod_out;
}
buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
if (buf == NULL) { goto mknod_out;
kfree(full_path);
rc = -ENOMEM;
FreeXid(xid);
return rc;
}
rc = CIFSSMBOpen(xid, pTcon, full_path,
FILE_CREATE, /* fail if exists */ cFYI(1, "sfu compat create special file");
GENERIC_WRITE /* BB would
WRITE_OWNER | WRITE_DAC be better? */, buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
/* Create a file and set the if (buf == NULL) {
file attribute to SYSTEM */ kfree(full_path);
CREATE_NOT_DIR | CREATE_OPTION_SPECIAL, rc = -ENOMEM;
&fileHandle, &oplock, buf, FreeXid(xid);
cifs_sb->local_nls, return rc;
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
/* BB FIXME - add handling for backlevel servers
which need legacy open and check for all
calls to SMBOpen for fallback to SMBLeagcyOpen */
if (!rc) {
/* BB Do not bother to decode buf since no
local inode yet to put timestamps in,
but we can reuse it safely */
unsigned int bytes_written;
struct win_dev *pdev;
pdev = (struct win_dev *)buf;
if (S_ISCHR(mode)) {
memcpy(pdev->type, "IntxCHR", 8);
pdev->major =
cpu_to_le64(MAJOR(device_number));
pdev->minor =
cpu_to_le64(MINOR(device_number));
rc = CIFSSMBWrite(xid, pTcon,
fileHandle,
sizeof(struct win_dev),
0, &bytes_written, (char *)pdev,
NULL, 0);
} else if (S_ISBLK(mode)) {
memcpy(pdev->type, "IntxBLK", 8);
pdev->major =
cpu_to_le64(MAJOR(device_number));
pdev->minor =
cpu_to_le64(MINOR(device_number));
rc = CIFSSMBWrite(xid, pTcon,
fileHandle,
sizeof(struct win_dev),
0, &bytes_written, (char *)pdev,
NULL, 0);
} /* else if(S_ISFIFO */
CIFSSMBClose(xid, pTcon, fileHandle);
d_drop(direntry);
}
kfree(buf);
/* add code here to set EAs */
}
} }
/* FIXME: would WRITE_OWNER | WRITE_DAC be better? */
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE,
GENERIC_WRITE, CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
&fileHandle, &oplock, buf, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc)
goto mknod_out;
/* BB Do not bother to decode buf since no local inode yet to put
* timestamps in, but we can reuse it safely */
pdev = (struct win_dev *)buf;
if (S_ISCHR(mode)) {
memcpy(pdev->type, "IntxCHR", 8);
pdev->major =
cpu_to_le64(MAJOR(device_number));
pdev->minor =
cpu_to_le64(MINOR(device_number));
rc = CIFSSMBWrite(xid, pTcon,
fileHandle,
sizeof(struct win_dev),
0, &bytes_written, (char *)pdev,
NULL, 0);
} else if (S_ISBLK(mode)) {
memcpy(pdev->type, "IntxBLK", 8);
pdev->major =
cpu_to_le64(MAJOR(device_number));
pdev->minor =
cpu_to_le64(MINOR(device_number));
rc = CIFSSMBWrite(xid, pTcon,
fileHandle,
sizeof(struct win_dev),
0, &bytes_written, (char *)pdev,
NULL, 0);
} /* else if (S_ISFIFO) */
CIFSSMBClose(xid, pTcon, fileHandle);
d_drop(direntry);
/* FIXME: add code here to set EAs */
mknod_out:
kfree(full_path); kfree(full_path);
kfree(buf);
FreeXid(xid); FreeXid(xid);
return rc; return rc;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment