ext_attr.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:6k
- /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001 Tacit Networks, Inc.
- * Author: Shirish H. Phatak <shirish@tacitnetworks.com>
- *
- * This file is part of InterMezzo, http://www.inter-mezzo.org.
- *
- * InterMezzo is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * InterMezzo is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with InterMezzo; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Extended attribute handling for presto.
- */
- #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_psdev.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);
- /* 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)) {
- CERROR("No alias for inode %dn", (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, buffer_len);
- if (!buf) {
- CERROR("InterMezzo: out of memory!!!n");
- return -ENOMEM;
- }
- error = copy_from_user(buf, buffer, buffer_len);
- if (error)
- return -EFAULT;
- } 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 ) {
- CERROR("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*/