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