Whamcloud - gitweb
merge HEAD to b_eq tag 20040209_1518 (kernel only)
authorericm <ericm>
Mon, 9 Feb 2004 08:42:22 +0000 (08:42 +0000)
committerericm <ericm>
Mon, 9 Feb 2004 08:42:22 +0000 (08:42 +0000)
major changes are from landing of b_recovery, which might have great impact
on liblustre.

lustre/include/linux/lustre_log.h
lustre/kernel_patches/patches/ext3-mballoc-2.4.24.patch
lustre/llite/llite_lib.c
lustre/obdfilter/filter_log.c
lustre/smfs/file.c

index 2b62378..1ea4740 100644 (file)
@@ -220,9 +220,9 @@ static inline int llog_gen_lt(struct llog_gen a, struct llog_gen b)
 static inline int llog_obd2ops(struct llog_ctxt *ctxt,
                                struct llog_operations **lop)
 {
-        if (ctxt == NULL)
+       if (ctxt == NULL)
                 return -ENOTCONN;
-
+        
         *lop = ctxt->loc_logops;
         if (*lop == NULL)
                 return -EOPNOTSUPP;
index 93da5aa..83d638b 100644 (file)
@@ -1,7 +1,7 @@
 Index: linux-2.4.24/fs/ext3/balloc.c
 ===================================================================
 --- linux-2.4.24.orig/fs/ext3/balloc.c 2004-01-10 17:04:42.000000000 +0300
-+++ linux-2.4.24/fs/ext3/balloc.c      2004-02-05 20:35:11.000000000 +0300
++++ linux-2.4.24/fs/ext3/balloc.c      2004-02-06 11:05:42.000000000 +0300
 @@ -11,6 +11,7 @@
   *        David S. Miller (davem@caip.rutgers.edu), 1995
   */
@@ -10,7 +10,7 @@ Index: linux-2.4.24/fs/ext3/balloc.c
  #include <linux/config.h>
  #include <linux/sched.h>
  #include <linux/fs.h>
-@@ -1007,3 +1008,298 @@
+@@ -1007,3 +1008,303 @@
                        bitmap_count);
  }
  #endif
@@ -194,8 +194,6 @@ Index: linux-2.4.24/fs/ext3/balloc.c
 +      struct alloc_status as;
 +      int err, bit, i;
 +
-+      int scaned = 0;
-+
 +      J_ASSERT(num && *num > 0);
 +
 +      if (DQUOT_ALLOC_BLOCK(inode, *num)) {
@@ -214,6 +212,10 @@ Index: linux-2.4.24/fs/ext3/balloc.c
 +      as.len = 0;
 +      as.num = 0;
 +
++      if (goal < le32_to_cpu(es->s_first_data_block) ||
++          goal >= le32_to_cpu(es->s_blocks_count))
++              goal = le32_to_cpu(es->s_first_data_block);
++
 +      lock_super(sb);
 +      first_group = (goal - le32_to_cpu(es->s_first_data_block)) /
 +                      EXT3_BLOCKS_PER_GROUP(sb);
@@ -221,7 +223,6 @@ Index: linux-2.4.24/fs/ext3/balloc.c
 +                      EXT3_BLOCKS_PER_GROUP(sb);
 +      group = first_group;
 +      do {
-+              scaned++;
 +              err = ext3_find_extent_in_group(&as, group, goal, *num);
 +              if (err < 0) 
 +                      goto error_out;
@@ -261,10 +262,14 @@ Index: linux-2.4.24/fs/ext3/balloc.c
 +              goto error_out;
 +      }
 +      bmbh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr];
-+      err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
++      /* Make sure we use undo access for the bitmap, because it is
++           critical that we do the frozen_data COW on bitmap buffers in
++           all cases even if the buffer is in BJ_Forget state in the
++           committing transaction.  */
++      err = ext3_journal_get_undo_access(handle, bmbh);
 +      if (err)
 +              goto error_out;
-+      err = ext3_journal_get_write_access(handle, bmbh);
++      err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
 +      if (err)
 +              goto error_out;
 +      err = ext3_journal_get_write_access(handle, bh);
@@ -312,7 +317,7 @@ Index: linux-2.4.24/fs/ext3/balloc.c
 Index: linux-2.4.24/fs/ext3/file.c
 ===================================================================
 --- linux-2.4.24.orig/fs/ext3/file.c   2004-01-31 02:06:18.000000000 +0300
-+++ linux-2.4.24/fs/ext3/file.c        2004-02-05 20:57:07.000000000 +0300
++++ linux-2.4.24/fs/ext3/file.c        2004-02-06 10:20:46.000000000 +0300
 @@ -69,6 +69,18 @@
        int err;
        struct inode *inode = file->f_dentry->d_inode;
@@ -335,7 +340,7 @@ Index: linux-2.4.24/fs/ext3/file.c
 Index: linux-2.4.24/fs/ext3/Makefile
 ===================================================================
 --- linux-2.4.24.orig/fs/ext3/Makefile 2004-02-05 18:44:25.000000000 +0300
-+++ linux-2.4.24/fs/ext3/Makefile      2004-02-05 20:35:11.000000000 +0300
++++ linux-2.4.24/fs/ext3/Makefile      2004-02-06 10:20:46.000000000 +0300
 @@ -14,7 +14,7 @@
  obj-y    := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
                ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o \
@@ -348,7 +353,7 @@ Index: linux-2.4.24/fs/ext3/Makefile
 Index: linux-2.4.24/include/linux/ext3_fs.h
 ===================================================================
 --- linux-2.4.24.orig/include/linux/ext3_fs.h  2004-01-30 00:09:37.000000000 +0300
-+++ linux-2.4.24/include/linux/ext3_fs.h       2004-02-05 20:35:11.000000000 +0300
++++ linux-2.4.24/include/linux/ext3_fs.h       2004-02-06 10:20:46.000000000 +0300
 @@ -58,6 +58,8 @@
  #define ext3_debug(f, a...)   do {} while (0)
  #endif
index 267c61c..f0c778c 100644 (file)
@@ -369,7 +369,7 @@ void ll_put_super(struct super_block *sb)
 } /* ll_put_super */
 
 int lustre_process_log(struct lustre_mount_data *lmd, char * profile,
-                       struct config_llog_instance *cfg)
+                       struct config_llog_instance *cfg, int allow_recov)
 {
         struct lustre_cfg lcfg;
         struct portals_cfg pcfg;
@@ -441,6 +441,13 @@ int lustre_process_log(struct lustre_mount_data *lmd, char * profile,
         if (obd == NULL)
                 GOTO(out_cleanup, err = -EINVAL);
 
+        /* Disable initial recovery on this import */
+        err = obd_set_info(obd->obd_self_export, 
+                           strlen("initial_recov"), "initial_recov", 
+                           sizeof(allow_recov), &allow_recov);
+        if (err)
+                GOTO(out_cleanup, err);
+
         err = obd_connect(&mdc_conn, obd, &mdc_uuid);
         if (err) {
                 CERROR("cannot connect to %s: rc = %d\n", lmd->lmd_mds, err);
@@ -535,7 +542,7 @@ int lustre_fill_super(struct super_block *sb, void *data, int silent)
                 cfg.cfg_instance = sbi->ll_instance;
                 cfg.cfg_uuid = sbi->ll_sb_uuid;
                 cfg.cfg_local_nid = lmd->lmd_local_nid;
-                err = lustre_process_log(lmd, lmd->lmd_profile, &cfg);
+                err = lustre_process_log(lmd, lmd->lmd_profile, &cfg, 1);
                 if (err < 0) {
                         CERROR("Unable to process log: %s\n", lmd->lmd_profile);
 
@@ -598,7 +605,8 @@ out_free:
                         OBD_ALLOC(cln_prof, len);
                         sprintf(cln_prof, "%s-clean", sbi->ll_lmd->lmd_profile);
 
-                        err = lustre_process_log(sbi->ll_lmd, cln_prof, &cfg);
+                        err = lustre_process_log(sbi->ll_lmd, cln_prof, &cfg, 
+                                                 0);
                         if (err < 0) 
                                 CERROR("Unable to process log: %s\n", cln_prof);
                         OBD_FREE(cln_prof, len);
@@ -611,6 +619,35 @@ out_free:
         goto out_dev;
 } /* lustre_fill_super */
 
+static void lustre_manual_cleanup(struct ll_sb_info *sbi) 
+{
+        struct lustre_cfg lcfg;
+        struct obd_device *obd;
+        int next = 0; 
+
+        while ((obd = class_devices_in_group(&sbi->ll_sb_uuid, &next)) != NULL)
+        {
+                int err;
+
+                LCFG_INIT(lcfg, LCFG_CLEANUP, obd->obd_name);
+                err = class_process_config(&lcfg);
+                if (err) {
+                        CERROR("cleanup failed: %s\n", obd->obd_name);
+                        //continue;
+                }
+
+                LCFG_INIT(lcfg, LCFG_DETACH, obd->obd_name);
+                err = class_process_config(&lcfg);
+                if (err) {
+                        CERROR("detach failed: %s\n", obd->obd_name);
+                        //continue;
+                }
+        }
+
+        if (sbi->ll_lmd != NULL) 
+                class_del_profile(sbi->ll_lmd->lmd_profile);
+}
+
 void lustre_put_super(struct super_block *sb)
 {
         struct ll_sb_info *sbi = ll_s2sbi(sb);
@@ -632,9 +669,12 @@ void lustre_put_super(struct super_block *sb)
                 OBD_ALLOC(cln_prof, len);
                 sprintf(cln_prof, "%s-clean", sbi->ll_lmd->lmd_profile);
 
-                err = lustre_process_log(sbi->ll_lmd, cln_prof, &cfg);
-                if (err < 0)
-                        CERROR("Unable to process log: %s\n", cln_prof);
+                err = lustre_process_log(sbi->ll_lmd, cln_prof, &cfg, 0);
+                if (err < 0) {
+                        CERROR("Unable to process log: %s, doing manual cleanup"
+                               "\n", cln_prof);
+                        lustre_manual_cleanup(sbi);
+                }
 
                 OBD_FREE(cln_prof, len);
                 OBD_FREE(sbi->ll_lmd, sizeof(*sbi->ll_lmd));
index 686fd30..eb3df7a 100644 (file)
@@ -158,13 +158,13 @@ int filter_recov_log_unlink_cb(struct llog_handle *llh,
         rc = obd_destroy(exp, oa, NULL, NULL);
         obdo_free(oa);
         if (rc == -ENOENT) {
-                CWARN("object already removed, send cookie\n");
+                CDEBUG(D_HA, "object already removed, send cookie\n");
                 llog_cancel(ctxt, NULL, 1, &cookie, 0);
                 RETURN(0);
         }
 
         if (rc == 0)
-                CWARN("object: "LPU64" in record is destroyed\n", oid);
+                CDEBUG(D_HA, "object: "LPU64" in record is destroyed\n", oid);
 
         RETURN(rc);
 }
index fec85af..455fccd 100644 (file)
 #include <linux/pagemap.h>
 #include "smfs_internal.h" 
 
-
 static int smfs_readpage(struct file *file, 
                         struct page *page)
 {
        struct  inode *inode = page->mapping->host;
        struct  inode *cache_inode;
-       int     rc;
-       
+       struct page *cache_page = NULL;
+       int rc = 0; 
+
        ENTRY;
        
        cache_inode = I2CI(inode);
  
         if (!cache_inode)
                 RETURN(-ENOENT);
+       
+       cache_page = grab_cache_page(cache_inode->i_mapping, page->index);
 
-       if (cache_inode->i_mapping->a_ops->readpage)
-               rc = cache_inode->i_mapping->a_ops->readpage(file, page);
-               
-        RETURN(rc);
+       if (!cache_page) 
+               GOTO(exit_release, rc = -ENOMEM);
+
+       if ((rc = cache_inode->i_mapping->a_ops->readpage(file, cache_page)))
+               GOTO(exit_release, 0);
        
+       wait_on_page(cache_page);
+
+       if (!Page_Uptodate(cache_page))
+               GOTO(exit_release, rc = -EIO);
+
+       memcpy(kmap(page), kmap(cache_page), PAGE_CACHE_SIZE);
+
+       flush_dcache_page(page);
+
+       kunmap(cache_page);
+       page_cache_release(cache_page);
+
+exit:  
+       kunmap(page);
+       SetPageUptodate(page);
+       UnlockPage(page);
+
+       RETURN(rc);
+
+exit_release:
+       if (cache_page) 
+               page_cache_release(cache_page);
+       UnlockPage(page);
+       RETURN(rc);
 }
+
 static int smfs_writepage(struct page *page)
 {
 
@@ -52,31 +80,109 @@ static int smfs_writepage(struct page *page)
                rc = cache_inode->i_mapping->a_ops->writepage(page);
                
         RETURN(rc);
-       
 }
+
 struct address_space_operations smfs_file_aops = {
        readpage:   smfs_readpage,
        writepage:  smfs_writepage,
 };
-                                                                                                                                                                                                     
+        
+/* instantiate a file handle to the cache file */
+void smfs_prepare_cachefile(struct inode *inode,
+                           struct file *file, 
+                           struct inode *cache_inode,
+                           struct file *cache_file,
+                           struct dentry *cache_dentry)
+{
+       ENTRY;
+       cache_file->f_pos = file->f_pos;
+        cache_file->f_mode = file->f_mode;
+        cache_file->f_flags = file->f_flags;
+        cache_file->f_count  = file->f_count;
+        cache_file->f_owner  = file->f_owner;
+       cache_file->f_error = file->f_error;
+       cache_file->f_op = inode->i_fop;
+       cache_file->f_dentry = cache_dentry;
+        cache_file->f_dentry->d_inode = cache_inode;
+       cache_file->f_vfsmnt = file->f_vfsmnt;
+       cache_file->private_data = file->private_data;
+       cache_file->f_it = file->f_it;
+       cache_file->f_reada = file->f_reada;
+       cache_file->f_ramax = file->f_ramax;
+       cache_file->f_raend = file->f_raend;
+       cache_file->f_ralen = file->f_ralen;
+       cache_file->f_rawin = file->f_rawin;
+       EXIT;
+}
+/* update file structs*/
+void smfs_update_file(struct file *file, 
+                     struct file *cache_file)
+{
+       ENTRY;
+       file->f_pos = cache_file->f_pos;
+        file->f_mode = cache_file->f_mode;
+        file->f_flags = cache_file->f_flags;
+        file->f_count  = cache_file->f_count;
+        file->f_owner  = cache_file->f_owner;
+       file->f_reada = cache_file->f_reada;
+       file->f_ramax = cache_file->f_ramax;
+       file->f_raend = cache_file->f_raend;
+       file->f_ralen = cache_file->f_ralen;
+       file->f_rawin = cache_file->f_rawin;
+       EXIT;
+}
 
 static ssize_t smfs_write (struct file *filp, const char *buf, 
                           size_t count, loff_t *ppos)
 {
        struct  inode *cache_inode;
        struct  dentry *dentry = filp->f_dentry;
-       int     rc;
+       struct  inode *inode = dentry->d_inode;
+        struct  file open_file;
+       struct  dentry open_dentry;
+       int     rc = 0;
        
        ENTRY;
        
-       cache_inode = I2CI(dentry->d_inode);
+       cache_inode = I2CI(inode);
  
         if (!cache_inode)
                 RETURN(-ENOENT);
-
+       
+       smfs_prepare_cachefile(inode, filp, cache_inode, 
+                              &open_file, &open_dentry);
+       
        if (cache_inode->i_fop->write)
-               cache_inode->i_fop->write(filp, buf, count, ppos);
+               rc = cache_inode->i_fop->write(&open_file, buf, count, ppos);
+       
+       duplicate_inode(cache_inode, inode);
+       smfs_update_file(filp, &open_file);
+
+       RETURN(rc);
+}
+int smfs_ioctl(struct inode * inode, struct file * filp, 
+              unsigned int cmd, unsigned long arg)
+{
+       struct  inode *cache_inode;
+       struct  dentry *dentry = filp->f_dentry;
+        struct  file open_file;
+       struct  dentry open_dentry;
+       ssize_t rc;
+       
+       ENTRY;
+       
+       cache_inode = I2CI(dentry->d_inode);
+        if (!cache_inode)
+                RETURN(-ENOENT);
+
+       smfs_prepare_cachefile(inode, filp, cache_inode, 
+                              &open_file, &open_dentry);
+       
+       if (cache_inode->i_fop->ioctl)
+               rc = cache_inode->i_fop->ioctl(cache_inode, &open_file, cmd, arg);
                
+       duplicate_inode(cache_inode, inode);
+       smfs_update_file(filp, &open_file);
         RETURN(rc);
 }
 
@@ -90,21 +196,166 @@ static ssize_t smfs_read (struct file *filp, char *buf,
        ENTRY;
        
        cache_inode = I2CI(dentry->d_inode);
         if (!cache_inode)
                 RETURN(-ENOENT);
 
        if (cache_inode->i_fop->read)
                rc = cache_inode->i_fop->read(filp, buf, count, ppos);
+    
+       duplicate_inode(cache_inode, dentry->d_inode);
+       RETURN(rc);
+}
+
+static loff_t smfs_llseek(struct file *file, 
+                         loff_t offset, 
+                         int origin)
+{
+       struct  inode *cache_inode;
+       struct  dentry *dentry = file->f_dentry;
+        struct  file open_file;
+       struct  dentry open_dentry;
+       ssize_t rc;
+       
+       ENTRY;
+       
+       cache_inode = I2CI(dentry->d_inode);
+        if (!cache_inode)
+                RETURN(-ENOENT);
+
+       smfs_prepare_cachefile(dentry->d_inode, file, cache_inode, 
+                              &open_file, &open_dentry);
+       
+       if (cache_inode->i_fop->llseek)
+               rc = cache_inode->i_fop->llseek(&open_file, offset, origin);
+       
+       duplicate_inode(cache_inode, dentry->d_inode);
+       smfs_update_file(file, &open_file);
                
         RETURN(rc);
 }
 
+static int smfs_mmap(struct file * file, struct vm_area_struct * vma)
+{
+       struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
+        struct inode *inode = mapping->host;
+        struct inode *cache_inode = NULL;
+        struct  file open_file;
+       struct  dentry open_dentry;
+       int    rc = 0;
+
+       cache_inode = I2CI(inode);
+        if (!cache_inode)
+                RETURN(-ENOENT);
+
+       smfs_prepare_cachefile(inode, file, cache_inode, 
+                              &open_file, &open_dentry);
+       
+       if (cache_inode->i_fop->mmap)
+               rc = cache_inode->i_fop->mmap(&open_file, vma);
+       
+       duplicate_inode(cache_inode, inode);
+       smfs_update_file(file, &open_file);
+       
+       RETURN(rc);
+}
+
+static int smfs_open(struct inode * inode, struct file * filp)
+{
+       struct inode *cache_inode = NULL;
+        struct  file open_file;
+       struct  dentry open_dentry;
+       int    rc = 0;
+
+       cache_inode = I2CI(inode);
+        if (!cache_inode)
+                RETURN(-ENOENT);
+
+       smfs_prepare_cachefile(inode, filp, cache_inode, 
+                              &open_file, &open_dentry);
+       
+       if (cache_inode->i_fop->open)
+               rc = cache_inode->i_fop->open(cache_inode, &open_file);
+        
+       duplicate_inode(cache_inode, inode);
+       smfs_update_file(filp, &open_file);
+       
+       RETURN(rc);
+
+}
+static int smfs_release(struct inode * inode, struct file * filp)
+{
+       struct inode *cache_inode = NULL;
+        struct  file open_file;
+       struct  dentry open_dentry;
+       int    rc = 0;
+
+       cache_inode = I2CI(inode);
+        if (!cache_inode)
+                RETURN(-ENOENT);
+       
+       smfs_prepare_cachefile(inode, filp, cache_inode, 
+                              &open_file, &open_dentry);
+
+       if (cache_inode->i_fop->release)
+               rc = cache_inode->i_fop->release(cache_inode, &open_file);
+
+       duplicate_inode(cache_inode, inode);
+       smfs_update_file(filp, &open_file);
+        
+       RETURN(rc);
+}
+int smfs_fsync(struct file * file, 
+                     struct dentry *dentry, 
+                     int datasync)
+{
+       struct inode *inode = dentry->d_inode;
+       struct inode *cache_inode;
+        struct  file open_file;
+       struct  dentry open_dentry;
+       int    rc = 0;
+
+       cache_inode = I2CI(inode);
+        if (!cache_inode)
+                RETURN(-ENOENT);
+       
+       smfs_prepare_cachefile(inode, file, cache_inode, 
+                              &open_file, &open_dentry);
+
+       if (cache_inode->i_fop->fsync)
+               rc = cache_inode->i_fop->fsync(&open_file, &open_dentry, datasync);
+       
+       duplicate_inode(cache_inode, inode);
+       smfs_update_file(file, &open_file);
+       
+       RETURN(rc);
+}
+
 struct file_operations smfs_file_fops = {
-       read:   smfs_read,
-       write:  smfs_write,
+       llseek:         smfs_llseek,
+       read:           smfs_read,
+       write:          smfs_write,
+       ioctl:          smfs_ioctl,
+       mmap:           smfs_mmap,
+       open:           smfs_open,
+       release:        smfs_release,
+       fsync:          smfs_fsync,
 };
 
+static void smfs_prepare_cache_dentry(struct dentry *dentry, struct inode *inode)
+{
+       atomic_set(&dentry->d_count, 1);
+       dentry->d_vfs_flags = 0;
+       dentry->d_flags = 0;
+       dentry->d_inode = inode;
+       dentry->d_op = NULL;
+       dentry->d_fsdata = NULL;
+       dentry->d_mounted = 0;
+       INIT_LIST_HEAD(&dentry->d_hash);
+       INIT_LIST_HEAD(&dentry->d_lru);
+       INIT_LIST_HEAD(&dentry->d_subdirs);
+       INIT_LIST_HEAD(&dentry->d_alias);
+}
+
 static void smfs_truncate(struct inode * inode)      
 {
        struct  inode *cache_inode;
@@ -117,29 +368,114 @@ static void smfs_truncate(struct inode * inode)
        if (cache_inode->i_op->truncate)
                cache_inode->i_op->truncate(cache_inode);
 
-       duplicate(inode, cache_inode);          
+       duplicate_inode(inode, cache_inode);            
         
        return; 
 } 
  
-static int smfs_setattr(struct dentry *dentry, struct iattr *attr)      
+int smfs_setattr(struct dentry *dentry, struct iattr *attr)      
 {
        struct  inode *cache_inode;
+       struct  dentry open_dentry;
+
        int     rc = 0;
 
        cache_inode = I2CI(dentry->d_inode);
 
        if (!cache_inode) 
                RETURN(-ENOENT);
+       smfs_prepare_cache_dentry(&open_dentry, cache_inode);
+       
+       if (cache_inode->i_op->setattr)
+               rc = cache_inode->i_op->setattr(&open_dentry, attr);
+
+       RETURN(rc);
+} 
+  
+int smfs_setxattr(struct dentry *dentry, const char *name,
+                 const void *value, size_t size, int flags)
+{
+       struct  inode *cache_inode;
+       struct  dentry open_dentry;
+       int     rc = 0;
+
+       cache_inode = I2CI(dentry->d_inode);
+
+       if (!cache_inode) 
+               RETURN(-ENOENT);
+
+       smfs_prepare_cache_dentry(&open_dentry, cache_inode);
        
        if (cache_inode->i_op->setattr)
-               rc = cache_inode->i_op->setattr(dentry, attr);
+               rc = cache_inode->i_op->setxattr(&open_dentry, name, value, size, flags);
 
        RETURN(rc);
 } 
-                                                                                                                                                                                     
+                        
+int smfs_getxattr(struct dentry *dentry, const char *name,
+                 void *buffer, size_t size)
+{
+       struct  inode *cache_inode;
+       struct  dentry open_dentry;
+       int     rc = 0;
+
+       cache_inode = I2CI(dentry->d_inode);
+
+       if (!cache_inode) 
+               RETURN(-ENOENT);
+
+       smfs_prepare_cache_dentry(&open_dentry, cache_inode);
+       
+       if (cache_inode->i_op->setattr)
+               rc = cache_inode->i_op->getxattr(&open_dentry, name, buffer, size);
+
+       RETURN(rc);
+}
+
+ssize_t smfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
+{
+       struct  inode *cache_inode;
+       struct  dentry open_dentry;
+       int     rc = 0;
+
+       cache_inode = I2CI(dentry->d_inode);
+
+       if (!cache_inode) 
+               RETURN(-ENOENT);
+
+       smfs_prepare_cache_dentry(&open_dentry, cache_inode);
+       
+       if (cache_inode->i_op->listxattr)
+               rc = cache_inode->i_op->listxattr(&open_dentry, buffer, size);
+
+       RETURN(rc);
+}                                                                                                                                                           
+
+int smfs_removexattr(struct dentry *dentry, const char *name)
+{
+       struct  inode *cache_inode;
+       struct  dentry open_dentry;
+       int     rc = 0;
+
+       cache_inode = I2CI(dentry->d_inode);
+
+       if (!cache_inode) 
+               RETURN(-ENOENT);
+
+       smfs_prepare_cache_dentry(&open_dentry, cache_inode);
+       
+       if (cache_inode->i_op->removexattr)
+               rc = cache_inode->i_op->removexattr(&open_dentry, name);
+
+       RETURN(rc);
+}
+
 struct inode_operations smfs_file_iops = {
        truncate:       smfs_truncate,          /* BKL held */
         setattr:        smfs_setattr,           /* BKL held */
+        setxattr:       smfs_setxattr,          /* BKL held */
+        getxattr:       smfs_getxattr,          /* BKL held */
+        listxattr:      smfs_listxattr,         /* BKL held */
+        removexattr:    smfs_removexattr,       /* BKL held */
 };