📄 inode.c
字号:
rpciod_down(); /* release rpciod */ destroy_nfsv4_state(server); if (server->hostname != NULL) kfree(server->hostname); kfree(server);}static struct file_system_type nfs_fs_type = { .owner = THIS_MODULE, .name = "nfs", .get_sb = nfs_get_sb, .kill_sb = nfs_kill_super, .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,};#ifdef CONFIG_NFS_V4static void nfs4_clear_inode(struct inode *);static struct super_operations nfs4_sops = { .alloc_inode = nfs_alloc_inode, .destroy_inode = nfs_destroy_inode, .write_inode = nfs_write_inode, .delete_inode = nfs_delete_inode, .statfs = nfs_statfs, .clear_inode = nfs4_clear_inode, .umount_begin = nfs_umount_begin, .show_options = nfs_show_options,};/* * Clean out any remaining NFSv4 state that might be left over due * to open() calls that passed nfs_atomic_lookup, but failed to call * nfs_open(). */static void nfs4_clear_inode(struct inode *inode){ struct nfs_inode *nfsi = NFS_I(inode); /* If we are holding a delegation, return it! */ if (nfsi->delegation != NULL) nfs_inode_return_delegation(inode); /* First call standard NFS clear_inode() code */ nfs_clear_inode(inode); /* Now clear out any remaining state */ while (!list_empty(&nfsi->open_states)) { struct nfs4_state *state; state = list_entry(nfsi->open_states.next, struct nfs4_state, inode_states); dprintk("%s(%s/%Ld): found unclaimed NFSv4 state %p\n", __FUNCTION__, inode->i_sb->s_id, (long long)NFS_FILEID(inode), state); BUG_ON(atomic_read(&state->count) != 1); nfs4_close_state(state, state->state); }}static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, int silent){ struct nfs_server *server; struct nfs4_client *clp = NULL; struct rpc_xprt *xprt = NULL; struct rpc_clnt *clnt = NULL; struct rpc_timeout timeparms; rpc_authflavor_t authflavour; int proto, err = -EIO; sb->s_blocksize_bits = 0; sb->s_blocksize = 0; server = NFS_SB(sb); if (data->rsize != 0) server->rsize = nfs_block_size(data->rsize, NULL); if (data->wsize != 0) server->wsize = nfs_block_size(data->wsize, NULL); server->flags = data->flags & NFS_MOUNT_FLAGMASK; /* NFSv4 doesn't use NLM locking */ server->flags |= NFS_MOUNT_NONLM; server->acregmin = data->acregmin*HZ; server->acregmax = data->acregmax*HZ; server->acdirmin = data->acdirmin*HZ; server->acdirmax = data->acdirmax*HZ; server->rpc_ops = &nfs_v4_clientops; /* Initialize timeout values */ timeparms.to_initval = data->timeo * HZ / 10; timeparms.to_retries = data->retrans; timeparms.to_exponential = 1; if (!timeparms.to_retries) timeparms.to_retries = 5; proto = data->proto; /* Which IP protocol do we use? */ switch (proto) { case IPPROTO_TCP: timeparms.to_maxval = RPC_MAX_TCP_TIMEOUT; if (!timeparms.to_initval) timeparms.to_initval = 600 * HZ / 10; break; case IPPROTO_UDP: timeparms.to_maxval = RPC_MAX_UDP_TIMEOUT; if (!timeparms.to_initval) timeparms.to_initval = 11 * HZ / 10; break; default: return -EINVAL; } clp = nfs4_get_client(&server->addr.sin_addr); if (!clp) { printk(KERN_WARNING "NFS: failed to create NFS4 client.\n"); return -EIO; } /* Now create transport and client */ authflavour = RPC_AUTH_UNIX; if (data->auth_flavourlen != 0) { if (data->auth_flavourlen > 1) printk(KERN_INFO "NFS: cannot yet deal with multiple auth flavours.\n"); if (copy_from_user(&authflavour, data->auth_flavours, sizeof(authflavour))) { err = -EFAULT; goto out_fail; } } down_write(&clp->cl_sem); if (clp->cl_rpcclient == NULL) { xprt = xprt_create_proto(proto, &server->addr, &timeparms); if (IS_ERR(xprt)) { up_write(&clp->cl_sem); printk(KERN_WARNING "NFS: cannot create RPC transport.\n"); err = PTR_ERR(xprt); goto out_fail; } clnt = rpc_create_client(xprt, server->hostname, &nfs_program, server->rpc_ops->version, authflavour); if (IS_ERR(clnt)) { up_write(&clp->cl_sem); printk(KERN_WARNING "NFS: cannot create RPC client.\n"); xprt_destroy(xprt); err = PTR_ERR(clnt); goto out_fail; } clnt->cl_chatty = 1; clp->cl_rpcclient = clnt; clp->cl_cred = rpcauth_lookupcred(clnt->cl_auth, 0); memcpy(clp->cl_ipaddr, server->ip_addr, sizeof(clp->cl_ipaddr)); nfs_idmap_new(clp); } if (list_empty(&clp->cl_superblocks)) { err = nfs4_init_client(clp); if (err != 0) { up_write(&clp->cl_sem); goto out_fail; } } list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks); clnt = rpc_clone_client(clp->cl_rpcclient); if (!IS_ERR(clnt)) server->nfs4_state = clp; up_write(&clp->cl_sem); clp = NULL; if (IS_ERR(clnt)) { printk(KERN_WARNING "NFS: cannot create RPC client.\n"); return PTR_ERR(clnt); } clnt->cl_intr = (server->flags & NFS4_MOUNT_INTR) ? 1 : 0; clnt->cl_softrtry = (server->flags & NFS4_MOUNT_SOFT) ? 1 : 0; server->client = clnt; if (server->nfs4_state->cl_idmap == NULL) { printk(KERN_WARNING "NFS: failed to create idmapper.\n"); return -ENOMEM; } if (clnt->cl_auth->au_flavor != authflavour) { if (rpcauth_create(authflavour, clnt) == NULL) { printk(KERN_WARNING "NFS: couldn't create credcache!\n"); return -ENOMEM; } } sb->s_op = &nfs4_sops; err = nfs_sb_init(sb, authflavour); if (err == 0) return 0;out_fail: if (clp) nfs4_put_client(clp); return err;}static int nfs4_compare_super(struct super_block *sb, void *data){ struct nfs_server *server = data; struct nfs_server *old = NFS_SB(sb); if (strcmp(server->hostname, old->hostname) != 0) return 0; if (strcmp(server->mnt_path, old->mnt_path) != 0) return 0; return 1;}static void *nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen){ void *p = NULL; if (!src->len) return ERR_PTR(-EINVAL); if (src->len < maxlen) maxlen = src->len; if (dst == NULL) { p = dst = kmalloc(maxlen + 1, GFP_KERNEL); if (p == NULL) return ERR_PTR(-ENOMEM); } if (copy_from_user(dst, src->data, maxlen)) { if (p != NULL) kfree(p); return ERR_PTR(-EFAULT); } dst[maxlen] = '\0'; return dst;}static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data){ int error; struct nfs_server *server; struct super_block *s; struct nfs4_mount_data *data = raw_data; void *p; if (!data) { printk("nfs_read_super: missing data argument\n"); return ERR_PTR(-EINVAL); } server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL); if (!server) return ERR_PTR(-ENOMEM); memset(server, 0, sizeof(struct nfs_server)); /* Zero out the NFS state stuff */ init_nfsv4_state(server); if (data->version != NFS4_MOUNT_VERSION) { printk("nfs warning: mount version %s than kernel\n", data->version < NFS4_MOUNT_VERSION ? "older" : "newer"); } p = nfs_copy_user_string(NULL, &data->hostname, 256); if (IS_ERR(p)) goto out_err; server->hostname = p; p = nfs_copy_user_string(NULL, &data->mnt_path, 1024); if (IS_ERR(p)) goto out_err; server->mnt_path = p; p = nfs_copy_user_string(server->ip_addr, &data->client_addr, sizeof(server->ip_addr) - 1); if (IS_ERR(p)) goto out_err; /* We now require that the mount process passes the remote address */ if (data->host_addrlen != sizeof(server->addr)) { s = ERR_PTR(-EINVAL); goto out_free; } if (copy_from_user(&server->addr, data->host_addr, sizeof(server->addr))) { s = ERR_PTR(-EFAULT); goto out_free; } if (server->addr.sin_family != AF_INET || server->addr.sin_addr.s_addr == INADDR_ANY) { printk("NFS: mount program didn't pass remote IP address!\n"); s = ERR_PTR(-EINVAL); goto out_free; } s = sget(fs_type, nfs4_compare_super, nfs_set_super, server); if (IS_ERR(s) || s->s_root) goto out_free; s->s_flags = flags; /* Fire up rpciod if not yet running */ if (rpciod_up() != 0) { printk(KERN_WARNING "NFS: couldn't start rpciod!\n"); s = ERR_PTR(-EIO); goto out_free; } error = nfs4_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0); if (error) { up_write(&s->s_umount); deactivate_super(s); return ERR_PTR(error); } s->s_flags |= MS_ACTIVE; return s;out_err: s = (struct super_block *)p;out_free: if (server->mnt_path) kfree(server->mnt_path); if (server->hostname) kfree(server->hostname); kfree(server); return s;}static void nfs4_kill_super(struct super_block *sb){ nfs_return_all_delegations(sb); nfs_kill_super(sb);}static struct file_system_type nfs4_fs_type = { .owner = THIS_MODULE, .name = "nfs4", .get_sb = nfs4_get_sb, .kill_sb = nfs4_kill_super, .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,};#define nfs4_init_once(nfsi) \ do { \ INIT_LIST_HEAD(&(nfsi)->open_states); \ nfsi->delegation = NULL; \ nfsi->delegation_state = 0; \ init_rwsem(&nfsi->rwsem); \ } while(0)#define register_nfs4fs() register_filesystem(&nfs4_fs_type)#define unregister_nfs4fs() unregister_filesystem(&nfs4_fs_type)#else#define nfs4_init_once(nfsi) \ do { } while (0)#define register_nfs4fs() (0)#define unregister_nfs4fs()#endifextern int nfs_init_nfspagecache(void);extern void nfs_destroy_nfspagecache(void);extern int nfs_init_readpagecache(void);extern int nfs_destroy_readpagecache(void);extern int nfs_init_writepagecache(void);extern int nfs_destroy_writepagecache(void);static kmem_cache_t * nfs_inode_cachep;static struct inode *nfs_alloc_inode(struct super_block *sb){ struct nfs_inode *nfsi; nfsi = (struct nfs_inode *)kmem_cache_alloc(nfs_inode_cachep, SLAB_KERNEL); if (!nfsi) return NULL; nfsi->flags = 0; return &nfsi->vfs_inode;}static void nfs_destroy_inode(struct inode *inode){ kmem_cache_free(nfs_inode_cachep, NFS_I(inode));}static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags){ struct nfs_inode *nfsi = (struct nfs_inode *) foo; if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) { inode_init_once(&nfsi->vfs_inode); spin_lock_init(&nfsi->req_lock); INIT_LIST_HEAD(&nfsi->dirty); INIT_LIST_HEAD(&nfsi->commit); INIT_LIST_HEAD(&nfsi->open_files); INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC); atomic_set(&nfsi->data_updates, 0); nfsi->ndirty = 0; nfsi->ncommit = 0; nfsi->npages = 0; init_waitqueue_head(&nfsi->nfs_i_wait); nfs4_init_once(nfsi); }} int nfs_init_inodecache(void){ nfs_inode_cachep = kmem_cache_create("nfs_inode_cache", sizeof(struct nfs_inode), 0, SLAB_RECLAIM_ACCOUNT, init_once, NULL); if (nfs_inode_cachep == NULL) return -ENOMEM; return 0;}void nfs_destroy_inodecache(void){ if (kmem_cache_destroy(nfs_inode_cachep)) printk(KERN_INFO "nfs_inode_cache: not all structures were freed\n");}/* * Initialize NFS */static int __init init_nfs_fs(void){ int err; err = nfs_init_nfspagecache(); if (err) goto out4; err = nfs_init_inodecache(); if (err) goto out3; err = nfs_init_readpagecache(); if (err) goto out2; err = nfs_init_writepagecache(); if (err) goto out1;#ifdef CONFIG_PROC_FS rpc_proc_register(&nfs_rpcstat);#endif err = register_filesystem(&nfs_fs_type); if (err) goto out; if ((err = register_nfs4fs()) != 0) goto out; return 0;out: rpc_proc_unregister("nfs"); nfs_destroy_writepagecache();out1: nfs_destroy_readpagecache();out2: nfs_destroy_inodecache();out3: nfs_destroy_nfspagecache();out4: return err;}static void __exit exit_nfs_fs(void){ nfs_destroy_writepagecache(); nfs_destroy_readpagecache(); nfs_destroy_inodecache(); nfs_destroy_nfspagecache();#ifdef CONFIG_PROC_FS rpc_proc_unregister("nfs");#endif unregister_filesystem(&nfs_fs_type); unregister_nfs4fs();}/* Not quite true; I just maintain it */MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");MODULE_LICENSE("GPL");module_init(init_nfs_fs)module_exit(exit_nfs_fs)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -