aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2009-04-03 11:42:42 -0400
committerDavid Howells <dhowells@redhat.com>2009-04-03 11:42:42 -0400
commit147272813e043fb44bd112527951da70c1e663de (patch)
tree4b67df2bb809c7b661e7c6f4b1692ab8af41a996
parent8ec442ae4c6577ed181682e534d4eef524e30b3c (diff)
NFS: Define and create server-level objects
Define and create server-level cache index objects (as managed by nfs_client structs). Each server object is created in the NFS top-level index object and is itself an index into which superblock-level objects are inserted. Ideally there would be one superblock-level object per server, and the former would be folded into the latter; however, since the "nosharecache" option exists this isn't possible. The server object key is a sequence consisting of: (1) NFS version (2) Server address family (eg: AF_INET or AF_INET6) (3) Server port. (4) Server IP address. The key blob is of variable length, depending on the length of (4). The server object is given no coherency data to carry in the auxiliary data permitted by the cache. Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: Steve Dickson <steved@redhat.com> Acked-by: Trond Myklebust <Trond.Myklebust@netapp.com> Acked-by: Al Viro <viro@zeniv.linux.org.uk> Tested-by: Daire Byrne <Daire.Byrne@framestore.com>
-rw-r--r--fs/nfs/Makefile2
-rw-r--r--fs/nfs/client.c5
-rw-r--r--fs/nfs/fscache-index.c65
-rw-r--r--fs/nfs/fscache.c52
-rw-r--r--fs/nfs/fscache.h10
-rw-r--r--include/linux/nfs_fs_sb.h4
6 files changed, 137 insertions, 1 deletions
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 0e0bb6c17a86..845159814de2 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -15,4 +15,4 @@ nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
15 callback.o callback_xdr.o callback_proc.o \ 15 callback.o callback_xdr.o callback_proc.o \
16 nfs4namespace.o 16 nfs4namespace.o
17nfs-$(CONFIG_SYSCTL) += sysctl.o 17nfs-$(CONFIG_SYSCTL) += sysctl.o
18nfs-$(CONFIG_NFS_FSCACHE) += fscache-index.o 18nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index aba38017bdef..aa04da8748a6 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -45,6 +45,7 @@
45#include "delegation.h" 45#include "delegation.h"
46#include "iostat.h" 46#include "iostat.h"
47#include "internal.h" 47#include "internal.h"
48#include "fscache.h"
48 49
49#define NFSDBG_FACILITY NFSDBG_CLIENT 50#define NFSDBG_FACILITY NFSDBG_CLIENT
50 51
@@ -154,6 +155,8 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
154 if (!IS_ERR(cred)) 155 if (!IS_ERR(cred))
155 clp->cl_machine_cred = cred; 156 clp->cl_machine_cred = cred;
156 157
158 nfs_fscache_get_client_cookie(clp);
159
157 return clp; 160 return clp;
158 161
159error_3: 162error_3:
@@ -187,6 +190,8 @@ static void nfs_free_client(struct nfs_client *clp)
187 190
188 nfs4_shutdown_client(clp); 191 nfs4_shutdown_client(clp);
189 192
193 nfs_fscache_release_client_cookie(clp);
194
190 /* -EIO all pending I/O */ 195 /* -EIO all pending I/O */
191 if (!IS_ERR(clp->cl_rpcclient)) 196 if (!IS_ERR(clp->cl_rpcclient))
192 rpc_shutdown_client(clp->cl_rpcclient); 197 rpc_shutdown_client(clp->cl_rpcclient);
diff --git a/fs/nfs/fscache-index.c b/fs/nfs/fscache-index.c
index 6d5bb5c69048..ff14b032459b 100644
--- a/fs/nfs/fscache-index.c
+++ b/fs/nfs/fscache-index.c
@@ -47,3 +47,68 @@ void nfs_fscache_unregister(void)
47{ 47{
48 fscache_unregister_netfs(&nfs_fscache_netfs); 48 fscache_unregister_netfs(&nfs_fscache_netfs);
49} 49}
50
51/*
52 * Layout of the key for an NFS server cache object.
53 */
54struct nfs_server_key {
55 uint16_t nfsversion; /* NFS protocol version */
56 uint16_t family; /* address family */
57 uint16_t port; /* IP port */
58 union {
59 struct in_addr ipv4_addr; /* IPv4 address */
60 struct in6_addr ipv6_addr; /* IPv6 address */
61 } addr[0];
62};
63
64/*
65 * Generate a key to describe a server in the main NFS index
66 * - We return the length of the key, or 0 if we can't generate one
67 */
68static uint16_t nfs_server_get_key(const void *cookie_netfs_data,
69 void *buffer, uint16_t bufmax)
70{
71 const struct nfs_client *clp = cookie_netfs_data;
72 const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &clp->cl_addr;
73 const struct sockaddr_in *sin = (struct sockaddr_in *) &clp->cl_addr;
74 struct nfs_server_key *key = buffer;
75 uint16_t len = sizeof(struct nfs_server_key);
76
77 key->nfsversion = clp->rpc_ops->version;
78 key->family = clp->cl_addr.ss_family;
79
80 memset(key, 0, len);
81
82 switch (clp->cl_addr.ss_family) {
83 case AF_INET:
84 key->port = sin->sin_port;
85 key->addr[0].ipv4_addr = sin->sin_addr;
86 len += sizeof(key->addr[0].ipv4_addr);
87 break;
88
89 case AF_INET6:
90 key->port = sin6->sin6_port;
91 key->addr[0].ipv6_addr = sin6->sin6_addr;
92 len += sizeof(key->addr[0].ipv6_addr);
93 break;
94
95 default:
96 printk(KERN_WARNING "NFS: Unknown network family '%d'\n",
97 clp->cl_addr.ss_family);
98 len = 0;
99 break;
100 }
101
102 return len;
103}
104
105/*
106 * Define the server object for FS-Cache. This is used to describe a server
107 * object to fscache_acquire_cookie(). It is keyed by the NFS protocol and
108 * server address parameters.
109 */
110const struct fscache_cookie_def nfs_fscache_server_index_def = {
111 .name = "NFS.server",
112 .type = FSCACHE_COOKIE_TYPE_INDEX,
113 .get_key = nfs_server_get_key,
114};
diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
new file mode 100644
index 000000000000..c3f056f89477
--- /dev/null
+++ b/fs/nfs/fscache.c
@@ -0,0 +1,52 @@
1/* NFS filesystem cache interface
2 *
3 * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12#include <linux/init.h>
13#include <linux/kernel.h>
14#include <linux/sched.h>
15#include <linux/mm.h>
16#include <linux/nfs_fs.h>
17#include <linux/nfs_fs_sb.h>
18#include <linux/in6.h>
19#include <linux/seq_file.h>
20
21#include "internal.h"
22#include "fscache.h"
23
24#define NFSDBG_FACILITY NFSDBG_FSCACHE
25
26/*
27 * Get the per-client index cookie for an NFS client if the appropriate mount
28 * flag was set
29 * - We always try and get an index cookie for the client, but get filehandle
30 * cookies on a per-superblock basis, depending on the mount flags
31 */
32void nfs_fscache_get_client_cookie(struct nfs_client *clp)
33{
34 /* create a cache index for looking up filehandles */
35 clp->fscache = fscache_acquire_cookie(nfs_fscache_netfs.primary_index,
36 &nfs_fscache_server_index_def,
37 clp);
38 dfprintk(FSCACHE, "NFS: get client cookie (0x%p/0x%p)\n",
39 clp, clp->fscache);
40}
41
42/*
43 * Dispose of a per-client cookie
44 */
45void nfs_fscache_release_client_cookie(struct nfs_client *clp)
46{
47 dfprintk(FSCACHE, "NFS: releasing client cookie (0x%p/0x%p)\n",
48 clp, clp->fscache);
49
50 fscache_relinquish_cookie(clp->fscache, 0);
51 clp->fscache = NULL;
52}
diff --git a/fs/nfs/fscache.h b/fs/nfs/fscache.h
index ccfcdc58066e..1d864bedf154 100644
--- a/fs/nfs/fscache.h
+++ b/fs/nfs/fscache.h
@@ -23,13 +23,23 @@
23 * fscache-index.c 23 * fscache-index.c
24 */ 24 */
25extern struct fscache_netfs nfs_fscache_netfs; 25extern struct fscache_netfs nfs_fscache_netfs;
26extern const struct fscache_cookie_def nfs_fscache_server_index_def;
26 27
27extern int nfs_fscache_register(void); 28extern int nfs_fscache_register(void);
28extern void nfs_fscache_unregister(void); 29extern void nfs_fscache_unregister(void);
29 30
31/*
32 * fscache.c
33 */
34extern void nfs_fscache_get_client_cookie(struct nfs_client *);
35extern void nfs_fscache_release_client_cookie(struct nfs_client *);
36
30#else /* CONFIG_NFS_FSCACHE */ 37#else /* CONFIG_NFS_FSCACHE */
31static inline int nfs_fscache_register(void) { return 0; } 38static inline int nfs_fscache_register(void) { return 0; }
32static inline void nfs_fscache_unregister(void) {} 39static inline void nfs_fscache_unregister(void) {}
33 40
41static inline void nfs_fscache_get_client_cookie(struct nfs_client *clp) {}
42static inline void nfs_fscache_release_client_cookie(struct nfs_client *clp) {}
43
34#endif /* CONFIG_NFS_FSCACHE */ 44#endif /* CONFIG_NFS_FSCACHE */
35#endif /* _NFS_FSCACHE_H */ 45#endif /* _NFS_FSCACHE_H */
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index a749f8564aa6..0a374b9c5093 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -64,6 +64,10 @@ struct nfs_client {
64 char cl_ipaddr[48]; 64 char cl_ipaddr[48];
65 unsigned char cl_id_uniquifier; 65 unsigned char cl_id_uniquifier;
66#endif 66#endif
67
68#ifdef CONFIG_NFS_FSCACHE
69 struct fscache_cookie *fscache; /* client index cache cookie */
70#endif
67}; 71};
68 72
69/* 73/*