Whamcloud - gitweb
Bug #357, no more gratituous new line..., or typecasting
[fs/lustre-release.git] / lustre / mds / mds_extN.c
index ee11330..8ba7979 100644 (file)
@@ -1,31 +1,45 @@
 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
  * vim:expandtab:shiftwidth=8:tabstop=8:
  *
- *  linux/mds/mds_extN.c
- *
+ *  lustre/mds/mds_extN.c
  *  Lustre Metadata Server (mds) journal abstraction routines
  *
- *  Copyright (C) 2002  Cluster File Systems, Inc.
- *  author: Andreas Dilger <adilger@clusterfs.com>
+ *  Copyright (C) 2002 Cluster File Systems, Inc.
+ *   Author: Andreas Dilger <adilger@clusterfs.com>
+ *
+ *   This file is part of Lustre, http://www.lustre.org.
  *
- *  This code is issued under the GNU General Public License.
- *  See the file COPYING in this distribution
+ *   Lustre 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.
  *
+ *   Lustre 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 Lustre; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #define DEBUG_SUBSYSTEM S_MDS
 
 #include <linux/fs.h>
 #include <linux/jbd.h>
+#include <linux/slab.h>
 #include <linux/extN_fs.h>
 #include <linux/extN_jbd.h>
 #include <linux/extN_xattr.h>
+#include <linux/kp30.h>
 #include <linux/lustre_mds.h>
+#include <linux/obd.h>
 #include <linux/module.h>
+#include <linux/obd_lov.h>
 
 static struct mds_fs_operations mds_extN_fs_ops;
-static kmem_cache_t *jcb_cache;
-static int jcb_cache_count;
+static kmem_cache_t *mcb_cache;
+static int mcb_cache_count;
 
 struct mds_cb_data {
         struct journal_callback cb_jcb;
@@ -33,17 +47,10 @@ struct mds_cb_data {
         __u64 cb_last_rcvd;
 };
 
-struct mds_objid {
-        __u16 mo_magic;
-        __u8  mo_unused;
-        __u8  mo_ost;
-        __u64 mo_id;
-};
-
 #define EXTN_XATTR_INDEX_LUSTRE         5
 #define XATTR_LUSTRE_MDS_OBJID          "system.lustre_mds_objid"
 
-#define XATTR_MDS_MO_MAGIC              0x4711
+#define XATTR_MDS_MO_MAGIC              0xEA0BD047
 
 /*
  * We don't currently need any additional blocks for rmdir and
@@ -55,6 +62,7 @@ static void *mds_extN_start(struct inode *inode, int op)
 {
         /* For updates to the last recieved file */
         int nblocks = EXTN_DATA_TRANS_BLOCKS;
+        void *handle;
 
         switch(op) {
         case MDS_FSOP_RMDIR:
@@ -84,84 +92,89 @@ static void *mds_extN_start(struct inode *inode, int op)
                  LBUG();
         }
 
-        return journal_start(EXTN_JOURNAL(inode), nblocks);
+        lock_kernel();
+        handle = journal_start(EXTN_JOURNAL(inode), nblocks);
+        unlock_kernel();
+
+        return handle;
 }
 
 static int mds_extN_commit(struct inode *inode, void *handle)
 {
-        return journal_stop((handle_t *)handle);
+        int rc;
+
+        lock_kernel();
+        rc = journal_stop((handle_t *)handle);
+        unlock_kernel();
+
+        return rc;
 }
 
 static int mds_extN_setattr(struct dentry *dentry, void *handle,
                             struct iattr *iattr)
 {
         struct inode *inode = dentry->d_inode;
+        int rc;
 
+        lock_kernel();
         if (inode->i_op->setattr)
-                return inode->i_op->setattr(dentry, iattr);
+                rc = inode->i_op->setattr(dentry, iattr);
         else
-                return inode_setattr(inode, iattr);
+                rc = inode_setattr(inode, iattr);
+
+        unlock_kernel();
+
+        return rc;
 }
 
-static int mds_extN_set_objid(struct inode *inode, void *handle, obd_id id)
+static int mds_extN_set_md(struct inode *inode, void *handle,
+                           struct lov_mds_md *lmm)
 {
-        struct mds_objid data;
         int rc;
 
-        data.mo_magic = cpu_to_le16(XATTR_MDS_MO_MAGIC);
-        data.mo_unused = 0;
-        data.mo_ost = 0;  /* FIXME: store OST index here */
-        data.mo_id = cpu_to_le64(id);
-
-        lock_kernel();
         down(&inode->i_sem);
-        if (id == 0) {
-                rc = extN_xattr_set(handle, inode, EXTN_XATTR_INDEX_LUSTRE,
-                                    XATTR_LUSTRE_MDS_OBJID, NULL, 0, 0);
-        } else {
-                rc = extN_xattr_set(handle, inode, EXTN_XATTR_INDEX_LUSTRE,
-                                    XATTR_LUSTRE_MDS_OBJID, &data,
-                                    sizeof(struct mds_objid), XATTR_CREATE);
-        }
-        up(&inode->i_sem);
+        lock_kernel();
+        rc = extN_xattr_set(handle, inode, EXTN_XATTR_INDEX_LUSTRE,
+                            XATTR_LUSTRE_MDS_OBJID, lmm,
+                            lmm ? lmm->lmm_easize : 0, 0);
         unlock_kernel();
+        up(&inode->i_sem);
 
-        if (rc)
-                CERROR("error adding objectid %Ld to inode %ld\n",
-                       (unsigned long long)id, inode->i_ino);
+        if (rc) {
+                CERROR("error adding objectid "LPX64" to inode %ld: %d\n",
+                       lmm->lmm_object_id, inode->i_ino, rc);
+                if (rc != -ENOSPC) LBUG();
+        }
         return rc;
 }
 
-static int mds_extN_get_objid(struct inode *inode, obd_id *id)
+static int mds_extN_get_md(struct inode *inode, struct lov_mds_md *lmm)
 {
-        struct mds_objid data;
         int rc;
+        int size = lmm->lmm_easize;
 
-        lock_kernel();
         down(&inode->i_sem);
+        lock_kernel();
         rc = extN_xattr_get(inode, EXTN_XATTR_INDEX_LUSTRE,
-                            XATTR_LUSTRE_MDS_OBJID, &data,
-                            sizeof(struct mds_objid));
-        up(&inode->i_sem);
+                            XATTR_LUSTRE_MDS_OBJID, lmm, size);
         unlock_kernel();
+        up(&inode->i_sem);
+
+        /* This gives us the MD size */
+        if (lmm == NULL)
+                return rc;
 
         if (rc < 0) {
-                CERROR("error getting EA %s from MDS inode %ld: rc = %d\n",
-                       XATTR_LUSTRE_MDS_OBJID, inode->i_ino, rc);
-                *id = 0;
-        } else if (data.mo_magic != cpu_to_le16(XATTR_MDS_MO_MAGIC)) {
-                CERROR("MDS object id %Ld has bad magic %x\n",
-                       (unsigned long long)le64_to_cpu(data.mo_id),
-                       le16_to_cpu(data.mo_magic));
-                rc = -EINVAL;
-        } else {
-                *id = le64_to_cpu(data.mo_id);
-                /* FIXME: will actually use data.mo_ost at some point */
-                if (data.mo_ost)
-                        CERROR("MDS objid %Ld with ost index %d!\n",
-                               *id, data.mo_ost);
+                CDEBUG(D_INFO, "error getting EA %s from MDS inode %ld: "
+                       "rc = %d\n", XATTR_LUSTRE_MDS_OBJID, inode->i_ino, rc);
+                memset(lmm, 0, size);
+                return rc;
         }
 
+        /* This field is byteswapped because it appears in the
+         * catalogue.  All others are opaque to the MDS */
+        lmm->lmm_object_id = le64_to_cpu(lmm->lmm_object_id);
+
         return rc;
 }
 
@@ -202,7 +215,7 @@ static void mds_extN_delete_inode(struct inode *inode)
                         EXIT;
                         return;
                 }
-                if (mds_extN_set_objid(inode, handle, 0))
+                if (mds_extN_set_md(inode, handle, NULL))
                         CERROR("error clearing objid on %ld\n", inode->i_ino);
 
                 if (mds_extN_fs_ops.cl_delete_inode)
@@ -218,44 +231,35 @@ static void mds_extN_callback_status(struct journal_callback *jcb, int error)
 {
         struct mds_cb_data *mcb = (struct mds_cb_data *)jcb;
 
-        CDEBUG(D_EXT2, "got callback for last_rcvd %Ld: rc = %d\n",
+        CDEBUG(D_EXT2, "got callback for last_rcvd "LPD64": rc = %d\n",
                mcb->cb_last_rcvd, error);
         if (!error && mcb->cb_last_rcvd > mcb->cb_mds->mds_last_committed)
                 mcb->cb_mds->mds_last_committed = mcb->cb_last_rcvd;
 
-        kmem_cache_free(jcb_cache, jcb);
-        --jcb_cache_count;
-}
-
-#ifdef HAVE_JOURNAL_CALLBACK
-static void mds_extN_callback_func(void *cb_data)
-{
-        mds_extN_callback_status(cb_data, 0);
+        kmem_cache_free(mcb_cache, mcb);
+        --mcb_cache_count;
 }
-#endif
 
 static int mds_extN_set_last_rcvd(struct mds_obd *mds, void *handle)
 {
         struct mds_cb_data *mcb;
 
-        mcb = kmem_cache_alloc(jcb_cache, GFP_NOFS);
+        mcb = kmem_cache_alloc(mcb_cache, GFP_NOFS);
         if (!mcb)
                 RETURN(-ENOMEM);
 
-        ++jcb_cache_count;
+        ++mcb_cache_count;
         mcb->cb_mds = mds;
         mcb->cb_last_rcvd = mds->mds_last_rcvd;
 
 #ifdef HAVE_JOURNAL_CALLBACK_STATUS
-        CDEBUG(D_EXT2, "set callback for last_rcvd: %Ld\n",
-               (unsigned long long)mcb->cb_last_rcvd);
+        CDEBUG(D_EXT2, "set callback for last_rcvd: "LPD64"\n",
+               mcb->cb_last_rcvd);
+        lock_kernel();
+        /* Note that an "incompatible pointer" warning here is OK for now */
         journal_callback_set(handle, mds_extN_callback_status,
                              (struct journal_callback *)mcb);
-#elif HAVE_JOURNAL_CALLBACK /* XXX original patch version - remove soon */
-#warning "using old journal callback kernel patch, please update"
-        CDEBUG(D_EXT2, "set callback for last_rcvd: %Ld\n",
-               (unsigned long long)mcb->cb_last_rcvd);
-        journal_callback_set(handle, mds_extN_callback_func, mcb);
+        unlock_kernel();
 #else
 #warning "no journal callback kernel patch, faking it..."
         {
@@ -265,7 +269,7 @@ static int mds_extN_set_last_rcvd(struct mds_obd *mds, void *handle)
                 CERROR("no journal callback kernel patch, faking it...\n");
                 next = jiffies + 300 * HZ;
         }
-        }
+
         mds_extN_callback_status((struct journal_callback *)mcb, 0);
 #endif
 
@@ -281,17 +285,36 @@ static int mds_extN_journal_data(struct file *filp)
         return 0;
 }
 
+/*
+ * We need to hack the return value for the free inode counts because
+ * the current EA code requires one filesystem block per inode with EAs,
+ * so it is possible to run out of blocks before we run out of inodes.
+ *
+ * This can be removed when the extN EA code is fixed.
+ */
+static int mds_extN_statfs(struct super_block *sb, struct statfs *sfs)
+{
+        int rc = vfs_statfs(sb, sfs);
+
+        if (!rc && sfs->f_bfree < sfs->f_ffree)
+                sfs->f_ffree = sfs->f_bfree;
+
+        return rc;
+}
+
 static struct mds_fs_operations mds_extN_fs_ops = {
+        fs_owner:               THIS_MODULE,
         fs_start:               mds_extN_start,
         fs_commit:              mds_extN_commit,
         fs_setattr:             mds_extN_setattr,
-        fs_set_objid:           mds_extN_set_objid,
-        fs_get_objid:           mds_extN_get_objid,
+        fs_set_md:              mds_extN_set_md,
+        fs_get_md:              mds_extN_get_md,
         fs_readpage:            mds_extN_readpage,
         fs_delete_inode:        mds_extN_delete_inode,
         cl_delete_inode:        clear_inode,
         fs_journal_data:        mds_extN_journal_data,
         fs_set_last_rcvd:       mds_extN_set_last_rcvd,
+        fs_statfs:              mds_extN_statfs,
 };
 
 static int __init mds_extN_init(void)
@@ -299,17 +322,18 @@ static int __init mds_extN_init(void)
         int rc;
 
         //rc = extN_xattr_register();
-        jcb_cache = kmem_cache_create("mds_extN_jcb",
+        mcb_cache = kmem_cache_create("mds_extN_mcb",
                                       sizeof(struct mds_cb_data), 0,
-                                      SLAB_POISON, NULL, NULL);
-        if (!jcb_cache) {
+                                      0, NULL, NULL);
+        if (!mcb_cache) {
                 CERROR("error allocating MDS journal callback cache\n");
                 GOTO(out, rc = -ENOMEM);
         }
+
         rc = mds_register_fs_type(&mds_extN_fs_ops, "extN");
 
         if (rc)
-                kmem_cache_destroy(jcb_cache);
+                kmem_cache_destroy(mcb_cache);
 out:
         return rc;
 }
@@ -319,17 +343,17 @@ static void __exit mds_extN_exit(void)
         int rc;
 
         mds_unregister_fs_type("extN");
-        rc = kmem_cache_destroy(jcb_cache);
+        rc = kmem_cache_destroy(mcb_cache);
 
-        if (rc || jcb_cache_count) {
+        if (rc || mcb_cache_count) {
                 CERROR("can't free MDS callback cache: count %d, rc = %d\n",
-                       jcb_cache_count, rc);
+                       mcb_cache_count, rc);
         }
 
         //rc = extN_xattr_unregister();
 }
 
-MODULE_AUTHOR("Cluster File Systems, Inc. <adilger@clusterfs.com>");
+MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
 MODULE_DESCRIPTION("Lustre MDS extN Filesystem Helper v0.1");
 MODULE_LICENSE("GPL");