Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[safe/jmp/linux-2.6] / fs / ncpfs / inode.c
index 1ddf77b..fa33851 100644 (file)
@@ -28,6 +28,8 @@
 #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 "ncplib_kernel.h"
 #include "getopt.h"
 
+#define NCP_DEFAULT_FILE_MODE 0600
+#define NCP_DEFAULT_DIR_MODE 0700
+#define NCP_DEFAULT_TIME_OUT 10
+#define NCP_DEFAULT_RETRY_COUNT 20
+
 static void ncp_delete_inode(struct inode *);
 static void ncp_put_super(struct super_block *);
 static int  ncp_statfs(struct dentry *, struct kstatfs *);
+static int  ncp_show_options(struct seq_file *, struct vfsmount *);
 
-static kmem_cache_t * ncp_inode_cachep;
+static struct kmem_cache * ncp_inode_cachep;
 
 static struct inode *ncp_alloc_inode(struct super_block *sb)
 {
        struct ncp_inode_info *ei;
-       ei = (struct ncp_inode_info *)kmem_cache_alloc(ncp_inode_cachep, SLAB_KERNEL);
+       ei = (struct ncp_inode_info *)kmem_cache_alloc(ncp_inode_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
        return &ei->vfs_inode;
@@ -56,24 +64,21 @@ static void ncp_destroy_inode(struct inode *inode)
        kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode));
 }
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void *foo)
 {
        struct ncp_inode_info *ei = (struct ncp_inode_info *) foo;
 
-       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-           SLAB_CTOR_CONSTRUCTOR) {
-               mutex_init(&ei->open_mutex);
-               inode_init_once(&ei->vfs_inode);
-       }
+       mutex_init(&ei->open_mutex);
+       inode_init_once(&ei->vfs_inode);
 }
+
 static int init_inodecache(void)
 {
        ncp_inode_cachep = kmem_cache_create("ncp_inode_cache",
                                             sizeof(struct ncp_inode_info),
                                             0, (SLAB_RECLAIM_ACCOUNT|
                                                SLAB_MEM_SPREAD),
-                                            init_once, NULL);
+                                            init_once);
        if (ncp_inode_cachep == NULL)
                return -ENOMEM;
        return 0;
@@ -81,8 +86,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(ncp_inode_cachep))
-               printk(KERN_INFO "ncp_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(ncp_inode_cachep);
 }
 
 static int ncp_remount(struct super_block *sb, int *flags, char* data)
@@ -91,7 +95,7 @@ static int ncp_remount(struct super_block *sb, int *flags, char* data)
        return 0;
 }
 
-static struct super_operations ncp_sops =
+static const struct super_operations ncp_sops =
 {
        .alloc_inode    = ncp_alloc_inode,
        .destroy_inode  = ncp_destroy_inode,
@@ -100,14 +104,9 @@ static struct super_operations ncp_sops =
        .put_super      = ncp_put_super,
        .statfs         = ncp_statfs,
        .remount_fs     = ncp_remount,
+       .show_options   = ncp_show_options,
 };
 
-extern struct dentry_operations ncp_root_dentry_operations;
-#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
-extern const struct address_space_operations ncp_symlink_aops;
-extern int ncp_symlink(struct inode*, struct dentry*, const char*);
-#endif
-
 /*
  * Fill in the ncpfs-specific information in the inode.
  */
@@ -224,14 +223,13 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
        inode->i_nlink = 1;
        inode->i_uid = server->m.uid;
        inode->i_gid = server->m.gid;
-       inode->i_blksize = NCP_BLOCK_SIZE;
 
        ncp_update_dates(inode, &nwinfo->i);
        ncp_update_inode(inode, nwinfo);
 }
 
 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
-static struct inode_operations ncp_symlink_inode_operations = {
+static const struct inode_operations ncp_symlink_inode_operations = {
        .readlink       = generic_readlink,
        .follow_link    = page_follow_link_light,
        .put_link       = page_put_link,
@@ -309,6 +307,37 @@ static void ncp_stop_tasks(struct ncp_server *server) {
        flush_scheduled_work();
 }
 
+static int  ncp_show_options(struct seq_file *seq, struct vfsmount *mnt)
+{
+       struct ncp_server *server = NCP_SBP(mnt->mnt_sb);
+       unsigned int tmp;
+
+       if (server->m.uid != 0)
+               seq_printf(seq, ",uid=%u", server->m.uid);
+       if (server->m.gid != 0)
+               seq_printf(seq, ",gid=%u", server->m.gid);
+       if (server->m.mounted_uid != 0)
+               seq_printf(seq, ",owner=%u", server->m.mounted_uid);
+       tmp = server->m.file_mode & S_IALLUGO;
+       if (tmp != NCP_DEFAULT_FILE_MODE)
+               seq_printf(seq, ",mode=0%o", tmp);
+       tmp = server->m.dir_mode & S_IALLUGO;
+       if (tmp != NCP_DEFAULT_DIR_MODE)
+               seq_printf(seq, ",dirmode=0%o", tmp);
+       if (server->m.time_out != NCP_DEFAULT_TIME_OUT * HZ / 100) {
+               tmp = server->m.time_out * 100 / HZ;
+               seq_printf(seq, ",timeout=%u", tmp);
+       }
+       if (server->m.retry_count != NCP_DEFAULT_RETRY_COUNT)
+               seq_printf(seq, ",retry=%u", server->m.retry_count);
+       if (server->m.flags != 0)
+               seq_printf(seq, ",flags=%lu", server->m.flags);
+       if (server->m.wdog_pid != NULL)
+               seq_printf(seq, ",wdogpid=%u", pid_vnr(server->m.wdog_pid));
+
+       return 0;
+}
+
 static const struct ncp_option ncp_opts[] = {
        { "uid",        OPT_INT,        'u' },
        { "gid",        OPT_INT,        'g' },
@@ -329,24 +358,26 @@ static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options)
        char *optarg;
        unsigned long optint;
        int version = 0;
+       int ret;
 
        data->flags = 0;
        data->int_flags = 0;
        data->mounted_uid = 0;
-       data->wdog_pid = -1;
+       data->wdog_pid = NULL;
        data->ncp_fd = ~0;
-       data->time_out = 10;
-       data->retry_count = 20;
+       data->time_out = NCP_DEFAULT_TIME_OUT;
+       data->retry_count = NCP_DEFAULT_RETRY_COUNT;
        data->uid = 0;
        data->gid = 0;
-       data->file_mode = 0600;
-       data->dir_mode = 0700;
+       data->file_mode = NCP_DEFAULT_FILE_MODE;
+       data->dir_mode = NCP_DEFAULT_DIR_MODE;
        data->info_fd = -1;
        data->mounted_vol[0] = 0;
        
        while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) {
-               if (optval < 0)
-                       return optval;
+               ret = optval;
+               if (ret < 0)
+                       goto err;
                switch (optval) {
                        case 'u':
                                data->uid = optint;
@@ -373,7 +404,7 @@ static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options)
                                data->flags = optint;
                                break;
                        case 'w':
-                               data->wdog_pid = optint;
+                               data->wdog_pid = find_get_pid(optint);
                                break;
                        case 'n':
                                data->ncp_fd = optint;
@@ -382,18 +413,21 @@ static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options)
                                data->info_fd = optint;
                                break;
                        case 'v':
-                               if (optint < NCP_MOUNT_VERSION_V4) {
-                                       return -ECHRNG;
-                               }
-                               if (optint > NCP_MOUNT_VERSION_V5) {
-                                       return -ECHRNG;
-                               }
+                               ret = -ECHRNG;
+                               if (optint < NCP_MOUNT_VERSION_V4)
+                                       goto err;
+                               if (optint > NCP_MOUNT_VERSION_V5)
+                                       goto err;
                                version = optint;
                                break;
                        
                }
        }
        return 0;
+err:
+       put_pid(data->wdog_pid);
+       data->wdog_pid = NULL;
+       return ret;
 }
 
 static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
@@ -411,11 +445,11 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
 #endif
        struct ncp_entry_info finfo;
 
-       server = kmalloc(sizeof(struct ncp_server), GFP_KERNEL);
+       data.wdog_pid = NULL;
+       server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
        if (!server)
                return -ENOMEM;
        sb->s_fs_info = server;
-       memset(server, 0, sizeof(struct ncp_server));
 
        error = -EFAULT;
        if (raw_data == NULL)
@@ -428,7 +462,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
                                data.flags = md->flags;
                                data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
                                data.mounted_uid = md->mounted_uid;
-                               data.wdog_pid = md->wdog_pid;
+                               data.wdog_pid = find_get_pid(md->wdog_pid);
                                data.ncp_fd = md->ncp_fd;
                                data.time_out = md->time_out;
                                data.retry_count = md->retry_count;
@@ -448,7 +482,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
                                data.flags = md->flags;
                                data.int_flags = 0;
                                data.mounted_uid = md->mounted_uid;
-                               data.wdog_pid = md->wdog_pid;
+                               data.wdog_pid = find_get_pid(md->wdog_pid);
                                data.ncp_fd = md->ncp_fd;
                                data.time_out = md->time_out;
                                data.retry_count = md->retry_count;
@@ -474,7 +508,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
        if (!ncp_filp)
                goto out;
        error = -ENOTSOCK;
-       sock_inode = ncp_filp->f_dentry->d_inode;
+       sock_inode = ncp_filp->f_path.dentry->d_inode;
        if (!S_ISSOCK(sock_inode->i_mode))
                goto out_fput;
        sock = SOCKET_I(sock_inode);
@@ -492,10 +526,15 @@ 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_bdi = &server->bdi;
 
        server = NCP_SBP(sb);
        memset(server, 0, sizeof(*server));
 
+       error = bdi_setup_and_register(&server->bdi, "ncpfs", BDI_CAP_MAP_COPY);
+       if (error)
+               goto out_bdi;
+
        server->ncp_filp = ncp_filp;
        server->ncp_sock = sock;
        
@@ -507,7 +546,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
                if (!server->info_filp)
                        goto out_fput;
                error = -ENOTSOCK;
-               sock_inode = server->info_filp->f_dentry->d_inode;
+               sock_inode = server->info_filp->f_path.dentry->d_inode;
                if (!S_ISSOCK(sock_inode->i_mode))
                        goto out_fput2;
                info_sock = SOCKET_I(sock_inode);
@@ -573,6 +612,12 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
        server->packet = vmalloc(NCP_PACKET_SIZE);
        if (server->packet == NULL)
                goto out_nls;
+       server->txbuf = vmalloc(NCP_PACKET_SIZE);
+       if (server->txbuf == NULL)
+               goto out_packet;
+       server->rxbuf = vmalloc(NCP_PACKET_SIZE);
+       if (server->rxbuf == NULL)
+               goto out_txbuf;
 
        sock->sk->sk_data_ready   = ncp_tcp_data_ready;
        sock->sk->sk_error_report = ncp_tcp_error_report;
@@ -580,12 +625,12 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
                server->rcv.ptr = (unsigned char*)&server->rcv.buf;
                server->rcv.len = 10;
                server->rcv.state = 0;
-               INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc, server);
-               INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc, server);
+               INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc);
+               INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc);
                sock->sk->sk_write_space = ncp_tcp_write_space;
        } else {
-               INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc, server);
-               INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc, server);
+               INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc);
+               INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc);
                server->timeout_tm.data = (unsigned long)server;
                server->timeout_tm.function = ncpdgram_timeout_call;
        }
@@ -594,7 +639,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
        error = ncp_connect(server);
        ncp_unlock_server(server);
        if (error < 0)
-               goto out_packet;
+               goto out_rxbuf;
        DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
 
        error = -EMSGSIZE;      /* -EREMOTESIDEINCOMPATIBLE */
@@ -663,8 +708,12 @@ out_disconnect:
        ncp_lock_server(server);
        ncp_disconnect(server);
        ncp_unlock_server(server);
-out_packet:
+out_rxbuf:
        ncp_stop_tasks(server);
+       vfree(server->rxbuf);
+out_txbuf:
+       vfree(server->txbuf);
+out_packet:
        vfree(server->packet);
 out_nls:
 #ifdef CONFIG_NCPFS_NLS
@@ -675,6 +724,8 @@ out_fput2:
        if (server->info_filp)
                fput(server->info_filp);
 out_fput:
+       bdi_destroy(&server->bdi);
+out_bdi:
        /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>:
         * 
         * The previously used put_filp(ncp_filp); was bogous, since
@@ -682,6 +733,7 @@ out_fput:
         */
        fput(ncp_filp);
 out:
+       put_pid(data.wdog_pid);
        sb->s_fs_info = NULL;
        kfree(server);
        return error;
@@ -691,6 +743,8 @@ 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);
@@ -699,28 +753,26 @@ static void ncp_put_super(struct super_block *sb)
 
 #ifdef CONFIG_NCPFS_NLS
        /* unload the NLS charsets */
-       if (server->nls_vol)
-       {
-               unload_nls(server->nls_vol);
-               server->nls_vol = NULL;
-       }
-       if (server->nls_io)
-       {
-               unload_nls(server->nls_io);
-               server->nls_io = NULL;
-       }
+       unload_nls(server->nls_vol);
+       unload_nls(server->nls_io);
 #endif /* CONFIG_NCPFS_NLS */
 
        if (server->info_filp)
                fput(server->info_filp);
        fput(server->ncp_filp);
-       kill_proc(server->m.wdog_pid, SIGTERM, 1);
+       kill_pid(server->m.wdog_pid, SIGTERM, 1);
+       put_pid(server->m.wdog_pid);
 
+       bdi_destroy(&server->bdi);
        kfree(server->priv.data);
        kfree(server->auth.object_name);
+       vfree(server->rxbuf);
+       vfree(server->txbuf);
        vfree(server->packet);
        sb->s_fs_info = NULL;
        kfree(server);
+
+       unlock_kernel();
 }
 
 static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
@@ -968,12 +1020,13 @@ static struct file_system_type ncp_fs_type = {
        .name           = "ncpfs",
        .get_sb         = ncp_get_sb,
        .kill_sb        = kill_anon_super,
+       .fs_flags       = FS_BINARY_MOUNTDATA,
 };
 
 static int __init init_ncp_fs(void)
 {
        int err;
-       DPRINTK("ncpfs: init_module called\n");
+       DPRINTK("ncpfs: init_ncp_fs called\n");
 
        err = init_inodecache();
        if (err)
@@ -990,7 +1043,7 @@ out1:
 
 static void __exit exit_ncp_fs(void)
 {
-       DPRINTK("ncpfs: cleanup_module called\n");
+       DPRINTK("ncpfs: exit_ncp_fs called\n");
        unregister_filesystem(&ncp_fs_type);
        destroy_inodecache();
 }