Commit a0d5b04c authored by David Howells's avatar David Howells

afs: Add metadata xattrs

Add xattrs to allow the user to get/set metadata in lieu of having pioctl()
available.  The following xattrs are now available:

 (*) afs.cell

     The name of the cell in which the vnode's volume resides.

 (*) afs.fid

     The volume ID, vnode ID and vnode uniquifier of the file as three hex
     numbers separated by colons.

 (*) afs.volume

     The name of the volume in which the vnode resides.

For example:

	# getfattr -d -m ".*" /mnt/scratch
	getfattr: Removing leading '/' from absolute path names
	# file: mnt/scratch
	afs.cell="mycell.myorg.org"
	afs.fid="10000b:1:1"
	afs.volume="scratch"
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent 602db5b7
...@@ -27,6 +27,7 @@ kafs-objs := \ ...@@ -27,6 +27,7 @@ kafs-objs := \
vlocation.o \ vlocation.o \
vnode.o \ vnode.o \
volume.o \ volume.o \
write.o write.o \
xattr.o
obj-$(CONFIG_AFS_FS) := kafs.o obj-$(CONFIG_AFS_FS) := kafs.o
...@@ -61,6 +61,7 @@ const struct inode_operations afs_dir_inode_operations = { ...@@ -61,6 +61,7 @@ const struct inode_operations afs_dir_inode_operations = {
.permission = afs_permission, .permission = afs_permission,
.getattr = afs_getattr, .getattr = afs_getattr,
.setattr = afs_setattr, .setattr = afs_setattr,
.listxattr = afs_listxattr,
}; };
const struct dentry_operations afs_fs_dentry_operations = { const struct dentry_operations afs_fs_dentry_operations = {
......
...@@ -46,6 +46,7 @@ const struct inode_operations afs_file_inode_operations = { ...@@ -46,6 +46,7 @@ const struct inode_operations afs_file_inode_operations = {
.getattr = afs_getattr, .getattr = afs_getattr,
.setattr = afs_setattr, .setattr = afs_setattr,
.permission = afs_permission, .permission = afs_permission,
.listxattr = afs_listxattr,
}; };
const struct address_space_operations afs_fs_aops = { const struct address_space_operations afs_fs_aops = {
......
...@@ -28,6 +28,11 @@ struct afs_iget_data { ...@@ -28,6 +28,11 @@ struct afs_iget_data {
struct afs_volume *volume; /* volume on which resides */ struct afs_volume *volume; /* volume on which resides */
}; };
static const struct inode_operations afs_symlink_inode_operations = {
.get_link = page_get_link,
.listxattr = afs_listxattr,
};
/* /*
* map the AFS file status to the inode member variables * map the AFS file status to the inode member variables
*/ */
...@@ -67,7 +72,7 @@ static int afs_inode_map_status(struct afs_vnode *vnode, struct key *key) ...@@ -67,7 +72,7 @@ static int afs_inode_map_status(struct afs_vnode *vnode, struct key *key)
inode->i_fop = &afs_mntpt_file_operations; inode->i_fop = &afs_mntpt_file_operations;
} else { } else {
inode->i_mode = S_IFLNK | vnode->status.mode; inode->i_mode = S_IFLNK | vnode->status.mode;
inode->i_op = &page_symlink_inode_operations; inode->i_op = &afs_symlink_inode_operations;
} }
inode_nohighmem(inode); inode_nohighmem(inode);
break; break;
......
...@@ -736,6 +736,11 @@ extern int afs_fsync(struct file *, loff_t, loff_t, int); ...@@ -736,6 +736,11 @@ extern int afs_fsync(struct file *, loff_t, loff_t, int);
extern int afs_launder_page(struct page *); extern int afs_launder_page(struct page *);
extern int afs_page_mkwrite(struct vm_fault *); extern int afs_page_mkwrite(struct vm_fault *);
/*
* xattr.c
*/
extern const struct xattr_handler *afs_xattr_handlers[];
extern ssize_t afs_listxattr(struct dentry *, char *, size_t);
/*****************************************************************************/ /*****************************************************************************/
/* /*
......
...@@ -35,6 +35,7 @@ const struct inode_operations afs_mntpt_inode_operations = { ...@@ -35,6 +35,7 @@ const struct inode_operations afs_mntpt_inode_operations = {
.lookup = afs_mntpt_lookup, .lookup = afs_mntpt_lookup,
.readlink = page_readlink, .readlink = page_readlink,
.getattr = afs_getattr, .getattr = afs_getattr,
.listxattr = afs_listxattr,
}; };
const struct inode_operations afs_autocell_inode_operations = { const struct inode_operations afs_autocell_inode_operations = {
......
...@@ -320,6 +320,7 @@ static int afs_fill_super(struct super_block *sb, ...@@ -320,6 +320,7 @@ static int afs_fill_super(struct super_block *sb,
sb->s_magic = AFS_FS_MAGIC; sb->s_magic = AFS_FS_MAGIC;
sb->s_op = &afs_super_ops; sb->s_op = &afs_super_ops;
sb->s_bdi = &as->volume->bdi; sb->s_bdi = &as->volume->bdi;
sb->s_xattr = afs_xattr_handlers;
strlcpy(sb->s_id, as->volume->vlocation->vldb.name, sizeof(sb->s_id)); strlcpy(sb->s_id, as->volume->vlocation->vldb.name, sizeof(sb->s_id));
/* allocate the root inode and dentry */ /* allocate the root inode and dentry */
......
/* 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 = strlen(cell->name);
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
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment