Whamcloud - gitweb
LU-957 scrub: OSD layer cleanup for OI scrub
authorFan Yong <yong.fan@whamcloud.com>
Wed, 30 May 2012 15:08:06 +0000 (23:08 +0800)
committerOleg Drokin <green@whamcloud.com>
Mon, 4 Jun 2012 22:43:21 +0000 (18:43 -0400)
1) Abstract some common functions in OSD layer.
2) Call lu_object_put() in osd_object_find() under failure case.
3) Do not release buffer_head until all the needed contents have
   been accessed in osd_oi_index_create_one().

Signed-off-by: Fan Yong <yong.fan@whamcloud.com>
Change-Id: I3e6880271ee73ec2c4638b02c7e9c55fc827bdf3
Reviewed-on: http://review.whamcloud.com/2551
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: Hudson
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/osd-ldiskfs/osd_compat.c
lustre/osd-ldiskfs/osd_handler.c
lustre/osd-ldiskfs/osd_igif.c
lustre/osd-ldiskfs/osd_internal.h
lustre/osd-ldiskfs/osd_io.c
lustre/osd-ldiskfs/osd_oi.c
lustre/osd-ldiskfs/osd_oi.h

index 69bea5d..1e9b397 100644 (file)
@@ -55,6 +55,7 @@
 #include <lvfs.h>
 
 #include "osd_internal.h"
+#include "osd_oi.h"
 
 struct osd_compat_objid_seq {
         /* protects on-fly initialization */
@@ -344,8 +345,7 @@ int osd_compat_add_entry(struct osd_thread_info *info, struct osd_device *osd,
 
         inode = &info->oti_inode;
         inode->i_sb = osd_sb(osd);
-        inode->i_ino = id->oii_ino;
-        inode->i_generation = id->oii_gen;
+       osd_id_to_inode(inode, id);
 
         child = &info->oti_child_dentry;
         child->d_name.hash = 0;
@@ -369,12 +369,12 @@ int osd_compat_objid_lookup(struct osd_thread_info *info,
         struct dentry              *d;
         struct dentry              *d_seq;
         struct ost_id              *ostid = &info->oti_ostid;
-        int                         rc = 0;
         int                         dirn;
         char                        name[32];
         struct ldiskfs_dir_entry_2 *de;
         struct buffer_head         *bh;
         struct inode               *dir;
+       struct inode               *inode;
         ENTRY;
 
         /* on the very first lookup we find and open directories */
@@ -405,25 +405,18 @@ int osd_compat_objid_lookup(struct osd_thread_info *info,
         bh = osd_ldiskfs_find_entry(dir, d_seq, &de, NULL);
         UNLOCK_INODE_MUTEX(dir);
 
-        rc = -ENOENT;
-        if (bh) {
-                struct inode *inode;
-
-                id->oii_ino = le32_to_cpu(de->inode);
-                brelse(bh);
+       if (bh == NULL)
+               RETURN(-ENOENT);
 
-                id->oii_gen = OSD_OII_NOGEN;
-                inode = osd_iget(info, dev, id);
+       osd_id_gen(id, le32_to_cpu(de->inode), OSD_OII_NOGEN);
+       brelse(bh);
 
-                if (IS_ERR(inode))
-                        GOTO(cleanup, rc = PTR_ERR(inode));
-                rc = 0;
-                id->oii_gen = inode->i_generation;
-                iput(inode);
-        }
+       inode = osd_iget(info, dev, id);
+       if (IS_ERR(inode))
+               RETURN(PTR_ERR(inode));
 
-cleanup:
-        RETURN(rc);
+       iput(inode);
+       RETURN(0);
 }
 
 int osd_compat_objid_insert(struct osd_thread_info *info,
@@ -555,6 +548,7 @@ int osd_compat_spec_lookup(struct osd_thread_info *info,
                           struct osd_inode_id *id)
 {
        struct dentry *dentry;
+       struct inode  *inode;
        char          *name;
        int            rc = -ENOENT;
        ENTRY;
@@ -563,20 +557,20 @@ int osd_compat_spec_lookup(struct osd_thread_info *info,
        if (name == NULL || strlen(name) == 0)
                RETURN(-ENOENT);
 
-        dentry = ll_lookup_one_len(name, osd_sb(osd)->s_root, strlen(name));
-        if (!IS_ERR(dentry)) {
-                if (dentry->d_inode) {
-                        if (is_bad_inode(dentry->d_inode)) {
-                                rc = -EIO;
-                        } else {
-                                id->oii_ino = dentry->d_inode->i_ino;
-                                id->oii_gen = dentry->d_inode->i_generation;
-                                rc = 0;
-                        }
-                }
-                dput(dentry);
-        }
+       dentry = ll_lookup_one_len(name, osd_sb(osd)->s_root, strlen(name));
+       if (!IS_ERR(dentry)) {
+               inode = dentry->d_inode;
+               if (inode) {
+                       if (is_bad_inode(inode)) {
+                               rc = -EIO;
+                       } else {
+                               osd_id_gen(id, inode->i_ino,
+                                          inode->i_generation);
+                               rc = 0;
+                       }
+               }
+               dput(dentry);
+       }
 
-        RETURN(rc);
+       RETURN(rc);
 }
-
index 057e062..b68f7f7 100644 (file)
@@ -243,43 +243,101 @@ static struct lu_object *osd_object_alloc(const struct lu_env *env,
         }
 }
 
+static int osd_get_lma(struct inode *inode, struct dentry *dentry,
+                      struct lustre_mdt_attrs *lma)
+{
+       int rc;
+
+       dentry->d_inode = inode;
+       rc = inode->i_op->getxattr(dentry, XATTR_NAME_LMA, (void *)lma,
+                                  sizeof(*lma));
+       if (rc > 0) {
+               /* Check LMA compatibility */
+               if (lma->lma_incompat & ~cpu_to_le32(LMA_INCOMPAT_SUPP)) {
+                       CWARN("%.16s: unsupported incompat LMA feature(s) "
+                             "%lx/%#x\n",
+                             LDISKFS_SB(inode->i_sb)->s_es->s_volume_name,
+                             inode->i_ino, le32_to_cpu(lma->lma_incompat) &
+                                                       ~LMA_INCOMPAT_SUPP);
+                       rc = -ENOSYS;
+               } else {
+                       lustre_lma_swab(lma);
+                       rc = 0;
+               }
+       } else if (rc == 0) {
+               rc = -ENODATA;
+       }
+
+       return rc;
+}
+
 /*
  * retrieve object from backend ext fs.
  **/
-struct inode *osd_iget(struct osd_thread_info *info,
-                       struct osd_device *dev,
-                       const struct osd_inode_id *id)
+struct inode *osd_iget(struct osd_thread_info *info, struct osd_device *dev,
+                      struct osd_inode_id *id)
+{
+       struct inode *inode = NULL;
+
+       inode = ldiskfs_iget(osd_sb(dev), id->oii_ino);
+       if (IS_ERR(inode)) {
+               CDEBUG(D_INODE, "no inode: ino = %u, rc = %ld\n",
+                      id->oii_ino, PTR_ERR(inode));
+       } else if (id->oii_gen != OSD_OII_NOGEN &&
+                  inode->i_generation != id->oii_gen) {
+               CDEBUG(D_INODE, "unmatched inode: ino = %u, gen0 = %u, "
+                      "gen1 = %u\n",
+                      id->oii_ino, id->oii_gen, inode->i_generation);
+               iput(inode);
+               inode = ERR_PTR(-ESTALE);
+       } else if (inode->i_nlink == 0) {
+               /* due to parallel readdir and unlink,
+               * we can have dead inode here. */
+               CDEBUG(D_INODE, "stale inode: ino = %u\n", id->oii_ino);
+               make_bad_inode(inode);
+               iput(inode);
+               inode = ERR_PTR(-ESTALE);
+       } else if (is_bad_inode(inode)) {
+               CWARN("%s: bad inode: ino = %u\n",
+               dev->od_dt_dev.dd_lu_dev.ld_obd->obd_name, id->oii_ino);
+               iput(inode);
+               inode = ERR_PTR(-ENOENT);
+       } else {
+               if (id->oii_gen == OSD_OII_NOGEN)
+                       osd_id_gen(id, inode->i_ino, inode->i_generation);
+
+               /* Do not update file c/mtime in ldiskfs.
+                * NB: we don't have any lock to protect this because we don't
+                * have reference on osd_object now, but contention with
+                * another lookup + attr_set can't happen in the tiny window
+                * between if (...) and set S_NOCMTIME. */
+               if (!(inode->i_flags & S_NOCMTIME))
+                       inode->i_flags |= S_NOCMTIME;
+       }
+       return inode;
+}
+
+struct inode *osd_iget_fid(struct osd_thread_info *info, struct osd_device *dev,
+                          struct osd_inode_id *id, struct lu_fid *fid)
 {
-        struct inode *inode = NULL;
+       struct lustre_mdt_attrs *lma   = &info->oti_mdt_attrs;
+       struct inode            *inode;
+       int                      rc;
 
-        inode = ldiskfs_iget(osd_sb(dev), id->oii_ino);
-        if (IS_ERR(inode)) {
-                CERROR("Cannot get inode, rc = %li\n", PTR_ERR(inode));
-        } else if (id->oii_gen != OSD_OII_NOGEN &&
-                   inode->i_generation != id->oii_gen) {
-                iput(inode);
-                inode = ERR_PTR(-ESTALE);
-        } else if (inode->i_nlink == 0) {
-                /* due to parallel readdir and unlink,
-                * we can have dead inode here. */
-                CWARN("stale inode\n");
-                make_bad_inode(inode);
-                iput(inode);
-                inode = ERR_PTR(-ESTALE);
-        } else if (is_bad_inode(inode)) {
-                CERROR("bad inode %lx\n",inode->i_ino);
-                iput(inode);
-                inode = ERR_PTR(-ENOENT);
-        } else {
-                /* Do not update file c/mtime in ldiskfs.
-                 * NB: we don't have any lock to protect this because we don't
-                 * have reference on osd_object now, but contention with
-                 * another lookup + attr_set can't happen in the tiny window
-                 * between if (...) and set S_NOCMTIME. */
-                if (!(inode->i_flags & S_NOCMTIME))
-                        inode->i_flags |= S_NOCMTIME;
-        }
-        return inode;
+       inode = osd_iget(info, dev, id);
+       if (IS_ERR(inode))
+               return inode;
+
+       rc = osd_get_lma(inode, &info->oti_obj_dentry, lma);
+       if (rc == 0) {
+               *fid = lma->lma_self_fid;
+       } else if (rc == -ENODATA) {
+               LU_IGIF_BUILD(fid, inode->i_ino, inode->i_generation);
+       } else {
+               iput(inode);
+               inode = ERR_PTR(rc);
+       }
+       return inode;
 }
 
 static int osd_fid_lookup(const struct lu_env *env,
@@ -340,18 +398,20 @@ static int osd_fid_lookup(const struct lu_env *env,
         }
 
         if (!S_ISDIR(inode->i_mode) || !ldiskfs_pdo) /* done */
-                goto out;
+               GOTO(out, result = 0);
+
+       LASSERT(obj->oo_hl_head == NULL);
+       obj->oo_hl_head = ldiskfs_htree_lock_head_alloc(HTREE_HBITS_DEF);
+       if (obj->oo_hl_head == NULL) {
+               obj->oo_inode = NULL;
+               iput(inode);
+               GOTO(out, result = -ENOMEM);
+       }
+       GOTO(out, result = 0);
 
-        LASSERT(obj->oo_hl_head == NULL);
-        obj->oo_hl_head = ldiskfs_htree_lock_head_alloc(HTREE_HBITS_DEF);
-        if (obj->oo_hl_head == NULL) {
-                obj->oo_inode = NULL;
-                iput(inode);
-                result = -ENOMEM;
-        }
 out:
-        LINVRNT(osd_invariant(obj));
-        RETURN(result);
+       LINVRNT(osd_invariant(obj));
+       return result;
 }
 
 /*
@@ -870,7 +930,7 @@ static void osd_conf_get(const struct lu_env *env,
          */
         param->ddp_max_name_len = LDISKFS_NAME_LEN;
         param->ddp_max_nlink    = LDISKFS_LINK_MAX;
-        param->ddp_block_shift  = osd_sb(osd_dt_dev(dev))->s_blocksize_bits;
+       param->ddp_block_shift  = sb->s_blocksize_bits;
         param->ddp_mntopts      = 0;
         if (test_opt(sb, XATTR_USER))
                 param->ddp_mntopts |= MNTOPT_USERXATTR;
@@ -1694,11 +1754,8 @@ static int __osd_oi_insert(const struct lu_env *env, struct osd_object *obj,
         LASSERT(obj->oo_inode != NULL);
         LASSERT(uc != NULL);
 
-        id->oii_ino = obj->oo_inode->i_ino;
-        id->oii_gen = obj->oo_inode->i_generation;
-
-        return osd_oi_insert(info, osd, fid, id, th,
-                             uc->mu_cap & CFS_CAP_SYS_RESOURCE_MASK);
+       osd_id_gen(id, obj->oo_inode->i_ino, obj->oo_inode->i_generation);
+       return osd_oi_insert(info, osd, fid, id, th);
 }
 
 static int osd_declare_object_create(const struct lu_env *env,
@@ -1895,15 +1952,6 @@ static int osd_ea_fid_set(const struct lu_env *env, struct dt_object *dt,
 }
 
 /**
- * Helper function to form igif
- */
-static inline void osd_igif_get(const struct lu_env *env, struct inode  *inode,
-                                struct lu_fid *fid)
-{
-        LU_IGIF_BUILD(fid, inode->i_ino, inode->i_generation);
-}
-
-/**
  * ldiskfs supports fid in dirent, it is passed in dentry->d_fsdata.
  * lustre 1.8 also uses d_fsdata for passing other info to ldiskfs.
  * To have compatilibility with 1.8 ldiskfs driver we need to have
@@ -1930,54 +1978,20 @@ void osd_get_ldiskfs_dirent_param(struct ldiskfs_dentry_param *param,
  * \retval 0 on success
  */
 static int osd_ea_fid_get(const struct lu_env *env, struct osd_object *obj,
-                          __u32 ino, struct lu_fid *fid)
+                         __u32 ino, struct lu_fid *fid)
 {
-        struct osd_thread_info  *info      = osd_oti_get(env);
-        struct lustre_mdt_attrs *mdt_attrs = &info->oti_mdt_attrs;
-        struct lu_device        *ldev   = obj->oo_dt.do_lu.lo_dev;
-        struct dentry           *dentry = &info->oti_child_dentry;
-        struct osd_inode_id     *id     = &info->oti_id;
-        struct osd_device       *dev;
-        struct inode            *inode;
-        int                      rc;
-
-        ENTRY;
-        dev  = osd_dev(ldev);
-
-        id->oii_ino = ino;
-        id->oii_gen = OSD_OII_NOGEN;
-
-        inode = osd_iget(info, dev, id);
-        if (IS_ERR(inode)) {
-                rc = PTR_ERR(inode);
-                GOTO(out,rc);
-        }
-        dentry->d_inode = inode;
+       struct osd_thread_info  *info = osd_oti_get(env);
+       struct osd_inode_id     *id = &info->oti_id;
+       struct inode            *inode;
+       ENTRY;
 
-        LASSERT(inode->i_op != NULL && inode->i_op->getxattr != NULL);
-        rc = inode->i_op->getxattr(dentry, XATTR_NAME_LMA, (void *)mdt_attrs,
-                                   sizeof *mdt_attrs);
-
-        /* Check LMA compatibility */
-        if (rc > 0 &&
-            (mdt_attrs->lma_incompat & ~cpu_to_le32(LMA_INCOMPAT_SUPP))) {
-                CWARN("Inode %lx: Unsupported incompat LMA feature(s) %#x\n",
-                      inode->i_ino, le32_to_cpu(mdt_attrs->lma_incompat) &
-                      ~LMA_INCOMPAT_SUPP);
-                return -ENOSYS;
-        }
+       osd_id_gen(id, ino, OSD_OII_NOGEN);
+       inode = osd_iget_fid(info, osd_obj2dev(obj), id, fid);
+       if (IS_ERR(inode))
+               RETURN(PTR_ERR(inode));
 
-        if (rc > 0) {
-                lustre_lma_swab(mdt_attrs);
-                memcpy(fid, &mdt_attrs->lma_self_fid, sizeof(*fid));
-                rc = 0;
-        } else if (rc == -ENODATA) {
-                osd_igif_get(env, inode, fid);
-                rc = 0;
-        }
-        iput(inode);
-out:
-        RETURN(rc);
+       iput(inode);
+       RETURN(0);
 }
 
 /**
@@ -2911,7 +2925,7 @@ static int osd_index_iam_insert(const struct lu_env *env, struct dt_object *dt,
         LASSERT(th != NULL);
 
         if (osd_object_auth(env, dt, capa, CAPA_OPC_INDEX_INSERT))
-                return -EACCES;
+               RETURN(-EACCES);
 
         OSD_EXEC_OP(th, insert);
 
@@ -3173,7 +3187,7 @@ struct osd_object *osd_object_find(const struct lu_env *env,
                         else
                                 LU_OBJECT_DEBUG(D_ERROR, env, luch,
                                                 "lu_object can't be located"
-                                                ""DFID"\n", PFID(fid));
+                                               DFID"\n", PFID(fid));
 
                         if (child == NULL) {
                                 lu_object_put(env, luch);
@@ -3184,6 +3198,7 @@ struct osd_object *osd_object_find(const struct lu_env *env,
                         LU_OBJECT_DEBUG(D_ERROR, env, luch,
                                         "lu_object does not exists "DFID"\n",
                                         PFID(fid));
+                       lu_object_put(env, luch);
                         child = ERR_PTR(-ENOENT);
                 }
         } else
index 8df57ab..fa7b0af 100644 (file)
@@ -55,8 +55,6 @@
 
 void lu_igif_to_id(const struct lu_fid *fid, struct osd_inode_id *id)
 {
-        LASSERT(fid_is_igif(fid));
-        id->oii_ino = lu_igif_ino(fid);
-        id->oii_gen = lu_igif_gen(fid);
+       LASSERT(fid_is_igif(fid));
+       osd_id_gen(id, lu_igif_ino(fid), lu_igif_gen(fid));
 }
-
index dcd29aa..f6858e1 100644 (file)
@@ -78,7 +78,6 @@
 
 struct inode;
 
-#define OSD_OII_NOGEN (0)
 #define OSD_COUNTERS (0)
 
 /** Enable thandle usage statistics */
@@ -441,7 +440,9 @@ struct osd_thread_info {
         struct htree_lock     *oti_hlock;
 
         struct lu_fid          oti_fid;
-        struct osd_inode_id    oti_id;
+       struct lu_fid          oti_fid2;
+       struct osd_inode_id    oti_id;
+       struct osd_inode_id    oti_id2;
         struct ost_id          oti_ostid;
 
         /*
@@ -535,9 +536,10 @@ int osd_object_auth(const struct lu_env *env, struct dt_object *dt,
                     struct lustre_capa *capa, __u64 opc);
 void osd_declare_qid(struct dt_object *dt, struct osd_thandle *oh,
                      int type, uid_t id, struct inode *inode);
-struct inode *osd_iget(struct osd_thread_info *info,
-                       struct osd_device *dev,
-                       const struct osd_inode_id *id);
+struct inode *osd_iget(struct osd_thread_info *info, struct osd_device *dev,
+                      struct osd_inode_id *id);
+struct inode *osd_iget_fid(struct osd_thread_info *info, struct osd_device *dev,
+                          struct osd_inode_id *id, struct lu_fid *fid);
 
 int osd_compat_init(struct osd_device *dev);
 void osd_compat_fini(struct osd_device *dev);
@@ -585,6 +587,14 @@ static inline int osd_invariant(const struct osd_object *obj)
 #define osd_invariant(obj) (1)
 #endif
 
+extern const struct dt_index_operations osd_otable_ops;
+
+static inline int osd_oi_fid2idx(struct osd_device *dev,
+                                const struct lu_fid *fid)
+{
+       return fid->f_seq & (dev->od_oi_count - 1);
+}
+
 static inline struct osd_oi *osd_fid2oi(struct osd_device *osd,
                                         const struct lu_fid *fid)
 {
@@ -593,7 +603,7 @@ static inline struct osd_oi *osd_fid2oi(struct osd_device *osd,
         LASSERT(osd->od_oi_table != NULL && osd->od_oi_count >= 1);
         /* It can work even od_oi_count equals to 1 although it's unexpected,
          * the only reason we set it to 1 is for performance measurement */
-        return osd->od_oi_table[fid->f_seq & (osd->od_oi_count - 1)];
+       return osd->od_oi_table[osd_oi_fid2idx(osd, fid)];
 }
 
 extern const struct lu_device_operations  osd_lu_ops;
@@ -688,6 +698,8 @@ static inline void osd_ipd_put(const struct lu_env *env,
 }
 
 int osd_ldiskfs_read(struct inode *inode, void *buf, int size, loff_t *offs);
+int osd_ldiskfs_write_record(struct inode *inode, void *buf, int bufsize,
+                            loff_t *offs, handle_t *handle);
 
 static inline
 struct dentry *osd_child_dentry_by_inode(const struct lu_env *env,
index c913d11..9adc20f 100644 (file)
@@ -969,8 +969,8 @@ static int osd_ldiskfs_writelink(struct inode *inode, char *buffer, int buflen)
         return 0;
 }
 
-static int osd_ldiskfs_write_record(struct inode *inode, void *buf, int bufsize,
-                                    loff_t *offs, handle_t *handle)
+int osd_ldiskfs_write_record(struct inode *inode, void *buf, int bufsize,
+                            loff_t *offs, handle_t *handle)
 {
         struct buffer_head *bh        = NULL;
         loff_t              offset    = *offs;
index d5f7a31..d13a0fa 100644 (file)
 
 /* fid_cpu_to_be() */
 #include <lustre_fid.h>
+#include <dt_object.h>
 
 #include "osd_oi.h"
 /* osd_lookup(), struct osd_thread_info */
 #include "osd_internal.h"
 #include "osd_igif.h"
-#include "dt_object.h"
-
-#define OSD_OI_FID_NR         (1UL << OSD_OI_FID_OID_BITS)
-#define OSD_OI_FID_NR_MAX     (1UL << OSD_OI_FID_OID_BITS_MAX)
 
 static unsigned int osd_oi_count = OSD_OI_FID_NR;
 CFS_MODULE_PARM(osd_oi_count, "i", int, 0444,
@@ -111,62 +108,56 @@ static void osd_oi_table_put(struct osd_thread_info *info,
 }
 
 static int osd_oi_index_create_one(struct osd_thread_info *info,
-                                   struct osd_device *osd, const char *name,
-                                   struct dt_index_features *feat)
+                                  struct osd_device *osd, const char *name,
+                                  struct dt_index_features *feat)
 {
-        const struct lu_env             *env = info->oti_env;
-        struct osd_inode_id             *id  = &info->oti_id;
-        struct buffer_head              *bh;
-        struct inode                    *inode;
-        struct ldiskfs_dir_entry_2      *de;
-        struct dentry                   *dentry;
-        struct inode                    *dir;
-        handle_t                        *jh;
-        int                              rc;
-
-        dentry = osd_child_dentry_by_inode(env, osd_sb(osd)->s_root->d_inode,
-                                           name, strlen(name));
-        dir = osd_sb(osd)->s_root->d_inode;
-        bh = osd_ldiskfs_find_entry(dir, dentry, &de, NULL);
-        if (bh) {
-                brelse(bh);
-
-                id->oii_ino = le32_to_cpu(de->inode);
-                id->oii_gen = OSD_OII_NOGEN;
-
-                inode = osd_iget(info, osd, id);
-                if (!IS_ERR(inode)) {
-                        iput(inode);
-                        RETURN(-EEXIST);
-                }
-                RETURN(PTR_ERR(inode));
-        }
-
-        jh = ldiskfs_journal_start_sb(osd_sb(osd), 100);
-        LASSERT(!IS_ERR(jh));
-
-        inode = ldiskfs_create_inode(jh, osd_sb(osd)->s_root->d_inode,
-                                     (S_IFREG | S_IRUGO | S_IWUSR));
-        LASSERT(!IS_ERR(inode));
-
-        if (feat->dif_flags & DT_IND_VARKEY)
-                rc = iam_lvar_create(inode, feat->dif_keysize_max,
-                                     feat->dif_ptrsize, feat->dif_recsize_max,
-                                     jh);
-        else
-                rc = iam_lfix_create(inode, feat->dif_keysize_max,
-                                     feat->dif_ptrsize, feat->dif_recsize_max,
-                                     jh);
-
-        dentry = osd_child_dentry_by_inode(env, osd_sb(osd)->s_root->d_inode,
-                                           name, strlen(name));
-        rc = osd_ldiskfs_add_entry(jh, dentry, inode, NULL);
-        LASSERT(rc == 0);
-
-        ldiskfs_journal_stop(jh);
-        iput(inode);
-
-        return rc;
+       const struct lu_env             *env = info->oti_env;
+       struct osd_inode_id             *id  = &info->oti_id;
+       struct buffer_head              *bh;
+       struct inode                    *inode;
+       struct ldiskfs_dir_entry_2      *de;
+       struct dentry                   *dentry;
+       struct super_block              *sb  = osd_sb(osd);
+       struct inode                    *dir = sb->s_root->d_inode;
+       handle_t                        *jh;
+       int                              rc;
+
+       dentry = osd_child_dentry_by_inode(env, dir, name, strlen(name));
+       bh = osd_ldiskfs_find_entry(dir, dentry, &de, NULL);
+       if (bh) {
+               osd_id_gen(id, le32_to_cpu(de->inode), OSD_OII_NOGEN);
+               brelse(bh);
+               inode = osd_iget(info, osd, id);
+               if (!IS_ERR(inode)) {
+                       iput(inode);
+                       inode = ERR_PTR(-EEXIST);
+               }
+               return PTR_ERR(inode);
+       }
+
+       jh = ldiskfs_journal_start_sb(sb, 100);
+       if (IS_ERR(jh))
+               return PTR_ERR(jh);
+
+       inode = ldiskfs_create_inode(jh, dir, (S_IFREG | S_IRUGO | S_IWUSR));
+       if (IS_ERR(inode)) {
+               ldiskfs_journal_stop(jh);
+               return PTR_ERR(inode);
+       }
+
+       if (feat->dif_flags & DT_IND_VARKEY)
+               rc = iam_lvar_create(inode, feat->dif_keysize_max,
+                                    feat->dif_ptrsize, feat->dif_recsize_max,
+                                    jh);
+       else
+               rc = iam_lfix_create(inode, feat->dif_keysize_max,
+                                    feat->dif_ptrsize, feat->dif_recsize_max,
+                                    jh);
+       dentry = osd_child_dentry_by_inode(env, dir, name, strlen(name));
+       rc = osd_ldiskfs_add_entry(jh, dentry, inode, NULL);
+       ldiskfs_journal_stop(jh);
+       iput(inode);
+       return rc;
 }
 
 static struct inode *osd_oi_index_open(struct osd_thread_info *info,
@@ -199,7 +190,7 @@ static struct inode *osd_oi_index_open(struct osd_thread_info *info,
 
         rc = osd_oi_index_create_one(info, osd, name, f);
         if (rc)
-                RETURN(ERR_PTR(rc));
+               return ERR_PTR(rc);
 
         dentry = ll_lookup_one_len(name, osd_sb(osd)->s_root, strlen(name));
         if (IS_ERR(dentry))
@@ -434,11 +425,27 @@ static int osd_oi_iam_lookup(struct osd_thread_info *oti,
         RETURN(rc);
 }
 
+int __osd_oi_lookup(struct osd_thread_info *info, struct osd_device *osd,
+                   const struct lu_fid *fid, struct osd_inode_id *id)
+{
+       struct lu_fid *oi_fid = &info->oti_fid2;
+       int            rc;
+
+       fid_cpu_to_be(oi_fid, fid);
+       rc = osd_oi_iam_lookup(info, osd_fid2oi(osd, fid), (struct dt_rec *)id,
+                              (const struct dt_key *)oi_fid);
+       if (rc > 0) {
+               osd_id_unpack(id, id);
+               rc = 0;
+       } else if (rc == 0) {
+               rc = -ENOENT;
+       }
+       return rc;
+}
+
 int osd_oi_lookup(struct osd_thread_info *info, struct osd_device *osd,
                   const struct lu_fid *fid, struct osd_inode_id *id)
 {
-        struct lu_fid       *oi_fid = &info->oti_fid;
-        const struct dt_key *key;
         int                  rc = 0;
 
         if (fid_is_idif(fid) || fid_seq(fid) == FID_SEQ_LLOG) {
@@ -446,36 +453,21 @@ int osd_oi_lookup(struct osd_thread_info *info, struct osd_device *osd,
                 rc = osd_compat_objid_lookup(info, osd, fid, id);
         } else if (fid_is_igif(fid)) {
                 lu_igif_to_id(fid, id);
-                rc = 0;
         } else if (fid_is_fs_root(fid)) {
-                struct inode *inode = osd_sb(osd)->s_root->d_inode;
-
-                id->oii_ino = inode->i_ino;
-                id->oii_gen = inode->i_generation;
-        } else {
+               osd_id_gen(id, osd_sb(osd)->s_root->d_inode->i_ino,
+                          osd_sb(osd)->s_root->d_inode->i_generation);
+       } else {
                if (unlikely(fid_seq(fid) == FID_SEQ_LOCAL_FILE))
                        return osd_compat_spec_lookup(info, osd, fid, id);
 
-                fid_cpu_to_be(oi_fid, fid);
-                key = (struct dt_key *)oi_fid;
-
-                rc = osd_oi_iam_lookup(info, osd_fid2oi(osd, fid),
-                                       (struct dt_rec *)id, key);
-
-                if (rc > 0) {
-                        id->oii_ino = be32_to_cpu(id->oii_ino);
-                        id->oii_gen = be32_to_cpu(id->oii_gen);
-                        rc = 0;
-                } else if (rc == 0) {
-                        rc = -ENOENT;
-                }
+               rc = __osd_oi_lookup(info, osd, fid, id);
         }
         return rc;
 }
 
 static int osd_oi_iam_insert(struct osd_thread_info *oti, struct osd_oi *oi,
-                             const struct dt_rec *rec, const struct dt_key *key,
-                             struct thandle *th, int ignore_quota)
+                            const struct dt_rec *rec, const struct dt_key *key,
+                            struct thandle *th)
 {
         struct iam_container  *bag;
         struct iam_rec        *iam_rec = (struct iam_rec *)oti->oti_ldp;
@@ -499,10 +491,7 @@ static int osd_oi_iam_insert(struct osd_thread_info *oti, struct osd_oi *oi,
         LASSERT(oh->ot_handle != NULL);
         LASSERT(oh->ot_handle->h_transaction != NULL);
 #ifdef HAVE_QUOTA_SUPPORT
-        if (ignore_quota)
-                cfs_cap_raise(CFS_CAP_SYS_RESOURCE);
-        else
-                cfs_cap_lower(CFS_CAP_SYS_RESOURCE);
+       cfs_cap_raise(CFS_CAP_SYS_RESOURCE);
 #endif
         if (S_ISDIR(oi->oi_inode->i_mode))
                 osd_fid_pack((struct osd_fid_pack *)iam_rec, rec,
@@ -520,32 +509,27 @@ static int osd_oi_iam_insert(struct osd_thread_info *oti, struct osd_oi *oi,
 }
 
 int osd_oi_insert(struct osd_thread_info *info, struct osd_device *osd,
-                 const struct lu_fid *fid, const struct osd_inode_id *id0,
-                 struct thandle *th, int ignore_quota)
+                 const struct lu_fid *fid, const struct osd_inode_id *id,
+                 struct thandle *th)
 {
-       struct lu_fid       *oi_fid = &info->oti_fid;
-       struct osd_inode_id *id;
-       const struct dt_key *key;
+       struct lu_fid       *oi_fid = &info->oti_fid2;
+       struct osd_inode_id *oi_id = &info->oti_id2;
 
        if (fid_is_igif(fid) || unlikely(fid_seq(fid) == FID_SEQ_DOT_LUSTRE))
                return 0;
 
        if (fid_is_idif(fid) || fid_seq(fid) == FID_SEQ_LLOG)
-               return osd_compat_objid_insert(info, osd, fid, id0, th);
+               return osd_compat_objid_insert(info, osd, fid, id, th);
 
        /* Server mount should not depends on OI files */
        if (unlikely(fid_seq(fid) == FID_SEQ_LOCAL_FILE))
-               return osd_compat_spec_insert(info, osd, fid, id0, th);
-
-        fid_cpu_to_be(oi_fid, fid);
-        key = (struct dt_key *)oi_fid;
+               return osd_compat_spec_insert(info, osd, fid, id, th);
 
-        id  = &info->oti_id;
-        id->oii_ino = cpu_to_be32(id0->oii_ino);
-        id->oii_gen = cpu_to_be32(id0->oii_gen);
-
-        return osd_oi_iam_insert(info, osd_fid2oi(osd, fid),
-                                 (struct dt_rec *)id, key, th, ignore_quota);
+       fid_cpu_to_be(oi_fid, fid);
+       osd_id_pack(oi_id, id);
+       return osd_oi_iam_insert(info, osd_fid2oi(osd, fid),
+                                (const struct dt_rec *)oi_id,
+                                (const struct dt_key *)oi_fid, th);
 }
 
 static int osd_oi_iam_delete(struct osd_thread_info *oti, struct osd_oi *oi,
@@ -575,24 +559,22 @@ static int osd_oi_iam_delete(struct osd_thread_info *oti, struct osd_oi *oi,
 }
 
 int osd_oi_delete(struct osd_thread_info *info,
-                  struct osd_device *osd, const struct lu_fid *fid,
-                  struct thandle *th)
+                 struct osd_device *osd, const struct lu_fid *fid,
+                 struct thandle *th)
 {
-        struct lu_fid       *oi_fid = &info->oti_fid;
-        const struct dt_key *key;
-
-        LASSERT(fid_seq(fid) != FID_SEQ_LOCAL_FILE);
+       struct lu_fid *oi_fid = &info->oti_fid2;
 
-        if (fid_is_idif(fid) || fid_seq(fid) == FID_SEQ_LLOG)
-                return osd_compat_objid_delete(info, osd, fid, th);
+       LASSERT(fid_seq(fid) != FID_SEQ_LOCAL_FILE);
 
-        fid_cpu_to_be(oi_fid, fid);
-        key = (struct dt_key *)oi_fid;
+       if (fid_is_idif(fid) || fid_seq(fid) == FID_SEQ_LLOG)
+               return osd_compat_objid_delete(info, osd, fid, th);
 
-        return osd_oi_iam_delete(info, osd_fid2oi(osd, fid), key, th);
+       fid_cpu_to_be(oi_fid, fid);
+       return osd_oi_iam_delete(info, osd_fid2oi(osd, fid),
+                                (const struct dt_key *)oi_fid, th);
 }
 
-int osd_oi_mod_init()
+int osd_oi_mod_init(void)
 {
         if (osd_oi_count == 0 || osd_oi_count > OSD_OI_FID_NR_MAX)
                 osd_oi_count = OSD_OI_FID_NR;
index 287ede3..bae99ed 100644 (file)
 #include <lu_object.h>
 #include <md_object.h>
 
+#define OSD_OI_FID_NR         (1UL << OSD_OI_FID_OID_BITS)
+#define OSD_OI_FID_NR_MAX     (1UL << OSD_OI_FID_OID_BITS_MAX)
+
+#define OSD_OII_NOGEN (0)
+
 struct lu_fid;
 struct osd_thread_info;
 struct lu_site;
@@ -70,25 +75,64 @@ struct osd_oi;
  * Storage cookie. Datum uniquely identifying inode on the underlying file
  * system.
  *
- * XXX Currently this is ext2/ext3/ldiskfs specific thing. In the future this
- * should be generalized to work with other local file systems.
+ * osd_inode_id is the internal ldiskfs identifier for an object. It should
+ * not be visible outside of the osd-ldiskfs. Other OSDs may have different
+ * identifiers, so this cannot form any part of the OSD API.
  */
 struct osd_inode_id {
-        __u32 oii_ino; /* inode number */
-        __u32 oii_gen; /* inode generation */
+       __u32 oii_ino; /* inode number */
+       __u32 oii_gen; /* inode generation */
 };
 
+static inline void osd_id_pack(struct osd_inode_id *tgt,
+                              const struct osd_inode_id *src)
+{
+       tgt->oii_ino = cpu_to_be32(src->oii_ino);
+       tgt->oii_gen = cpu_to_be32(src->oii_gen);
+}
+
+static inline void osd_id_unpack(struct osd_inode_id *tgt,
+                                struct osd_inode_id *src)
+{
+       tgt->oii_ino = be32_to_cpu(src->oii_ino);
+       tgt->oii_gen = be32_to_cpu(src->oii_gen);
+}
+
+static inline void osd_id_gen(struct osd_inode_id *id, __u32 ino, __u32 gen)
+{
+       id->oii_ino = ino;
+       id->oii_gen = gen;
+}
+
+static inline void osd_id_to_inode(struct inode *inode,
+                                  const struct osd_inode_id *id)
+{
+       inode->i_ino        = id->oii_ino;
+       inode->i_generation = id->oii_gen;
+}
+
+static inline int osd_id_eq(const struct osd_inode_id *id0,
+                           const struct osd_inode_id *id1)
+{
+       return (id0->oii_ino == id1->oii_ino) &&
+              (id0->oii_gen == id1->oii_gen ||
+               id0->oii_gen == OSD_OII_NOGEN ||
+               id1->oii_gen == OSD_OII_NOGEN);
+}
+
 int osd_oi_mod_init(void);
 int osd_oi_init(struct osd_thread_info *info, struct osd_device *osd);
 void osd_oi_fini(struct osd_thread_info *info, struct osd_device *osd);
+int __osd_oi_lookup(struct osd_thread_info *info, struct osd_device *osd,
+                   const struct lu_fid *fid, struct osd_inode_id *id);
 int  osd_oi_lookup(struct osd_thread_info *info, struct osd_device *osd,
-                   const struct lu_fid *fid, struct osd_inode_id *id);
+                  const struct lu_fid *fid, struct osd_inode_id *id);
 int  osd_oi_insert(struct osd_thread_info *info, struct osd_device *osd,
-                   const struct lu_fid *fid, const struct osd_inode_id *id,
-                   struct thandle *th, int ingore_quota);
+                  const struct lu_fid *fid, const struct osd_inode_id *id,
+                  struct thandle *th);
 int  osd_oi_delete(struct osd_thread_info *info,
-                   struct osd_device *osd, const struct lu_fid *fid,
-                   struct thandle *th);
+                  struct osd_device *osd, const struct lu_fid *fid,
+                  struct thandle *th);
 
 #endif /* __KERNEL__ */
 #endif /* _OSD_OI_H */