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 = cell->name_len; 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, "%llx:%llx:%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->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 }; 122