]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - fs/ncpfs/inode.c
convert get_sb_nodev() users
[linux-2.6.git] / fs / ncpfs / inode.c
index cf06eb9f050e31db04c2852832471358a790272c..d290545aa0c4b98c932e316c7dd4fcf3961b1126 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"
 
-static void ncp_delete_inode(struct inode *);
+#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_evict_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 struct kmem_cache * ncp_inode_cachep;
 
@@ -56,21 +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, struct kmem_cache * cachep, unsigned long flags)
+static void init_once(void *foo)
 {
        struct ncp_inode_info *ei = (struct ncp_inode_info *) foo;
 
        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;
@@ -92,18 +100,13 @@ static const struct super_operations ncp_sops =
        .alloc_inode    = ncp_alloc_inode,
        .destroy_inode  = ncp_destroy_inode,
        .drop_inode     = generic_delete_inode,
-       .delete_inode   = ncp_delete_inode,
+       .evict_inode    = ncp_evict_inode,
        .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.
  */
@@ -136,7 +139,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);
@@ -155,18 +158,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;
@@ -205,7 +211,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)
 {
@@ -251,6 +257,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)) {
@@ -279,31 +286,64 @@ ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
 }
 
 static void
-ncp_delete_inode(struct inode *inode)
+ncp_evict_inode(struct inode *inode)
 {
        truncate_inode_pages(&inode->i_data, 0);
+       end_writeback(inode);
 
        if (S_ISDIR(inode->i_mode)) {
-               DDPRINTK("ncp_delete_inode: put directory %ld\n", inode->i_ino);
+               DDPRINTK("ncp_evict_inode: put directory %ld\n", inode->i_ino);
        }
 
        if (ncp_make_closed(inode) != 0) {
                /* We can't do anything but complain. */
-               printk(KERN_ERR "ncp_delete_inode: could not close\n");
+               printk(KERN_ERR "ncp_evict_inode: could not close\n");
        }
-       clear_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();
 }
 
+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' },
@@ -331,12 +371,12 @@ static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options)
        data->mounted_uid = 0;
        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;
        
@@ -492,10 +532,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;
        
@@ -526,10 +571,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;        */
@@ -554,16 +601,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
@@ -580,6 +623,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) {
@@ -595,6 +643,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);
@@ -619,8 +668,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 */
@@ -681,14 +732,19 @@ 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);
 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
-        * it doesn't proper unlocking.
+        * The previously used put_filp(ncp_filp); was bogus, since
+        * it doesn't perform proper unlocking.
         */
        fput(ncp_filp);
 out:
@@ -710,17 +766,12 @@ 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 */
+       mutex_destroy(&server->rcv.creq_mutex);
+       mutex_destroy(&server->root_setup_lock);
+       mutex_destroy(&server->mutex);
 
        if (server->info_filp)
                fput(server->info_filp);
@@ -728,6 +779,7 @@ static void ncp_put_super(struct super_block *sb)
        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);
@@ -813,10 +865,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 */
@@ -886,9 +936,8 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
                                tmpattr.ia_valid = ATTR_MODE;
                                tmpattr.ia_mode = attr->ia_mode;
 
-                               result = inode_setattr(inode, &tmpattr);
-                               if (result)
-                                       goto out;
+                               setattr_copy(inode, &tmpattr);
+                               mark_inode_dirty(inode);
                        }
                }
 #endif
@@ -916,15 +965,12 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
                result = ncp_make_closed(inode);
                if (result)
                        goto out;
-               {
-                       struct iattr tmpattr;
-                       
-                       tmpattr.ia_valid = ATTR_SIZE;
-                       tmpattr.ia_size = attr->ia_size;
-                       
-                       result = inode_setattr(inode, &tmpattr);
+
+               if (attr->ia_size != i_size_read(inode)) {
+                       result = vmtruncate(inode, attr->ia_size);
                        if (result)
                                goto out;
+                       mark_inode_dirty(inode);
                }
        }
        if ((attr->ia_valid & ATTR_CTIME) != 0) {
@@ -947,8 +993,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
@@ -964,30 +1008,36 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
                        NCP_FINFO(inode)->nwattr = info.attributes;
 #endif
        }
-       if (!result)
-               result = inode_setattr(inode, attr);
+       if (result)
+               goto out;
+
+       setattr_copy(inode, 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,
 };
 
 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)
@@ -1004,7 +1054,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();
 }