]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - fs/ncpfs/inode.c
Merge branch 'master' into tk71
[mv-sheeva.git] / fs / ncpfs / inode.c
index b4de38cf49f5f3a802a112cbd99226e12d49cf38..00a1d1c3d3a494c34dc02230509ffa88485a37ae 100644 (file)
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/vfs.h>
 #include <linux/mount.h>
 #include <linux/seq_file.h>
-
-#include <linux/ncp_fs.h>
+#include <linux/namei.h>
 
 #include <net/sock.h>
 
-#include "ncplib_kernel.h"
+#include "ncp_fs.h"
 #include "getopt.h"
 
 #define NCP_DEFAULT_FILE_MODE 0600
@@ -59,11 +57,18 @@ static struct inode *ncp_alloc_inode(struct super_block *sb)
        return &ei->vfs_inode;
 }
 
-static void ncp_destroy_inode(struct inode *inode)
+static void ncp_i_callback(struct rcu_head *head)
 {
+       struct inode *inode = container_of(head, struct inode, i_rcu);
+       INIT_LIST_HEAD(&inode->i_dentry);
        kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode));
 }
 
+static void ncp_destroy_inode(struct inode *inode)
+{
+       call_rcu(&inode->i_rcu, ncp_i_callback);
+}
+
 static void init_once(void *foo)
 {
        struct ncp_inode_info *ei = (struct ncp_inode_info *) foo;
@@ -139,7 +144,7 @@ static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi)
                inode->i_mode = nwi->nfs.mode;
        }
 
-       inode->i_blocks = (inode->i_size + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
+       inode->i_blocks = (i_size_read(inode) + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
 
        inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate);
        inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate);
@@ -158,18 +163,21 @@ static void ncp_update_attrs(struct inode *inode, struct ncp_entry_info *nwinfo)
                inode->i_mode = server->m.dir_mode;
                /* for directories dataStreamSize seems to be some
                   Object ID ??? */
-               inode->i_size = NCP_BLOCK_SIZE;
+               i_size_write(inode, NCP_BLOCK_SIZE);
        } else {
+               u32 size;
+
                inode->i_mode = server->m.file_mode;
-               inode->i_size = le32_to_cpu(nwi->dataStreamSize);
+               size = le32_to_cpu(nwi->dataStreamSize);
+               i_size_write(inode, size);
 #ifdef CONFIG_NCPFS_EXTRAS
                if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) 
                 && (nwi->attributes & aSHARED)) {
                        switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
                                case aHIDDEN:
                                        if (server->m.flags & NCP_MOUNT_SYMLINKS) {
-                                               if (/* (inode->i_size >= NCP_MIN_SYMLINK_SIZE)
-                                                && */ (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) {
+                                               if (/* (size >= NCP_MIN_SYMLINK_SIZE)
+                                                && */ (size <= NCP_MAX_SYMLINK_SIZE)) {
                                                        inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
                                                        NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK;
                                                        break;
@@ -208,7 +216,7 @@ void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo)
 }
 
 /*
- * Fill in the inode based on the ncp_entry_info structure.
+ * Fill in the inode based on the ncp_entry_info structure.  Used only for brand new inodes.
  */
 static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
 {
@@ -254,6 +262,7 @@ ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
        if (inode) {
                atomic_set(&NCP_FINFO(inode)->opened, info->opened);
 
+               inode->i_mapping->backing_dev_info = sb->s_bdi;
                inode->i_ino = info->ino;
                ncp_set_attr(inode, info);
                if (S_ISREG(inode->i_mode)) {
@@ -299,12 +308,19 @@ ncp_evict_inode(struct inode *inode)
 
 static void ncp_stop_tasks(struct ncp_server *server) {
        struct sock* sk = server->ncp_sock->sk;
-               
+
+       lock_sock(sk);
        sk->sk_error_report = server->error_report;
        sk->sk_data_ready   = server->data_ready;
        sk->sk_write_space  = server->write_space;
+       release_sock(sk);
        del_timer_sync(&server->timeout_tm);
-       flush_scheduled_work();
+
+       flush_work_sync(&server->rcv.tq);
+       if (sk->sk_socket->type == SOCK_STREAM)
+               flush_work_sync(&server->tx.tq);
+       else
+               flush_work_sync(&server->timeout_tq);
 }
 
 static int  ncp_show_options(struct seq_file *seq, struct vfsmount *mnt)
@@ -526,6 +542,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
        sb->s_blocksize_bits = 10;
        sb->s_magic = NCP_SUPER_MAGIC;
        sb->s_op = &ncp_sops;
+       sb->s_d_op = &ncp_dentry_operations;
        sb->s_bdi = &server->bdi;
 
        server = NCP_SBP(sb);
@@ -565,10 +582,12 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
 /*     server->conn_status = 0;        */
 /*     server->root_dentry = NULL;     */
 /*     server->root_setuped = 0;       */
+       mutex_init(&server->root_setup_lock);
 #ifdef CONFIG_NCPFS_PACKET_SIGNING
 /*     server->sign_wanted = 0;        */
 /*     server->sign_active = 0;        */
 #endif
+       init_rwsem(&server->auth_rwsem);
        server->auth.auth_type = NCP_AUTH_NONE;
 /*     server->auth.object_name_len = 0;       */
 /*     server->auth.object_name = NULL;        */
@@ -593,16 +612,12 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
        server->nls_io = load_nls_default();
 #endif /* CONFIG_NCPFS_NLS */
 
-       server->dentry_ttl = 0; /* no caching */
+       atomic_set(&server->dentry_ttl, 0);     /* no caching */
 
        INIT_LIST_HEAD(&server->tx.requests);
        mutex_init(&server->rcv.creq_mutex);
        server->tx.creq         = NULL;
        server->rcv.creq        = NULL;
-       server->data_ready      = sock->sk->sk_data_ready;
-       server->write_space     = sock->sk->sk_write_space;
-       server->error_report    = sock->sk->sk_error_report;
-       sock->sk->sk_user_data  = server;
 
        init_timer(&server->timeout_tm);
 #undef NCP_PACKET_SIZE
@@ -619,6 +634,11 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
        if (server->rxbuf == NULL)
                goto out_txbuf;
 
+       lock_sock(sock->sk);
+       server->data_ready      = sock->sk->sk_data_ready;
+       server->write_space     = sock->sk->sk_write_space;
+       server->error_report    = sock->sk->sk_error_report;
+       sock->sk->sk_user_data  = server;
        sock->sk->sk_data_ready   = ncp_tcp_data_ready;
        sock->sk->sk_error_report = ncp_tcp_error_report;
        if (sock->type == SOCK_STREAM) {
@@ -634,6 +654,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
                server->timeout_tm.data = (unsigned long)server;
                server->timeout_tm.function = ncpdgram_timeout_call;
        }
+       release_sock(sock->sk);
 
        ncp_lock_server(server);
        error = ncp_connect(server);
@@ -658,8 +679,10 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
                                goto out_disconnect;
                        }
                }
+               ncp_lock_server(server);
                if (options & 2)
                        server->sign_wanted = 1;
+               ncp_unlock_server(server);
        }
        else 
 #endif /* CONFIG_NCPFS_PACKET_SIGNING */
@@ -699,7 +722,6 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
        sb->s_root = d_alloc_root(root_inode);
         if (!sb->s_root)
                goto out_no_root;
-       sb->s_root->d_op = &ncp_root_dentry_operations;
        return 0;
 
 out_no_root:
@@ -720,6 +742,9 @@ out_nls:
        unload_nls(server->nls_io);
        unload_nls(server->nls_vol);
 #endif
+       mutex_destroy(&server->rcv.creq_mutex);
+       mutex_destroy(&server->root_setup_lock);
+       mutex_destroy(&server->mutex);
 out_fput2:
        if (server->info_filp)
                fput(server->info_filp);
@@ -743,8 +768,6 @@ static void ncp_put_super(struct super_block *sb)
 {
        struct ncp_server *server = NCP_SBP(sb);
 
-       lock_kernel();
-
        ncp_lock_server(server);
        ncp_disconnect(server);
        ncp_unlock_server(server);
@@ -756,6 +779,9 @@ static void ncp_put_super(struct super_block *sb)
        unload_nls(server->nls_vol);
        unload_nls(server->nls_io);
 #endif /* CONFIG_NCPFS_NLS */
+       mutex_destroy(&server->rcv.creq_mutex);
+       mutex_destroy(&server->root_setup_lock);
+       mutex_destroy(&server->mutex);
 
        if (server->info_filp)
                fput(server->info_filp);
@@ -771,8 +797,6 @@ static void ncp_put_super(struct super_block *sb)
        vfree(server->packet);
        sb->s_fs_info = NULL;
        kfree(server);
-
-       unlock_kernel();
 }
 
 static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
@@ -851,10 +875,8 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
 
        result = -EIO;
 
-       lock_kernel();  
-
        server = NCP_SERVER(inode);
-       if ((!server) || !ncp_conn_valid(server))
+       if (!server)    /* How this could happen? */
                goto out;
 
        /* ageing the dentry to force validation */
@@ -981,8 +1003,6 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
                result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
                                      inode, info_mask, &info);
                if (result != 0) {
-                       result = -EACCES;
-
                        if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
                                /* NetWare seems not to allow this. I
                                   do not know why. So, just tell the
@@ -1005,20 +1025,21 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
        mark_inode_dirty(inode);
 
 out:
-       unlock_kernel();
+       if (result > 0)
+               result = -EACCES;
        return result;
 }
 
-static int ncp_get_sb(struct file_system_type *fs_type,
-       int flags, const char *dev_name, void *data, struct vfsmount *mnt)
+static struct dentry *ncp_mount(struct file_system_type *fs_type,
+       int flags, const char *dev_name, void *data)
 {
-       return get_sb_nodev(fs_type, flags, data, ncp_fill_super, mnt);
+       return mount_nodev(fs_type, flags, data, ncp_fill_super);
 }
 
 static struct file_system_type ncp_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "ncpfs",
-       .get_sb         = ncp_get_sb,
+       .mount          = ncp_mount,
        .kill_sb        = kill_anon_super,
        .fs_flags       = FS_BINARY_MOUNTDATA,
 };