/*
- * linux/fs/ext2/namei.c
+ * linux/fs/obdfs/namei.c
*
* Copyright (C) 1992, 1993, 1994, 1995
* Remy Card (card@masi.ibp.fr)
*
* from
*
- * linux/fs/minix/namei.c
+ * linux/fs/ext2/namei.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
*
* 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.
*/
-struct page * obdfs_find_entry (struct inode * dir,
+static struct page * obdfs_find_entry (struct inode * dir,
const char * const name, int namelen,
struct ext2_dir_entry_2 ** res_dir, int lock)
{
if (namelen > EXT2_NAME_LEN)
return NULL;
- CDEBUG(D_INODE, "dirsize is %ld\n", dir->i_size);
+ CDEBUG(D_INODE, "dirsize is %Ld\n", dir->i_size);
page = 0;
offset = 0;
/* this code is executed quadratically often */
/* do minimal checking `by hand' */
int de_len;
- CDEBUG(D_INODE, "Entry %p len %d, page at %#lx - %#lx , offset %lx\n",
- de, le16_to_cpu(de->rec_len), page_address(page), page_address(page) +
- PAGE_SIZE, offset);
+ /* CDEBUG(D_INODE, "Entry %p len %d, page at %#lx - %#lx , offset %lx\n",
+ de, le16_to_cpu(de->rec_len), page_address(page),
+ page_address(page) + PAGE_SIZE, offset); */
if ((char *) de + namelen <= dlimit &&
ext2_match (namelen, name, de)) {
/* prevent looping on a bad block */
de_len = le16_to_cpu(de->rec_len);
if (de_len <= 0) {
- CDEBUG(D_INODE, "Bad entry: at %p len %d\n",
- de, de_len);
+ printk("Bad entry at %p len %d\n", de, de_len);
goto failure;
}
offset += de_len;
de = (struct ext2_dir_entry_2 *)
((char *) de + de_len);
- CDEBUG(D_INODE, "Next while %lx\n", offset);
+ /* CDEBUG(D_INODE, "Next while %lx\n", offset); */
}
if ( lock )
UnlockPage(page);
* 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,
return NULL;
}
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)) {
+ 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);
if (le32_to_cpu(de->inode)) {
/*
* Display all dentries holding the specified inode.
*/
+#if 0
static void show_dentry(struct list_head * dlist, int subdirs)
{
struct list_head *tmp = dlist;
const char * unhashed = "";
if ( subdirs )
- dentry = list_entry(tmp, struct dentry, d_child);
- else
- dentry = list_entry(tmp, struct dentry, d_alias);
+ dentry = list_entry(tmp, struct dentry, d_child);
+ else
+ dentry = list_entry(tmp, struct dentry, d_alias);
if (list_empty(&dentry->d_hash))
unhashed = "(unhashed)";
unhashed);
}
}
+#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;
+}
/*
struct page *page;
struct ext2_dir_entry_2 * de;
int err = -EIO;
- struct obdfs_sb_info *sbi;
- ino_t ino;
ENTRY;
- sbi = dir->i_sb->u.generic_sbp;
- /*
- * N.B. Several error exits in ext2_new_inode don't set err.
- */
- ino = sbi->osi_ops->o_create(sbi->osi_conn_info.conn_id, 0, &err);
- if ( err )
- return err;
- err = -EIO;
- inode = iget(dir->i_sb, ino);
- if (!inode || !list_empty(&inode->i_dentry)) {
- CDEBUG(D_INODE, "No inode, ino %ld\n", ino);
+ inode = obdfs_new_inode(dir);
+ if ( IS_ERR(inode) ) {
EXIT;
- return err;
+ return PTR_ERR(inode);
}
- inode->i_op = &obdfs_inode_ops;
+ 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);
de->inode = cpu_to_le32(inode->i_ino);
ext2_set_de_type(dir->i_sb, de, S_IFREG);
dir->i_version = ++event;
- sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id,
- 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)
struct inode * inode;
struct page *page;
struct ext2_dir_entry_2 * de;
- int err = -EIO;
- struct obdfs_sb_info *sbi;
-
- ino_t ino;
+ int err;
ENTRY;
- sbi = dir->i_sb->u.generic_sbp;
- /*
- * N.B. Several error exits in ext2_new_inode don't set err.
- */
- ino = sbi->osi_ops->o_create(sbi->osi_conn_info.conn_id, 0, &err);
- if ( ino == -1 )
- return -1;
- inode = iget(dir->i_sb, ino);
- if (!inode)
- return err;
+ 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);
dir->i_version = ++event;
ext2_set_de_type(dir->i_sb, de, inode->i_mode);
mark_inode_dirty(inode);
- sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id,
- 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;
int obdfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
{
- struct inode * child;
- struct page *page, *child_page;
+ struct inode * inode;
+ struct page *page, *inode_page;
struct ext2_dir_entry_2 * de;
- struct obdfs_sb_info *sbi;
int err;
- ino_t ino;
ENTRY;
- sbi = dir->i_sb->u.generic_sbp;
err = -EMLINK;
if (dir->i_nlink >= EXT2_LINK_MAX)
goto out;
- err = -EIO;
- ino = iops(dir)->o_create(sbi->osi_conn_info.conn_id, 0, &err);
- if ( ino == -1 )
- return -1;
- child = iget(dir->i_sb, ino);
- if (!child)
- return err;
-
+ inode = obdfs_new_inode(dir);
+ if ( IS_ERR(inode) ) {
+ EXIT;
+ return PTR_ERR(inode);
+ }
- child->i_op = &obdfs_inode_ops;
- child->i_size = PAGE_SIZE;
- child->i_blocks = 0;
- child_page = obdfs_getpage(child, 0, 1, LOCKED);
- if (!child_page) {
- child->i_nlink--; /* is this nlink == 0? */
- mark_inode_dirty(child);
- iput (child);
+ inode->i_op = &obdfs_dir_inode_operations;
+ inode->i_blocks = 0;
+ inode_page = obdfs_getpage(inode, 0, 1, LOCKED);
+ if (!inode_page) {
+ inode->i_nlink--; /* is this nlink == 0? */
+ mark_inode_dirty(inode);
+ iput (inode);
return err;
}
- child->i_blocks = PAGE_SIZE/child->i_sb->s_blocksize;
/* create . and .. */
- de = (struct ext2_dir_entry_2 *) page_address(child_page);
- de->inode = cpu_to_le32(child->i_ino);
+ de = (struct ext2_dir_entry_2 *) page_address(inode_page);
+ de->inode = cpu_to_le32(inode->i_ino);
de->name_len = 1;
de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(de->name_len));
strcpy (de->name, ".");
strcpy (de->name, "..");
ext2_set_de_type(dir->i_sb, de, S_IFDIR);
- iops(dir)->o_brw(WRITE, sbi->osi_conn_info.conn_id, child, child_page, 1);
- UnlockPage(child_page);
- page_cache_release(child_page);
-
- child->i_nlink = 2;
- child->i_mode = S_IFDIR | mode;
+ 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;
if (dir->i_mode & S_ISGID)
- child->i_mode |= S_ISGID;
- mark_inode_dirty(child);
+ inode->i_mode |= S_ISGID;
+ mark_inode_dirty(inode);
/* now deal with the parent */
page = obdfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
goto out_no_entry;
}
- de->inode = cpu_to_le32(child->i_ino);
+ de->inode = cpu_to_le32(inode->i_ino);
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, sbi->osi_conn_info.conn_id, dir, page, 1);
+ err = obdfs_do_writepage(dir, page, IS_SYNC(dir));
+
UnlockPage(page);
+
page_cache_release(page);
- d_instantiate(dentry, child);
+ d_instantiate(dentry, inode);
err = 0;
out:
EXIT;
return err;
out_no_entry:
- child->i_nlink = 0;
- mark_inode_dirty(child);
- iput (child);
+ inode->i_nlink = 0;
+ mark_inode_dirty(inode);
+ iput (inode);
EXIT;
goto out;
}
struct inode * inode;
struct page *page;
struct ext2_dir_entry_2 * de;
- struct obdfs_sb_info *sbi;
+ int err;
- ENTRY;
- sbi = dir->i_sb->u.generic_sbp;
+ ENTRY;
retval = -ENOENT;
page = obdfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, LOCKED);
dir->i_version = ++event;
if (retval)
goto end_rmdir;
- sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id, 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)",
struct inode * inode;
struct page *page;
struct ext2_dir_entry_2 * de;
- struct obdfs_sb_info *sbi;
+ int err;
ENTRY;
- sbi = dir->i_sb->u.generic_sbp;
retval = -ENOENT;
page = obdfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, LOCKED);
if (retval)
goto end_unlink;
dir->i_version = ++event;
- sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id, 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);
{
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;
- struct obdfs_sb_info *sbi;
- ino_t ino;
ENTRY;
-
- sbi = dir->i_sb->u.generic_sbp;
- /*
- * N.B. Several error exits in ext2_new_inode don't set err.
- */
- ino = sbi->osi_ops->o_create(sbi->osi_conn_info.conn_id, 0, &err);
- if ( ino == -1 )
- return -1;
- inode = iget(dir->i_sb, ino);
- if (!inode)
- return err;
+ inode = obdfs_new_inode(dir);
+ oinfo = inode->u.generic_ip;
+ if ( IS_ERR(inode) ) {
+ EXIT;
+ return PTR_ERR(inode);
+ }
inode->i_mode = S_IFLNK | S_IRWXUGO;
- inode->i_op = &obdfs_inode_ops;
+ 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);
inode->i_nlink--;
mark_inode_dirty(inode);
iput (inode);
+ EXIT;
return err;
}
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);
link[i++] = c;
link[i] = 0;
if (name_page) {
- sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id,
- 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);
de->inode = cpu_to_le32(inode->i_ino);
ext2_set_de_type(dir->i_sb, de, S_IFLNK);
dir->i_version = ++event;
- sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id,
- 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:
+ EXIT;
return err;
out_no_entry:
struct ext2_dir_entry_2 * de;
struct page *page;
int err;
- struct obdfs_sb_info *sbi;
ENTRY;
- sbi = dir->i_sb->u.generic_sbp;
if (S_ISDIR(inode->i_mode))
return -EPERM;
de->inode = cpu_to_le32(inode->i_ino);
ext2_set_de_type(dir->i_sb, de, inode->i_mode);
dir->i_version = ++event;
- sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id,
- 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;
struct page * old_page, * new_page, * dir_page;
struct ext2_dir_entry_2 * old_de, * new_de;
int retval;
- struct obdfs_sb_info *sbi;
ENTRY;
- sbi = old_dir->i_sb->u.generic_sbp;
new_page = dir_page = NULL;
mark_inode_dirty(old_dir);
if (dir_page) {
PARENT_INO(page_address(dir_page)) = le32_to_cpu(new_dir->i_ino);
- sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id,
- 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) {
}
}
if ( old_page != new_page ) {
- unsigned long offset = old_page->offset;
+ unsigned long index = old_page->index;
/* 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, offset, 0, LOCKED);
+ old_page = obdfs_getpage(old_dir, index >> PAGE_SHIFT, 0, LOCKED);
CDEBUG(D_INODE, "old_page at %p\n", old_page);
- sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id,
- old_dir, old_page, 0);
+ obdfs_do_writepage(old_dir, old_page, IS_SYNC(old_dir));
}
-#if 0
- if (IS_SYNC(old_dir)) {
- ll_rw_block (WRITE, 1, &old_bh);
- wait_on_buffer (old_bh);
- }
-#endif
- sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id,
- 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;