Whamcloud - gitweb
Pass inline data from filesystem through obdo to VFS.
[fs/lustre-release.git] / lustre / obdfs / namei.c
index b16a5ef..6b80666 100644 (file)
@@ -199,6 +199,9 @@ struct dentry *obdfs_lookup(struct inode * dir, struct dentry *dentry)
 
  * returns a locked and held page upon success 
  */
+
+/* XXX I believe these pages should in fact NOT be locked */
+
 static struct page *obdfs_add_entry (struct inode * dir,
                                     const char * name, int namelen,
                                     struct ext2_dir_entry_2 ** res_dir,
@@ -440,6 +443,47 @@ static void show_dentry(struct list_head * dlist, int subdirs)
 #endif
 
 
+struct inode *obdfs_new_inode(struct inode *dir)
+{
+       struct obdo *obdo;
+       struct inode *inode;
+       struct obdfs_inode_info *oinfo;
+       int err;
+
+       obdo = obdo_alloc();
+       if (!obdo) {
+               EXIT;
+               return ERR_PTR(-ENOMEM);
+       }
+
+       err = IOPS(dir, create)(IID(dir), obdo);
+       if ( err ) 
+               return ERR_PTR(err);
+
+       inode = iget(dir->i_sb, (unsigned long)obdo->o_id);
+       if (!inode) {
+               obdo_free(obdo);
+               EXIT;
+               return ERR_PTR(-EIO);
+       }
+
+       if (!list_empty(&inode->i_dentry)) {
+               CDEBUG(D_INODE, "New inode (%ld) has aliases!\n", 
+                      inode->i_ino);
+               iput(inode);
+               EXIT;
+               return ERR_PTR(-EIO);
+       }
+
+       obdo_free(obdo);
+
+       oinfo = inode->u.generic_ip;
+       INIT_LIST_HEAD(&oinfo->oi_list);
+       EXIT;
+       return inode;
+}
+
+
 /*
  * By the time this is called, we already have created
  * the directory cache entry for the new file, but it
@@ -454,21 +498,13 @@ int obdfs_create (struct inode * dir, struct dentry * dentry, int mode)
        struct page *page;
        struct ext2_dir_entry_2 * de;
        int err = -EIO;
-       obd_id 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);
+       if ( IS_ERR(inode) ) {
                EXIT;
-               return -EIO;
+               return PTR_ERR(inode);
        }
 
        inode->i_op = &obdfs_file_inode_operations;
@@ -485,18 +521,14 @@ 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;
 }
 
 int obdfs_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
@@ -506,19 +538,13 @@ int obdfs_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
        struct ext2_dir_entry_2 * de;
        int err;
 
-       obd_id 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);
+       if ( IS_ERR(inode) ) {
+               EXIT;
+               return PTR_ERR(inode);
+       }
 
        inode->i_uid = current->fsuid;
        init_special_inode(inode, mode, rdev);
@@ -529,15 +555,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;
@@ -557,7 +578,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;
-       obd_id id;
 
        ENTRY;
 
@@ -565,13 +585,11 @@ 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;
-
+       inode = obdfs_new_inode(dir);
+       if ( IS_ERR(inode) ) {
+               EXIT;
+               return PTR_ERR(inode);
+       }
 
        inode->i_op = &obdfs_dir_inode_operations;
        inode->i_blocks = 0;    
@@ -598,11 +616,12 @@ 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);
+       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);
+       /* XXX handle err */
 
        inode->i_nlink = 2;
        inode->i_mode = S_IFDIR | mode;
@@ -620,17 +639,13 @@ 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;
@@ -720,6 +735,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 +759,9 @@ 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));
        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)",
@@ -778,6 +789,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 +815,9 @@ 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));
        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);
@@ -831,33 +838,27 @@ int obdfs_symlink (struct inode * dir, struct dentry *dentry, const char * symna
 {
        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;
-       obd_id 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);
+       oinfo = inode->u.generic_ip;
+       if ( IS_ERR(inode) ) {
                EXIT;
-               return err;
-       }
-       inode =  iget(dir->i_sb, (ino_t)id);
-       if (!inode) {
-               EXIT;
-               return err;
+               return PTR_ERR(inode);
        }
+
        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++)
                ;
 
-       if (l >= sizeof (inode->u.ext2_i.i_data)) {
+       if (l >= sizeof (oinfo->oi_inline)) {
                CDEBUG(D_INODE, "l=%d, normal symlink\n", l);
 
                name_page = obdfs_getpage(inode, 0, 1, LOCKED);
@@ -870,7 +871,8 @@ 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);
 
@@ -880,7 +882,7 @@ int obdfs_symlink (struct inode * dir, struct dentry *dentry, const char * symna
                link[i++] = c;
        link[i] = 0;
        if (name_page) {
-               iops(inode)->o_brw(WRITE, iid(inode), inode, name_page, 1);
+               obdfs_do_writepage(inode, name_page, IS_SYNC(inode));
                PDEBUG(name_page, "symlink");
                UnlockPage(name_page);
                page_cache_release(name_page);
@@ -894,14 +896,9 @@ int obdfs_symlink (struct inode * dir, struct dentry *dentry, const char * symna
        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);
+       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:
@@ -938,15 +935,10 @@ 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);
+
+       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;
@@ -1056,7 +1048,7 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry,
        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);
+               obdfs_do_writepage(old_inode, dir_page, IS_SYNC(old_inode));
                old_dir->i_nlink--;
                mark_inode_dirty(old_dir);
                if (new_inode) {
@@ -1075,21 +1067,10 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry,
                page_cache_release(old_page);
                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);
-       }
-#if 0
-       if (IS_SYNC(old_dir)) {
-               ll_rw_block (WRITE, 1, &old_bh);
-               wait_on_buffer (old_bh);
+               obdfs_do_writepage(old_dir, old_page, IS_SYNC(old_dir));
        }
-#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
+
+       obdfs_do_writepage(new_dir, new_page, IS_SYNC(new_dir));
 
        retval = 0;