diff options
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/Makefile | 2 | ||||
-rw-r--r-- | fs/nfs/client.c | 5 | ||||
-rw-r--r-- | fs/nfs/fscache-index.c | 65 | ||||
-rw-r--r-- | fs/nfs/fscache.c | 52 | ||||
-rw-r--r-- | fs/nfs/fscache.h | 10 |
5 files changed, 133 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 |
17 | nfs-$(CONFIG_SYSCTL) += sysctl.o | 17 | nfs-$(CONFIG_SYSCTL) += sysctl.o |
18 | nfs-$(CONFIG_NFS_FSCACHE) += fscache-index.o | 18 | nfs-$(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 | ||
159 | error_3: | 162 | error_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 | */ | ||
54 | struct 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 | */ | ||
68 | static 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 | */ | ||
110 | const 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 | */ | ||
32 | void 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 | */ | ||
45 | void 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 | */ |
25 | extern struct fscache_netfs nfs_fscache_netfs; | 25 | extern struct fscache_netfs nfs_fscache_netfs; |
26 | extern const struct fscache_cookie_def nfs_fscache_server_index_def; | ||
26 | 27 | ||
27 | extern int nfs_fscache_register(void); | 28 | extern int nfs_fscache_register(void); |
28 | extern void nfs_fscache_unregister(void); | 29 | extern void nfs_fscache_unregister(void); |
29 | 30 | ||
31 | /* | ||
32 | * fscache.c | ||
33 | */ | ||
34 | extern void nfs_fscache_get_client_cookie(struct nfs_client *); | ||
35 | extern void nfs_fscache_release_client_cookie(struct nfs_client *); | ||
36 | |||
30 | #else /* CONFIG_NFS_FSCACHE */ | 37 | #else /* CONFIG_NFS_FSCACHE */ |
31 | static inline int nfs_fscache_register(void) { return 0; } | 38 | static inline int nfs_fscache_register(void) { return 0; } |
32 | static inline void nfs_fscache_unregister(void) {} | 39 | static inline void nfs_fscache_unregister(void) {} |
33 | 40 | ||
41 | static inline void nfs_fscache_get_client_cookie(struct nfs_client *clp) {} | ||
42 | static 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 */ |