Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
[CIFS] don't allow demultiplex thread to exit until kthread_stop is called
[CIFS] when not using unix extensions, check for and set ATTR_READONLY on create and mkdir
[CIFS] add local struct inode pointer to cifs_setattr
[CIFS] cifs_find_tcp_session cleanup

+80 -65
+1
fs/cifs/cifspdu.h
··· 340 #define OPEN_NO_RECALL 0x00400000 341 #define OPEN_FREE_SPACE_QUERY 0x00800000 /* should be zero */ 342 #define CREATE_OPTIONS_MASK 0x007FFFFF 343 #define CREATE_OPTION_SPECIAL 0x20000000 /* system. NB not sent over wire */ 344 345 /* ImpersonationLevel flags */
··· 340 #define OPEN_NO_RECALL 0x00400000 341 #define OPEN_FREE_SPACE_QUERY 0x00800000 /* should be zero */ 342 #define CREATE_OPTIONS_MASK 0x007FFFFF 343 + #define CREATE_OPTION_READONLY 0x10000000 344 #define CREATE_OPTION_SPECIAL 0x20000000 /* system. NB not sent over wire */ 345 346 /* ImpersonationLevel flags */
+6 -10
fs/cifs/cifssmb.c
··· 1224 else /* BB FIXME BB */ 1225 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); 1226 1227 - /* if ((omode & S_IWUGO) == 0) 1228 - pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/ 1229 - /* Above line causes problems due to vfs splitting create into two 1230 - pieces - need to set mode after file created not while it is 1231 - being created */ 1232 1233 /* BB FIXME BB */ 1234 /* pSMB->CreateOptions = cpu_to_le32(create_options & ··· 1328 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM); 1329 else 1330 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL); 1331 /* XP does not handle ATTR_POSIX_SEMANTICS */ 1332 /* but it helps speed up case sensitive checks for other 1333 servers such as Samba */ 1334 if (tcon->ses->capabilities & CAP_UNIX) 1335 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS); 1336 1337 - /* if ((omode & S_IWUGO) == 0) 1338 - pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/ 1339 - /* Above line causes problems due to vfs splitting create into two 1340 - pieces - need to set mode after file created not while it is 1341 - being created */ 1342 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); 1343 pSMB->CreateDisposition = cpu_to_le32(openDisposition); 1344 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
··· 1224 else /* BB FIXME BB */ 1225 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); 1226 1227 + if (create_options & CREATE_OPTION_READONLY) 1228 + pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY); 1229 1230 /* BB FIXME BB */ 1231 /* pSMB->CreateOptions = cpu_to_le32(create_options & ··· 1331 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM); 1332 else 1333 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL); 1334 + 1335 /* XP does not handle ATTR_POSIX_SEMANTICS */ 1336 /* but it helps speed up case sensitive checks for other 1337 servers such as Samba */ 1338 if (tcon->ses->capabilities & CAP_UNIX) 1339 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS); 1340 1341 + if (create_options & CREATE_OPTION_READONLY) 1342 + pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY); 1343 + 1344 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); 1345 pSMB->CreateDisposition = cpu_to_le32(openDisposition); 1346 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
+39 -38
fs/cifs/connect.c
··· 348 int reconnect; 349 350 current->flags |= PF_MEMALLOC; 351 - server->tsk = current; /* save process info to wake at shutdown */ 352 cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current))); 353 write_lock(&GlobalSMBSeslock); 354 atomic_inc(&tcpSesAllocCount); ··· 650 651 spin_lock(&GlobalMid_Lock); 652 server->tcpStatus = CifsExiting; 653 - server->tsk = NULL; 654 /* check if we have blocked requests that need to free */ 655 /* Note that cifs_max_pending is normally 50, but 656 can be set at module install time to as little as two */ 657 if (atomic_read(&server->inFlight) >= cifs_max_pending) 658 atomic_set(&server->inFlight, cifs_max_pending - 1); 659 /* We do not want to set the max_pending too low or we ··· 1327 1328 static struct cifsSesInfo * 1329 cifs_find_tcp_session(struct in_addr *target_ip_addr, 1330 - struct in6_addr *target_ip6_addr, 1331 - char *userName, struct TCP_Server_Info **psrvTcp) 1332 { 1333 struct list_head *tmp; 1334 struct cifsSesInfo *ses; 1335 - *psrvTcp = NULL; 1336 - read_lock(&GlobalSMBSeslock); 1337 1338 list_for_each(tmp, &GlobalSMBSessionList) { 1339 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); 1340 - if (ses->server) { 1341 - if ((target_ip_addr && 1342 - (ses->server->addr.sockAddr.sin_addr.s_addr 1343 - == target_ip_addr->s_addr)) || (target_ip6_addr 1344 - && memcmp(&ses->server->addr.sockAddr6.sin6_addr, 1345 - target_ip6_addr, sizeof(*target_ip6_addr)))) { 1346 - /* BB lock server and tcp session and increment 1347 - use count here?? */ 1348 1349 - /* found a match on the TCP session */ 1350 - *psrvTcp = ses->server; 1351 1352 - /* BB check if reconnection needed */ 1353 - if (strncmp 1354 - (ses->userName, userName, 1355 - MAX_USERNAME_SIZE) == 0){ 1356 - read_unlock(&GlobalSMBSeslock); 1357 - /* Found exact match on both TCP and 1358 - SMB sessions */ 1359 - return ses; 1360 - } 1361 - } 1362 } 1363 /* else tcp and smb sessions need reconnection */ 1364 } 1365 read_unlock(&GlobalSMBSeslock); 1366 return NULL; 1367 } 1368 ··· 2196 srvTcp->tcpStatus = CifsExiting; 2197 spin_unlock(&GlobalMid_Lock); 2198 if (srvTcp->tsk) { 2199 - struct task_struct *tsk; 2200 /* If we could verify that kthread_stop would 2201 always wake up processes blocked in 2202 tcp in recv_mesg then we could remove the 2203 send_sig call */ 2204 force_sig(SIGKILL, srvTcp->tsk); 2205 - tsk = srvTcp->tsk; 2206 - if (tsk) 2207 - kthread_stop(tsk); 2208 } 2209 } 2210 /* If find_unc succeeded then rc == 0 so we can not end */ ··· 2217 if ((temp_rc == -ESHUTDOWN) && 2218 (pSesInfo->server) && 2219 (pSesInfo->server->tsk)) { 2220 - struct task_struct *tsk; 2221 force_sig(SIGKILL, 2222 pSesInfo->server->tsk); 2223 - tsk = pSesInfo->server->tsk; 2224 - if (tsk) 2225 - kthread_stop(tsk); 2226 } 2227 } else { 2228 cFYI(1, ("No session or bad tcon")); 2229 if ((pSesInfo->server) && 2230 (pSesInfo->server->tsk)) { 2231 - struct task_struct *tsk; 2232 force_sig(SIGKILL, 2233 pSesInfo->server->tsk); 2234 - tsk = pSesInfo->server->tsk; 2235 - if (tsk) 2236 - kthread_stop(tsk); 2237 } 2238 } 2239 sesInfoFree(pSesInfo);
··· 348 int reconnect; 349 350 current->flags |= PF_MEMALLOC; 351 cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current))); 352 write_lock(&GlobalSMBSeslock); 353 atomic_inc(&tcpSesAllocCount); ··· 651 652 spin_lock(&GlobalMid_Lock); 653 server->tcpStatus = CifsExiting; 654 + spin_unlock(&GlobalMid_Lock); 655 + 656 + /* don't exit until kthread_stop is called */ 657 + set_current_state(TASK_UNINTERRUPTIBLE); 658 + while (!kthread_should_stop()) { 659 + schedule(); 660 + set_current_state(TASK_UNINTERRUPTIBLE); 661 + } 662 + set_current_state(TASK_RUNNING); 663 + 664 /* check if we have blocked requests that need to free */ 665 /* Note that cifs_max_pending is normally 50, but 666 can be set at module install time to as little as two */ 667 + spin_lock(&GlobalMid_Lock); 668 if (atomic_read(&server->inFlight) >= cifs_max_pending) 669 atomic_set(&server->inFlight, cifs_max_pending - 1); 670 /* We do not want to set the max_pending too low or we ··· 1318 1319 static struct cifsSesInfo * 1320 cifs_find_tcp_session(struct in_addr *target_ip_addr, 1321 + struct in6_addr *target_ip6_addr, 1322 + char *userName, struct TCP_Server_Info **psrvTcp) 1323 { 1324 struct list_head *tmp; 1325 struct cifsSesInfo *ses; 1326 1327 + *psrvTcp = NULL; 1328 + 1329 + read_lock(&GlobalSMBSeslock); 1330 list_for_each(tmp, &GlobalSMBSessionList) { 1331 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); 1332 + if (!ses->server) 1333 + continue; 1334 1335 + if (target_ip_addr && 1336 + ses->server->addr.sockAddr.sin_addr.s_addr != target_ip_addr->s_addr) 1337 + continue; 1338 + else if (target_ip6_addr && 1339 + memcmp(&ses->server->addr.sockAddr6.sin6_addr, 1340 + target_ip6_addr, sizeof(*target_ip6_addr))) 1341 + continue; 1342 + /* BB lock server and tcp session; increment use count here?? */ 1343 1344 + /* found a match on the TCP session */ 1345 + *psrvTcp = ses->server; 1346 + 1347 + /* BB check if reconnection needed */ 1348 + if (strncmp(ses->userName, userName, MAX_USERNAME_SIZE) == 0) { 1349 + read_unlock(&GlobalSMBSeslock); 1350 + /* Found exact match on both TCP and 1351 + SMB sessions */ 1352 + return ses; 1353 } 1354 /* else tcp and smb sessions need reconnection */ 1355 } 1356 read_unlock(&GlobalSMBSeslock); 1357 + 1358 return NULL; 1359 } 1360 ··· 2186 srvTcp->tcpStatus = CifsExiting; 2187 spin_unlock(&GlobalMid_Lock); 2188 if (srvTcp->tsk) { 2189 /* If we could verify that kthread_stop would 2190 always wake up processes blocked in 2191 tcp in recv_mesg then we could remove the 2192 send_sig call */ 2193 force_sig(SIGKILL, srvTcp->tsk); 2194 + kthread_stop(srvTcp->tsk); 2195 } 2196 } 2197 /* If find_unc succeeded then rc == 0 so we can not end */ ··· 2210 if ((temp_rc == -ESHUTDOWN) && 2211 (pSesInfo->server) && 2212 (pSesInfo->server->tsk)) { 2213 force_sig(SIGKILL, 2214 pSesInfo->server->tsk); 2215 + kthread_stop(pSesInfo->server->tsk); 2216 } 2217 } else { 2218 cFYI(1, ("No session or bad tcon")); 2219 if ((pSesInfo->server) && 2220 (pSesInfo->server->tsk)) { 2221 force_sig(SIGKILL, 2222 pSesInfo->server->tsk); 2223 + kthread_stop(pSesInfo->server->tsk); 2224 } 2225 } 2226 sesInfoFree(pSesInfo);
+13 -3
fs/cifs/dir.c
··· 119 { 120 int rc = -ENOENT; 121 int xid; 122 int oplock = 0; 123 int desiredAccess = GENERIC_READ | GENERIC_WRITE; 124 __u16 fileHandle; ··· 177 FreeXid(xid); 178 return -ENOMEM; 179 } 180 if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) 181 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, 182 - desiredAccess, CREATE_NOT_DIR, 183 &fileHandle, &oplock, buf, cifs_sb->local_nls, 184 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 185 else ··· 198 if (rc == -EIO) { 199 /* old server, retry the open legacy style */ 200 rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, 201 - desiredAccess, CREATE_NOT_DIR, 202 &fileHandle, &oplock, buf, cifs_sb->local_nls, 203 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 204 } ··· 208 /* If Open reported that we actually created a file 209 then we now have to set the mode if possible */ 210 if ((pTcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) { 211 - mode &= ~current->fs->umask; 212 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 213 CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, 214 (__u64)current->fsuid,
··· 119 { 120 int rc = -ENOENT; 121 int xid; 122 + int create_options = CREATE_NOT_DIR; 123 int oplock = 0; 124 int desiredAccess = GENERIC_READ | GENERIC_WRITE; 125 __u16 fileHandle; ··· 176 FreeXid(xid); 177 return -ENOMEM; 178 } 179 + 180 + mode &= ~current->fs->umask; 181 + 182 + /* 183 + * if we're not using unix extensions, see if we need to set 184 + * ATTR_READONLY on the create call 185 + */ 186 + if (!pTcon->unix_ext && (mode & S_IWUGO) == 0) 187 + create_options |= CREATE_OPTION_READONLY; 188 + 189 if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) 190 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, 191 + desiredAccess, create_options, 192 &fileHandle, &oplock, buf, cifs_sb->local_nls, 193 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 194 else ··· 187 if (rc == -EIO) { 188 /* old server, retry the open legacy style */ 189 rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, 190 + desiredAccess, create_options, 191 &fileHandle, &oplock, buf, cifs_sb->local_nls, 192 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 193 } ··· 197 /* If Open reported that we actually created a file 198 then we now have to set the mode if possible */ 199 if ((pTcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) { 200 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 201 CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, 202 (__u64)current->fsuid,
+21 -14
fs/cifs/inode.c
··· 974 * failed to get it from the server or was set bogus */ 975 if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2)) 976 direntry->d_inode->i_nlink = 2; 977 if (pTcon->unix_ext) { 978 - mode &= ~current->fs->umask; 979 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 980 CIFSSMBUnixSetPerms(xid, pTcon, full_path, 981 mode, ··· 994 CIFS_MOUNT_MAP_SPECIAL_CHR); 995 } 996 } else { 997 - /* BB to be implemented via Windows secrty descriptors 998 - eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, 999 - -1, -1, local_nls); */ 1000 if (direntry->d_inode) { 1001 direntry->d_inode->i_mode = mode; 1002 direntry->d_inode->i_mode |= S_IFDIR; ··· 1415 __u64 uid = 0xFFFFFFFFFFFFFFFFULL; 1416 __u64 gid = 0xFFFFFFFFFFFFFFFFULL; 1417 struct cifsInodeInfo *cifsInode; 1418 1419 xid = GetXid(); 1420 1421 cFYI(1, ("setattr on file %s attrs->iavalid 0x%x", 1422 direntry->d_name.name, attrs->ia_valid)); 1423 1424 - cifs_sb = CIFS_SB(direntry->d_inode->i_sb); 1425 pTcon = cifs_sb->tcon; 1426 1427 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { 1428 /* check if we have permission to change attrs */ 1429 - rc = inode_change_ok(direntry->d_inode, attrs); 1430 if (rc < 0) { 1431 FreeXid(xid); 1432 return rc; ··· 1440 FreeXid(xid); 1441 return -ENOMEM; 1442 } 1443 - cifsInode = CIFS_I(direntry->d_inode); 1444 1445 if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) { 1446 /* ··· 1451 will be truncated anyway? Also, should we error out here if 1452 the flush returns error? 1453 */ 1454 - rc = filemap_write_and_wait(direntry->d_inode->i_mapping); 1455 if (rc != 0) { 1456 - CIFS_I(direntry->d_inode)->write_behind_rc = rc; 1457 rc = 0; 1458 } 1459 } ··· 1529 */ 1530 1531 if (rc == 0) { 1532 - rc = cifs_vmtruncate(direntry->d_inode, attrs->ia_size); 1533 - cifs_truncate_page(direntry->d_inode->i_mapping, 1534 - direntry->d_inode->i_size); 1535 } else 1536 goto cifs_setattr_exit; 1537 } ··· 1564 rc = 0; 1565 #ifdef CONFIG_CIFS_EXPERIMENTAL 1566 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) 1567 - rc = mode_to_acl(direntry->d_inode, full_path, mode); 1568 else if ((mode & S_IWUGO) == 0) { 1569 #else 1570 if ((mode & S_IWUGO) == 0) { ··· 1672 /* do not need local check to inode_check_ok since the server does 1673 that */ 1674 if (!rc) 1675 - rc = inode_setattr(direntry->d_inode, attrs); 1676 cifs_setattr_exit: 1677 kfree(full_path); 1678 FreeXid(xid);
··· 974 * failed to get it from the server or was set bogus */ 975 if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2)) 976 direntry->d_inode->i_nlink = 2; 977 + mode &= ~current->fs->umask; 978 if (pTcon->unix_ext) { 979 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 980 CIFSSMBUnixSetPerms(xid, pTcon, full_path, 981 mode, ··· 994 CIFS_MOUNT_MAP_SPECIAL_CHR); 995 } 996 } else { 997 + if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) && 998 + (mode & S_IWUGO) == 0) { 999 + FILE_BASIC_INFO pInfo; 1000 + memset(&pInfo, 0, sizeof(pInfo)); 1001 + pInfo.Attributes = cpu_to_le32(ATTR_READONLY); 1002 + CIFSSMBSetTimes(xid, pTcon, full_path, 1003 + &pInfo, cifs_sb->local_nls, 1004 + cifs_sb->mnt_cifs_flags & 1005 + CIFS_MOUNT_MAP_SPECIAL_CHR); 1006 + } 1007 if (direntry->d_inode) { 1008 direntry->d_inode->i_mode = mode; 1009 direntry->d_inode->i_mode |= S_IFDIR; ··· 1408 __u64 uid = 0xFFFFFFFFFFFFFFFFULL; 1409 __u64 gid = 0xFFFFFFFFFFFFFFFFULL; 1410 struct cifsInodeInfo *cifsInode; 1411 + struct inode *inode = direntry->d_inode; 1412 1413 xid = GetXid(); 1414 1415 cFYI(1, ("setattr on file %s attrs->iavalid 0x%x", 1416 direntry->d_name.name, attrs->ia_valid)); 1417 1418 + cifs_sb = CIFS_SB(inode->i_sb); 1419 pTcon = cifs_sb->tcon; 1420 1421 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { 1422 /* check if we have permission to change attrs */ 1423 + rc = inode_change_ok(inode, attrs); 1424 if (rc < 0) { 1425 FreeXid(xid); 1426 return rc; ··· 1432 FreeXid(xid); 1433 return -ENOMEM; 1434 } 1435 + cifsInode = CIFS_I(inode); 1436 1437 if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) { 1438 /* ··· 1443 will be truncated anyway? Also, should we error out here if 1444 the flush returns error? 1445 */ 1446 + rc = filemap_write_and_wait(inode->i_mapping); 1447 if (rc != 0) { 1448 + cifsInode->write_behind_rc = rc; 1449 rc = 0; 1450 } 1451 } ··· 1521 */ 1522 1523 if (rc == 0) { 1524 + rc = cifs_vmtruncate(inode, attrs->ia_size); 1525 + cifs_truncate_page(inode->i_mapping, inode->i_size); 1526 } else 1527 goto cifs_setattr_exit; 1528 } ··· 1557 rc = 0; 1558 #ifdef CONFIG_CIFS_EXPERIMENTAL 1559 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) 1560 + rc = mode_to_acl(inode, full_path, mode); 1561 else if ((mode & S_IWUGO) == 0) { 1562 #else 1563 if ((mode & S_IWUGO) == 0) { ··· 1665 /* do not need local check to inode_check_ok since the server does 1666 that */ 1667 if (!rc) 1668 + rc = inode_setattr(inode, attrs); 1669 cifs_setattr_exit: 1670 kfree(full_path); 1671 FreeXid(xid);