NFS: Define and create inode-level cache objects
[deliverable/linux.git] / fs / nfs / fscache.c
CommitLineData
14727281
DH
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
08734048
DH
26static struct rb_root nfs_fscache_keys = RB_ROOT;
27static DEFINE_SPINLOCK(nfs_fscache_keys_lock);
28
14727281
DH
29/*
30 * Get the per-client index cookie for an NFS client if the appropriate mount
31 * flag was set
32 * - We always try and get an index cookie for the client, but get filehandle
33 * cookies on a per-superblock basis, depending on the mount flags
34 */
35void nfs_fscache_get_client_cookie(struct nfs_client *clp)
36{
37 /* create a cache index for looking up filehandles */
38 clp->fscache = fscache_acquire_cookie(nfs_fscache_netfs.primary_index,
39 &nfs_fscache_server_index_def,
40 clp);
41 dfprintk(FSCACHE, "NFS: get client cookie (0x%p/0x%p)\n",
42 clp, clp->fscache);
43}
44
45/*
46 * Dispose of a per-client cookie
47 */
48void nfs_fscache_release_client_cookie(struct nfs_client *clp)
49{
50 dfprintk(FSCACHE, "NFS: releasing client cookie (0x%p/0x%p)\n",
51 clp, clp->fscache);
52
53 fscache_relinquish_cookie(clp->fscache, 0);
54 clp->fscache = NULL;
55}
08734048
DH
56
57/*
58 * Get the cache cookie for an NFS superblock. We have to handle
59 * uniquification here because the cache doesn't do it for us.
60 */
61void nfs_fscache_get_super_cookie(struct super_block *sb,
62 struct nfs_parsed_mount_data *data)
63{
64 struct nfs_fscache_key *key, *xkey;
65 struct nfs_server *nfss = NFS_SB(sb);
66 struct rb_node **p, *parent;
67 const char *uniq = data->fscache_uniq ?: "";
68 int diff, ulen;
69
70 ulen = strlen(uniq);
71 key = kzalloc(sizeof(*key) + ulen, GFP_KERNEL);
72 if (!key)
73 return;
74
75 key->nfs_client = nfss->nfs_client;
76 key->key.super.s_flags = sb->s_flags & NFS_MS_MASK;
77 key->key.nfs_server.flags = nfss->flags;
78 key->key.nfs_server.rsize = nfss->rsize;
79 key->key.nfs_server.wsize = nfss->wsize;
80 key->key.nfs_server.acregmin = nfss->acregmin;
81 key->key.nfs_server.acregmax = nfss->acregmax;
82 key->key.nfs_server.acdirmin = nfss->acdirmin;
83 key->key.nfs_server.acdirmax = nfss->acdirmax;
84 key->key.nfs_server.fsid = nfss->fsid;
85 key->key.rpc_auth.au_flavor = nfss->client->cl_auth->au_flavor;
86
87 key->key.uniq_len = ulen;
88 memcpy(key->key.uniquifier, uniq, ulen);
89
90 spin_lock(&nfs_fscache_keys_lock);
91 p = &nfs_fscache_keys.rb_node;
92 parent = NULL;
93 while (*p) {
94 parent = *p;
95 xkey = rb_entry(parent, struct nfs_fscache_key, node);
96
97 if (key->nfs_client < xkey->nfs_client)
98 goto go_left;
99 if (key->nfs_client > xkey->nfs_client)
100 goto go_right;
101
102 diff = memcmp(&key->key, &xkey->key, sizeof(key->key));
103 if (diff < 0)
104 goto go_left;
105 if (diff > 0)
106 goto go_right;
107
108 if (key->key.uniq_len == 0)
109 goto non_unique;
110 diff = memcmp(key->key.uniquifier,
111 xkey->key.uniquifier,
112 key->key.uniq_len);
113 if (diff < 0)
114 goto go_left;
115 if (diff > 0)
116 goto go_right;
117 goto non_unique;
118
119 go_left:
120 p = &(*p)->rb_left;
121 continue;
122 go_right:
123 p = &(*p)->rb_right;
124 }
125
126 rb_link_node(&key->node, parent, p);
127 rb_insert_color(&key->node, &nfs_fscache_keys);
128 spin_unlock(&nfs_fscache_keys_lock);
129 nfss->fscache_key = key;
130
131 /* create a cache index for looking up filehandles */
132 nfss->fscache = fscache_acquire_cookie(nfss->nfs_client->fscache,
133 &nfs_fscache_super_index_def,
134 nfss);
135 dfprintk(FSCACHE, "NFS: get superblock cookie (0x%p/0x%p)\n",
136 nfss, nfss->fscache);
137 return;
138
139non_unique:
140 spin_unlock(&nfs_fscache_keys_lock);
141 kfree(key);
142 nfss->fscache_key = NULL;
143 nfss->fscache = NULL;
144 printk(KERN_WARNING "NFS:"
145 " Cache request denied due to non-unique superblock keys\n");
146}
147
148/*
149 * release a per-superblock cookie
150 */
151void nfs_fscache_release_super_cookie(struct super_block *sb)
152{
153 struct nfs_server *nfss = NFS_SB(sb);
154
155 dfprintk(FSCACHE, "NFS: releasing superblock cookie (0x%p/0x%p)\n",
156 nfss, nfss->fscache);
157
158 fscache_relinquish_cookie(nfss->fscache, 0);
159 nfss->fscache = NULL;
160
161 if (nfss->fscache_key) {
162 spin_lock(&nfs_fscache_keys_lock);
163 rb_erase(&nfss->fscache_key->node, &nfs_fscache_keys);
164 spin_unlock(&nfs_fscache_keys_lock);
165 kfree(nfss->fscache_key);
166 nfss->fscache_key = NULL;
167 }
168}
This page took 0.031431 seconds and 5 git commands to generate.