diff options
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r-- | fs/cifs/inode.c | 193 |
1 files changed, 111 insertions, 82 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 49719b8228e5..aadc2b68678b 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -383,10 +383,10 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
383 | 383 | ||
384 | /* check for Minshall+French symlinks */ | 384 | /* check for Minshall+French symlinks */ |
385 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { | 385 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { |
386 | int tmprc = CIFSCheckMFSymlink(xid, tcon, cifs_sb, &fattr, | 386 | int tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr, |
387 | full_path); | 387 | full_path); |
388 | if (tmprc) | 388 | if (tmprc) |
389 | cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc); | 389 | cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc); |
390 | } | 390 | } |
391 | 391 | ||
392 | if (*pinode == NULL) { | 392 | if (*pinode == NULL) { |
@@ -404,18 +404,20 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
404 | } | 404 | } |
405 | 405 | ||
406 | static int | 406 | static int |
407 | cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, | 407 | cifs_sfu_type(struct cifs_fattr *fattr, const char *path, |
408 | struct cifs_sb_info *cifs_sb, unsigned int xid) | 408 | struct cifs_sb_info *cifs_sb, unsigned int xid) |
409 | { | 409 | { |
410 | int rc; | 410 | int rc; |
411 | int oplock = 0; | 411 | int oplock = 0; |
412 | __u16 netfid; | ||
413 | struct tcon_link *tlink; | 412 | struct tcon_link *tlink; |
414 | struct cifs_tcon *tcon; | 413 | struct cifs_tcon *tcon; |
414 | struct cifs_fid fid; | ||
415 | struct cifs_open_parms oparms; | ||
415 | struct cifs_io_parms io_parms; | 416 | struct cifs_io_parms io_parms; |
416 | char buf[24]; | 417 | char buf[24]; |
417 | unsigned int bytes_read; | 418 | unsigned int bytes_read; |
418 | char *pbuf; | 419 | char *pbuf; |
420 | int buf_type = CIFS_NO_BUFFER; | ||
419 | 421 | ||
420 | pbuf = buf; | 422 | pbuf = buf; |
421 | 423 | ||
@@ -436,62 +438,69 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, | |||
436 | return PTR_ERR(tlink); | 438 | return PTR_ERR(tlink); |
437 | tcon = tlink_tcon(tlink); | 439 | tcon = tlink_tcon(tlink); |
438 | 440 | ||
439 | rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ, | 441 | oparms.tcon = tcon; |
440 | CREATE_NOT_DIR, &netfid, &oplock, NULL, | 442 | oparms.cifs_sb = cifs_sb; |
441 | cifs_sb->local_nls, | 443 | oparms.desired_access = GENERIC_READ; |
442 | cifs_sb->mnt_cifs_flags & | 444 | oparms.create_options = CREATE_NOT_DIR; |
443 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 445 | oparms.disposition = FILE_OPEN; |
444 | if (rc == 0) { | 446 | oparms.path = path; |
445 | int buf_type = CIFS_NO_BUFFER; | 447 | oparms.fid = &fid; |
446 | /* Read header */ | 448 | oparms.reconnect = false; |
447 | io_parms.netfid = netfid; | 449 | |
448 | io_parms.pid = current->tgid; | 450 | rc = CIFS_open(xid, &oparms, &oplock, NULL); |
449 | io_parms.tcon = tcon; | 451 | if (rc) { |
450 | io_parms.offset = 0; | 452 | cifs_put_tlink(tlink); |
451 | io_parms.length = 24; | 453 | return rc; |
452 | rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, | 454 | } |
453 | &buf_type); | 455 | |
454 | if ((rc == 0) && (bytes_read >= 8)) { | 456 | /* Read header */ |
455 | if (memcmp("IntxBLK", pbuf, 8) == 0) { | 457 | io_parms.netfid = fid.netfid; |
456 | cifs_dbg(FYI, "Block device\n"); | 458 | io_parms.pid = current->tgid; |
457 | fattr->cf_mode |= S_IFBLK; | 459 | io_parms.tcon = tcon; |
458 | fattr->cf_dtype = DT_BLK; | 460 | io_parms.offset = 0; |
459 | if (bytes_read == 24) { | 461 | io_parms.length = 24; |
460 | /* we have enough to decode dev num */ | 462 | |
461 | __u64 mjr; /* major */ | 463 | rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type); |
462 | __u64 mnr; /* minor */ | 464 | if ((rc == 0) && (bytes_read >= 8)) { |
463 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); | 465 | if (memcmp("IntxBLK", pbuf, 8) == 0) { |
464 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); | 466 | cifs_dbg(FYI, "Block device\n"); |
465 | fattr->cf_rdev = MKDEV(mjr, mnr); | 467 | fattr->cf_mode |= S_IFBLK; |
466 | } | 468 | fattr->cf_dtype = DT_BLK; |
467 | } else if (memcmp("IntxCHR", pbuf, 8) == 0) { | 469 | if (bytes_read == 24) { |
468 | cifs_dbg(FYI, "Char device\n"); | 470 | /* we have enough to decode dev num */ |
469 | fattr->cf_mode |= S_IFCHR; | 471 | __u64 mjr; /* major */ |
470 | fattr->cf_dtype = DT_CHR; | 472 | __u64 mnr; /* minor */ |
471 | if (bytes_read == 24) { | 473 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); |
472 | /* we have enough to decode dev num */ | 474 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); |
473 | __u64 mjr; /* major */ | 475 | fattr->cf_rdev = MKDEV(mjr, mnr); |
474 | __u64 mnr; /* minor */ | ||
475 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); | ||
476 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); | ||
477 | fattr->cf_rdev = MKDEV(mjr, mnr); | ||
478 | } | ||
479 | } else if (memcmp("IntxLNK", pbuf, 7) == 0) { | ||
480 | cifs_dbg(FYI, "Symlink\n"); | ||
481 | fattr->cf_mode |= S_IFLNK; | ||
482 | fattr->cf_dtype = DT_LNK; | ||
483 | } else { | ||
484 | fattr->cf_mode |= S_IFREG; /* file? */ | ||
485 | fattr->cf_dtype = DT_REG; | ||
486 | rc = -EOPNOTSUPP; | ||
487 | } | 476 | } |
477 | } else if (memcmp("IntxCHR", pbuf, 8) == 0) { | ||
478 | cifs_dbg(FYI, "Char device\n"); | ||
479 | fattr->cf_mode |= S_IFCHR; | ||
480 | fattr->cf_dtype = DT_CHR; | ||
481 | if (bytes_read == 24) { | ||
482 | /* we have enough to decode dev num */ | ||
483 | __u64 mjr; /* major */ | ||
484 | __u64 mnr; /* minor */ | ||
485 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); | ||
486 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); | ||
487 | fattr->cf_rdev = MKDEV(mjr, mnr); | ||
488 | } | ||
489 | } else if (memcmp("IntxLNK", pbuf, 7) == 0) { | ||
490 | cifs_dbg(FYI, "Symlink\n"); | ||
491 | fattr->cf_mode |= S_IFLNK; | ||
492 | fattr->cf_dtype = DT_LNK; | ||
488 | } else { | 493 | } else { |
489 | fattr->cf_mode |= S_IFREG; /* then it is a file */ | 494 | fattr->cf_mode |= S_IFREG; /* file? */ |
490 | fattr->cf_dtype = DT_REG; | 495 | fattr->cf_dtype = DT_REG; |
491 | rc = -EOPNOTSUPP; /* or some unknown SFU type */ | 496 | rc = -EOPNOTSUPP; |
492 | } | 497 | } |
493 | CIFSSMBClose(xid, tcon, netfid); | 498 | } else { |
499 | fattr->cf_mode |= S_IFREG; /* then it is a file */ | ||
500 | fattr->cf_dtype = DT_REG; | ||
501 | rc = -EOPNOTSUPP; /* or some unknown SFU type */ | ||
494 | } | 502 | } |
503 | CIFSSMBClose(xid, tcon, fid.netfid); | ||
495 | cifs_put_tlink(tlink); | 504 | cifs_put_tlink(tlink); |
496 | return rc; | 505 | return rc; |
497 | } | 506 | } |
@@ -518,10 +527,15 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path, | |||
518 | return PTR_ERR(tlink); | 527 | return PTR_ERR(tlink); |
519 | tcon = tlink_tcon(tlink); | 528 | tcon = tlink_tcon(tlink); |
520 | 529 | ||
521 | rc = CIFSSMBQAllEAs(xid, tcon, path, "SETFILEBITS", | 530 | if (tcon->ses->server->ops->query_all_EAs == NULL) { |
522 | ea_value, 4 /* size of buf */, cifs_sb->local_nls, | 531 | cifs_put_tlink(tlink); |
523 | cifs_sb->mnt_cifs_flags & | 532 | return -EOPNOTSUPP; |
524 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 533 | } |
534 | |||
535 | rc = tcon->ses->server->ops->query_all_EAs(xid, tcon, path, | ||
536 | "SETFILEBITS", ea_value, 4 /* size of buf */, | ||
537 | cifs_sb->local_nls, | ||
538 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
525 | cifs_put_tlink(tlink); | 539 | cifs_put_tlink(tlink); |
526 | if (rc < 0) | 540 | if (rc < 0) |
527 | return (int)rc; | 541 | return (int)rc; |
@@ -663,7 +677,7 @@ cgfi_exit: | |||
663 | int | 677 | int |
664 | cifs_get_inode_info(struct inode **inode, const char *full_path, | 678 | cifs_get_inode_info(struct inode **inode, const char *full_path, |
665 | FILE_ALL_INFO *data, struct super_block *sb, int xid, | 679 | FILE_ALL_INFO *data, struct super_block *sb, int xid, |
666 | const __u16 *fid) | 680 | const struct cifs_fid *fid) |
667 | { | 681 | { |
668 | bool validinum = false; | 682 | bool validinum = false; |
669 | __u16 srchflgs; | 683 | __u16 srchflgs; |
@@ -800,10 +814,10 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, | |||
800 | 814 | ||
801 | /* check for Minshall+French symlinks */ | 815 | /* check for Minshall+French symlinks */ |
802 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { | 816 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { |
803 | tmprc = CIFSCheckMFSymlink(xid, tcon, cifs_sb, &fattr, | 817 | tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr, |
804 | full_path); | 818 | full_path); |
805 | if (tmprc) | 819 | if (tmprc) |
806 | cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc); | 820 | cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc); |
807 | } | 821 | } |
808 | 822 | ||
809 | if (!*inode) { | 823 | if (!*inode) { |
@@ -1032,7 +1046,8 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, | |||
1032 | { | 1046 | { |
1033 | int oplock = 0; | 1047 | int oplock = 0; |
1034 | int rc; | 1048 | int rc; |
1035 | __u16 netfid; | 1049 | struct cifs_fid fid; |
1050 | struct cifs_open_parms oparms; | ||
1036 | struct inode *inode = dentry->d_inode; | 1051 | struct inode *inode = dentry->d_inode; |
1037 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | 1052 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); |
1038 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1053 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
@@ -1055,10 +1070,16 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, | |||
1055 | goto out; | 1070 | goto out; |
1056 | } | 1071 | } |
1057 | 1072 | ||
1058 | rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, | 1073 | oparms.tcon = tcon; |
1059 | DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR, | 1074 | oparms.cifs_sb = cifs_sb; |
1060 | &netfid, &oplock, NULL, cifs_sb->local_nls, | 1075 | oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES; |
1061 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 1076 | oparms.create_options = CREATE_NOT_DIR; |
1077 | oparms.disposition = FILE_OPEN; | ||
1078 | oparms.path = full_path; | ||
1079 | oparms.fid = &fid; | ||
1080 | oparms.reconnect = false; | ||
1081 | |||
1082 | rc = CIFS_open(xid, &oparms, &oplock, NULL); | ||
1062 | if (rc != 0) | 1083 | if (rc != 0) |
1063 | goto out; | 1084 | goto out; |
1064 | 1085 | ||
@@ -1079,7 +1100,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, | |||
1079 | goto out_close; | 1100 | goto out_close; |
1080 | } | 1101 | } |
1081 | info_buf->Attributes = cpu_to_le32(dosattr); | 1102 | info_buf->Attributes = cpu_to_le32(dosattr); |
1082 | rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid, | 1103 | rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid, |
1083 | current->tgid); | 1104 | current->tgid); |
1084 | /* although we would like to mark the file hidden | 1105 | /* although we would like to mark the file hidden |
1085 | if that fails we will still try to rename it */ | 1106 | if that fails we will still try to rename it */ |
@@ -1090,7 +1111,8 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, | |||
1090 | } | 1111 | } |
1091 | 1112 | ||
1092 | /* rename the file */ | 1113 | /* rename the file */ |
1093 | rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls, | 1114 | rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL, |
1115 | cifs_sb->local_nls, | ||
1094 | cifs_sb->mnt_cifs_flags & | 1116 | cifs_sb->mnt_cifs_flags & |
1095 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1117 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1096 | if (rc != 0) { | 1118 | if (rc != 0) { |
@@ -1100,7 +1122,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, | |||
1100 | 1122 | ||
1101 | /* try to set DELETE_ON_CLOSE */ | 1123 | /* try to set DELETE_ON_CLOSE */ |
1102 | if (!cifsInode->delete_pending) { | 1124 | if (!cifsInode->delete_pending) { |
1103 | rc = CIFSSMBSetFileDisposition(xid, tcon, true, netfid, | 1125 | rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid, |
1104 | current->tgid); | 1126 | current->tgid); |
1105 | /* | 1127 | /* |
1106 | * some samba versions return -ENOENT when we try to set the | 1128 | * some samba versions return -ENOENT when we try to set the |
@@ -1120,7 +1142,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, | |||
1120 | } | 1142 | } |
1121 | 1143 | ||
1122 | out_close: | 1144 | out_close: |
1123 | CIFSSMBClose(xid, tcon, netfid); | 1145 | CIFSSMBClose(xid, tcon, fid.netfid); |
1124 | out: | 1146 | out: |
1125 | kfree(info_buf); | 1147 | kfree(info_buf); |
1126 | cifs_put_tlink(tlink); | 1148 | cifs_put_tlink(tlink); |
@@ -1132,13 +1154,13 @@ out: | |||
1132 | * them anyway. | 1154 | * them anyway. |
1133 | */ | 1155 | */ |
1134 | undo_rename: | 1156 | undo_rename: |
1135 | CIFSSMBRenameOpenFile(xid, tcon, netfid, dentry->d_name.name, | 1157 | CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name, |
1136 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 1158 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
1137 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1159 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1138 | undo_setattr: | 1160 | undo_setattr: |
1139 | if (dosattr != origattr) { | 1161 | if (dosattr != origattr) { |
1140 | info_buf->Attributes = cpu_to_le32(origattr); | 1162 | info_buf->Attributes = cpu_to_le32(origattr); |
1141 | if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid, | 1163 | if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid, |
1142 | current->tgid)) | 1164 | current->tgid)) |
1143 | cifsInode->cifsAttrs = origattr; | 1165 | cifsInode->cifsAttrs = origattr; |
1144 | } | 1166 | } |
@@ -1549,7 +1571,8 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry, | |||
1549 | struct tcon_link *tlink; | 1571 | struct tcon_link *tlink; |
1550 | struct cifs_tcon *tcon; | 1572 | struct cifs_tcon *tcon; |
1551 | struct TCP_Server_Info *server; | 1573 | struct TCP_Server_Info *server; |
1552 | __u16 srcfid; | 1574 | struct cifs_fid fid; |
1575 | struct cifs_open_parms oparms; | ||
1553 | int oplock, rc; | 1576 | int oplock, rc; |
1554 | 1577 | ||
1555 | tlink = cifs_sb_tlink(cifs_sb); | 1578 | tlink = cifs_sb_tlink(cifs_sb); |
@@ -1576,17 +1599,23 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry, | |||
1576 | if (to_dentry->d_parent != from_dentry->d_parent) | 1599 | if (to_dentry->d_parent != from_dentry->d_parent) |
1577 | goto do_rename_exit; | 1600 | goto do_rename_exit; |
1578 | 1601 | ||
1602 | oparms.tcon = tcon; | ||
1603 | oparms.cifs_sb = cifs_sb; | ||
1579 | /* open the file to be renamed -- we need DELETE perms */ | 1604 | /* open the file to be renamed -- we need DELETE perms */ |
1580 | rc = CIFSSMBOpen(xid, tcon, from_path, FILE_OPEN, DELETE, | 1605 | oparms.desired_access = DELETE; |
1581 | CREATE_NOT_DIR, &srcfid, &oplock, NULL, | 1606 | oparms.create_options = CREATE_NOT_DIR; |
1582 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 1607 | oparms.disposition = FILE_OPEN; |
1583 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1608 | oparms.path = from_path; |
1609 | oparms.fid = &fid; | ||
1610 | oparms.reconnect = false; | ||
1611 | |||
1612 | rc = CIFS_open(xid, &oparms, &oplock, NULL); | ||
1584 | if (rc == 0) { | 1613 | if (rc == 0) { |
1585 | rc = CIFSSMBRenameOpenFile(xid, tcon, srcfid, | 1614 | rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, |
1586 | (const char *) to_dentry->d_name.name, | 1615 | (const char *) to_dentry->d_name.name, |
1587 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 1616 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
1588 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1617 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1589 | CIFSSMBClose(xid, tcon, srcfid); | 1618 | CIFSSMBClose(xid, tcon, fid.netfid); |
1590 | } | 1619 | } |
1591 | do_rename_exit: | 1620 | do_rename_exit: |
1592 | cifs_put_tlink(tlink); | 1621 | cifs_put_tlink(tlink); |