X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fobdfs%2Fnamei.c;h=6b806664bd90b2348c9871f5099657e44a99753d;hb=c227004555dd3485504b72e6d17ad3bb1bde744f;hp=316a17ab149c3924c2e7d8d760d8d3b005c14919;hpb=8bb299c93313daad5d14e4b08b0a672eda144214;p=fs%2Flustre-release.git diff --git a/lustre/obdfs/namei.c b/lustre/obdfs/namei.c index 316a17a..6b80666 100644 --- a/lustre/obdfs/namei.c +++ b/lustre/obdfs/namei.c @@ -1,5 +1,5 @@ /* - * linux/fs/ext2/namei.c + * linux/fs/obdfs/namei.c * * Copyright (C) 1992, 1993, 1994, 1995 * Remy Card (card@masi.ibp.fr) @@ -8,7 +8,7 @@ * * from * - * linux/fs/minix/namei.c + * linux/fs/ext2/namei.c * * Copyright (C) 1991, 1992 Linus Torvalds * @@ -36,7 +36,7 @@ #include #include -#include "obdfs.h" +#include /* * define how far ahead to read directories while searching them. @@ -70,7 +70,7 @@ static inline int ext2_match (int len, const char * const name, * 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) { @@ -86,7 +86,7 @@ struct page * obdfs_find_entry (struct inode * dir, 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; @@ -107,9 +107,9 @@ struct page * obdfs_find_entry (struct inode * dir, /* 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)) { @@ -125,14 +125,13 @@ struct page * obdfs_find_entry (struct inode * dir, /* 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); @@ -200,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, @@ -294,10 +296,8 @@ static struct page *obdfs_add_entry (struct inode * 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)) { @@ -409,6 +409,7 @@ static inline void ext2_set_de_type(struct super_block *sb, /* * Display all dentries holding the specified inode. */ +#if 0 static void show_dentry(struct list_head * dlist, int subdirs) { struct list_head *tmp = dlist; @@ -418,9 +419,9 @@ static void show_dentry(struct list_head * dlist, int subdirs) 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)"; @@ -439,6 +440,48 @@ static void show_dentry(struct list_head * dlist, int subdirs) 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; +} /* @@ -455,27 +498,16 @@ int obdfs_create (struct inode * dir, struct dentry * dentry, int mode) 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); @@ -489,19 +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; - 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) @@ -509,23 +536,15 @@ 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); @@ -536,16 +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); - 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; @@ -561,44 +574,36 @@ out_no_entry: 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, "."); @@ -611,15 +616,18 @@ 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, 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); @@ -627,32 +635,28 @@ int obdfs_mkdir(struct inode * dir, struct dentry * dentry, int mode) 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; } @@ -731,10 +735,9 @@ int obdfs_rmdir (struct inode * dir, struct dentry *dentry) 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); @@ -756,14 +759,9 @@ int obdfs_rmdir (struct inode * dir, struct dentry *dentry) 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)", @@ -791,10 +789,9 @@ int obdfs_unlink(struct inode * dir, struct dentry *dentry) 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); @@ -818,14 +815,9 @@ int obdfs_unlink(struct inode * dir, struct dentry *dentry) 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); @@ -846,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; - 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); @@ -880,11 +866,13 @@ int obdfs_symlink (struct inode * dir, struct dentry *dentry, const char * symna 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); @@ -894,8 +882,7 @@ int obdfs_symlink (struct inode * dir, struct dentry *dentry, const char * symna 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); @@ -909,18 +896,13 @@ 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; - 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: @@ -937,10 +919,8 @@ int obdfs_link (struct dentry * old_dentry, 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; @@ -955,16 +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; - 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; @@ -989,10 +963,8 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry, 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; @@ -1076,8 +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); - 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) { @@ -1090,29 +1061,16 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry, } } 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;