Whamcloud - gitweb
obdfs/flushd.c: turned on page aging, and set pupdated to run more often
[fs/lustre-release.git] / lustre / obdfs / namei.c
index b874135..87ddc55 100644 (file)
@@ -63,16 +63,17 @@ static inline int ext2_match (int len, const char * const name,
 }
 
 /*
- *     ext2_find_entry()
+ *     obdfs_find_entry()
  *
  * finds an entry in the specified directory with the wanted name. It
  * returns the cache buffer in which the entry was found, and the entry
- * itself (as a parameter - res_dir). It does NOT read the inode of the
+ * itself (as a parameter - res_dir).  It does NOT read the inode of the
  * entry - you'll have to do that yourself if you want to.
  */
 static struct page * obdfs_find_entry (struct inode * dir,
-                                            const char * const name, int namelen,
-                                            struct ext2_dir_entry_2 ** res_dir, int lock)
+                                      const char * const name, int namelen,
+                                      struct ext2_dir_entry_2 ** res_dir,
+                                      int lock)
 {
        struct super_block * sb;
        unsigned long offset;
@@ -149,19 +150,20 @@ failure:
        }
        EXIT;
        return NULL;
-}
+} /* obdfs_find_entry */
 
-struct dentry *obdfs_lookup(struct inode * dir, struct dentry *dentry)
+struct dentry *obdfs_lookup(struct inode *dir, struct dentry *dentry)
 {
-       struct inode * inode;
-       struct ext2_dir_entry_2 * de;
-       struct page * page;
+       struct inode *inode;
+       struct ext2_dir_entry_2 *de;
+       struct page *page;
        ENTRY;
 
        if (dentry->d_name.len > EXT2_NAME_LEN)
                return ERR_PTR(-ENAMETOOLONG);
 
-       page = obdfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, LOCKED);
+       page = obdfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len,
+                               &de, LOCKED);
        inode = NULL;
        if ( !page ) 
                CDEBUG(D_INODE, "No page - negative entry.\n");
@@ -184,11 +186,11 @@ struct dentry *obdfs_lookup(struct inode * dir, struct dentry *dentry)
        d_add(dentry, inode);
        EXIT;
        return NULL;
-}
+} /* obdfs_lookup */
 
 
 /*
- *     ext2_add_entry()
+ *     obdfs_add_entry()
  *
  * adds a file entry to the specified directory, using the same
  * semantics as ext2_find_entry(). It returns NULL if it failed.
@@ -196,9 +198,14 @@ struct dentry *obdfs_lookup(struct inode * dir, struct dentry *dentry)
  * NOTE!! The inode part of 'de' is left at 0 - which means you
  * may not sleep between calling this and putting something into
  * the entry, as someone else might have used it while you slept.
-
+ *
  * returns a locked and held page upon success 
  */
+
+
+/* We do this with a locked page: that's not necessary, since the semaphore
+ * on the inode protects this page as well.
+ */
 static struct page *obdfs_add_entry (struct inode * dir,
                                     const char * name, int namelen,
                                     struct ext2_dir_entry_2 ** res_dir,
@@ -228,8 +235,9 @@ static struct page *obdfs_add_entry (struct inode * dir,
         */
        if (dir->i_size == 0)
        {
-               EXIT;
+               OIDEBUG(dir);
                *err = -ENOENT;
+               EXIT;
                return NULL;
        }
        page = obdfs_getpage(dir, 0, 0, LOCKED);
@@ -238,13 +246,16 @@ static struct page *obdfs_add_entry (struct inode * dir,
                return NULL;
        }
        rec_len = EXT2_DIR_REC_LEN(namelen);
-       CDEBUG(D_INODE, "reclen: %d\n", rec_len);
+       /* CDEBUG(D_INODE, "reclen: %d\n", rec_len); */
+       PDEBUG(page, "starting search");
        offset = 0;
        de = (struct ext2_dir_entry_2 *) page_address(page);
        *err = -ENOSPC;
        while (1) {
-               CDEBUG(D_INODE, "Considering entry at %p, (page at %#lx - %#lx), offset %ld\n",
-                      de, page_address(page), page_address(page) + PAGE_SIZE, offset);
+               /* CDEBUG(D_INODE,
+                      "Entry at %p, (page at %#lx - %#lx), offset %ld\n",
+                      de, page_address(page), page_address(page) + PAGE_SIZE,
+                      offset); */
                if ((char *)de >= PAGE_SIZE + (char *)page_address(page)) {
                        UnlockPage(page);
                        page_cache_release(page);
@@ -253,6 +264,7 @@ static struct page *obdfs_add_entry (struct inode * dir,
                                EXIT;
                                return NULL;
                        }
+                       PDEBUG(page, "new directory page");
                        if (dir->i_size <= offset) {
                                if (dir->i_size == 0) {
                                        *err = -ENOENT;
@@ -275,7 +287,6 @@ static struct page *obdfs_add_entry (struct inode * dir,
                                de = (struct ext2_dir_entry_2 *) page_address(page);
                        }
                }
-               CDEBUG(D_INODE, "\n");
                if (!obdfs_check_dir_entry ("ext2_add_entry", dir, de, page,
                                           offset)) {
                        *err = -ENOENT;
@@ -292,27 +303,32 @@ static struct page *obdfs_add_entry (struct inode * dir,
                                EXIT;
                                return NULL;
                }
-               CDEBUG(D_INODE, "Testing for enough space at de %p\n", de);
+               /* CDEBUG(D_INODE, "Testing for enough space at de %p\n", de);*/
                if ( (le32_to_cpu(de->inode) == 0 && le16_to_cpu(de->rec_len) >= rec_len) ||
                     (le16_to_cpu(de->rec_len) >= EXT2_DIR_REC_LEN(de->name_len) + rec_len)) {
                        offset += le16_to_cpu(de->rec_len);
-                       CDEBUG(D_INODE, "Found enough space de %p, offset %#lx\n", de, offset);
+                       /* CDEBUG(D_INODE,
+                              "Found enough space de %p, offset %#lx\n",
+                              de, offset); */
                        if (le32_to_cpu(de->inode)) {
-                               CDEBUG(D_INODE, "Inserting new in %p\n", de);
+                               /*CDEBUG(D_INODE, "Insert new in %p\n", de);*/
                                de1 = (struct ext2_dir_entry_2 *) ((char *) de +
                                        EXT2_DIR_REC_LEN(de->name_len));
-                               CDEBUG(D_INODE, "-- de1 at %p\n", de1);
+                               /*CDEBUG(D_INODE, "-- de1 at %p\n", de1);*/
                                de1->rec_len = cpu_to_le16(le16_to_cpu(de->rec_len) -
                                        EXT2_DIR_REC_LEN(de->name_len));
                                de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(de->name_len));
                                de = de1;
                        }
-                       CDEBUG(D_INODE, "Reclen adjusted; copy %d bytes to %p, page at %#lx EOP at %#lx\n", namelen, de->name, page_address(page), page_address(page) + PAGE_SIZE);
+                       /* CDEBUG(D_INODE,
+                              "Reclen adjusted; copy %d bytes to %p, "
+                              "page at %#lx EOP at %#lx\n",
+                              namelen, de->name, page_address(page),
+                              page_address(page) + PAGE_SIZE); */
                        de->inode = 0;
                        de->name_len = namelen;
                        de->file_type = 0;
                        memcpy (de->name, name, namelen);
-                       CDEBUG(D_INODE, "Copy done\n");
                        /*
                         * XXX shouldn't update any times until successful
                         * completion of syscall, but too many callers depend
@@ -330,27 +346,25 @@ static struct page *obdfs_add_entry (struct inode * dir,
                        dir->i_version = ++event;
                        *res_dir = de;
                        *err = 0;
-                       PDEBUG(page, "addentry");
-                       CDEBUG(D_INODE, "Regular exit from add_entry");
+                       PDEBUG(page, "add_entry");
+                       /* XXX unlock page here */
                        EXIT;
                        return page;
                }
-               CDEBUG(D_INODE, "\n");
                offset += le16_to_cpu(de->rec_len);
                de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
                
        }
-       CDEBUG(D_INODE, "\n");
 
        UnlockPage(page);
        page_cache_release(page);
-       PDEBUG(page, "addentry");
+       PDEBUG(page, "add_entry");
        EXIT;
        return NULL;
-}
+} /* obdfs_add_entry */
 
 /*
- * ext2_delete_entry deletes a directory entry by merging it with the
+ * obdfs_delete_entry deletes a directory entry by merging it with the
  * previous entry
  */
 static int obdfs_delete_entry (struct ext2_dir_entry_2 * dir,
@@ -380,7 +394,7 @@ static int obdfs_delete_entry (struct ext2_dir_entry_2 * dir,
                de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
        }
        return -ENOENT;
-}
+} /* obdfs_delete_entry */
 
 
 static inline void ext2_set_de_type(struct super_block *sb,
@@ -436,10 +450,59 @@ static void show_dentry(struct list_head * dlist, int subdirs)
                               dentry->d_name.name, dentry->d_count,
                               unhashed);
        }
-}
+} /* show_dentry */
 #endif
 
 
+static struct inode *obdfs_new_inode(struct inode *dir, int mode)
+{
+       struct obdo *oa;
+       struct inode *inode;
+       int err;
+
+       ENTRY;
+       oa = obdo_alloc();
+       if (!oa) {
+               EXIT;
+               return ERR_PTR(-ENOMEM);
+       }
+
+       /* Send a hint to the create method on the type of file to create */
+       oa->o_mode = mode;
+       oa->o_valid |= OBD_MD_FLMODE;
+
+       err = IOPS(dir, create)(IID(dir), oa);
+
+       if ( err ) {
+               obdo_free(oa);
+               EXIT;
+               return ERR_PTR(err);
+       }
+
+       inode = iget(dir->i_sb, (ino_t)oa->o_id);
+
+       if (!inode) {
+               IOPS(dir, destroy)(IID(dir), oa);
+               obdo_free(oa);
+               EXIT;
+               return ERR_PTR(-EIO);
+       }
+
+       if (!list_empty(&inode->i_dentry)) {
+               CDEBUG(D_INODE, "New inode (%ld) has aliases!\n", inode->i_ino);
+               IOPS(dir, destroy)(IID(dir), oa);
+               obdo_free(oa);
+               iput(inode);
+               EXIT;
+               return ERR_PTR(-EIO);
+       }
+       obdo_free(oa);
+
+       EXIT;
+       return inode;
+} /* obdfs_new_inode */
+
+
 /*
  * By the time this is called, we already have created
  * the directory cache entry for the new file, but it
@@ -454,25 +517,15 @@ int obdfs_create (struct inode * dir, struct dentry * dentry, int mode)
        struct page *page;
        struct ext2_dir_entry_2 * de;
        int err = -EIO;
-       objid id;
 
         ENTRY;
-
-       /*
-        * N.B. Several error exits in ext2_new_inode don't set err.
-        */
-       err = iops(dir)->o_create(iid(dir), 0, &id);
-       if ( err ) 
-               return err;
-       inode =  iget(dir->i_sb, (ino_t)id);
-       if (!inode || !list_empty(&inode->i_dentry)) {
-               CDEBUG(D_INODE, "No inode, ino %ld\n", id);
+       inode = obdfs_new_inode(dir, mode);
+       if ( IS_ERR(inode) ) {
                EXIT;
-               return -EIO;
+               return PTR_ERR(inode);
        }
 
        inode->i_op = &obdfs_file_inode_operations;
-       inode->i_mode = mode;
        mark_inode_dirty(inode);
        page = obdfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
        if (!page) {
@@ -485,19 +538,15 @@ int obdfs_create (struct inode * dir, struct dentry * dentry, int mode)
        de->inode = cpu_to_le32(inode->i_ino);
        ext2_set_de_type(dir->i_sb, de, S_IFREG);
        dir->i_version = ++event;
-       iops(dir)->o_brw(WRITE, iid(dir), dir, page, 0);
+
+       err = obdfs_do_writepage(dir, page, IS_SYNC(dir));
        UnlockPage(page);
-#if 0
-       if (IS_SYNC(dir)) {
-               ll_rw_block (WRITE, 1, &bh);
-               wait_on_buffer (bh);
-       }
-#endif
+
        page_cache_release(page);
        d_instantiate(dentry, inode);
        EXIT;
-       return 0;
-}
+       return err;
+} /* obdfs_create */
 
 int obdfs_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
 {
@@ -506,19 +555,12 @@ int obdfs_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
        struct ext2_dir_entry_2 * de;
        int err;
 
-       objid id;
-
         ENTRY;
-
-       /*
-        * N.B. Several error exits in ext2_new_inode don't set err.
-        */
-       err = iops(dir)->o_create(iid(dir), 0, &id);
-       if ( err ) 
-               return err;
-       inode =  iget(dir->i_sb, (ino_t)id);
-       if (!inode)
-               return -EIO;
+       inode = obdfs_new_inode(dir, mode);
+       if ( IS_ERR(inode) ) {
+               EXIT;
+               return PTR_ERR(inode);
+       }
 
        inode->i_uid = current->fsuid;
        init_special_inode(inode, mode, rdev);
@@ -529,15 +571,10 @@ int obdfs_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
        dir->i_version = ++event;
        ext2_set_de_type(dir->i_sb, de, inode->i_mode);
        mark_inode_dirty(inode);
-       iops(dir)->o_brw(WRITE, iid(dir), dir, page, 0);
+
+       err = obdfs_do_writepage(dir, page, IS_SYNC(dir));
        UnlockPage(page);
 
-#if 0
-       if (IS_SYNC(dir)) {
-               ll_rw_block (WRITE, 1, &bh);
-               wait_on_buffer (bh);
-       }
-#endif
        d_instantiate(dentry, inode);
        page_cache_release(page);
        err = 0;
@@ -549,7 +586,7 @@ out_no_entry:
        mark_inode_dirty(inode);
        iput(inode);
        goto out;
-}
+} /* obdfs_mknod */
 
 int obdfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
 {
@@ -557,7 +594,6 @@ int obdfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
        struct page *page, *inode_page;
        struct ext2_dir_entry_2 * de;
        int err;
-       objid id;
 
        ENTRY;
 
@@ -565,13 +601,15 @@ int obdfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
        if (dir->i_nlink >= EXT2_LINK_MAX)
                goto out;
 
-       err = iops(dir)->o_create(iid(dir), 0, &id);
-       if ( err ) 
-               return err;
-       inode =  iget(dir->i_sb, (ino_t)id);
-       if (!inode)
-               return -EIO;
+       mode |= S_IFDIR;
+       if (dir->i_mode & S_ISGID)
+               mode |= S_ISGID;
 
+       inode = obdfs_new_inode(dir, mode);
+       if ( IS_ERR(inode) ) {
+               EXIT;
+               return PTR_ERR(inode);
+       }
 
        inode->i_op = &obdfs_dir_inode_operations;
        inode->i_blocks = 0;    
@@ -598,16 +636,14 @@ int obdfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
        strcpy (de->name, "..");
        ext2_set_de_type(dir->i_sb, de, S_IFDIR);
        
-       iops(dir)->o_brw(WRITE, iid(dir), inode, inode_page, 1);
+       /* XXX handle err */
+       err = obdfs_do_writepage(inode, inode_page, IS_SYNC(inode));
        inode->i_blocks = PAGE_SIZE/inode->i_sb->s_blocksize;
        inode->i_size = PAGE_SIZE;
        UnlockPage(inode_page);
        page_cache_release(inode_page);
 
        inode->i_nlink = 2;
-       inode->i_mode = S_IFDIR | mode;
-       if (dir->i_mode & S_ISGID)
-               inode->i_mode |= S_ISGID;
        mark_inode_dirty(inode);
 
        /* now deal with the parent */
@@ -620,20 +656,15 @@ int obdfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
        ext2_set_de_type(dir->i_sb, de, S_IFDIR);
        dir->i_version = ++event;
 
-#if 0
-       if (IS_SYNC(dir)) {
-               ll_rw_block (WRITE, 1, &bh);
-               wait_on_buffer (bh);
-       }
-#endif
        dir->i_nlink++;
        dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
        mark_inode_dirty(dir);
-       iops(dir)->o_brw(WRITE, iid(dir), dir, page, 1);
+       err = obdfs_do_writepage(dir, page, IS_SYNC(dir));
+
        UnlockPage(page);
+
        page_cache_release(page);
        d_instantiate(dentry, inode);
-       err = 0;
 out:
        EXIT;
        return err;
@@ -644,7 +675,7 @@ out_no_entry:
        iput (inode);
        EXIT;
        goto out;
-}
+} /* obdfs_mkdir */
 
 
 /*
@@ -712,7 +743,7 @@ static int empty_dir (struct inode * inode)
        UnlockPage(page);
        page_cache_release(page);
        return 1;
-}
+} /* empty_dir */
 
 int obdfs_rmdir (struct inode * dir, struct dentry *dentry)
 {
@@ -720,6 +751,7 @@ int obdfs_rmdir (struct inode * dir, struct dentry *dentry)
        struct inode * inode;
        struct page *page;
        struct ext2_dir_entry_2 * de;
+       int err;
 
        ENTRY;
 
@@ -743,14 +775,10 @@ int obdfs_rmdir (struct inode * dir, struct dentry *dentry)
        dir->i_version = ++event;
        if (retval)
                goto end_rmdir;
-       iops(dir)->o_brw(WRITE, iid(dir), dir, page, 0);
+       err = obdfs_do_writepage(dir, page, IS_SYNC(dir));
+       /* XXX handle err? */
        UnlockPage(page);
-#if 0
-       if (IS_SYNC(dir)) {
-               ll_rw_block (WRITE, 1, &bh);
-               wait_on_buffer (bh);
-       }
-#endif
+
        if (inode->i_nlink != 2)
                ext2_warning (inode->i_sb, "ext2_rmdir",
                              "empty directory has nlink!=2 (%d)",
@@ -770,7 +798,7 @@ end_rmdir:
                page_cache_release(page);
        EXIT;
        return retval;
-}
+} /* obdfs_rmdir */
 
 int obdfs_unlink(struct inode * dir, struct dentry *dentry)
 {
@@ -778,6 +806,7 @@ int obdfs_unlink(struct inode * dir, struct dentry *dentry)
        struct inode * inode;
        struct page *page;
        struct ext2_dir_entry_2 * de;
+       int err;
 
         ENTRY;
 
@@ -803,14 +832,10 @@ int obdfs_unlink(struct inode * dir, struct dentry *dentry)
        if (retval)
                goto end_unlink;
        dir->i_version = ++event;
-       iops(dir)->o_brw(WRITE, iid(dir), dir, page, 0);
+       err = obdfs_do_writepage(dir, page, IS_SYNC(dir));
+       /* XXX handle err? */
        UnlockPage(page);
-#if 0
-       if (IS_SYNC(dir)) {
-               ll_rw_block (WRITE, 1, &bh);
-               wait_on_buffer (bh);
-       }
-#endif
+
        dir->i_ctime = dir->i_mtime = CURRENT_TIME;
        dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
        mark_inode_dirty(dir);
@@ -825,39 +850,33 @@ end_unlink:
                page_cache_release(page);
        EXIT;
        return retval;
-}
+} /* obdfs_unlink */
 
-int obdfs_symlink (struct inode * dir, struct dentry *dentry, const char * symname)
+int obdfs_symlink (struct inode * dir, struct dentry *dentry,
+                  const char * symname)
 {
        struct ext2_dir_entry_2 * de;
        struct inode * inode;
+       struct obdfs_inode_info *oinfo;
        struct page* page = NULL, * name_page = NULL;
        char * link;
        int i, l, err = -EIO;
        char c;
-       objid id;
 
         ENTRY;
-       /*
-        * N.B. Several error exits in ext2_new_inode don't set err.
-        */
-       err = iops(dir)->o_create(iid(dir), 0, &id);
-       if ( err )  {
+       inode = obdfs_new_inode(dir, S_IFLNK | S_IRWXUGO);
+       if ( IS_ERR(inode) ) {
                EXIT;
-               return err;
+               return PTR_ERR(inode);
        }
-       inode =  iget(dir->i_sb, (ino_t)id);
-       if (!inode) {
-               EXIT;
-               return err;
-       }
-       inode->i_mode = S_IFLNK | S_IRWXUGO;
+
        inode->i_op = &obdfs_symlink_inode_operations;
-       for (l = 0; l < inode->i_sb->s_blocksize - 1 &&
-            symname [l]; l++)
+       for (l = 0; l < inode->i_sb->s_blocksize - 1 && symname [l]; l++)
                ;
 
-       if (l >= sizeof (inode->u.ext2_i.i_data)) {
+       oinfo = obdfs_i2info(inode);
+
+       if (l >= sizeof(oinfo->oi_inline)) {
                CDEBUG(D_INODE, "l=%d, normal symlink\n", l);
 
                name_page = obdfs_getpage(inode, 0, 1, LOCKED);
@@ -870,17 +889,18 @@ int obdfs_symlink (struct inode * dir, struct dentry *dentry, const char * symna
                }
                link = (char *)page_address(name_page);
        } else {
-               link = (char *) inode->u.ext2_i.i_data;
+               link = oinfo->oi_inline;
+               oinfo->oi_flags |= OBD_FL_INLINEDATA;
 
                CDEBUG(D_INODE, "l=%d, fast symlink\n", l);
-
        }
        i = 0;
        while (i < inode->i_sb->s_blocksize - 1 && (c = *(symname++)))
                link[i++] = c;
        link[i] = 0;
        if (name_page) {
-               iops(inode)->o_brw(WRITE, iid(inode), inode, name_page, 1);
+               err = obdfs_do_writepage(inode, name_page, IS_SYNC(inode));
+               /* XXX handle err */
                PDEBUG(name_page, "symlink");
                UnlockPage(name_page);
                page_cache_release(name_page);
@@ -888,22 +908,17 @@ int obdfs_symlink (struct inode * dir, struct dentry *dentry, const char * symna
        inode->i_size = i;
        mark_inode_dirty(inode);
 
-       page = obdfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
+       page = obdfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len,
+                               &de, &err);
        if (!page)
                goto out_no_entry;
        de->inode = cpu_to_le32(inode->i_ino);
        ext2_set_de_type(dir->i_sb, de, S_IFLNK);
        dir->i_version = ++event;
-       iops(dir)->o_brw(WRITE, iid(dir), dir, page, 1);
+       err = obdfs_do_writepage(dir, page, IS_SYNC(dir));
        UnlockPage(page);
-#if 0
-       if (IS_SYNC(dir)) {
-               ll_rw_block (WRITE, 1, &bh);
-               wait_on_buffer (bh);
-       }
-#endif
+
        d_instantiate(dentry, inode);
-       err = 0;
 out:
        EXIT;
        return err;
@@ -913,7 +928,7 @@ out_no_entry:
        mark_inode_dirty(inode);
        iput (inode);
        goto out;
-}
+} /* obdfs_symlink */
 
 int obdfs_link (struct dentry * old_dentry,
                struct inode * dir, struct dentry *dentry)
@@ -938,23 +953,18 @@ int obdfs_link (struct dentry * old_dentry,
        de->inode = cpu_to_le32(inode->i_ino);
        ext2_set_de_type(dir->i_sb, de, inode->i_mode);
        dir->i_version = ++event;
-       iops(dir)->o_brw(WRITE, iid(dir), dir, page, 0);
+
+       err = obdfs_do_writepage(dir, page, IS_SYNC(dir));
        UnlockPage(page);
 
-#if 0
-       if (IS_SYNC(dir)) {
-               ll_rw_block (WRITE, 1, &bh);
-               wait_on_buffer (bh);
-       }
-#endif
        page_cache_release(page);
        inode->i_nlink++;
        inode->i_ctime = CURRENT_TIME;
        mark_inode_dirty(inode);
        inode->i_count++;
        d_instantiate(dentry, inode);
-       return 0;
-}
+       return err;
+} /* obdfs_link */
 
 #define PARENT_INO(buffer) \
        ((struct ext2_dir_entry_2 *) ((char *) buffer + \
@@ -970,7 +980,7 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry,
        struct inode * old_inode, * new_inode;
        struct page * old_page, * new_page, * dir_page;
        struct ext2_dir_entry_2 * old_de, * new_de;
-       int retval;
+       int err;
 
         ENTRY;
 
@@ -986,7 +996,7 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry,
         *  same name. Goodbye sticky bit ;-<
         */
        old_inode = old_dentry->d_inode;
-       retval = -ENOENT;
+       err = -ENOENT;
        if (!old_page || le32_to_cpu(old_de->inode) != old_inode->i_ino)
                goto end_rename;
 
@@ -1007,11 +1017,11 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry,
        if (S_ISDIR(old_inode->i_mode)) {
                /* can only rename into empty new directory */
                if (new_inode) {
-                       retval = -ENOTEMPTY;
+                       err = -ENOTEMPTY;
                        if (!empty_dir (new_inode))
                                goto end_rename;
                }
-               retval = -EIO;
+               err = -EIO;
                dir_page= obdfs_getpage (old_inode, 0, 0, LOCKED);
                PDEBUG(dir_page, "rename dir page");
 
@@ -1019,7 +1029,7 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry,
                        goto end_rename;
                if (le32_to_cpu(PARENT_INO(page_address(dir_page))) != old_dir->i_ino)
                        goto end_rename;
-               retval = -EMLINK;
+               err = -EMLINK;
                if (!new_inode && new_dir!=old_dir &&
                                new_dir->i_nlink >= EXT2_LINK_MAX)
                        goto end_rename;
@@ -1028,7 +1038,7 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry,
        if (!new_page) {
                new_page = obdfs_add_entry (new_dir, new_dentry->d_name.name,
                                        new_dentry->d_name.len, &new_de,
-                                       &retval);
+                                       &err);
                PDEBUG(new_page, "rename new page");
                if (!new_page)
                        goto end_rename;
@@ -1055,8 +1065,10 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry,
        old_dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
        mark_inode_dirty(old_dir);
        if (dir_page) {
-               PARENT_INO(page_address(dir_page)) = le32_to_cpu(new_dir->i_ino);
-               iops(old_inode)->o_brw(WRITE, iid(old_inode), old_inode, dir_page, 0);
+               PARENT_INO(page_address(dir_page)) =le32_to_cpu(new_dir->i_ino);
+               err = obdfs_do_writepage(old_inode, dir_page,
+                                        IS_SYNC(old_inode));
+               /* XXX handle err */
                old_dir->i_nlink--;
                mark_inode_dirty(old_dir);
                if (new_inode) {
@@ -1073,25 +1085,14 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry,
                /* lock the old_page and release unlocked copy */
                CDEBUG(D_INODE, "old_page at %p\n", old_page);
                page_cache_release(old_page);
-               old_page = obdfs_getpage(old_dir, index >> PAGE_SHIFT, 0, LOCKED);
+               old_page = obdfs_getpage(old_dir, index << PAGE_SHIFT, 0,
+                                        LOCKED);
                CDEBUG(D_INODE, "old_page at %p\n", old_page);
-               iops(old_dir)->o_brw(WRITE, iid(old_dir), old_dir, old_page,0);
+               err = obdfs_do_writepage(old_dir, old_page, IS_SYNC(old_dir));
+               /* XXX handle err */
        }
-#if 0
-       if (IS_SYNC(old_dir)) {
-               ll_rw_block (WRITE, 1, &old_bh);
-               wait_on_buffer (old_bh);
-       }
-#endif
-       iops(new_dir)->o_brw(WRITE, iid(new_dir), new_dir, new_page, 0);
-#if 0
-       if (IS_SYNC(new_dir)) {
-               ll_rw_block (WRITE, 1, &new_bh);
-               wait_on_buffer (new_bh);
-       }
-#endif
 
-       retval = 0;
+       err = obdfs_do_writepage(new_dir, new_page, IS_SYNC(new_dir));
 
 end_rename:
        if (old_page && PageLocked(old_page) )
@@ -1107,6 +1108,5 @@ end_rename:
        if (dir_page)
                page_cache_release(dir_page);
 
-
-       return retval;
-}
+       return err;
+} /* obdfs_rename */