diff options
author | David Howells <dhowells@redhat.com> | 2017-07-06 10:50:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-09 17:40:12 -0400 |
commit | d3e3b7eac886fb1383db2f22b81550fa6d87f62f (patch) | |
tree | f3a8e5d9775aeb053290e2157a946425e9803cd2 /fs/afs | |
parent | fd2498211a551fd42b2d6b9050d649d43536e75c (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/Makefile | 3 | ||||
-rw-r--r-- | fs/afs/dir.c | 1 | ||||
-rw-r--r-- | fs/afs/file.c | 1 | ||||
-rw-r--r-- | fs/afs/inode.c | 7 | ||||
-rw-r--r-- | fs/afs/internal.h | 5 | ||||
-rw-r--r-- | fs/afs/mntpt.c | 1 | ||||
-rw-r--r-- | fs/afs/super.c | 1 | ||||
-rw-r--r-- | fs/afs/xattr.c | 121 |
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 | ||
32 | obj-$(CONFIG_AFS_FS) := kafs.o | 33 | obj-$(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 | ||
66 | const struct dentry_operations afs_fs_dentry_operations = { | 67 | const 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 | ||
51 | const struct address_space_operations afs_fs_aops = { | 52 | const 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 | ||
31 | static 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 *); | |||
731 | extern int afs_flush(struct file *, fl_owner_t); | 731 | extern int afs_flush(struct file *, fl_owner_t); |
732 | extern int afs_fsync(struct file *, loff_t, loff_t, int); | 732 | extern int afs_fsync(struct file *, loff_t, loff_t, int); |
733 | 733 | ||
734 | /* | ||
735 | * xattr.c | ||
736 | */ | ||
737 | extern const struct xattr_handler *afs_xattr_handlers[]; | ||
738 | extern 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 | ||
40 | const struct inode_operations afs_autocell_inode_operations = { | 41 | const 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 | |||
18 | static 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 | */ | ||
26 | ssize_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 | */ | ||
39 | static 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 | |||
57 | static 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 | */ | ||
66 | static 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 | |||
85 | static 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 | */ | ||
93 | static 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 | |||
111 | static const struct xattr_handler afs_xattr_afs_volume_handler = { | ||
112 | .name = "afs.volume", | ||
113 | .get = afs_xattr_get_volume, | ||
114 | }; | ||
115 | |||
116 | const 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 | }; | ||