Merge branch 'linus' into x86/urgent
authorIngo Molnar <mingo@elte.hu>
Tue, 13 May 2008 09:32:58 +0000 (11:32 +0200)
committerIngo Molnar <mingo@elte.hu>
Tue, 13 May 2008 09:32:58 +0000 (11:32 +0200)
fs/cifs/cifspdu.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/dir.c
fs/cifs/inode.c
include/linux/sched.h

index a0d26b5..c43bf4b 100644 (file)
 #define OPEN_NO_RECALL          0x00400000
 #define OPEN_FREE_SPACE_QUERY   0x00800000     /* should be zero */
 #define CREATE_OPTIONS_MASK     0x007FFFFF
+#define CREATE_OPTION_READONLY 0x10000000
 #define CREATE_OPTION_SPECIAL   0x20000000   /* system. NB not sent over wire */
 
 /* ImpersonationLevel flags */
index cfd9750..95fbba4 100644 (file)
@@ -1224,11 +1224,8 @@ OldOpenRetry:
        else /* BB FIXME BB */
                pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
 
-       /* if ((omode & S_IWUGO) == 0)
-               pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
-       /*  Above line causes problems due to vfs splitting create into two
-           pieces - need to set mode after file created not while it is
-           being created */
+       if (create_options & CREATE_OPTION_READONLY)
+               pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
 
        /* BB FIXME BB */
 /*     pSMB->CreateOptions = cpu_to_le32(create_options &
@@ -1331,17 +1328,16 @@ openRetry:
                pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
        else
                pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
+
        /* XP does not handle ATTR_POSIX_SEMANTICS */
        /* but it helps speed up case sensitive checks for other
        servers such as Samba */
        if (tcon->ses->capabilities & CAP_UNIX)
                pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
 
-       /* if ((omode & S_IWUGO) == 0)
-               pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
-       /*  Above line causes problems due to vfs splitting create into two
-               pieces - need to set mode after file created not while it is
-               being created */
+       if (create_options & CREATE_OPTION_READONLY)
+               pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
+
        pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
        pSMB->CreateDisposition = cpu_to_le32(openDisposition);
        pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
index 791ca5c..f428bf3 100644 (file)
@@ -348,7 +348,6 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
        int reconnect;
 
        current->flags |= PF_MEMALLOC;
-       server->tsk = current;  /* save process info to wake at shutdown */
        cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current)));
        write_lock(&GlobalSMBSeslock);
        atomic_inc(&tcpSesAllocCount);
@@ -651,10 +650,20 @@ multi_t2_fnd:
 
        spin_lock(&GlobalMid_Lock);
        server->tcpStatus = CifsExiting;
-       server->tsk = NULL;
+       spin_unlock(&GlobalMid_Lock);
+
+       /* don't exit until kthread_stop is called */
+       set_current_state(TASK_UNINTERRUPTIBLE);
+       while (!kthread_should_stop()) {
+               schedule();
+               set_current_state(TASK_UNINTERRUPTIBLE);
+       }
+       set_current_state(TASK_RUNNING);
+
        /* check if we have blocked requests that need to free */
        /* Note that cifs_max_pending is normally 50, but
        can be set at module install time to as little as two */
+       spin_lock(&GlobalMid_Lock);
        if (atomic_read(&server->inFlight) >= cifs_max_pending)
                atomic_set(&server->inFlight, cifs_max_pending - 1);
        /* 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,
 
 static struct cifsSesInfo *
 cifs_find_tcp_session(struct in_addr *target_ip_addr,
-               struct in6_addr *target_ip6_addr,
-                char *userName, struct TCP_Server_Info **psrvTcp)
+                     struct in6_addr *target_ip6_addr,
+                     char *userName, struct TCP_Server_Info **psrvTcp)
 {
        struct list_head *tmp;
        struct cifsSesInfo *ses;
+
        *psrvTcp = NULL;
-       read_lock(&GlobalSMBSeslock);
 
+       read_lock(&GlobalSMBSeslock);
        list_for_each(tmp, &GlobalSMBSessionList) {
                ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
-               if (ses->server) {
-                       if ((target_ip_addr &&
-                               (ses->server->addr.sockAddr.sin_addr.s_addr
-                                 == target_ip_addr->s_addr)) || (target_ip6_addr
-                               && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
-                                       target_ip6_addr, sizeof(*target_ip6_addr)))) {
-                               /* BB lock server and tcp session and increment
-                                     use count here?? */
-
-                               /* found a match on the TCP session */
-                               *psrvTcp = ses->server;
-
-                               /* BB check if reconnection needed */
-                               if (strncmp
-                                   (ses->userName, userName,
-                                    MAX_USERNAME_SIZE) == 0){
-                                       read_unlock(&GlobalSMBSeslock);
-                                       /* Found exact match on both TCP and
-                                          SMB sessions */
-                                       return ses;
-                               }
-                       }
+               if (!ses->server)
+                       continue;
+
+               if (target_ip_addr &&
+                   ses->server->addr.sockAddr.sin_addr.s_addr != target_ip_addr->s_addr)
+                               continue;
+               else if (target_ip6_addr &&
+                        memcmp(&ses->server->addr.sockAddr6.sin6_addr,
+                               target_ip6_addr, sizeof(*target_ip6_addr)))
+                               continue;
+               /* BB lock server and tcp session; increment use count here?? */
+
+               /* found a match on the TCP session */
+               *psrvTcp = ses->server;
+
+               /* BB check if reconnection needed */
+               if (strncmp(ses->userName, userName, MAX_USERNAME_SIZE) == 0) {
+                       read_unlock(&GlobalSMBSeslock);
+                       /* Found exact match on both TCP and
+                          SMB sessions */
+                       return ses;
                }
                /* else tcp and smb sessions need reconnection */
        }
        read_unlock(&GlobalSMBSeslock);
+
        return NULL;
 }
 
@@ -2186,15 +2196,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                        srvTcp->tcpStatus = CifsExiting;
                        spin_unlock(&GlobalMid_Lock);
                        if (srvTcp->tsk) {
-                               struct task_struct *tsk;
                                /* If we could verify that kthread_stop would
                                   always wake up processes blocked in
                                   tcp in recv_mesg then we could remove the
                                   send_sig call */
                                force_sig(SIGKILL, srvTcp->tsk);
-                               tsk = srvTcp->tsk;
-                               if (tsk)
-                                       kthread_stop(tsk);
+                               kthread_stop(srvTcp->tsk);
                        }
                }
                 /* 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,
                                        if ((temp_rc == -ESHUTDOWN) &&
                                            (pSesInfo->server) &&
                                            (pSesInfo->server->tsk)) {
-                                               struct task_struct *tsk;
                                                force_sig(SIGKILL,
                                                        pSesInfo->server->tsk);
-                                               tsk = pSesInfo->server->tsk;
-                                               if (tsk)
-                                                       kthread_stop(tsk);
+                                               kthread_stop(pSesInfo->server->tsk);
                                        }
                                } else {
                                        cFYI(1, ("No session or bad tcon"));
                                        if ((pSesInfo->server) &&
                                            (pSesInfo->server->tsk)) {
-                                               struct task_struct *tsk;
                                                force_sig(SIGKILL,
                                                        pSesInfo->server->tsk);
-                                               tsk = pSesInfo->server->tsk;
-                                               if (tsk)
-                                                       kthread_stop(tsk);
+                                               kthread_stop(pSesInfo->server->tsk);
                                        }
                                }
                                sesInfoFree(pSesInfo);
index 6ed7759..e4e0078 100644 (file)
@@ -119,6 +119,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
 {
        int rc = -ENOENT;
        int xid;
+       int create_options = CREATE_NOT_DIR;
        int oplock = 0;
        int desiredAccess = GENERIC_READ | GENERIC_WRITE;
        __u16 fileHandle;
@@ -176,9 +177,19 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
                FreeXid(xid);
                return -ENOMEM;
        }
+
+       mode &= ~current->fs->umask;
+
+       /*
+        * if we're not using unix extensions, see if we need to set
+        * ATTR_READONLY on the create call
+        */
+       if (!pTcon->unix_ext && (mode & S_IWUGO) == 0)
+               create_options |= CREATE_OPTION_READONLY;
+
        if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
                rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
-                        desiredAccess, CREATE_NOT_DIR,
+                        desiredAccess, create_options,
                         &fileHandle, &oplock, buf, cifs_sb->local_nls,
                         cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
        else
@@ -187,7 +198,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
        if (rc == -EIO) {
                /* old server, retry the open legacy style */
                rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
-                       desiredAccess, CREATE_NOT_DIR,
+                       desiredAccess, create_options,
                        &fileHandle, &oplock, buf, cifs_sb->local_nls,
                        cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
        }
@@ -197,7 +208,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
                /* If Open reported that we actually created a file
                then we now have to set the mode if possible */
                if ((pTcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
-                       mode &= ~current->fs->umask;
                        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
                                CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
                                        (__u64)current->fsuid,
index 0d9d2e6..fcbdbb6 100644 (file)
@@ -974,8 +974,8 @@ mkdir_get_info:
                  * failed to get it from the server or was set bogus */
                if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
                                direntry->d_inode->i_nlink = 2;
+               mode &= ~current->fs->umask;
                if (pTcon->unix_ext) {
-                       mode &= ~current->fs->umask;
                        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
                                CIFSSMBUnixSetPerms(xid, pTcon, full_path,
                                                    mode,
@@ -994,9 +994,16 @@ mkdir_get_info:
                                                    CIFS_MOUNT_MAP_SPECIAL_CHR);
                        }
                } else {
-                       /* BB to be implemented via Windows secrty descriptors
-                          eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
-                                                -1, -1, local_nls); */
+                       if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
+                           (mode & S_IWUGO) == 0) {
+                               FILE_BASIC_INFO pInfo;
+                               memset(&pInfo, 0, sizeof(pInfo));
+                               pInfo.Attributes = cpu_to_le32(ATTR_READONLY);
+                               CIFSSMBSetTimes(xid, pTcon, full_path,
+                                               &pInfo, cifs_sb->local_nls,
+                                               cifs_sb->mnt_cifs_flags &
+                                               CIFS_MOUNT_MAP_SPECIAL_CHR);
+                       }
                        if (direntry->d_inode) {
                                direntry->d_inode->i_mode = mode;
                                direntry->d_inode->i_mode |= S_IFDIR;
@@ -1408,18 +1415,19 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
        __u64 uid = 0xFFFFFFFFFFFFFFFFULL;
        __u64 gid = 0xFFFFFFFFFFFFFFFFULL;
        struct cifsInodeInfo *cifsInode;
+       struct inode *inode = direntry->d_inode;
 
        xid = GetXid();
 
        cFYI(1, ("setattr on file %s attrs->iavalid 0x%x",
                 direntry->d_name.name, attrs->ia_valid));
 
-       cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
+       cifs_sb = CIFS_SB(inode->i_sb);
        pTcon = cifs_sb->tcon;
 
        if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) {
                /* check if we have permission to change attrs */
-               rc = inode_change_ok(direntry->d_inode, attrs);
+               rc = inode_change_ok(inode, attrs);
                if (rc < 0) {
                        FreeXid(xid);
                        return rc;
@@ -1432,7 +1440,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
                FreeXid(xid);
                return -ENOMEM;
        }
-       cifsInode = CIFS_I(direntry->d_inode);
+       cifsInode = CIFS_I(inode);
 
        if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) {
                /*
@@ -1443,9 +1451,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
                   will be truncated anyway? Also, should we error out here if
                   the flush returns error?
                 */
-               rc = filemap_write_and_wait(direntry->d_inode->i_mapping);
+               rc = filemap_write_and_wait(inode->i_mapping);
                if (rc != 0) {
-                       CIFS_I(direntry->d_inode)->write_behind_rc = rc;
+                       cifsInode->write_behind_rc = rc;
                        rc = 0;
                }
        }
@@ -1521,9 +1529,8 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
                   */
 
                if (rc == 0) {
-                       rc = cifs_vmtruncate(direntry->d_inode, attrs->ia_size);
-                       cifs_truncate_page(direntry->d_inode->i_mapping,
-                                          direntry->d_inode->i_size);
+                       rc = cifs_vmtruncate(inode, attrs->ia_size);
+                       cifs_truncate_page(inode->i_mapping, inode->i_size);
                } else
                        goto cifs_setattr_exit;
        }
@@ -1557,7 +1564,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
                rc = 0;
 #ifdef CONFIG_CIFS_EXPERIMENTAL
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
-                       rc = mode_to_acl(direntry->d_inode, full_path, mode);
+                       rc = mode_to_acl(inode, full_path, mode);
                else if ((mode & S_IWUGO) == 0) {
 #else
                if ((mode & S_IWUGO) == 0) {
@@ -1665,7 +1672,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
        /* do not need local check to inode_check_ok since the server does
           that */
        if (!rc)
-               rc = inode_setattr(direntry->d_inode, attrs);
+               rc = inode_setattr(inode, attrs);
 cifs_setattr_exit:
        kfree(full_path);
        FreeXid(xid);
index 5a63f2d..5395a61 100644 (file)
@@ -2038,7 +2038,7 @@ static inline int need_resched(void)
  * cond_resched_softirq() will enable bhs before scheduling.
  */
 extern int _cond_resched(void);
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPT_BKL
 static inline int cond_resched(void)
 {
        return 0;