Viewing file: ext_attr.c (5.72 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/* * Extended attribute handling for presto. * * Copyright (C) 2001. All rights reserved. * Shirish H. Phatak * Tacit Networks, Inc. * */
#define __NO_VERSION__ #include <linux/module.h> #include <linux/kernel.h> #include <linux/mm.h> #include <linux/string.h> #include <linux/stat.h> #include <linux/errno.h> #include <linux/locks.h> #include <linux/unistd.h>
#include <asm/system.h> #include <asm/uaccess.h>
#include <linux/fs.h> #include <linux/stat.h> #include <linux/errno.h> #include <linux/locks.h> #include <linux/string.h> #include <asm/uaccess.h> #include <linux/slab.h> #include <linux/vmalloc.h> #include <asm/segment.h> #include <linux/smp_lock.h>
#include <linux/intermezzo_fs.h> #include <linux/intermezzo_upcall.h> #include <linux/intermezzo_psdev.h> #include <linux/intermezzo_kml.h>
#ifdef CONFIG_FS_EXT_ATTR #include <linux/ext_attr.h>
extern inline void presto_debug_fail_blkdev(struct presto_file_set *fset, unsigned long value);
extern int presto_prep(struct dentry *, struct presto_cache **, struct presto_file_set **);
/* VFS interface */ /* XXX! Fixme test for user defined attributes */ int presto_set_ext_attr(struct inode *inode, const char *name, void *buffer, size_t buffer_len, int flags) { int error; struct presto_cache *cache; struct presto_file_set *fset; struct lento_vfs_context info; struct dentry *dentry; int minor = presto_i2m(inode); char *buf = NULL;
ENTRY; if (minor < 0) { EXIT; return -1; }
if ( ISLENTO(minor) ) { EXIT; return -EINVAL; }
/* BAD...vfs should really pass down the dentry to use, especially * since every other operation in iops does. But for now * we do a reverse mapping from inode to the first dentry */ if (list_empty(&inode->i_dentry)) { printk("No alias for inode %d\n", (int) inode->i_ino); EXIT; return -EINVAL; }
dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias);
error = presto_prep(dentry, &cache, &fset); if ( error ) { EXIT; return error; }
if ((buffer != NULL) && (buffer_len != 0)) { /* If buffer is a user space pointer copy it to kernel space * and reset the flag. We do this since the journal functions need * access to the contents of the buffer, and the file system * does not care. When we actually invoke the function, we remove * the EXT_ATTR_FLAG_USER flag. * * XXX:Check if the "fs does not care" assertion is always true -SHP * (works for ext3) */ if (flags & EXT_ATTR_FLAG_USER) { PRESTO_ALLOC(buf, char *, buffer_len); if (!buf) { printk("InterMezzo: out of memory!!!\n"); return -ENOMEM; } error = copy_from_user(buf, buffer, buffer_len); if (error) return error; } else buf = buffer; } else buf = buffer;
if ( presto_get_permit(inode) < 0 ) { EXIT; if (buffer_len && (flags & EXT_ATTR_FLAG_USER)) PRESTO_FREE(buf, buffer_len); return -EROFS; }
/* Simulate presto_setup_info */ memset(&info, 0, sizeof(info)); /* For now redundant..but we keep it around just in case */ info.flags = LENTO_FL_IGNORE_TIME; if (!ISLENTO(cache->cache_psdev->uc_minor)) info.flags |= LENTO_FL_KML;
/* We pass in the kernel space pointer and reset the * EXT_ATTR_FLAG_USER flag. * See comments above. */ /* Note that mode is already set by VFS so we send in a NULL */ error = presto_do_set_ext_attr(fset, dentry, name, buf, buffer_len, flags & ~EXT_ATTR_FLAG_USER, NULL, &info); presto_put_permit(inode);
if (buffer_len && (flags & EXT_ATTR_FLAG_USER)) PRESTO_FREE(buf, buffer_len); EXIT; return error; }
/* Lento Interface */ /* XXX: ignore flags? We should be forcing these operations through? -SHP*/ int lento_set_ext_attr(const char *path, const char *name, void *buffer, size_t buffer_len, int flags, mode_t mode, struct lento_vfs_context *info) { int error; char * pathname; struct nameidata nd; struct dentry *dentry; struct presto_file_set *fset;
ENTRY; lock_kernel();
pathname=getname(path); error = PTR_ERR(pathname); if (IS_ERR(pathname)) { EXIT; goto exit; }
/* Note that ext_attrs apply to both files and directories..*/ error=presto_walk(pathname,&nd); if (error) goto exit; dentry = nd.dentry;
fset = presto_fset(dentry); error = -EINVAL; if ( !fset ) { printk("No fileset!\n"); EXIT; goto exit_dentry; }
if (buffer==NULL) buffer_len=0;
error = presto_do_set_ext_attr(fset, dentry, name, buffer, buffer_len, flags, &mode, info); exit_dentry: path_release(&nd); exit_path: putname(pathname); exit: unlock_kernel(); return error; }
#endif /*CONFIG_FS_EXT_ATTR*/
|