[PATCH] mutex subsystem, semaphore to mutex: VFS, ->i_sem
[pandora-kernel.git] / fs / cifs / cifsfs.c
index 877095a..e10213b 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/seq_file.h>
 #include <linux/vfs.h>
 #include <linux/mempool.h>
+#include <linux/delay.h>
 #include "cifsfs.h"
 #include "cifspdu.h"
 #define DECLARE_GLOBALS_HERE
@@ -405,6 +406,7 @@ static struct quotactl_ops cifs_quotactl_ops = {
 };
 #endif
 
+#ifdef CONFIG_CIFS_EXPERIMENTAL
 static void cifs_umount_begin(struct super_block * sblock)
 {
        struct cifs_sb_info *cifs_sb;
@@ -422,16 +424,23 @@ static void cifs_umount_begin(struct super_block * sblock)
                tcon->tidStatus = CifsExiting;
        up(&tcon->tconSem);
 
+       /* cancel_brl_requests(tcon); */
+       /* cancel_notify_requests(tcon); */
        if(tcon->ses && tcon->ses->server)
        {
-               cERROR(1,("wake up tasks now - umount begin not complete"));
+               cFYI(1,("wake up tasks now - umount begin not complete"));
                wake_up_all(&tcon->ses->server->request_q);
+               wake_up_all(&tcon->ses->server->response_q);
+               msleep(1); /* yield */
+               /* we have to kick the requests once more */
+               wake_up_all(&tcon->ses->server->response_q);
+               msleep(1);
        }
 /* BB FIXME - finish add checks for tidStatus BB */
 
        return;
 }
-       
+#endif 
 
 static int cifs_remount(struct super_block *sb, int *flags, char *data)
 {
@@ -450,7 +459,9 @@ struct super_operations cifs_super_ops = {
    unless later we add lazy close of inodes or unless the kernel forgets to call
    us with the same number of releases (closes) as opens */
        .show_options = cifs_show_options,
-/*     .umount_begin   = cifs_umount_begin, */ /* BB finish in the future */
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+       .umount_begin   = cifs_umount_begin,
+#endif
        .remount_fs = cifs_remount,
 };
 
@@ -478,57 +489,30 @@ cifs_get_sb(struct file_system_type *fs_type,
        return sb;
 }
 
-static ssize_t
-cifs_read_wrapper(struct file * file, char __user *read_data, size_t read_size,
-          loff_t * poffset)
+static ssize_t cifs_file_writev(struct file *file, const struct iovec *iov,
+                               unsigned long nr_segs, loff_t *ppos)
 {
-       if(file->f_dentry == NULL)
-               return -EIO;
-       else if(file->f_dentry->d_inode == NULL)
-               return -EIO;
-
-       cFYI(1,("In read_wrapper size %zd at %lld",read_size,*poffset));
+       struct inode *inode = file->f_dentry->d_inode;
+       ssize_t written;
 
-       if(CIFS_I(file->f_dentry->d_inode)->clientCanCacheRead) {
-               return generic_file_read(file,read_data,read_size,poffset);
-       } else {
-               /* BB do we need to lock inode from here until after invalidate? */
-/*             if(file->f_dentry->d_inode->i_mapping) {
-                       filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
-                       filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
-               }*/
-/*             cifs_revalidate(file->f_dentry);*/ /* BB fixme */
-
-               /* BB we should make timer configurable - perhaps 
-                  by simply calling cifs_revalidate here */
-               /* invalidate_remote_inode(file->f_dentry->d_inode);*/
-               return generic_file_read(file,read_data,read_size,poffset);
-       }
+       written = generic_file_writev(file, iov, nr_segs, ppos);
+       if (!CIFS_I(inode)->clientCanCacheAll)
+               filemap_fdatawrite(inode->i_mapping);
+       return written;
 }
 
-static ssize_t
-cifs_write_wrapper(struct file * file, const char __user *write_data,
-           size_t write_size, loff_t * poffset) 
+static ssize_t cifs_file_aio_write(struct kiocb *iocb, const char __user *buf,
+                                  size_t count, loff_t pos)
 {
+       struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
        ssize_t written;
 
-       if(file->f_dentry == NULL)
-               return -EIO;
-       else if(file->f_dentry->d_inode == NULL)
-               return -EIO;
-
-       cFYI(1,("In write_wrapper size %zd at %lld",write_size,*poffset));
-
-       written = generic_file_write(file,write_data,write_size,poffset);
-       if(!CIFS_I(file->f_dentry->d_inode)->clientCanCacheAll)  {
-               if(file->f_dentry->d_inode->i_mapping) {
-                       filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
-               }
-       }
+       written = generic_file_aio_write(iocb, buf, count, pos);
+       if (!CIFS_I(inode)->clientCanCacheAll)
+               filemap_fdatawrite(inode->i_mapping);
        return written;
 }
 
-
 static struct file_system_type cifs_fs_type = {
        .owner = THIS_MODULE,
        .name = "cifs",
@@ -589,8 +573,12 @@ struct inode_operations cifs_symlink_inode_ops = {
 };
 
 struct file_operations cifs_file_ops = {
-       .read = cifs_read_wrapper,
-       .write = cifs_write_wrapper, 
+       .read = do_sync_read,
+       .write = do_sync_write,
+       .readv = generic_file_readv,
+       .writev = cifs_file_writev,
+       .aio_read = generic_file_aio_read,
+       .aio_write = cifs_file_aio_write,
        .open = cifs_open,
        .release = cifs_close,
        .lock = cifs_lock,
@@ -603,10 +591,6 @@ struct file_operations cifs_file_ops = {
 #endif /* CONFIG_CIFS_POSIX */
 
 #ifdef CONFIG_CIFS_EXPERIMENTAL
-       .readv = generic_file_readv,
-       .writev = generic_file_writev,
-       .aio_read = generic_file_aio_read,
-       .aio_write = generic_file_aio_write,
        .dir_notify = cifs_dir_notify,
 #endif /* CONFIG_CIFS_EXPERIMENTAL */
 };
@@ -626,6 +610,46 @@ struct file_operations cifs_file_direct_ops = {
        .ioctl  = cifs_ioctl,
 #endif /* CONFIG_CIFS_POSIX */
 
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+       .dir_notify = cifs_dir_notify,
+#endif /* CONFIG_CIFS_EXPERIMENTAL */
+};
+struct file_operations cifs_file_nobrl_ops = {
+       .read = do_sync_read,
+       .write = do_sync_write,
+       .readv = generic_file_readv,
+       .writev = cifs_file_writev,
+       .aio_read = generic_file_aio_read,
+       .aio_write = cifs_file_aio_write,
+       .open = cifs_open,
+       .release = cifs_close,
+       .fsync = cifs_fsync,
+       .flush = cifs_flush,
+       .mmap  = cifs_file_mmap,
+       .sendfile = generic_file_sendfile,
+#ifdef CONFIG_CIFS_POSIX
+       .ioctl  = cifs_ioctl,
+#endif /* CONFIG_CIFS_POSIX */
+
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+       .dir_notify = cifs_dir_notify,
+#endif /* CONFIG_CIFS_EXPERIMENTAL */
+};
+
+struct file_operations cifs_file_direct_nobrl_ops = {
+       /* no mmap, no aio, no readv - 
+          BB reevaluate whether they can be done with directio, no cache */
+       .read = cifs_user_read,
+       .write = cifs_user_write,
+       .open = cifs_open,
+       .release = cifs_close,
+       .fsync = cifs_fsync,
+       .flush = cifs_flush,
+       .sendfile = generic_file_sendfile, /* BB removeme BB */
+#ifdef CONFIG_CIFS_POSIX
+       .ioctl  = cifs_ioctl,
+#endif /* CONFIG_CIFS_POSIX */
+
 #ifdef CONFIG_CIFS_EXPERIMENTAL
        .dir_notify = cifs_dir_notify,
 #endif /* CONFIG_CIFS_EXPERIMENTAL */
@@ -836,9 +860,9 @@ static int cifs_oplock_thread(void * dummyarg)
                                DeleteOplockQEntry(oplock_item);
                                /* can not grab inode sem here since it would
                                deadlock when oplock received on delete 
-                               since vfs_unlink holds the i_sem across
+                               since vfs_unlink holds the i_mutex across
                                the call */
-                               /* down(&inode->i_sem);*/
+                               /* mutex_lock(&inode->i_mutex);*/
                                if (S_ISREG(inode->i_mode)) {
                                        rc = filemap_fdatawrite(inode->i_mapping);
                                        if(CIFS_I(inode)->clientCanCacheRead == 0) {
@@ -847,7 +871,7 @@ static int cifs_oplock_thread(void * dummyarg)
                                        }
                                } else
                                        rc = 0;
-                               /* up(&inode->i_sem);*/
+                               /* mutex_unlock(&inode->i_mutex);*/
                                if (rc)
                                        CIFS_I(inode)->write_behind_rc = rc;
                                cFYI(1,("Oplock flush inode %p rc %d",inode,rc));
@@ -877,6 +901,9 @@ static int cifs_oplock_thread(void * dummyarg)
 
 static int cifs_dnotify_thread(void * dummyarg)
 {
+       struct list_head *tmp;
+       struct cifsSesInfo *ses;
+
        daemonize("cifsdnotifyd");
        allow_signal(SIGTERM);
 
@@ -885,7 +912,19 @@ static int cifs_dnotify_thread(void * dummyarg)
                if(try_to_freeze())
                        continue;
                set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(39*HZ);
+               schedule_timeout(15*HZ);
+               read_lock(&GlobalSMBSeslock);
+               /* check if any stuck requests that need
+                  to be woken up and wakeq so the
+                  thread can wake up and error out */
+               list_for_each(tmp, &GlobalSMBSessionList) {
+                       ses = list_entry(tmp, struct cifsSesInfo, 
+                               cifsSessionList);
+                       if(ses && ses->server && 
+                            atomic_read(&ses->server->inFlight))
+                               wake_up_all(&ses->server->response_q);
+               }
+               read_unlock(&GlobalSMBSeslock);
        } while(!signal_pending(current));
        complete_and_exit (&cifs_dnotify_exited, 0);
 }