diff options
author | Jeff Layton <jlayton@redhat.com> | 2010-08-05 13:58:22 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2010-08-16 13:00:44 -0400 |
commit | 5d9ac7fd32f600f9451ea58abdb07f7ed42e921d (patch) | |
tree | bfc83c4bb3fcb50b32216056f10b80dc437e6446 /fs/cifs/dir.c | |
parent | da5cabf80e2433131bf0ed8993abc0f7ea618c73 (diff) |
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>
Diffstat (limited to 'fs/cifs/dir.c')
-rw-r--r-- | fs/cifs/dir.c | 149 |
1 files changed, 74 insertions, 75 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 578d88c5b46e..f17d50047f07 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -496,6 +496,11 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | |||
496 | struct cifsTconInfo *pTcon; | 496 | struct cifsTconInfo *pTcon; |
497 | char *full_path = NULL; | 497 | char *full_path = NULL; |
498 | struct inode *newinode = NULL; | 498 | struct inode *newinode = NULL; |
499 | int oplock = 0; | ||
500 | u16 fileHandle; | ||
501 | FILE_ALL_INFO *buf = NULL; | ||
502 | unsigned int bytes_written; | ||
503 | struct win_dev *pdev; | ||
499 | 504 | ||
500 | if (!old_valid_dev(device_number)) | 505 | if (!old_valid_dev(device_number)) |
501 | return -EINVAL; | 506 | return -EINVAL; |
@@ -506,9 +511,12 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | |||
506 | pTcon = cifs_sb->tcon; | 511 | pTcon = cifs_sb->tcon; |
507 | 512 | ||
508 | full_path = build_path_from_dentry(direntry); | 513 | full_path = build_path_from_dentry(direntry); |
509 | if (full_path == NULL) | 514 | if (full_path == NULL) { |
510 | rc = -ENOMEM; | 515 | rc = -ENOMEM; |
511 | else if (pTcon->unix_ext) { | 516 | goto mknod_out; |
517 | } | ||
518 | |||
519 | if (pTcon->unix_ext) { | ||
512 | struct cifs_unix_set_info_args args = { | 520 | struct cifs_unix_set_info_args args = { |
513 | .mode = mode & ~current_umask(), | 521 | .mode = mode & ~current_umask(), |
514 | .ctime = NO_CHANGE_64, | 522 | .ctime = NO_CHANGE_64, |
@@ -527,87 +535,78 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | |||
527 | cifs_sb->local_nls, | 535 | cifs_sb->local_nls, |
528 | cifs_sb->mnt_cifs_flags & | 536 | cifs_sb->mnt_cifs_flags & |
529 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 537 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
538 | if (rc) | ||
539 | goto mknod_out; | ||
530 | 540 | ||
531 | if (!rc) { | 541 | rc = cifs_get_inode_info_unix(&newinode, full_path, |
532 | rc = cifs_get_inode_info_unix(&newinode, full_path, | ||
533 | inode->i_sb, xid); | 542 | inode->i_sb, xid); |
534 | if (pTcon->nocase) | 543 | if (pTcon->nocase) |
535 | direntry->d_op = &cifs_ci_dentry_ops; | 544 | direntry->d_op = &cifs_ci_dentry_ops; |
536 | else | 545 | else |
537 | direntry->d_op = &cifs_dentry_ops; | 546 | direntry->d_op = &cifs_dentry_ops; |
538 | if (rc == 0) | ||
539 | d_instantiate(direntry, newinode); | ||
540 | } | ||
541 | } else { | ||
542 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { | ||
543 | int oplock = 0; | ||
544 | u16 fileHandle; | ||
545 | FILE_ALL_INFO *buf; | ||
546 | 547 | ||
547 | cFYI(1, "sfu compat create special file"); | 548 | if (rc == 0) |
549 | d_instantiate(direntry, newinode); | ||
550 | goto mknod_out; | ||
551 | } | ||
548 | 552 | ||
549 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); | 553 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) |
550 | if (buf == NULL) { | 554 | goto mknod_out; |
551 | kfree(full_path); | ||
552 | rc = -ENOMEM; | ||
553 | FreeXid(xid); | ||
554 | return rc; | ||
555 | } | ||
556 | 555 | ||
557 | rc = CIFSSMBOpen(xid, pTcon, full_path, | 556 | |
558 | FILE_CREATE, /* fail if exists */ | 557 | cFYI(1, "sfu compat create special file"); |
559 | GENERIC_WRITE /* BB would | 558 | |
560 | WRITE_OWNER | WRITE_DAC be better? */, | 559 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); |
561 | /* Create a file and set the | 560 | if (buf == NULL) { |
562 | file attribute to SYSTEM */ | 561 | kfree(full_path); |
563 | CREATE_NOT_DIR | CREATE_OPTION_SPECIAL, | 562 | rc = -ENOMEM; |
564 | &fileHandle, &oplock, buf, | 563 | FreeXid(xid); |
565 | cifs_sb->local_nls, | 564 | return rc; |
566 | cifs_sb->mnt_cifs_flags & | ||
567 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
568 | |||
569 | /* BB FIXME - add handling for backlevel servers | ||
570 | which need legacy open and check for all | ||
571 | calls to SMBOpen for fallback to SMBLeagcyOpen */ | ||
572 | if (!rc) { | ||
573 | /* BB Do not bother to decode buf since no | ||
574 | local inode yet to put timestamps in, | ||
575 | but we can reuse it safely */ | ||
576 | unsigned int bytes_written; | ||
577 | struct win_dev *pdev; | ||
578 | pdev = (struct win_dev *)buf; | ||
579 | if (S_ISCHR(mode)) { | ||
580 | memcpy(pdev->type, "IntxCHR", 8); | ||
581 | pdev->major = | ||
582 | cpu_to_le64(MAJOR(device_number)); | ||
583 | pdev->minor = | ||
584 | cpu_to_le64(MINOR(device_number)); | ||
585 | rc = CIFSSMBWrite(xid, pTcon, | ||
586 | fileHandle, | ||
587 | sizeof(struct win_dev), | ||
588 | 0, &bytes_written, (char *)pdev, | ||
589 | NULL, 0); | ||
590 | } else if (S_ISBLK(mode)) { | ||
591 | memcpy(pdev->type, "IntxBLK", 8); | ||
592 | pdev->major = | ||
593 | cpu_to_le64(MAJOR(device_number)); | ||
594 | pdev->minor = | ||
595 | cpu_to_le64(MINOR(device_number)); | ||
596 | rc = CIFSSMBWrite(xid, pTcon, | ||
597 | fileHandle, | ||
598 | sizeof(struct win_dev), | ||
599 | 0, &bytes_written, (char *)pdev, | ||
600 | NULL, 0); | ||
601 | } /* else if(S_ISFIFO */ | ||
602 | CIFSSMBClose(xid, pTcon, fileHandle); | ||
603 | d_drop(direntry); | ||
604 | } | ||
605 | kfree(buf); | ||
606 | /* add code here to set EAs */ | ||
607 | } | ||
608 | } | 565 | } |
609 | 566 | ||
567 | /* FIXME: would WRITE_OWNER | WRITE_DAC be better? */ | ||
568 | rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE, | ||
569 | GENERIC_WRITE, CREATE_NOT_DIR | CREATE_OPTION_SPECIAL, | ||
570 | &fileHandle, &oplock, buf, cifs_sb->local_nls, | ||
571 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
572 | if (rc) | ||
573 | goto mknod_out; | ||
574 | |||
575 | /* BB Do not bother to decode buf since no local inode yet to put | ||
576 | * timestamps in, but we can reuse it safely */ | ||
577 | |||
578 | pdev = (struct win_dev *)buf; | ||
579 | if (S_ISCHR(mode)) { | ||
580 | memcpy(pdev->type, "IntxCHR", 8); | ||
581 | pdev->major = | ||
582 | cpu_to_le64(MAJOR(device_number)); | ||
583 | pdev->minor = | ||
584 | cpu_to_le64(MINOR(device_number)); | ||
585 | rc = CIFSSMBWrite(xid, pTcon, | ||
586 | fileHandle, | ||
587 | sizeof(struct win_dev), | ||
588 | 0, &bytes_written, (char *)pdev, | ||
589 | NULL, 0); | ||
590 | } else if (S_ISBLK(mode)) { | ||
591 | memcpy(pdev->type, "IntxBLK", 8); | ||
592 | pdev->major = | ||
593 | cpu_to_le64(MAJOR(device_number)); | ||
594 | pdev->minor = | ||
595 | cpu_to_le64(MINOR(device_number)); | ||
596 | rc = CIFSSMBWrite(xid, pTcon, | ||
597 | fileHandle, | ||
598 | sizeof(struct win_dev), | ||
599 | 0, &bytes_written, (char *)pdev, | ||
600 | NULL, 0); | ||
601 | } /* else if (S_ISFIFO) */ | ||
602 | CIFSSMBClose(xid, pTcon, fileHandle); | ||
603 | d_drop(direntry); | ||
604 | |||
605 | /* FIXME: add code here to set EAs */ | ||
606 | |||
607 | mknod_out: | ||
610 | kfree(full_path); | 608 | kfree(full_path); |
609 | kfree(buf); | ||
611 | FreeXid(xid); | 610 | FreeXid(xid); |
612 | return rc; | 611 | return rc; |
613 | } | 612 | } |