mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									fd2498211a
								
							
						
					
					
						commit
						d3e3b7eac8
					
				
					 8 changed files with 138 additions and 2 deletions
				
			
		| 
						 | 
					@ -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 = {
 | 
				
			||||||
	.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 = {
 | 
				
			||||||
	.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 {
 | 
				
			||||||
	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)
 | 
				
			||||||
			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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -731,6 +731,11 @@ extern int afs_writeback_all(struct afs_vnode *);
 | 
				
			||||||
extern int afs_flush(struct file *, fl_owner_t);
 | 
					extern int afs_flush(struct file *, fl_owner_t);
 | 
				
			||||||
extern int afs_fsync(struct file *, loff_t, loff_t, int);
 | 
					extern int afs_fsync(struct file *, loff_t, loff_t, int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * 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 = {
 | 
				
			||||||
	.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 = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -319,6 +319,7 @@ static int afs_fill_super(struct super_block *sb,
 | 
				
			||||||
	sb->s_blocksize_bits	= PAGE_SHIFT;
 | 
						sb->s_blocksize_bits	= PAGE_SHIFT;
 | 
				
			||||||
	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_xattr		= afs_xattr_handlers;
 | 
				
			||||||
	ret = super_setup_bdi(sb);
 | 
						ret = super_setup_bdi(sb);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										121
									
								
								fs/afs/xattr.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								fs/afs/xattr.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,121 @@
 | 
				
			||||||
 | 
					/* 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
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
		Loading…
	
		Reference in a new issue