linux/fs/afs/xattr.c
David Howells 989782dcdc afs: Overhaul cell database management
Overhaul the way that the in-kernel AFS client keeps track of cells in the
following manner:

 (1) Cells are now held in an rbtree to make walking them quicker and RCU
     managed (though this is probably overkill).

 (2) Cells now have a manager work item that:

     (A) Looks after fetching and refreshing the VL server list.

     (B) Manages cell record lifetime, including initialising and
     	 destruction.

     (B) Manages cell record caching whereby threads are kept around for a
     	 certain time after last use and then destroyed.

     (C) Manages the FS-Cache index cookie for a cell.  It is not permitted
     	 for a cookie to be in use twice, so we have to be careful to not
     	 allow a new cell record to exist at the same time as an old record
     	 of the same name.

 (3) Each AFS network namespace is given a manager work item that manages
     the cells within it, maintaining a single timer to prod cells into
     updating their DNS records.

     This uses the reduce_timer() facility to make the timer expire at the
     soonest timed event that needs happening.

 (4) When a module is being unloaded, cells and cell managers are now
     counted out using dec_after_work() to make sure the module text is
     pinned until after the data structures have been cleaned up.

 (5) Each cell's VL server list is now protected by a seqlock rather than a
     semaphore.

Signed-off-by: David Howells <dhowells@redhat.com>
2017-11-13 15:38:18 +00:00

122 lines
3.0 KiB
C

/* Extended attribute handling for AFS. We use xattrs to get and set metadata
* instead of providing pioctl().
*
* Copyright (C) 2017 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation; either version
* 2 of the Licence, or (at your option) any later version.
*/
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/xattr.h>
#include "internal.h"
static const char afs_xattr_list[] =
"afs.cell\0"
"afs.fid\0"
"afs.volume";
/*
* Retrieve a list of the supported xattrs.
*/
ssize_t afs_listxattr(struct dentry *dentry, char *buffer, size_t size)
{
if (size == 0)
return sizeof(afs_xattr_list);
if (size < sizeof(afs_xattr_list))
return -ERANGE;
memcpy(buffer, afs_xattr_list, sizeof(afs_xattr_list));
return sizeof(afs_xattr_list);
}
/*
* Get the name of the cell on which a file resides.
*/
static int afs_xattr_get_cell(const struct xattr_handler *handler,
struct dentry *dentry,
struct inode *inode, const char *name,
void *buffer, size_t size)
{
struct afs_vnode *vnode = AFS_FS_I(inode);
struct afs_cell *cell = vnode->volume->cell;
size_t namelen;
namelen = cell->name_len;
if (size == 0)
return namelen;
if (namelen > size)
return -ERANGE;
memcpy(buffer, cell->name, size);
return namelen;
}
static const struct xattr_handler afs_xattr_afs_cell_handler = {
.name = "afs.cell",
.get = afs_xattr_get_cell,
};
/*
* Get the volume ID, vnode ID and vnode uniquifier of a file as a sequence of
* hex numbers separated by colons.
*/
static int afs_xattr_get_fid(const struct xattr_handler *handler,
struct dentry *dentry,
struct inode *inode, const char *name,
void *buffer, size_t size)
{
struct afs_vnode *vnode = AFS_FS_I(inode);
char text[8 + 1 + 8 + 1 + 8 + 1];
size_t len;
len = sprintf(text, "%x:%x:%x",
vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
if (size == 0)
return len;
if (len > size)
return -ERANGE;
memcpy(buffer, text, len);
return len;
}
static const struct xattr_handler afs_xattr_afs_fid_handler = {
.name = "afs.fid",
.get = afs_xattr_get_fid,
};
/*
* Get the name of the volume on which a file resides.
*/
static int afs_xattr_get_volume(const struct xattr_handler *handler,
struct dentry *dentry,
struct inode *inode, const char *name,
void *buffer, size_t size)
{
struct afs_vnode *vnode = AFS_FS_I(inode);
const char *volname = vnode->volume->vlocation->vldb.name;
size_t namelen;
namelen = strlen(volname);
if (size == 0)
return namelen;
if (namelen > size)
return -ERANGE;
memcpy(buffer, volname, size);
return namelen;
}
static const struct xattr_handler afs_xattr_afs_volume_handler = {
.name = "afs.volume",
.get = afs_xattr_get_volume,
};
const struct xattr_handler *afs_xattr_handlers[] = {
&afs_xattr_afs_cell_handler,
&afs_xattr_afs_fid_handler,
&afs_xattr_afs_volume_handler,
NULL
};