diff options
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/CHANGES | 5 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 21 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 3 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 23 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 6 | ||||
-rw-r--r-- | fs/cifs/connect.c | 5 | ||||
-rw-r--r-- | fs/cifs/dir.c | 4 | ||||
-rw-r--r-- | fs/cifs/file.c | 7 | ||||
-rw-r--r-- | fs/cifs/inode.c | 148 | ||||
-rw-r--r-- | fs/cifs/misc.c | 3 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 77 |
11 files changed, 172 insertions, 130 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 28e3d5c5fcac..1f3465201fdf 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -2,6 +2,11 @@ Version 1.53 | |||
2 | ------------ | 2 | ------------ |
3 | DFS support added (Microsoft Distributed File System client support needed | 3 | DFS support added (Microsoft Distributed File System client support needed |
4 | for referrals which enable a hierarchical name space among servers). | 4 | for referrals which enable a hierarchical name space among servers). |
5 | Disable temporary caching of mode bits to servers which do not support | ||
6 | storing of mode (e.g. Windows servers, when client mounts without cifsacl | ||
7 | mount option) and add new "dynperm" mount option to enable temporary caching | ||
8 | of mode (enable old behavior). Fix hang on mount caused when server crashes | ||
9 | tcp session during negotiate protocol. | ||
5 | 10 | ||
6 | Version 1.52 | 11 | Version 1.52 |
7 | ------------ | 12 | ------------ |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 5df93fd6303f..86b4d5f405ae 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -97,9 +97,6 @@ cifs_read_super(struct super_block *sb, void *data, | |||
97 | { | 97 | { |
98 | struct inode *inode; | 98 | struct inode *inode; |
99 | struct cifs_sb_info *cifs_sb; | 99 | struct cifs_sb_info *cifs_sb; |
100 | #ifdef CONFIG_CIFS_DFS_UPCALL | ||
101 | int len; | ||
102 | #endif | ||
103 | int rc = 0; | 100 | int rc = 0; |
104 | 101 | ||
105 | /* BB should we make this contingent on mount parm? */ | 102 | /* BB should we make this contingent on mount parm? */ |
@@ -117,15 +114,17 @@ cifs_read_super(struct super_block *sb, void *data, | |||
117 | * complex operation (mount), and in case of fail | 114 | * complex operation (mount), and in case of fail |
118 | * just exit instead of doing mount and attempting | 115 | * just exit instead of doing mount and attempting |
119 | * undo it if this copy fails?*/ | 116 | * undo it if this copy fails?*/ |
120 | len = strlen(data); | 117 | if (data) { |
121 | cifs_sb->mountdata = kzalloc(len + 1, GFP_KERNEL); | 118 | int len = strlen(data); |
122 | if (cifs_sb->mountdata == NULL) { | 119 | cifs_sb->mountdata = kzalloc(len + 1, GFP_KERNEL); |
123 | kfree(sb->s_fs_info); | 120 | if (cifs_sb->mountdata == NULL) { |
124 | sb->s_fs_info = NULL; | 121 | kfree(sb->s_fs_info); |
125 | return -ENOMEM; | 122 | sb->s_fs_info = NULL; |
123 | return -ENOMEM; | ||
124 | } | ||
125 | strncpy(cifs_sb->mountdata, data, len + 1); | ||
126 | cifs_sb->mountdata[len] = '\0'; | ||
126 | } | 127 | } |
127 | strncpy(cifs_sb->mountdata, data, len + 1); | ||
128 | cifs_sb->mountdata[len] = '\0'; | ||
129 | #endif | 128 | #endif |
130 | 129 | ||
131 | rc = cifs_mount(sb, cifs_sb, data, devname); | 130 | rc = cifs_mount(sb, cifs_sb, data, devname); |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 08914053242b..9cfcf326ead3 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -333,7 +333,6 @@ struct cifsFileInfo { | |||
333 | bool messageMode:1; /* for pipes: message vs byte mode */ | 333 | bool messageMode:1; /* for pipes: message vs byte mode */ |
334 | atomic_t wrtPending; /* handle in use - defer close */ | 334 | atomic_t wrtPending; /* handle in use - defer close */ |
335 | struct semaphore fh_sem; /* prevents reopen race after dead ses*/ | 335 | struct semaphore fh_sem; /* prevents reopen race after dead ses*/ |
336 | char *search_resume_name; /* BB removeme BB */ | ||
337 | struct cifs_search_info srch_inf; | 336 | struct cifs_search_info srch_inf; |
338 | }; | 337 | }; |
339 | 338 | ||
@@ -626,7 +625,7 @@ GLOBAL_EXTERN atomic_t tcpSesAllocCount; | |||
626 | GLOBAL_EXTERN atomic_t tcpSesReconnectCount; | 625 | GLOBAL_EXTERN atomic_t tcpSesReconnectCount; |
627 | GLOBAL_EXTERN atomic_t tconInfoReconnectCount; | 626 | GLOBAL_EXTERN atomic_t tconInfoReconnectCount; |
628 | 627 | ||
629 | /* Various Debug counters to remove someday (BB) */ | 628 | /* Various Debug counters */ |
630 | GLOBAL_EXTERN atomic_t bufAllocCount; /* current number allocated */ | 629 | GLOBAL_EXTERN atomic_t bufAllocCount; /* current number allocated */ |
631 | #ifdef CONFIG_CIFS_STATS2 | 630 | #ifdef CONFIG_CIFS_STATS2 |
632 | GLOBAL_EXTERN atomic_t totBufAllocCount; /* total allocated over all time */ | 631 | GLOBAL_EXTERN atomic_t totBufAllocCount; /* total allocated over all time */ |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 65d58b4e6a61..0f327c224da3 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -79,6 +79,19 @@ | |||
79 | #define TRANS2_GET_DFS_REFERRAL 0x10 | 79 | #define TRANS2_GET_DFS_REFERRAL 0x10 |
80 | #define TRANS2_REPORT_DFS_INCOSISTENCY 0x11 | 80 | #define TRANS2_REPORT_DFS_INCOSISTENCY 0x11 |
81 | 81 | ||
82 | /* SMB Transact (Named Pipe) subcommand codes */ | ||
83 | #define TRANS_SET_NMPIPE_STATE 0x0001 | ||
84 | #define TRANS_RAW_READ_NMPIPE 0x0011 | ||
85 | #define TRANS_QUERY_NMPIPE_STATE 0x0021 | ||
86 | #define TRANS_QUERY_NMPIPE_INFO 0x0022 | ||
87 | #define TRANS_PEEK_NMPIPE 0x0023 | ||
88 | #define TRANS_TRANSACT_NMPIPE 0x0026 | ||
89 | #define TRANS_RAW_WRITE_NMPIPE 0x0031 | ||
90 | #define TRANS_READ_NMPIPE 0x0036 | ||
91 | #define TRANS_WRITE_NMPIPE 0x0037 | ||
92 | #define TRANS_WAIT_NMPIPE 0x0053 | ||
93 | #define TRANS_CALL_NMPIPE 0x0054 | ||
94 | |||
82 | /* NT Transact subcommand codes */ | 95 | /* NT Transact subcommand codes */ |
83 | #define NT_TRANSACT_CREATE 0x01 | 96 | #define NT_TRANSACT_CREATE 0x01 |
84 | #define NT_TRANSACT_IOCTL 0x02 | 97 | #define NT_TRANSACT_IOCTL 0x02 |
@@ -328,12 +341,13 @@ | |||
328 | #define CREATE_COMPLETE_IF_OPLK 0x00000100 /* should be zero */ | 341 | #define CREATE_COMPLETE_IF_OPLK 0x00000100 /* should be zero */ |
329 | #define CREATE_NO_EA_KNOWLEDGE 0x00000200 | 342 | #define CREATE_NO_EA_KNOWLEDGE 0x00000200 |
330 | #define CREATE_EIGHT_DOT_THREE 0x00000400 /* doc says this is obsolete | 343 | #define CREATE_EIGHT_DOT_THREE 0x00000400 /* doc says this is obsolete |
331 | open for recovery flag - should | 344 | "open for recovery" flag - should |
332 | be zero */ | 345 | be zero in any case */ |
346 | #define CREATE_OPEN_FOR_RECOVERY 0x00000400 | ||
333 | #define CREATE_RANDOM_ACCESS 0x00000800 | 347 | #define CREATE_RANDOM_ACCESS 0x00000800 |
334 | #define CREATE_DELETE_ON_CLOSE 0x00001000 | 348 | #define CREATE_DELETE_ON_CLOSE 0x00001000 |
335 | #define CREATE_OPEN_BY_ID 0x00002000 | 349 | #define CREATE_OPEN_BY_ID 0x00002000 |
336 | #define CREATE_OPEN_BACKUP_INTN 0x00004000 | 350 | #define CREATE_OPEN_BACKUP_INTENT 0x00004000 |
337 | #define CREATE_NO_COMPRESSION 0x00008000 | 351 | #define CREATE_NO_COMPRESSION 0x00008000 |
338 | #define CREATE_RESERVE_OPFILTER 0x00100000 /* should be zero */ | 352 | #define CREATE_RESERVE_OPFILTER 0x00100000 /* should be zero */ |
339 | #define OPEN_REPARSE_POINT 0x00200000 | 353 | #define OPEN_REPARSE_POINT 0x00200000 |
@@ -722,7 +736,6 @@ typedef struct smb_com_tconx_rsp_ext { | |||
722 | #define SMB_CSC_CACHE_AUTO_REINT 0x0004 | 736 | #define SMB_CSC_CACHE_AUTO_REINT 0x0004 |
723 | #define SMB_CSC_CACHE_VDO 0x0008 | 737 | #define SMB_CSC_CACHE_VDO 0x0008 |
724 | #define SMB_CSC_NO_CACHING 0x000C | 738 | #define SMB_CSC_NO_CACHING 0x000C |
725 | |||
726 | #define SMB_UNIQUE_FILE_NAME 0x0010 | 739 | #define SMB_UNIQUE_FILE_NAME 0x0010 |
727 | #define SMB_EXTENDED_SIGNATURES 0x0020 | 740 | #define SMB_EXTENDED_SIGNATURES 0x0020 |
728 | 741 | ||
@@ -806,7 +819,7 @@ typedef struct smb_com_findclose_req { | |||
806 | #define ICOUNT_MASK 0x00FF | 819 | #define ICOUNT_MASK 0x00FF |
807 | #define PIPE_READ_MODE 0x0100 | 820 | #define PIPE_READ_MODE 0x0100 |
808 | #define NAMED_PIPE_TYPE 0x0400 | 821 | #define NAMED_PIPE_TYPE 0x0400 |
809 | #define PIPE_END_POINT 0x0800 | 822 | #define PIPE_END_POINT 0x4000 |
810 | #define BLOCKING_NAMED_PIPE 0x8000 | 823 | #define BLOCKING_NAMED_PIPE 0x8000 |
811 | 824 | ||
812 | typedef struct smb_com_open_req { /* also handles create */ | 825 | typedef struct smb_com_open_req { /* also handles create */ |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index fb655b4593c6..4511b708f0f3 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -1728,7 +1728,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1728 | { | 1728 | { |
1729 | int rc = 0; | 1729 | int rc = 0; |
1730 | LOCK_REQ *pSMB = NULL; | 1730 | LOCK_REQ *pSMB = NULL; |
1731 | LOCK_RSP *pSMBr = NULL; | 1731 | /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */ |
1732 | int bytes_returned; | 1732 | int bytes_returned; |
1733 | int timeout = 0; | 1733 | int timeout = 0; |
1734 | __u16 count; | 1734 | __u16 count; |
@@ -1739,8 +1739,6 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1739 | if (rc) | 1739 | if (rc) |
1740 | return rc; | 1740 | return rc; |
1741 | 1741 | ||
1742 | pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */ | ||
1743 | |||
1744 | if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) { | 1742 | if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) { |
1745 | timeout = CIFS_ASYNC_OP; /* no response expected */ | 1743 | timeout = CIFS_ASYNC_OP; /* no response expected */ |
1746 | pSMB->Timeout = 0; | 1744 | pSMB->Timeout = 0; |
@@ -1774,7 +1772,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1774 | 1772 | ||
1775 | if (waitFlag) { | 1773 | if (waitFlag) { |
1776 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, | 1774 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, |
1777 | (struct smb_hdr *) pSMBr, &bytes_returned); | 1775 | (struct smb_hdr *) pSMB, &bytes_returned); |
1778 | cifs_small_buf_release(pSMB); | 1776 | cifs_small_buf_release(pSMB); |
1779 | } else { | 1777 | } else { |
1780 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB, | 1778 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB, |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 023434f72c15..e8fa46c7cff2 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -653,6 +653,7 @@ multi_t2_fnd: | |||
653 | spin_lock(&GlobalMid_Lock); | 653 | spin_lock(&GlobalMid_Lock); |
654 | server->tcpStatus = CifsExiting; | 654 | server->tcpStatus = CifsExiting; |
655 | spin_unlock(&GlobalMid_Lock); | 655 | spin_unlock(&GlobalMid_Lock); |
656 | wake_up_all(&server->response_q); | ||
656 | 657 | ||
657 | /* don't exit until kthread_stop is called */ | 658 | /* don't exit until kthread_stop is called */ |
658 | set_current_state(TASK_UNINTERRUPTIBLE); | 659 | set_current_state(TASK_UNINTERRUPTIBLE); |
@@ -2120,6 +2121,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2120 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; | 2121 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; |
2121 | } | 2122 | } |
2122 | 2123 | ||
2124 | if ((volume_info.cifs_acl) && (volume_info.dynperm)) | ||
2125 | cERROR(1, ("mount option dynperm ignored if cifsacl " | ||
2126 | "mount option supported")); | ||
2127 | |||
2123 | tcon = | 2128 | tcon = |
2124 | find_unc(sin_server.sin_addr.s_addr, volume_info.UNC, | 2129 | find_unc(sin_server.sin_addr.s_addr, volume_info.UNC, |
2125 | volume_info.username); | 2130 | volume_info.username); |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index f0b5b5f3dd2e..fb69c1fa85c9 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -260,7 +260,9 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
260 | buf, inode->i_sb, xid, | 260 | buf, inode->i_sb, xid, |
261 | &fileHandle); | 261 | &fileHandle); |
262 | if (newinode) { | 262 | if (newinode) { |
263 | newinode->i_mode = mode; | 263 | if (cifs_sb->mnt_cifs_flags & |
264 | CIFS_MOUNT_DYNPERM) | ||
265 | newinode->i_mode = mode; | ||
264 | if ((oplock & CIFS_CREATE_ACTION) && | 266 | if ((oplock & CIFS_CREATE_ACTION) && |
265 | (cifs_sb->mnt_cifs_flags & | 267 | (cifs_sb->mnt_cifs_flags & |
266 | CIFS_MOUNT_SET_UID)) { | 268 | CIFS_MOUNT_SET_UID)) { |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 8636cec2642c..0aac824371a5 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -546,7 +546,6 @@ int cifs_close(struct inode *inode, struct file *file) | |||
546 | msleep(timeout); | 546 | msleep(timeout); |
547 | timeout *= 8; | 547 | timeout *= 8; |
548 | } | 548 | } |
549 | kfree(pSMBFile->search_resume_name); | ||
550 | kfree(file->private_data); | 549 | kfree(file->private_data); |
551 | file->private_data = NULL; | 550 | file->private_data = NULL; |
552 | } else | 551 | } else |
@@ -605,12 +604,6 @@ int cifs_closedir(struct inode *inode, struct file *file) | |||
605 | else | 604 | else |
606 | cifs_buf_release(ptmp); | 605 | cifs_buf_release(ptmp); |
607 | } | 606 | } |
608 | ptmp = pCFileStruct->search_resume_name; | ||
609 | if (ptmp) { | ||
610 | cFYI(1, ("closedir free resume name")); | ||
611 | pCFileStruct->search_resume_name = NULL; | ||
612 | kfree(ptmp); | ||
613 | } | ||
614 | kfree(file->private_data); | 607 | kfree(file->private_data); |
615 | file->private_data = NULL; | 608 | file->private_data = NULL; |
616 | } | 609 | } |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 129dbfe4dca7..722be543ceec 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -418,6 +418,7 @@ int cifs_get_inode_info(struct inode **pinode, | |||
418 | char *buf = NULL; | 418 | char *buf = NULL; |
419 | bool adjustTZ = false; | 419 | bool adjustTZ = false; |
420 | bool is_dfs_referral = false; | 420 | bool is_dfs_referral = false; |
421 | umode_t default_mode; | ||
421 | 422 | ||
422 | pTcon = cifs_sb->tcon; | 423 | pTcon = cifs_sb->tcon; |
423 | cFYI(1, ("Getting info on %s", full_path)); | 424 | cFYI(1, ("Getting info on %s", full_path)); |
@@ -530,47 +531,42 @@ int cifs_get_inode_info(struct inode **pinode, | |||
530 | inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj; | 531 | inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj; |
531 | } | 532 | } |
532 | 533 | ||
533 | /* set default mode. will override for dirs below */ | 534 | /* get default inode mode */ |
534 | if (atomic_read(&cifsInfo->inUse) == 0) | 535 | if (attr & ATTR_DIRECTORY) |
535 | /* new inode, can safely set these fields */ | 536 | default_mode = cifs_sb->mnt_dir_mode; |
536 | inode->i_mode = cifs_sb->mnt_file_mode; | 537 | else |
537 | else /* since we set the inode type below we need to mask off | 538 | default_mode = cifs_sb->mnt_file_mode; |
538 | to avoid strange results if type changes and both | 539 | |
539 | get orred in */ | 540 | /* set permission bits */ |
540 | inode->i_mode &= ~S_IFMT; | 541 | if (atomic_read(&cifsInfo->inUse) == 0 || |
541 | /* if (attr & ATTR_REPARSE) */ | 542 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) |
542 | /* We no longer handle these as symlinks because we could not | 543 | inode->i_mode = default_mode; |
543 | follow them due to the absolute path with drive letter */ | 544 | else { |
544 | if (attr & ATTR_DIRECTORY) { | 545 | /* just reenable write bits if !ATTR_READONLY */ |
545 | /* override default perms since we do not do byte range locking | 546 | if ((inode->i_mode & S_IWUGO) == 0 && |
546 | on dirs */ | 547 | (attr & ATTR_READONLY) == 0) |
547 | inode->i_mode = cifs_sb->mnt_dir_mode; | 548 | inode->i_mode |= (S_IWUGO & default_mode); |
548 | inode->i_mode |= S_IFDIR; | 549 | inode->i_mode &= ~S_IFMT; |
549 | } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && | 550 | } |
550 | (cifsInfo->cifsAttrs & ATTR_SYSTEM) && | 551 | /* clear write bits if ATTR_READONLY is set */ |
551 | /* No need to le64 convert size of zero */ | 552 | if (attr & ATTR_READONLY) |
552 | (pfindData->EndOfFile == 0)) { | 553 | inode->i_mode &= ~S_IWUGO; |
553 | inode->i_mode = cifs_sb->mnt_file_mode; | 554 | |
554 | inode->i_mode |= S_IFIFO; | 555 | /* set inode type */ |
555 | /* BB Finish for SFU style symlinks and devices */ | 556 | if ((attr & ATTR_SYSTEM) && |
556 | } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && | 557 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) { |
557 | (cifsInfo->cifsAttrs & ATTR_SYSTEM)) { | 558 | /* no need to fix endianness on 0 */ |
558 | if (decode_sfu_inode(inode, le64_to_cpu(pfindData->EndOfFile), | 559 | if (pfindData->EndOfFile == 0) |
559 | full_path, cifs_sb, xid)) | 560 | inode->i_mode |= S_IFIFO; |
560 | cFYI(1, ("Unrecognized sfu inode type")); | 561 | else if (decode_sfu_inode(inode, |
561 | 562 | le64_to_cpu(pfindData->EndOfFile), | |
562 | cFYI(1, ("sfu mode 0%o", inode->i_mode)); | 563 | full_path, cifs_sb, xid)) |
564 | cFYI(1, ("unknown SFU file type\n")); | ||
563 | } else { | 565 | } else { |
564 | inode->i_mode |= S_IFREG; | 566 | if (attr & ATTR_DIRECTORY) |
565 | /* treat dos attribute of read-only as read-only mode eg 555 */ | 567 | inode->i_mode |= S_IFDIR; |
566 | if (cifsInfo->cifsAttrs & ATTR_READONLY) | 568 | else |
567 | inode->i_mode &= ~(S_IWUGO); | 569 | inode->i_mode |= S_IFREG; |
568 | else if ((inode->i_mode & S_IWUGO) == 0) | ||
569 | /* the ATTR_READONLY flag may have been */ | ||
570 | /* changed on server -- set any w bits */ | ||
571 | /* allowed by mnt_file_mode */ | ||
572 | inode->i_mode |= (S_IWUGO & cifs_sb->mnt_file_mode); | ||
573 | /* BB add code to validate if device or weird share or device type? */ | ||
574 | } | 570 | } |
575 | 571 | ||
576 | spin_lock(&inode->i_lock); | 572 | spin_lock(&inode->i_lock); |
@@ -1019,8 +1015,11 @@ mkdir_get_info: | |||
1019 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1015 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1020 | } | 1016 | } |
1021 | if (direntry->d_inode) { | 1017 | if (direntry->d_inode) { |
1022 | direntry->d_inode->i_mode = mode; | 1018 | if (cifs_sb->mnt_cifs_flags & |
1023 | direntry->d_inode->i_mode |= S_IFDIR; | 1019 | CIFS_MOUNT_DYNPERM) |
1020 | direntry->d_inode->i_mode = | ||
1021 | (mode | S_IFDIR); | ||
1022 | |||
1024 | if (cifs_sb->mnt_cifs_flags & | 1023 | if (cifs_sb->mnt_cifs_flags & |
1025 | CIFS_MOUNT_SET_UID) { | 1024 | CIFS_MOUNT_SET_UID) { |
1026 | direntry->d_inode->i_uid = | 1025 | direntry->d_inode->i_uid = |
@@ -1547,13 +1546,26 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1547 | } else | 1546 | } else |
1548 | goto cifs_setattr_exit; | 1547 | goto cifs_setattr_exit; |
1549 | } | 1548 | } |
1550 | if (attrs->ia_valid & ATTR_UID) { | 1549 | |
1551 | cFYI(1, ("UID changed to %d", attrs->ia_uid)); | 1550 | /* |
1552 | uid = attrs->ia_uid; | 1551 | * Without unix extensions we can't send ownership changes to the |
1553 | } | 1552 | * server, so silently ignore them. This is consistent with how |
1554 | if (attrs->ia_valid & ATTR_GID) { | 1553 | * local DOS/Windows filesystems behave (VFAT, NTFS, etc). With |
1555 | cFYI(1, ("GID changed to %d", attrs->ia_gid)); | 1554 | * CIFSACL support + proper Windows to Unix idmapping, we may be |
1556 | gid = attrs->ia_gid; | 1555 | * able to support this in the future. |
1556 | */ | ||
1557 | if (!pTcon->unix_ext && | ||
1558 | !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) { | ||
1559 | attrs->ia_valid &= ~(ATTR_UID | ATTR_GID); | ||
1560 | } else { | ||
1561 | if (attrs->ia_valid & ATTR_UID) { | ||
1562 | cFYI(1, ("UID changed to %d", attrs->ia_uid)); | ||
1563 | uid = attrs->ia_uid; | ||
1564 | } | ||
1565 | if (attrs->ia_valid & ATTR_GID) { | ||
1566 | cFYI(1, ("GID changed to %d", attrs->ia_gid)); | ||
1567 | gid = attrs->ia_gid; | ||
1568 | } | ||
1557 | } | 1569 | } |
1558 | 1570 | ||
1559 | time_buf.Attributes = 0; | 1571 | time_buf.Attributes = 0; |
@@ -1563,7 +1575,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1563 | attrs->ia_valid &= ~ATTR_MODE; | 1575 | attrs->ia_valid &= ~ATTR_MODE; |
1564 | 1576 | ||
1565 | if (attrs->ia_valid & ATTR_MODE) { | 1577 | if (attrs->ia_valid & ATTR_MODE) { |
1566 | cFYI(1, ("Mode changed to 0x%x", attrs->ia_mode)); | 1578 | cFYI(1, ("Mode changed to 0%o", attrs->ia_mode)); |
1567 | mode = attrs->ia_mode; | 1579 | mode = attrs->ia_mode; |
1568 | } | 1580 | } |
1569 | 1581 | ||
@@ -1578,18 +1590,18 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1578 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 1590 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
1579 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) | 1591 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) |
1580 | rc = mode_to_acl(inode, full_path, mode); | 1592 | rc = mode_to_acl(inode, full_path, mode); |
1581 | else if ((mode & S_IWUGO) == 0) { | 1593 | else |
1582 | #else | ||
1583 | if ((mode & S_IWUGO) == 0) { | ||
1584 | #endif | 1594 | #endif |
1585 | /* not writeable */ | 1595 | if (((mode & S_IWUGO) == 0) && |
1586 | if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) { | 1596 | (cifsInode->cifsAttrs & ATTR_READONLY) == 0) { |
1587 | set_dosattr = true; | 1597 | set_dosattr = true; |
1588 | time_buf.Attributes = | 1598 | time_buf.Attributes = cpu_to_le32(cifsInode->cifsAttrs | |
1589 | cpu_to_le32(cifsInode->cifsAttrs | | 1599 | ATTR_READONLY); |
1590 | ATTR_READONLY); | 1600 | /* fix up mode if we're not using dynperm */ |
1591 | } | 1601 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) |
1592 | } else if (cifsInode->cifsAttrs & ATTR_READONLY) { | 1602 | attrs->ia_mode = inode->i_mode & ~S_IWUGO; |
1603 | } else if ((mode & S_IWUGO) && | ||
1604 | (cifsInode->cifsAttrs & ATTR_READONLY)) { | ||
1593 | /* If file is readonly on server, we would | 1605 | /* If file is readonly on server, we would |
1594 | not be able to write to it - so if any write | 1606 | not be able to write to it - so if any write |
1595 | bit is enabled for user or group or other we | 1607 | bit is enabled for user or group or other we |
@@ -1600,6 +1612,20 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1600 | /* Windows ignores set to zero */ | 1612 | /* Windows ignores set to zero */ |
1601 | if (time_buf.Attributes == 0) | 1613 | if (time_buf.Attributes == 0) |
1602 | time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL); | 1614 | time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL); |
1615 | |||
1616 | /* reset local inode permissions to normal */ | ||
1617 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) { | ||
1618 | attrs->ia_mode &= ~(S_IALLUGO); | ||
1619 | if (S_ISDIR(inode->i_mode)) | ||
1620 | attrs->ia_mode |= | ||
1621 | cifs_sb->mnt_dir_mode; | ||
1622 | else | ||
1623 | attrs->ia_mode |= | ||
1624 | cifs_sb->mnt_file_mode; | ||
1625 | } | ||
1626 | } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) { | ||
1627 | /* ignore mode change - ATTR_READONLY hasn't changed */ | ||
1628 | attrs->ia_valid &= ~ATTR_MODE; | ||
1603 | } | 1629 | } |
1604 | } | 1630 | } |
1605 | 1631 | ||
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 1d69b8014e0b..4b17f8fe3157 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
@@ -519,8 +519,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) | |||
519 | pnotify = (struct file_notify_information *) | 519 | pnotify = (struct file_notify_information *) |
520 | ((char *)&pSMBr->hdr.Protocol + data_offset); | 520 | ((char *)&pSMBr->hdr.Protocol + data_offset); |
521 | cFYI(1, ("dnotify on %s Action: 0x%x", | 521 | cFYI(1, ("dnotify on %s Action: 0x%x", |
522 | pnotify->FileName, | 522 | pnotify->FileName, pnotify->Action)); |
523 | pnotify->Action)); /* BB removeme BB */ | ||
524 | /* cifs_dump_mem("Rcvd notify Data: ",buf, | 523 | /* cifs_dump_mem("Rcvd notify Data: ",buf, |
525 | sizeof(struct smb_hdr)+60); */ | 524 | sizeof(struct smb_hdr)+60); */ |
526 | return true; | 525 | return true; |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 713c25110197..83f306954883 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -132,6 +132,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, | |||
132 | __u32 attr; | 132 | __u32 attr; |
133 | __u64 allocation_size; | 133 | __u64 allocation_size; |
134 | __u64 end_of_file; | 134 | __u64 end_of_file; |
135 | umode_t default_mode; | ||
135 | 136 | ||
136 | /* save mtime and size */ | 137 | /* save mtime and size */ |
137 | local_mtime = tmp_inode->i_mtime; | 138 | local_mtime = tmp_inode->i_mtime; |
@@ -187,48 +188,54 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, | |||
187 | if (atomic_read(&cifsInfo->inUse) == 0) { | 188 | if (atomic_read(&cifsInfo->inUse) == 0) { |
188 | tmp_inode->i_uid = cifs_sb->mnt_uid; | 189 | tmp_inode->i_uid = cifs_sb->mnt_uid; |
189 | tmp_inode->i_gid = cifs_sb->mnt_gid; | 190 | tmp_inode->i_gid = cifs_sb->mnt_gid; |
190 | /* set default mode. will override for dirs below */ | 191 | } |
191 | tmp_inode->i_mode = cifs_sb->mnt_file_mode; | 192 | |
192 | } else { | 193 | if (attr & ATTR_DIRECTORY) |
193 | /* mask off the type bits since it gets set | 194 | default_mode = cifs_sb->mnt_dir_mode; |
194 | below and we do not want to get two type | 195 | else |
195 | bits set */ | 196 | default_mode = cifs_sb->mnt_file_mode; |
197 | |||
198 | /* set initial permissions */ | ||
199 | if ((atomic_read(&cifsInfo->inUse) == 0) || | ||
200 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) | ||
201 | tmp_inode->i_mode = default_mode; | ||
202 | else { | ||
203 | /* just reenable write bits if !ATTR_READONLY */ | ||
204 | if ((tmp_inode->i_mode & S_IWUGO) == 0 && | ||
205 | (attr & ATTR_READONLY) == 0) | ||
206 | tmp_inode->i_mode |= (S_IWUGO & default_mode); | ||
207 | |||
196 | tmp_inode->i_mode &= ~S_IFMT; | 208 | tmp_inode->i_mode &= ~S_IFMT; |
197 | } | 209 | } |
198 | 210 | ||
199 | if (attr & ATTR_DIRECTORY) { | 211 | /* clear write bits if ATTR_READONLY is set */ |
200 | *pobject_type = DT_DIR; | 212 | if (attr & ATTR_READONLY) |
201 | /* override default perms since we do not lock dirs */ | 213 | tmp_inode->i_mode &= ~S_IWUGO; |
202 | if (atomic_read(&cifsInfo->inUse) == 0) | 214 | |
203 | tmp_inode->i_mode = cifs_sb->mnt_dir_mode; | 215 | /* set inode type */ |
204 | tmp_inode->i_mode |= S_IFDIR; | 216 | if ((attr & ATTR_SYSTEM) && |
205 | } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && | 217 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) { |
206 | (attr & ATTR_SYSTEM)) { | ||
207 | if (end_of_file == 0) { | 218 | if (end_of_file == 0) { |
208 | *pobject_type = DT_FIFO; | ||
209 | tmp_inode->i_mode |= S_IFIFO; | 219 | tmp_inode->i_mode |= S_IFIFO; |
220 | *pobject_type = DT_FIFO; | ||
210 | } else { | 221 | } else { |
211 | /* rather than get the type here, we mark the | 222 | /* |
212 | inode as needing revalidate and get the real type | 223 | * trying to get the type can be slow, so just call |
213 | (blk vs chr vs. symlink) later ie in lookup */ | 224 | * this a regular file for now, and mark for reval |
214 | *pobject_type = DT_REG; | 225 | */ |
215 | tmp_inode->i_mode |= S_IFREG; | 226 | tmp_inode->i_mode |= S_IFREG; |
227 | *pobject_type = DT_REG; | ||
216 | cifsInfo->time = 0; | 228 | cifsInfo->time = 0; |
217 | } | 229 | } |
218 | /* we no longer mark these because we could not follow them */ | ||
219 | /* } else if (attr & ATTR_REPARSE) { | ||
220 | *pobject_type = DT_LNK; | ||
221 | tmp_inode->i_mode |= S_IFLNK; */ | ||
222 | } else { | 230 | } else { |
223 | *pobject_type = DT_REG; | 231 | if (attr & ATTR_DIRECTORY) { |
224 | tmp_inode->i_mode |= S_IFREG; | 232 | tmp_inode->i_mode |= S_IFDIR; |
225 | if (attr & ATTR_READONLY) | 233 | *pobject_type = DT_DIR; |
226 | tmp_inode->i_mode &= ~(S_IWUGO); | 234 | } else { |
227 | else if ((tmp_inode->i_mode & S_IWUGO) == 0) | 235 | tmp_inode->i_mode |= S_IFREG; |
228 | /* the ATTR_READONLY flag may have been changed on */ | 236 | *pobject_type = DT_REG; |
229 | /* server -- set any w bits allowed by mnt_file_mode */ | 237 | } |
230 | tmp_inode->i_mode |= (S_IWUGO & cifs_sb->mnt_file_mode); | 238 | } |
231 | } /* could add code here - to validate if device or weird share type? */ | ||
232 | 239 | ||
233 | /* can not fill in nlink here as in qpathinfo version and Unx search */ | 240 | /* can not fill in nlink here as in qpathinfo version and Unx search */ |
234 | if (atomic_read(&cifsInfo->inUse) == 0) | 241 | if (atomic_read(&cifsInfo->inUse) == 0) |
@@ -675,8 +682,6 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, | |||
675 | cifsFile->invalidHandle = true; | 682 | cifsFile->invalidHandle = true; |
676 | CIFSFindClose(xid, pTcon, cifsFile->netfid); | 683 | CIFSFindClose(xid, pTcon, cifsFile->netfid); |
677 | } | 684 | } |
678 | kfree(cifsFile->search_resume_name); | ||
679 | cifsFile->search_resume_name = NULL; | ||
680 | if (cifsFile->srch_inf.ntwrk_buf_start) { | 685 | if (cifsFile->srch_inf.ntwrk_buf_start) { |
681 | cFYI(1, ("freeing SMB ff cache buf on search rewind")); | 686 | cFYI(1, ("freeing SMB ff cache buf on search rewind")); |
682 | if (cifsFile->srch_inf.smallBuf) | 687 | if (cifsFile->srch_inf.smallBuf) |
@@ -1043,9 +1048,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) | |||
1043 | } /* else { | 1048 | } /* else { |
1044 | cifsFile->invalidHandle = true; | 1049 | cifsFile->invalidHandle = true; |
1045 | CIFSFindClose(xid, pTcon, cifsFile->netfid); | 1050 | CIFSFindClose(xid, pTcon, cifsFile->netfid); |
1046 | } | 1051 | } */ |
1047 | kfree(cifsFile->search_resume_name); | ||
1048 | cifsFile->search_resume_name = NULL; */ | ||
1049 | 1052 | ||
1050 | rc = find_cifs_entry(xid, pTcon, file, | 1053 | rc = find_cifs_entry(xid, pTcon, file, |
1051 | ¤t_entry, &num_to_fill); | 1054 | ¤t_entry, &num_to_fill); |