ext_attr.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:6k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
  2.  * vim:expandtab:shiftwidth=8:tabstop=8:
  3.  * 
  4.  *  Copyright (C) 2001 Tacit Networks, Inc.
  5.  *    Author: Shirish H. Phatak <shirish@tacitnetworks.com>
  6.  *
  7.  *   This file is part of InterMezzo, http://www.inter-mezzo.org.
  8.  *
  9.  *   InterMezzo is free software; you can redistribute it and/or
  10.  *   modify it under the terms of version 2 of the GNU General Public
  11.  *   License as published by the Free Software Foundation.
  12.  *
  13.  *   InterMezzo is distributed in the hope that it will be useful,
  14.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  *   GNU General Public License for more details.
  17.  *
  18.  *   You should have received a copy of the GNU General Public License
  19.  *   along with InterMezzo; if not, write to the Free Software
  20.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  *
  22.  * Extended attribute handling for presto.
  23.  */
  24. #define __NO_VERSION__
  25. #include <linux/module.h>
  26. #include <linux/kernel.h>
  27. #include <linux/mm.h>
  28. #include <linux/string.h>
  29. #include <linux/stat.h>
  30. #include <linux/errno.h>
  31. #include <linux/locks.h>
  32. #include <linux/unistd.h>
  33. #include <asm/system.h>
  34. #include <asm/uaccess.h>
  35. #include <linux/fs.h>
  36. #include <linux/stat.h>
  37. #include <linux/errno.h>
  38. #include <linux/locks.h>
  39. #include <linux/string.h>
  40. #include <asm/uaccess.h>
  41. #include <linux/slab.h>
  42. #include <linux/vmalloc.h>
  43. #include <asm/segment.h>
  44. #include <linux/smp_lock.h>
  45. #include <linux/intermezzo_fs.h>
  46. #include <linux/intermezzo_psdev.h>
  47. #ifdef CONFIG_FS_EXT_ATTR
  48. #include <linux/ext_attr.h>
  49. extern inline void presto_debug_fail_blkdev(struct presto_file_set *fset,
  50.                                             unsigned long value);
  51. /* VFS interface */
  52. /* XXX! Fixme test for user defined attributes */
  53. int presto_set_ext_attr(struct inode *inode, 
  54.                         const char *name, void *buffer,
  55.                         size_t buffer_len, int flags) 
  56. {
  57.         int error;
  58.         struct presto_cache *cache;
  59.         struct presto_file_set *fset;
  60.         struct lento_vfs_context info;
  61.         struct dentry *dentry;
  62.         int minor = presto_i2m(inode);
  63.         char *buf = NULL;
  64.         ENTRY;
  65.         if (minor < 0) {
  66.                 EXIT;
  67.                 return -1;
  68.         }
  69.         if ( ISLENTO(minor) ) {
  70.                 EXIT;
  71.                 return -EINVAL;
  72.         }
  73.         /* BAD...vfs should really pass down the dentry to use, especially
  74.          * since every other operation in iops does. But for now
  75.          * we do a reverse mapping from inode to the first dentry 
  76.          */
  77.         if (list_empty(&inode->i_dentry)) {
  78.                 CERROR("No alias for inode %dn", (int) inode->i_ino);
  79.                 EXIT;
  80.                 return -EINVAL;
  81.         }
  82.         dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias);
  83.         error = presto_prep(dentry, &cache, &fset);
  84.         if ( error ) {
  85.                 EXIT;
  86.                 return error;
  87.         }
  88.         if ((buffer != NULL) && (buffer_len != 0)) {
  89.             /* If buffer is a user space pointer copy it to kernel space
  90.             * and reset the flag. We do this since the journal functions need
  91.             * access to the contents of the buffer, and the file system
  92.             * does not care. When we actually invoke the function, we remove
  93.             * the EXT_ATTR_FLAG_USER flag.
  94.             *
  95.             * XXX:Check if the "fs does not care" assertion is always true -SHP
  96.             * (works for ext3)
  97.             */
  98.             if (flags & EXT_ATTR_FLAG_USER) {
  99.                 PRESTO_ALLOC(buf, buffer_len);
  100.                 if (!buf) {
  101.                         CERROR("InterMezzo: out of memory!!!n");
  102.                         return -ENOMEM;
  103.                 }
  104.                 error = copy_from_user(buf, buffer, buffer_len);
  105.                 if (error) 
  106.                         return -EFAULT;
  107.             } else 
  108.                 buf = buffer;
  109.         } else
  110.                 buf = buffer;
  111.         if ( presto_get_permit(inode) < 0 ) {
  112.                 EXIT;
  113.                 if (buffer_len && (flags & EXT_ATTR_FLAG_USER))
  114.                         PRESTO_FREE(buf, buffer_len);
  115.                 return -EROFS;
  116.         }
  117.         /* Simulate presto_setup_info */
  118.         memset(&info, 0, sizeof(info));
  119.         /* For now redundant..but we keep it around just in case */
  120.         info.flags = LENTO_FL_IGNORE_TIME;
  121.         if (!ISLENTO(cache->cache_psdev->uc_minor))
  122.             info.flags |= LENTO_FL_KML;
  123.         /* We pass in the kernel space pointer and reset the 
  124.          * EXT_ATTR_FLAG_USER flag.
  125.          * See comments above. 
  126.          */ 
  127.         /* Note that mode is already set by VFS so we send in a NULL */
  128.         error = presto_do_set_ext_attr(fset, dentry, name, buf,
  129.                                        buffer_len, flags & ~EXT_ATTR_FLAG_USER,
  130.                                        NULL, &info);
  131.         presto_put_permit(inode);
  132.         if (buffer_len && (flags & EXT_ATTR_FLAG_USER))
  133.                 PRESTO_FREE(buf, buffer_len);
  134.         EXIT;
  135.         return error;
  136. }
  137. /* Lento Interface */
  138. /* XXX: ignore flags? We should be forcing these operations through? -SHP*/
  139. int lento_set_ext_attr(const char *path, const char *name, 
  140.                        void *buffer, size_t buffer_len, int flags, mode_t mode, 
  141.                        struct lento_vfs_context *info) 
  142. {
  143.         int error;
  144.         char * pathname;
  145.         struct nameidata nd;
  146.         struct dentry *dentry;
  147.         struct presto_file_set *fset;
  148.         ENTRY;
  149.         lock_kernel();
  150.         pathname=getname(path);
  151.         error = PTR_ERR(pathname);
  152.         if (IS_ERR(pathname)) {
  153.                 EXIT;
  154.                 goto exit;
  155.         }
  156.         /* Note that ext_attrs apply to both files and directories..*/
  157.         error=presto_walk(pathname,&nd);
  158.         if (error) 
  159. goto exit;
  160.         dentry = nd.dentry;
  161.         fset = presto_fset(dentry);
  162.         error = -EINVAL;
  163.         if ( !fset ) {
  164.                 CERROR("No fileset!n");
  165.                 EXIT;
  166.                 goto exit_dentry;
  167.         }
  168.         if (buffer==NULL) buffer_len=0;
  169.         error = presto_do_set_ext_attr(fset, dentry, name, buffer,
  170.                                        buffer_len, flags, &mode, info);
  171. exit_dentry:
  172.         path_release(&nd);
  173. exit_path:
  174.         putname(pathname);
  175. exit:
  176.         unlock_kernel();
  177.         return error; 
  178. }
  179. #endif /*CONFIG_FS_EXT_ATTR*/