Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 140217
b: refs/heads/master
c: 0873404
h: refs/heads/master
i:
  140215: 126ea1e
v: v3
  • Loading branch information
David Howells committed Apr 3, 2009
1 parent 15abc7e commit 1e64e0f
Show file tree
Hide file tree
Showing 7 changed files with 215 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 147272813e043fb44bd112527951da70c1e663de
refs/heads/master: 08734048b380103f0412f58b84c2f76a2c8b599f
34 changes: 34 additions & 0 deletions trunk/fs/nfs/fscache-index.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,37 @@ const struct fscache_cookie_def nfs_fscache_server_index_def = {
.type = FSCACHE_COOKIE_TYPE_INDEX,
.get_key = nfs_server_get_key,
};

/*
* Generate a key to describe a superblock key in the main NFS index
*/
static uint16_t nfs_super_get_key(const void *cookie_netfs_data,
void *buffer, uint16_t bufmax)
{
const struct nfs_fscache_key *key;
const struct nfs_server *nfss = cookie_netfs_data;
uint16_t len;

key = nfss->fscache_key;
len = sizeof(key->key) + key->key.uniq_len;
if (len > bufmax) {
len = 0;
} else {
memcpy(buffer, &key->key, sizeof(key->key));
memcpy(buffer + sizeof(key->key),
key->key.uniquifier, key->key.uniq_len);
}

return len;
}

/*
* Define the superblock object for FS-Cache. This is used to describe a
* superblock object to fscache_acquire_cookie(). It is keyed by all the NFS
* parameters that might cause a separate superblock.
*/
const struct fscache_cookie_def nfs_fscache_super_index_def = {
.name = "NFS.super",
.type = FSCACHE_COOKIE_TYPE_INDEX,
.get_key = nfs_super_get_key,
};
116 changes: 116 additions & 0 deletions trunk/fs/nfs/fscache.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@

#define NFSDBG_FACILITY NFSDBG_FSCACHE

static struct rb_root nfs_fscache_keys = RB_ROOT;
static DEFINE_SPINLOCK(nfs_fscache_keys_lock);

/*
* Get the per-client index cookie for an NFS client if the appropriate mount
* flag was set
Expand Down Expand Up @@ -50,3 +53,116 @@ void nfs_fscache_release_client_cookie(struct nfs_client *clp)
fscache_relinquish_cookie(clp->fscache, 0);
clp->fscache = NULL;
}

/*
* Get the cache cookie for an NFS superblock. We have to handle
* uniquification here because the cache doesn't do it for us.
*/
void nfs_fscache_get_super_cookie(struct super_block *sb,
struct nfs_parsed_mount_data *data)
{
struct nfs_fscache_key *key, *xkey;
struct nfs_server *nfss = NFS_SB(sb);
struct rb_node **p, *parent;
const char *uniq = data->fscache_uniq ?: "";
int diff, ulen;

ulen = strlen(uniq);
key = kzalloc(sizeof(*key) + ulen, GFP_KERNEL);
if (!key)
return;

key->nfs_client = nfss->nfs_client;
key->key.super.s_flags = sb->s_flags & NFS_MS_MASK;
key->key.nfs_server.flags = nfss->flags;
key->key.nfs_server.rsize = nfss->rsize;
key->key.nfs_server.wsize = nfss->wsize;
key->key.nfs_server.acregmin = nfss->acregmin;
key->key.nfs_server.acregmax = nfss->acregmax;
key->key.nfs_server.acdirmin = nfss->acdirmin;
key->key.nfs_server.acdirmax = nfss->acdirmax;
key->key.nfs_server.fsid = nfss->fsid;
key->key.rpc_auth.au_flavor = nfss->client->cl_auth->au_flavor;

key->key.uniq_len = ulen;
memcpy(key->key.uniquifier, uniq, ulen);

spin_lock(&nfs_fscache_keys_lock);
p = &nfs_fscache_keys.rb_node;
parent = NULL;
while (*p) {
parent = *p;
xkey = rb_entry(parent, struct nfs_fscache_key, node);

if (key->nfs_client < xkey->nfs_client)
goto go_left;
if (key->nfs_client > xkey->nfs_client)
goto go_right;

diff = memcmp(&key->key, &xkey->key, sizeof(key->key));
if (diff < 0)
goto go_left;
if (diff > 0)
goto go_right;

if (key->key.uniq_len == 0)
goto non_unique;
diff = memcmp(key->key.uniquifier,
xkey->key.uniquifier,
key->key.uniq_len);
if (diff < 0)
goto go_left;
if (diff > 0)
goto go_right;
goto non_unique;

go_left:
p = &(*p)->rb_left;
continue;
go_right:
p = &(*p)->rb_right;
}

rb_link_node(&key->node, parent, p);
rb_insert_color(&key->node, &nfs_fscache_keys);
spin_unlock(&nfs_fscache_keys_lock);
nfss->fscache_key = key;

/* create a cache index for looking up filehandles */
nfss->fscache = fscache_acquire_cookie(nfss->nfs_client->fscache,
&nfs_fscache_super_index_def,
nfss);
dfprintk(FSCACHE, "NFS: get superblock cookie (0x%p/0x%p)\n",
nfss, nfss->fscache);
return;

non_unique:
spin_unlock(&nfs_fscache_keys_lock);
kfree(key);
nfss->fscache_key = NULL;
nfss->fscache = NULL;
printk(KERN_WARNING "NFS:"
" Cache request denied due to non-unique superblock keys\n");
}

/*
* release a per-superblock cookie
*/
void nfs_fscache_release_super_cookie(struct super_block *sb)
{
struct nfs_server *nfss = NFS_SB(sb);

dfprintk(FSCACHE, "NFS: releasing superblock cookie (0x%p/0x%p)\n",
nfss, nfss->fscache);

fscache_relinquish_cookie(nfss->fscache, 0);
nfss->fscache = NULL;

if (nfss->fscache_key) {
spin_lock(&nfs_fscache_keys_lock);
rb_erase(&nfss->fscache_key->node, &nfs_fscache_keys);
spin_unlock(&nfs_fscache_keys_lock);
kfree(nfss->fscache_key);
nfss->fscache_key = NULL;
}
}
49 changes: 49 additions & 0 deletions trunk/fs/nfs/fscache.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,49 @@

#ifdef CONFIG_NFS_FSCACHE

/*
* set of NFS FS-Cache objects that form a superblock key
*/
struct nfs_fscache_key {
struct rb_node node;
struct nfs_client *nfs_client; /* the server */

/* the elements of the unique key - as used by nfs_compare_super() and
* nfs_compare_mount_options() to distinguish superblocks */
struct {
struct {
unsigned long s_flags; /* various flags
* (& NFS_MS_MASK) */
} super;

struct {
struct nfs_fsid fsid;
int flags;
unsigned int rsize; /* read size */
unsigned int wsize; /* write size */
unsigned int acregmin; /* attr cache timeouts */
unsigned int acregmax;
unsigned int acdirmin;
unsigned int acdirmax;
} nfs_server;

struct {
rpc_authflavor_t au_flavor;
} rpc_auth;

/* uniquifier - can be used if nfs_server.flags includes
* NFS_MOUNT_UNSHARED */
u8 uniq_len;
char uniquifier[0];
} key;
};

/*
* fscache-index.c
*/
extern struct fscache_netfs nfs_fscache_netfs;
extern const struct fscache_cookie_def nfs_fscache_server_index_def;
extern const struct fscache_cookie_def nfs_fscache_super_index_def;

extern int nfs_fscache_register(void);
extern void nfs_fscache_unregister(void);
Expand All @@ -34,12 +72,23 @@ extern void nfs_fscache_unregister(void);
extern void nfs_fscache_get_client_cookie(struct nfs_client *);
extern void nfs_fscache_release_client_cookie(struct nfs_client *);

extern void nfs_fscache_get_super_cookie(struct super_block *,
struct nfs_parsed_mount_data *);
extern void nfs_fscache_release_super_cookie(struct super_block *);

#else /* CONFIG_NFS_FSCACHE */
static inline int nfs_fscache_register(void) { return 0; }
static inline void nfs_fscache_unregister(void) {}

static inline void nfs_fscache_get_client_cookie(struct nfs_client *clp) {}
static inline void nfs_fscache_release_client_cookie(struct nfs_client *clp) {}

static inline void nfs_fscache_get_super_cookie(
struct super_block *sb,
struct nfs_parsed_mount_data *data)
{
}
static inline void nfs_fscache_release_super_cookie(struct super_block *sb) {}

#endif /* CONFIG_NFS_FSCACHE */
#endif /* _NFS_FSCACHE_H */
3 changes: 3 additions & 0 deletions trunk/fs/nfs/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <linux/mount.h>
#include <linux/security.h>

#define NFS_MS_MASK (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_SYNCHRONOUS)

struct nfs_string;

/* Maximum number of readahead requests
Expand Down Expand Up @@ -41,6 +43,7 @@ struct nfs_parsed_mount_data {
unsigned int auth_flavor_len;
rpc_authflavor_t auth_flavors[1];
char *client_address;
char *fscache_uniq;

struct {
struct sockaddr_storage address;
Expand Down
9 changes: 7 additions & 2 deletions trunk/fs/nfs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
#include "delegation.h"
#include "iostat.h"
#include "internal.h"
#include "fscache.h"

#define NFSDBG_FACILITY NFSDBG_VFS

Expand Down Expand Up @@ -1870,8 +1871,6 @@ static void nfs_clone_super(struct super_block *sb,
nfs_initialise_sb(sb);
}

#define NFS_MS_MASK (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_SYNCHRONOUS)

static int nfs_compare_mount_options(const struct super_block *s, const struct nfs_server *b, int flags)
{
const struct nfs_server *a = s->s_fs_info;
Expand Down Expand Up @@ -2036,6 +2035,7 @@ static int nfs_get_sb(struct file_system_type *fs_type,
if (!s->s_root) {
/* initial superblock/root creation */
nfs_fill_super(s, data);
nfs_fscache_get_super_cookie(s, data);
}

mntroot = nfs_get_root(s, mntfh);
Expand All @@ -2056,6 +2056,7 @@ static int nfs_get_sb(struct file_system_type *fs_type,
out:
kfree(data->nfs_server.hostname);
kfree(data->mount_server.hostname);
kfree(data->fscache_uniq);
security_free_mnt_opts(&data->lsm_opts);
out_free_fh:
kfree(mntfh);
Expand Down Expand Up @@ -2083,6 +2084,7 @@ static void nfs_kill_super(struct super_block *s)

bdi_unregister(&server->backing_dev_info);
kill_anon_super(s);
nfs_fscache_release_super_cookie(s);
nfs_free_server(server);
}

Expand Down Expand Up @@ -2390,6 +2392,7 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
if (!s->s_root) {
/* initial superblock/root creation */
nfs4_fill_super(s);
nfs_fscache_get_super_cookie(s, data);
}

mntroot = nfs4_get_root(s, mntfh);
Expand All @@ -2411,6 +2414,7 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
kfree(data->client_address);
kfree(data->nfs_server.export_path);
kfree(data->nfs_server.hostname);
kfree(data->fscache_uniq);
security_free_mnt_opts(&data->lsm_opts);
out_free_fh:
kfree(mntfh);
Expand All @@ -2437,6 +2441,7 @@ static void nfs4_kill_super(struct super_block *sb)
kill_anon_super(sb);

nfs4_renewd_prepare_shutdown(server);
nfs_fscache_release_super_cookie(sb);
nfs_free_server(server);
}

Expand Down
5 changes: 5 additions & 0 deletions trunk/include/linux/nfs_fs_sb.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ struct nfs_server {
unsigned long mount_time; /* when this fs was mounted */
dev_t s_dev; /* superblock dev numbers */

#ifdef CONFIG_NFS_FSCACHE
struct nfs_fscache_key *fscache_key; /* unique key for superblock */
struct fscache_cookie *fscache; /* superblock cookie */
#endif

#ifdef CONFIG_NFS_V4
u32 attr_bitmask[2];/* V4 bitmask representing the set
of attributes supported on this
Expand Down

0 comments on commit 1e64e0f

Please sign in to comment.