Skip to content

Commit 542dafa

Browse files
committed
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
2 parents 9404ef0 + e691b9d commit 542dafa

File tree

5 files changed

+81
-66
lines changed

5 files changed

+81
-66
lines changed

fs/cifs/cifspdu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@
340340
#define OPEN_NO_RECALL 0x00400000
341341
#define OPEN_FREE_SPACE_QUERY 0x00800000 /* should be zero */
342342
#define CREATE_OPTIONS_MASK 0x007FFFFF
343+
#define CREATE_OPTION_READONLY 0x10000000
343344
#define CREATE_OPTION_SPECIAL 0x20000000 /* system. NB not sent over wire */
344345

345346
/* ImpersonationLevel flags */

fs/cifs/cifssmb.c

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,11 +1224,8 @@ SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
12241224
else /* BB FIXME BB */
12251225
pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
12261226

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);
12321229

12331230
/* BB FIXME BB */
12341231
/* pSMB->CreateOptions = cpu_to_le32(create_options &
@@ -1331,17 +1328,16 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
13311328
pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
13321329
else
13331330
pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1331+
13341332
/* XP does not handle ATTR_POSIX_SEMANTICS */
13351333
/* but it helps speed up case sensitive checks for other
13361334
servers such as Samba */
13371335
if (tcon->ses->capabilities & CAP_UNIX)
13381336
pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
13391337

1340-
/* if ((omode & S_IWUGO) == 0)
1341-
pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1342-
/* Above line causes problems due to vfs splitting create into two
1343-
pieces - need to set mode after file created not while it is
1344-
being created */
1338+
if (create_options & CREATE_OPTION_READONLY)
1339+
pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1340+
13451341
pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
13461342
pSMB->CreateDisposition = cpu_to_le32(openDisposition);
13471343
pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);

fs/cifs/connect.c

Lines changed: 40 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,6 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
348348
int reconnect;
349349

350350
current->flags |= PF_MEMALLOC;
351-
server->tsk = current; /* save process info to wake at shutdown */
352351
cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current)));
353352
write_lock(&GlobalSMBSeslock);
354353
atomic_inc(&tcpSesAllocCount);
@@ -651,10 +650,20 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
651650

652651
spin_lock(&GlobalMid_Lock);
653652
server->tcpStatus = CifsExiting;
654-
server->tsk = NULL;
653+
spin_unlock(&GlobalMid_Lock);
654+
655+
/* don't exit until kthread_stop is called */
656+
set_current_state(TASK_UNINTERRUPTIBLE);
657+
while (!kthread_should_stop()) {
658+
schedule();
659+
set_current_state(TASK_UNINTERRUPTIBLE);
660+
}
661+
set_current_state(TASK_RUNNING);
662+
655663
/* check if we have blocked requests that need to free */
656664
/* Note that cifs_max_pending is normally 50, but
657665
can be set at module install time to as little as two */
666+
spin_lock(&GlobalMid_Lock);
658667
if (atomic_read(&server->inFlight) >= cifs_max_pending)
659668
atomic_set(&server->inFlight, cifs_max_pending - 1);
660669
/* We do not want to set the max_pending too low or we
@@ -1318,42 +1327,43 @@ cifs_parse_mount_options(char *options, const char *devname,
13181327

13191328
static struct cifsSesInfo *
13201329
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)
1330+
struct in6_addr *target_ip6_addr,
1331+
char *userName, struct TCP_Server_Info **psrvTcp)
13231332
{
13241333
struct list_head *tmp;
13251334
struct cifsSesInfo *ses;
1335+
13261336
*psrvTcp = NULL;
1327-
read_lock(&GlobalSMBSeslock);
13281337

1338+
read_lock(&GlobalSMBSeslock);
13291339
list_for_each(tmp, &GlobalSMBSessionList) {
13301340
ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
1331-
if (ses->server) {
1332-
if ((target_ip_addr &&
1333-
(ses->server->addr.sockAddr.sin_addr.s_addr
1334-
== target_ip_addr->s_addr)) || (target_ip6_addr
1335-
&& memcmp(&ses->server->addr.sockAddr6.sin6_addr,
1336-
target_ip6_addr, sizeof(*target_ip6_addr)))) {
1337-
/* BB lock server and tcp session and increment
1338-
use count here?? */
1339-
1340-
/* found a match on the TCP session */
1341-
*psrvTcp = ses->server;
1342-
1343-
/* BB check if reconnection needed */
1344-
if (strncmp
1345-
(ses->userName, userName,
1346-
MAX_USERNAME_SIZE) == 0){
1347-
read_unlock(&GlobalSMBSeslock);
1348-
/* Found exact match on both TCP and
1349-
SMB sessions */
1350-
return ses;
1351-
}
1352-
}
1341+
if (!ses->server)
1342+
continue;
1343+
1344+
if (target_ip_addr &&
1345+
ses->server->addr.sockAddr.sin_addr.s_addr != target_ip_addr->s_addr)
1346+
continue;
1347+
else if (target_ip6_addr &&
1348+
memcmp(&ses->server->addr.sockAddr6.sin6_addr,
1349+
target_ip6_addr, sizeof(*target_ip6_addr)))
1350+
continue;
1351+
/* BB lock server and tcp session; increment use count here?? */
1352+
1353+
/* found a match on the TCP session */
1354+
*psrvTcp = ses->server;
1355+
1356+
/* BB check if reconnection needed */
1357+
if (strncmp(ses->userName, userName, MAX_USERNAME_SIZE) == 0) {
1358+
read_unlock(&GlobalSMBSeslock);
1359+
/* Found exact match on both TCP and
1360+
SMB sessions */
1361+
return ses;
13531362
}
13541363
/* else tcp and smb sessions need reconnection */
13551364
}
13561365
read_unlock(&GlobalSMBSeslock);
1366+
13571367
return NULL;
13581368
}
13591369

@@ -2186,15 +2196,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
21862196
srvTcp->tcpStatus = CifsExiting;
21872197
spin_unlock(&GlobalMid_Lock);
21882198
if (srvTcp->tsk) {
2189-
struct task_struct *tsk;
21902199
/* If we could verify that kthread_stop would
21912200
always wake up processes blocked in
21922201
tcp in recv_mesg then we could remove the
21932202
send_sig call */
21942203
force_sig(SIGKILL, srvTcp->tsk);
2195-
tsk = srvTcp->tsk;
2196-
if (tsk)
2197-
kthread_stop(tsk);
2204+
kthread_stop(srvTcp->tsk);
21982205
}
21992206
}
22002207
/* If find_unc succeeded then rc == 0 so we can not end */
@@ -2210,23 +2217,17 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
22102217
if ((temp_rc == -ESHUTDOWN) &&
22112218
(pSesInfo->server) &&
22122219
(pSesInfo->server->tsk)) {
2213-
struct task_struct *tsk;
22142220
force_sig(SIGKILL,
22152221
pSesInfo->server->tsk);
2216-
tsk = pSesInfo->server->tsk;
2217-
if (tsk)
2218-
kthread_stop(tsk);
2222+
kthread_stop(pSesInfo->server->tsk);
22192223
}
22202224
} else {
22212225
cFYI(1, ("No session or bad tcon"));
22222226
if ((pSesInfo->server) &&
22232227
(pSesInfo->server->tsk)) {
2224-
struct task_struct *tsk;
22252228
force_sig(SIGKILL,
22262229
pSesInfo->server->tsk);
2227-
tsk = pSesInfo->server->tsk;
2228-
if (tsk)
2229-
kthread_stop(tsk);
2230+
kthread_stop(pSesInfo->server->tsk);
22302231
}
22312232
}
22322233
sesInfoFree(pSesInfo);

fs/cifs/dir.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
119119
{
120120
int rc = -ENOENT;
121121
int xid;
122+
int create_options = CREATE_NOT_DIR;
122123
int oplock = 0;
123124
int desiredAccess = GENERIC_READ | GENERIC_WRITE;
124125
__u16 fileHandle;
@@ -176,9 +177,19 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
176177
FreeXid(xid);
177178
return -ENOMEM;
178179
}
180+
181+
mode &= ~current->fs->umask;
182+
183+
/*
184+
* if we're not using unix extensions, see if we need to set
185+
* ATTR_READONLY on the create call
186+
*/
187+
if (!pTcon->unix_ext && (mode & S_IWUGO) == 0)
188+
create_options |= CREATE_OPTION_READONLY;
189+
179190
if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
180191
rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
181-
desiredAccess, CREATE_NOT_DIR,
192+
desiredAccess, create_options,
182193
&fileHandle, &oplock, buf, cifs_sb->local_nls,
183194
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
184195
else
@@ -187,7 +198,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
187198
if (rc == -EIO) {
188199
/* old server, retry the open legacy style */
189200
rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
190-
desiredAccess, CREATE_NOT_DIR,
201+
desiredAccess, create_options,
191202
&fileHandle, &oplock, buf, cifs_sb->local_nls,
192203
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
193204
}
@@ -197,7 +208,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
197208
/* If Open reported that we actually created a file
198209
then we now have to set the mode if possible */
199210
if ((pTcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
200-
mode &= ~current->fs->umask;
201211
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
202212
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
203213
(__u64)current->fsuid,

fs/cifs/inode.c

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -974,8 +974,8 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
974974
* failed to get it from the server or was set bogus */
975975
if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
976976
direntry->d_inode->i_nlink = 2;
977+
mode &= ~current->fs->umask;
977978
if (pTcon->unix_ext) {
978-
mode &= ~current->fs->umask;
979979
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
980980
CIFSSMBUnixSetPerms(xid, pTcon, full_path,
981981
mode,
@@ -994,9 +994,16 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
994994
CIFS_MOUNT_MAP_SPECIAL_CHR);
995995
}
996996
} 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+
}
10001007
if (direntry->d_inode) {
10011008
direntry->d_inode->i_mode = mode;
10021009
direntry->d_inode->i_mode |= S_IFDIR;
@@ -1408,18 +1415,19 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
14081415
__u64 uid = 0xFFFFFFFFFFFFFFFFULL;
14091416
__u64 gid = 0xFFFFFFFFFFFFFFFFULL;
14101417
struct cifsInodeInfo *cifsInode;
1418+
struct inode *inode = direntry->d_inode;
14111419

14121420
xid = GetXid();
14131421

14141422
cFYI(1, ("setattr on file %s attrs->iavalid 0x%x",
14151423
direntry->d_name.name, attrs->ia_valid));
14161424

1417-
cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
1425+
cifs_sb = CIFS_SB(inode->i_sb);
14181426
pTcon = cifs_sb->tcon;
14191427

14201428
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) {
14211429
/* check if we have permission to change attrs */
1422-
rc = inode_change_ok(direntry->d_inode, attrs);
1430+
rc = inode_change_ok(inode, attrs);
14231431
if (rc < 0) {
14241432
FreeXid(xid);
14251433
return rc;
@@ -1432,7 +1440,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
14321440
FreeXid(xid);
14331441
return -ENOMEM;
14341442
}
1435-
cifsInode = CIFS_I(direntry->d_inode);
1443+
cifsInode = CIFS_I(inode);
14361444

14371445
if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) {
14381446
/*
@@ -1443,9 +1451,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
14431451
will be truncated anyway? Also, should we error out here if
14441452
the flush returns error?
14451453
*/
1446-
rc = filemap_write_and_wait(direntry->d_inode->i_mapping);
1454+
rc = filemap_write_and_wait(inode->i_mapping);
14471455
if (rc != 0) {
1448-
CIFS_I(direntry->d_inode)->write_behind_rc = rc;
1456+
cifsInode->write_behind_rc = rc;
14491457
rc = 0;
14501458
}
14511459
}
@@ -1521,9 +1529,8 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
15211529
*/
15221530

15231531
if (rc == 0) {
1524-
rc = cifs_vmtruncate(direntry->d_inode, attrs->ia_size);
1525-
cifs_truncate_page(direntry->d_inode->i_mapping,
1526-
direntry->d_inode->i_size);
1532+
rc = cifs_vmtruncate(inode, attrs->ia_size);
1533+
cifs_truncate_page(inode->i_mapping, inode->i_size);
15271534
} else
15281535
goto cifs_setattr_exit;
15291536
}
@@ -1557,7 +1564,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
15571564
rc = 0;
15581565
#ifdef CONFIG_CIFS_EXPERIMENTAL
15591566
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
1560-
rc = mode_to_acl(direntry->d_inode, full_path, mode);
1567+
rc = mode_to_acl(inode, full_path, mode);
15611568
else if ((mode & S_IWUGO) == 0) {
15621569
#else
15631570
if ((mode & S_IWUGO) == 0) {
@@ -1665,7 +1672,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
16651672
/* do not need local check to inode_check_ok since the server does
16661673
that */
16671674
if (!rc)
1668-
rc = inode_setattr(direntry->d_inode, attrs);
1675+
rc = inode_setattr(inode, attrs);
16691676
cifs_setattr_exit:
16701677
kfree(full_path);
16711678
FreeXid(xid);

0 commit comments

Comments
 (0)