summaryrefslogtreecommitdiffstats
path: root/fs/afs
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2017-07-06 10:50:27 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-07-09 17:40:12 -0400
commitd3e3b7eac886fb1383db2f22b81550fa6d87f62f (patch)
treef3a8e5d9775aeb053290e2157a946425e9803cd2 /fs/afs
parentfd2498211a551fd42b2d6b9050d649d43536e75c (diff)
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: David Howells <dhowells@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/afs')
-rw-r--r--fs/afs/Makefile3
-rw-r--r--fs/afs/dir.c1
-rw-r--r--fs/afs/file.c1
-rw-r--r--fs/afs/inode.c7
-rw-r--r--fs/afs/internal.h5
-rw-r--r--fs/afs/mntpt.c1
-rw-r--r--fs/afs/super.c1
-rw-r--r--fs/afs/xattr.c121
8 files changed, 138 insertions, 2 deletions
diff --git a/fs/afs/Makefile b/fs/afs/Makefile
index 4f64b95d57bd..095c54165dfd 100644
--- a/fs/afs/Makefile
+++ b/fs/afs/Makefile
@@ -27,6 +27,7 @@ kafs-objs := \
27 vlocation.o \ 27 vlocation.o \
28 vnode.o \ 28 vnode.o \
29 volume.o \ 29 volume.o \
30 write.o 30 write.o \
31 xattr.o
31 32
32obj-$(CONFIG_AFS_FS) := kafs.o 33obj-$(CONFIG_AFS_FS) := kafs.o
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 949f960337f5..613a77058263 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -61,6 +61,7 @@ const struct inode_operations afs_dir_inode_operations = {
61 .permission = afs_permission, 61 .permission = afs_permission,
62 .getattr = afs_getattr, 62 .getattr = afs_getattr,
63 .setattr = afs_setattr, 63 .setattr = afs_setattr,
64 .listxattr = afs_listxattr,
64}; 65};
65 66
66const struct dentry_operations afs_fs_dentry_operations = { 67const struct dentry_operations afs_fs_dentry_operations = {
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 0d5b8508869b..510cba15fa56 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -46,6 +46,7 @@ const struct inode_operations afs_file_inode_operations = {
46 .getattr = afs_getattr, 46 .getattr = afs_getattr,
47 .setattr = afs_setattr, 47 .setattr = afs_setattr,
48 .permission = afs_permission, 48 .permission = afs_permission,
49 .listxattr = afs_listxattr,
49}; 50};
50 51
51const struct address_space_operations afs_fs_aops = { 52const struct address_space_operations afs_fs_aops = {
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index aae55dd15108..342316a9e3e0 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -28,6 +28,11 @@ struct afs_iget_data {
28 struct afs_volume *volume; /* volume on which resides */ 28 struct afs_volume *volume; /* volume on which resides */
29}; 29};
30 30
31static const struct inode_operations afs_symlink_inode_operations = {
32 .get_link = page_get_link,
33 .listxattr = afs_listxattr,
34};
35
31/* 36/*
32 * map the AFS file status to the inode member variables 37 * map the AFS file status to the inode member variables
33 */ 38 */
@@ -67,7 +72,7 @@ static int afs_inode_map_status(struct afs_vnode *vnode, struct key *key)
67 inode->i_fop = &afs_mntpt_file_operations; 72 inode->i_fop = &afs_mntpt_file_operations;
68 } else { 73 } else {
69 inode->i_mode = S_IFLNK | vnode->status.mode; 74 inode->i_mode = S_IFLNK | vnode->status.mode;
70 inode->i_op = &page_symlink_inode_operations; 75 inode->i_op = &afs_symlink_inode_operations;
71 } 76 }
72 inode_nohighmem(inode); 77 inode_nohighmem(inode);
73 break; 78 break;
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 4e2556606623..82e16556afea 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -731,6 +731,11 @@ extern int afs_writeback_all(struct afs_vnode *);
731extern int afs_flush(struct file *, fl_owner_t); 731extern int afs_flush(struct file *, fl_owner_t);
732extern int afs_fsync(struct file *, loff_t, loff_t, int); 732extern int afs_fsync(struct file *, loff_t, loff_t, int);
733 733
734/*
735 * xattr.c
736 */
737extern const struct xattr_handler *afs_xattr_handlers[];
738extern ssize_t afs_listxattr(struct dentry *, char *, size_t);
734 739
735/*****************************************************************************/ 740/*****************************************************************************/
736/* 741/*
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
index bd3b65cde282..690fea9d84c3 100644
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -35,6 +35,7 @@ const struct inode_operations afs_mntpt_inode_operations = {
35 .lookup = afs_mntpt_lookup, 35 .lookup = afs_mntpt_lookup,
36 .readlink = page_readlink, 36 .readlink = page_readlink,
37 .getattr = afs_getattr, 37 .getattr = afs_getattr,
38 .listxattr = afs_listxattr,
38}; 39};
39 40
40const struct inode_operations afs_autocell_inode_operations = { 41const struct inode_operations afs_autocell_inode_operations = {
diff --git a/fs/afs/super.c b/fs/afs/super.c
index c79633e5cfd8..67680c2d96cf 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -319,6 +319,7 @@ static int afs_fill_super(struct super_block *sb,
319 sb->s_blocksize_bits = PAGE_SHIFT; 319 sb->s_blocksize_bits = PAGE_SHIFT;
320 sb->s_magic = AFS_FS_MAGIC; 320 sb->s_magic = AFS_FS_MAGIC;
321 sb->s_op = &afs_super_ops; 321 sb->s_op = &afs_super_ops;
322 sb->s_xattr = afs_xattr_handlers;
322 ret = super_setup_bdi(sb); 323 ret = super_setup_bdi(sb);
323 if (ret) 324 if (ret)
324 return ret; 325 return ret;
diff --git a/fs/afs/xattr.c b/fs/afs/xattr.c
new file mode 100644
index 000000000000..2830e4f48d85
--- /dev/null
+++ b/fs/afs/xattr.c
@@ -0,0 +1,121 @@
1/* Extended attribute handling for AFS. We use xattrs to get and set metadata
2 * instead of providing pioctl().
3 *
4 * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved.
5 * Written by David Howells (dhowells@redhat.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public Licence
9 * as published by the Free Software Foundation; either version
10 * 2 of the Licence, or (at your option) any later version.
11 */
12
13#include <linux/slab.h>
14#include <linux/fs.h>
15#include <linux/xattr.h>
16#include "internal.h"
17
18static const char afs_xattr_list[] =
19 "afs.cell\0"
20 "afs.fid\0"
21 "afs.volume";
22
23/*
24 * Retrieve a list of the supported xattrs.
25 */
26ssize_t afs_listxattr(struct dentry *dentry, char *buffer, size_t size)
27{
28 if (size == 0)
29 return sizeof(afs_xattr_list);
30 if (size < sizeof(afs_xattr_list))
31 return -ERANGE;
32 memcpy(buffer, afs_xattr_list, sizeof(afs_xattr_list));
33 return sizeof(afs_xattr_list);
34}
35
36/*
37 * Get the name of the cell on which a file resides.
38 */
39static int afs_xattr_get_cell(const struct xattr_handler *handler,
40 struct dentry *dentry,
41 struct inode *inode, const char *name,
42 void *buffer, size_t size)
43{
44 struct afs_vnode *vnode = AFS_FS_I(inode);
45 struct afs_cell *cell = vnode->volume->cell;
46 size_t namelen;
47
48 namelen = strlen(cell->name);
49 if (size == 0)
50 return namelen;
51 if (namelen > size)
52 return -ERANGE;
53 memcpy(buffer, cell->name, size);
54 return namelen;
55}
56
57static const struct xattr_handler afs_xattr_afs_cell_handler = {
58 .name = "afs.cell",
59 .get = afs_xattr_get_cell,
60};
61
62/*
63 * Get the volume ID, vnode ID and vnode uniquifier of a file as a sequence of
64 * hex numbers separated by colons.
65 */
66static int afs_xattr_get_fid(const struct xattr_handler *handler,
67 struct dentry *dentry,
68 struct inode *inode, const char *name,
69 void *buffer, size_t size)
70{
71 struct afs_vnode *vnode = AFS_FS_I(inode);
72 char text[8 + 1 + 8 + 1 + 8 + 1];
73 size_t len;
74
75 len = sprintf(text, "%x:%x:%x",
76 vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
77 if (size == 0)
78 return len;
79 if (len > size)
80 return -ERANGE;
81 memcpy(buffer, text, len);
82 return len;
83}
84
85static const struct xattr_handler afs_xattr_afs_fid_handler = {
86 .name = "afs.fid",
87 .get = afs_xattr_get_fid,
88};
89
90/*
91 * Get the name of the volume on which a file resides.
92 */
93static int afs_xattr_get_volume(const struct xattr_handler *handler,
94 struct dentry *dentry,
95 struct inode *inode, const char *name,
96 void *buffer, size_t size)
97{
98 struct afs_vnode *vnode = AFS_FS_I(inode);
99 const char *volname = vnode->volume->vlocation->vldb.name;
100 size_t namelen;
101
102 namelen = strlen(volname);
103 if (size == 0)
104 return namelen;
105 if (namelen > size)
106 return -ERANGE;
107 memcpy(buffer, volname, size);
108 return namelen;
109}
110
111static const struct xattr_handler afs_xattr_afs_volume_handler = {
112 .name = "afs.volume",
113 .get = afs_xattr_get_volume,
114};
115
116const struct xattr_handler *afs_xattr_handlers[] = {
117 &afs_xattr_afs_cell_handler,
118 &afs_xattr_afs_fid_handler,
119 &afs_xattr_afs_volume_handler,
120 NULL
121};