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: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
committed by
Steve French
parent
da5cabf80e
commit
5d9ac7fd32
153
fs/cifs/dir.c
153
fs/cifs/dir.c
@@ -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,
|
|||||||
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,
|
|||||||
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);
|
||||||
buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
|
goto mknod_out;
|
||||||
if (buf == NULL) {
|
|
||||||
kfree(full_path);
|
|
||||||
rc = -ENOMEM;
|
|
||||||
FreeXid(xid);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = CIFSSMBOpen(xid, pTcon, full_path,
|
|
||||||
FILE_CREATE, /* fail if exists */
|
|
||||||
GENERIC_WRITE /* BB would
|
|
||||||
WRITE_OWNER | WRITE_DAC be better? */,
|
|
||||||
/* Create a file and set the
|
|
||||||
file attribute to SYSTEM */
|
|
||||||
CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
|
|
||||||
&fileHandle, &oplock, buf,
|
|
||||||
cifs_sb->local_nls,
|
|
||||||
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 */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
|
||||||
|
goto mknod_out;
|
||||||
|
|
||||||
|
|
||||||
|
cFYI(1, "sfu compat create special file");
|
||||||
|
|
||||||
|
buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
|
||||||
|
if (buf == NULL) {
|
||||||
|
kfree(full_path);
|
||||||
|
rc = -ENOMEM;
|
||||||
|
FreeXid(xid);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user