From 3f3092503c5a7a4f16e36474884182a59e4be13c Mon Sep 17 00:00:00 2001 From: braam Date: Mon, 15 Oct 2001 05:33:22 +0000 Subject: [PATCH] ext2 page cache updates --- lustre/demos/basesetup.sh | 4 + lustre/demos/config.sh | 4 +- lustre/include/linux/obd_class.h | 11 + lustre/obdclass/genops.c | 6 +- lustre/obdfs/Makefile.am | 2 +- lustre/obdfs/Makefile.in | 10 +- lustre/obdfs/dir.c | 6 +- lustre/obdfs/file.c | 2 +- lustre/obdfs/namei.c | 535 ++++++++++++++------------------------- lustre/obdfs/rw.c | 3 +- lustre/obdfs/super.c | 1 + 11 files changed, 216 insertions(+), 368 deletions(-) diff --git a/lustre/demos/basesetup.sh b/lustre/demos/basesetup.sh index f2cf372..7d1beb3 100755 --- a/lustre/demos/basesetup.sh +++ b/lustre/demos/basesetup.sh @@ -10,6 +10,10 @@ OBDDIR="`dirname $0`/.." # source config info . $OBDDIR/demos/config.sh +insmod obdclass +insmod obdext2 +insmod obdfs + # module configuration if [ "$MODCONF" -a -f $MODCONF ]; then if [ -z "`grep -i "alias *char-major-$OBDMAJ *obdclass" $MODCONF`" ]; then diff --git a/lustre/demos/config.sh b/lustre/demos/config.sh index 5a5140d..4d19a29 100644 --- a/lustre/demos/config.sh +++ b/lustre/demos/config.sh @@ -25,8 +25,8 @@ OBDMAJ=186 # If LOOPDEV is empty, then it is assumed that BASEDEV is a real block device # that doesn't mind being overwritten - don't use a partition with data on it!! -LOOPDEV="" -BASEDEV="/dev/hda5" +LOOPDEV="/dev/loop0" +BASEDEV="/dev/loop0" # The following are mount points for the filesystems during the test. MNTOBD="/mnt/obd" diff --git a/lustre/include/linux/obd_class.h b/lustre/include/linux/obd_class.h index 1ea91e7..6926875 100644 --- a/lustre/include/linux/obd_class.h +++ b/lustre/include/linux/obd_class.h @@ -33,6 +33,7 @@ typedef uint32_t obd_blksize; typedef uint32_t obd_mode; typedef uint32_t obd_uid; typedef uint32_t obd_gid; +typedef uint16_t obd_rdev; typedef uint32_t obd_flag; typedef uint32_t obd_count; @@ -54,6 +55,7 @@ struct obdo { obd_mode o_mode; obd_uid o_uid; obd_gid o_gid; + obd_rdev o_rdev; obd_flag o_flags; obd_flag o_obdflags; obd_count o_nlink; @@ -82,6 +84,7 @@ struct obdo { #define OBD_MD_FLGENER (0x00002000UL) #define OBD_MD_FLINLINE (0x00004000UL) #define OBD_MD_FLOBDMD (0x00008000UL) +#define OBD_MD_FLRDEV (0x00010000UL) #define OBD_MD_FLNOTOBD (~(OBD_MD_FLOBDMD | OBD_MD_FLOBDFLG | OBD_MD_FLBLOCKS)) /* @@ -322,6 +325,8 @@ static __inline__ void obdo_cpy_md(struct obdo *dst, struct obdo *src) dst->o_gid = src->o_gid; if ( src->o_valid & OBD_MD_FLFLAGS ) dst->o_flags = src->o_flags; + if ( src->o_valid & OBD_MD_FLRDEV ) + dst->o_rdev = src->o_rdev; /* if ( src->o_valid & OBD_MD_FLOBDFLG ) dst->o_obdflags = src->o_obdflags; @@ -366,6 +371,8 @@ static __inline__ void obdo_from_inode(struct obdo *dst, struct inode *src) dst->o_uid = src->i_uid; if ( dst->o_valid & OBD_MD_FLGID ) dst->o_gid = src->i_gid; + if ( dst->o_valid & OBD_MD_FLRDEV ) + dst->o_rdev = src->i_rdev; if ( dst->o_valid & OBD_MD_FLFLAGS ) dst->o_flags = src->i_flags; if ( dst->o_valid & OBD_MD_FLNLINK ) @@ -397,6 +404,8 @@ static __inline__ void obdo_to_inode(struct inode *dst, struct obdo *src) dst->i_uid = src->o_uid; if ( src->o_valid & OBD_MD_FLGID ) dst->i_gid = src->o_gid; + if ( src->o_valid & OBD_MD_FLRDEV ) + dst->i_rdev = src->o_rdev; if ( src->o_valid & OBD_MD_FLFLAGS ) dst->i_flags = src->o_flags; if ( src->o_valid & OBD_MD_FLNLINK ) @@ -429,6 +438,8 @@ static __inline__ int obdo_cmp_md(struct obdo *dst, struct obdo *src, res = (res || (dst->o_uid != src->o_uid)); if ( compare & OBD_MD_FLGID ) res = (res || (dst->o_gid != src->o_gid)); + if ( compare & OBD_MD_FLRDEV ) + res = (res || (dst->o_rdev != src->o_rdev)); if ( compare & OBD_MD_FLFLAGS ) res = (res || (dst->o_flags != src->o_flags)); if ( compare & OBD_MD_FLNLINK ) diff --git a/lustre/obdclass/genops.c b/lustre/obdclass/genops.c index a261dd8..545b0c7 100644 --- a/lustre/obdclass/genops.c +++ b/lustre/obdclass/genops.c @@ -270,16 +270,14 @@ int gen_copy_data(struct obd_conn *dst_conn, struct obdo *dst, while (index < ((src->o_size + PAGE_SIZE - 1) >> PAGE_SHIFT)) { obd_count num_oa = 1; obd_count num_buf = 1; - char *buf; obd_size brw_count = PAGE_SIZE; obd_off brw_offset = (page->index) << PAGE_SHIFT; obd_flag flagr = 0; obd_flag flagw = OBD_BRW_CREATE; page->index = index; - buf = (char *)page_address(page); err = OBP(src_conn->oc_dev, brw)(READ, src_conn, num_oa, &src, - &num_buf, &buf, &brw_count, + &num_buf, &page, &brw_count, &brw_offset, &flagr); if ( err ) { @@ -289,7 +287,7 @@ int gen_copy_data(struct obd_conn *dst_conn, struct obdo *dst, CDEBUG(D_INFO, "Read page %ld ...\n", page->index); err = OBP(dst_conn->oc_dev, brw)(WRITE, dst_conn, num_oa, &dst, - &num_buf, &buf, &brw_count, + &num_buf, &page, &brw_count, &brw_offset, &flagw); /* XXX should handle dst->o_size, dst->o_blocks here */ diff --git a/lustre/obdfs/Makefile.am b/lustre/obdfs/Makefile.am index 1432ae7..62e0606 100644 --- a/lustre/obdfs/Makefile.am +++ b/lustre/obdfs/Makefile.am @@ -6,6 +6,6 @@ MODULE = obdfs modulefs_DATA = obdfs.o EXTRA_PROGRAMS = obdfs -obdfs_SOURCES = flushd.c rw.c file.c dir.c sysctl.c super.c namei.c symlink.c +obdfs_SOURCES = dirdata.c flushd.c rw.c file.c dir.c sysctl.c super.c namei.c symlink.c include $(top_srcdir)/Rules diff --git a/lustre/obdfs/Makefile.in b/lustre/obdfs/Makefile.in index fd9838f..262ea31 100644 --- a/lustre/obdfs/Makefile.in +++ b/lustre/obdfs/Makefile.in @@ -93,7 +93,7 @@ modulefsdir = @modulefsdir@ MODULE = obdfs modulefs_DATA = obdfs.o EXTRA_PROGRAMS = obdfs -obdfs_SOURCES = flushd.c rw.c file.c dir.c sysctl.c super.c namei.c symlink.c +obdfs_SOURCES = dirdata.c flushd.c rw.c file.c dir.c sysctl.c super.c namei.c symlink.c mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = @@ -101,8 +101,8 @@ DEFS = @DEFS@ -I. -I$(srcdir) CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ -obdfs_OBJECTS = flushd.o rw.o file.o dir.o sysctl.o super.o namei.o \ -symlink.o +obdfs_OBJECTS = dirdata.o flushd.o rw.o file.o dir.o sysctl.o super.o \ +namei.o symlink.o obdfs_LDADD = $(LDADD) obdfs_DEPENDENCIES = obdfs_LDFLAGS = @@ -119,8 +119,8 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) TAR = gtar GZIP_ENV = --best -DEP_FILES = .deps/dir.P .deps/file.P .deps/flushd.P .deps/namei.P \ -.deps/rw.P .deps/super.P .deps/symlink.P .deps/sysctl.P +DEP_FILES = .deps/dir.P .deps/dirdata.P .deps/file.P .deps/flushd.P \ +.deps/namei.P .deps/rw.P .deps/super.P .deps/symlink.P .deps/sysctl.P SOURCES = $(obdfs_SOURCES) OBJECTS = $(obdfs_OBJECTS) diff --git a/lustre/obdfs/dir.c b/lustre/obdfs/dir.c index 1462f30..af115d9 100644 --- a/lustre/obdfs/dir.c +++ b/lustre/obdfs/dir.c @@ -48,15 +48,17 @@ static ssize_t obdfs_dir_read (struct file * filp, char * buf, } static int obdfs_readdir(struct file *, void *, filldir_t); +extern int new_obdfs_readdir(struct file *, void *, filldir_t); struct file_operations obdfs_dir_operations = { read: obdfs_dir_read, - readdir: obdfs_readdir + readdir: new_obdfs_readdir }; +extern struct dentry *new_obdfs_lookup(struct inode * dir, struct dentry *dentry); struct inode_operations obdfs_dir_inode_operations = { create: obdfs_create, - lookup: obdfs_lookup, + lookup: new_obdfs_lookup, link: obdfs_link, unlink: obdfs_unlink, symlink: obdfs_symlink, diff --git a/lustre/obdfs/file.c b/lustre/obdfs/file.c index ff07ce3..f58c057 100644 --- a/lustre/obdfs/file.c +++ b/lustre/obdfs/file.c @@ -83,7 +83,7 @@ struct file_operations obdfs_file_operations = { extern int obdfs_notify_change(struct dentry *de, struct iattr *attr); struct inode_operations obdfs_file_inode_operations = { create: obdfs_create, - lookup: obdfs_lookup, + lookup: NULL, link: obdfs_link, unlink: obdfs_unlink, symlink: obdfs_symlink, diff --git a/lustre/obdfs/namei.c b/lustre/obdfs/namei.c index e899303..9ea0c1c 100644 --- a/lustre/obdfs/namei.c +++ b/lustre/obdfs/namei.c @@ -22,6 +22,8 @@ * * Changes for use in OBDFS * Copyright (c) 1999, Seagate Technology Inc. + * Copyright (C) 2001, Cluster File Systems, Inc. + * Rewritten based on recent ext2 page cache use. * */ @@ -30,16 +32,62 @@ #include #include #include - - +extern struct address_space_operations obdfs_aops; /* - * define how far ahead to read directories while searching them. + * Couple of helper functions - make the code slightly cleaner. */ -#define NAMEI_RA_CHUNKS 2 -#define NAMEI_RA_BLOCKS 4 -#define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS) -#define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b)) +extern int ext2_add_link (struct dentry *dentry, struct inode *inode); +extern ino_t ext2_inode_by_name(struct inode * dir, struct dentry *dentry); +int ext2_make_empty(struct inode *inode, struct inode *parent); +struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir, + struct dentry *dentry, struct page ** res_page); +int ext2_delete_entry (struct ext2_dir_entry_2 * dir, struct page * page ); + + +static inline void ext2_inc_count(struct inode *inode) +{ + inode->i_nlink++; + mark_inode_dirty(inode); +} + +static inline void ext2_dec_count(struct inode *inode) +{ + inode->i_nlink--; + mark_inode_dirty(inode); +} + +static inline int ext2_add_nondir(struct dentry *dentry, struct inode *inode) +{ + int err = ext2_add_link(dentry, inode); + if (!err) { + d_instantiate(dentry, inode); + return 0; + } + ext2_dec_count(inode); + iput(inode); + return err; +} + +/* methods */ +struct dentry *new_obdfs_lookup(struct inode * dir, struct dentry *dentry) +{ + struct inode * inode; + ino_t ino; + + if (dentry->d_name.len > EXT2_NAME_LEN) + return ERR_PTR(-ENAMETOOLONG); + + ino = ext2_inode_by_name(dir, dentry); + inode = NULL; + if (ino) { + inode = iget(dir->i_sb, ino); + if (!inode) + return ERR_PTR(-EACCES); + } + d_add(dentry, inode); + return NULL; +} /* @@ -58,6 +106,7 @@ static inline int ext2_match (int len, const char * const name, return !memcmp(name, de->name, len); } + /* * obdfs_find_entry() * @@ -147,42 +196,6 @@ failure: return NULL; } /* obdfs_find_entry */ -struct dentry *obdfs_lookup(struct inode *dir, struct dentry *dentry) -{ - 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); - inode = NULL; - if ( !page ) - CDEBUG(D_INFO, "No page - negative entry.\n"); - if ( page && !de ) { - CDEBUG(D_INODE, "Danger: PAGE but de.\n"); - return ERR_PTR(-ENOENT); - } - if (page) { - unsigned long ino = le32_to_cpu(de->inode); - page_cache_release(page); - obd_unlock_page(page); - inode = iget(dir->i_sb, ino); - - if (!inode) { - CDEBUG(D_INODE, "No inode.\n"); - EXIT; - return ERR_PTR(-EACCES); - } - } - d_add(dentry, inode); - EXIT; - return NULL; -} /* obdfs_lookup */ - /* * obdfs_add_entry() * @@ -342,7 +355,7 @@ static struct page *obdfs_add_entry (struct inode * dir, dir->i_version = ++event; *res_dir = de; *err = 0; - PDEBUG(page, "add_entry"); + // PDEBUG(page, "add_entry"); /* XXX unlock page here */ EXIT; return page; @@ -519,174 +532,158 @@ static struct inode *obdfs_new_inode(struct inode *dir, int mode) */ int obdfs_create (struct inode * dir, struct dentry * dentry, int mode) { - struct inode * inode; - struct page *page; - struct ext2_dir_entry_2 * de; - int err = -EIO; - - ENTRY; - inode = obdfs_new_inode(dir, mode); - if ( IS_ERR(inode) ) { - EXIT; - return PTR_ERR(inode); - } - - inode->i_op = &obdfs_file_inode_operations; - mark_inode_dirty(inode); - page = obdfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err); - if (!page) { - inode->i_nlink--; - mark_inode_dirty(inode); - iput (inode); - EXIT; - return err; - } - de->inode = cpu_to_le32(inode->i_ino); - ext2_set_de_type(dir->i_sb, de, S_IFREG); - dir->i_version = ++event; - - err = obdfs_do_writepage(page, IS_SYNC(dir)); - obd_unlock_page(page); - page_cache_release(page); - d_instantiate(dentry, inode); - EXIT; - return err; + struct inode * inode = obdfs_new_inode (dir, mode); + int err = PTR_ERR(inode); + if (!IS_ERR(inode)) { + inode->i_op = &obdfs_file_inode_operations; + inode->i_fop = &obdfs_file_operations; + inode->i_mapping->a_ops = &obdfs_aops; + mark_inode_dirty(inode); + err = ext2_add_nondir(dentry, inode); + } + return err; } /* obdfs_create */ + 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; - struct obdfs_inode_info *oinfo; - int err; - - ENTRY; - inode = obdfs_new_inode(dir, mode); - if ( IS_ERR(inode) ) { - EXIT; - return PTR_ERR(inode); - } + struct inode * inode = obdfs_new_inode (dir, mode); + int err = PTR_ERR(inode); + if (!IS_ERR(inode)) { + init_special_inode(inode, mode, rdev); + mark_inode_dirty(inode); + err = ext2_add_nondir(dentry, inode); + } + return err; +} - inode->i_uid = current->fsuid; - init_special_inode(inode, mode, rdev); +int obdfs_symlink (struct inode * dir, struct dentry * dentry, + const char * symname) +{ + struct super_block * sb = dir->i_sb; + int err = -ENAMETOOLONG; + unsigned l = strlen(symname)+1; + struct inode * inode; + struct obdfs_inode_info *oinfo; oinfo = obdfs_i2info(inode); - ((obd_count *)oinfo->oi_inline)[0] = rdev; - oinfo->oi_flags |= OBD_FL_INLINEDATA; - 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); - dir->i_version = ++event; - ext2_set_de_type(dir->i_sb, de, inode->i_mode); - mark_inode_dirty(inode); + if (l > sb->s_blocksize) + goto out; - err = obdfs_do_writepage(page, IS_SYNC(dir)); - obd_unlock_page(page); + inode = obdfs_new_inode (dir, S_IFLNK | S_IRWXUGO); + err = PTR_ERR(inode); + if (IS_ERR(inode)) + goto out; - d_instantiate(dentry, inode); - page_cache_release(page); - err = 0; + if (l >= sizeof(oinfo->oi_inline)) { + /* slow symlink */ + inode->i_op = &obdfs_symlink_inode_operations; + inode->i_mapping->a_ops = &obdfs_aops; + err = block_symlink(inode, symname, l); + if (err) + goto out_fail; + } else { + /* fast symlink */ + inode->i_op = &obdfs_fast_symlink_inode_operations; + memcpy((char*)&inode->u.ext2_i.i_data,symname,l); + inode->i_size = l-1; + } + mark_inode_dirty(inode); + + err = ext2_add_nondir(dentry, inode); out: - return err; + return err; -out_no_entry: - inode->i_nlink--; - mark_inode_dirty(inode); - iput(inode); - goto out; -} /* obdfs_mknod */ +out_fail: + ext2_dec_count(inode); + iput (inode); + goto out; +} -int obdfs_mkdir(struct inode * dir, struct dentry * dentry, int mode) + + +int obdfs_link (struct dentry * old_dentry, struct inode * dir, + struct dentry *dentry) { - struct inode * inode; - struct page *page, *inode_page; - struct ext2_dir_entry_2 * de; - int err; + struct inode *inode = old_dentry->d_inode; - ENTRY; + if (S_ISDIR(inode->i_mode)) + return -EPERM; - err = -EMLINK; - if (dir->i_nlink >= EXT2_LINK_MAX) - goto out; + if (inode->i_nlink >= EXT2_LINK_MAX) + return -EMLINK; - mode |= S_IFDIR; - if (dir->i_mode & S_ISGID) - mode |= S_ISGID; + inode->i_ctime = CURRENT_TIME; + ext2_inc_count(inode); + atomic_inc(&inode->i_count); - inode = obdfs_new_inode(dir, mode); - if ( IS_ERR(inode) ) { - EXIT; - return PTR_ERR(inode); - } + return ext2_add_nondir(dentry, inode); +} - 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 -EIO; - } - de = (struct ext2_dir_entry_2 *) page_address(inode_page); - - /* create . and .. */ - 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, "."); - ext2_set_de_type(dir->i_sb, de, S_IFDIR); - de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); - de->inode = cpu_to_le32(dir->i_ino); - de->rec_len = cpu_to_le16(PAGE_SIZE - EXT2_DIR_REC_LEN(1)); - de->name_len = 2; - strcpy (de->name, ".."); - ext2_set_de_type(dir->i_sb, de, S_IFDIR); - inode->i_nlink = 2; - - err = obdfs_do_writepage(inode_page, IS_SYNC(inode)); - inode->i_blocks = PAGE_SIZE/inode->i_sb->s_blocksize; - inode->i_size = PAGE_SIZE; - obd_unlock_page(inode_page); - page_cache_release(inode_page); - mark_inode_dirty(inode); - if (err) { - EXIT; - goto out_no_entry; - } - /* now deal with the parent */ - page = obdfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len, &de, &err); - if (!page) { - EXIT; - goto out_no_entry; - } +int obdfs_mkdir(struct inode * dir, struct dentry * dentry, int mode) +{ + struct inode * inode; + int err = -EMLINK; - de->inode = cpu_to_le32(inode->i_ino); - ext2_set_de_type(dir->i_sb, de, S_IFDIR); - dir->i_version = ++event; + if (dir->i_nlink >= EXT2_LINK_MAX) + goto out; - dir->i_nlink++; - dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; - mark_inode_dirty(dir); - err = obdfs_do_writepage(page, IS_SYNC(dir)); + ext2_inc_count(dir); - obd_unlock_page(page); + inode = obdfs_new_inode (dir, S_IFDIR | mode); + err = PTR_ERR(inode); + if (IS_ERR(inode)) + goto out_dir; - page_cache_release(page); - d_instantiate(dentry, inode); - EXIT; + inode->i_op = &obdfs_dir_inode_operations; + inode->i_fop = &obdfs_dir_operations; + inode->i_mapping->a_ops = &obdfs_aops; + + ext2_inc_count(inode); + + err = ext2_make_empty(inode, dir); + if (err) + goto out_fail; + + err = ext2_add_link(dentry, inode); + if (err) + goto out_fail; + + d_instantiate(dentry, inode); out: - return err; + return err; + +out_fail: + ext2_dec_count(inode); + ext2_dec_count(inode); + iput(inode); +out_dir: + ext2_dec_count(dir); + goto out; +} -out_no_entry: - inode->i_nlink = 0; - mark_inode_dirty(inode); - iput (inode); - goto out; -} /* obdfs_mkdir */ +int obdfs_unlink(struct inode * dir, struct dentry *dentry) +{ + struct inode * inode = dentry->d_inode; + struct ext2_dir_entry_2 * de; + struct page * page; + int err = -ENOENT; + + de = ext2_find_entry (dir, dentry, &page); + if (!de) + goto out; + + err = ext2_delete_entry (de, page); + if (err) + goto out; + + inode->i_ctime = dir->i_ctime; + ext2_dec_count(inode); + err = 0; +out: + return err; +} /* @@ -810,171 +807,7 @@ end_rmdir: return retval; } /* obdfs_rmdir */ -int obdfs_unlink(struct inode * dir, struct dentry *dentry) -{ - int retval; - struct inode * inode; - struct page *page; - struct ext2_dir_entry_2 * de; - - ENTRY; - - retval = -ENOENT; - page = obdfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, LOCKED); - if (!page) - goto end_unlink; - - inode = dentry->d_inode; - DQUOT_INIT(inode); - - retval = -EIO; - if (le32_to_cpu(de->inode) != inode->i_ino) - goto end_unlink; - - if (!inode->i_nlink) { - ext2_warning (inode->i_sb, "ext2_unlink", - "Deleting nonexistent file (%lu), %d", - inode->i_ino, inode->i_nlink); - inode->i_nlink = 1; - } - retval = obdfs_delete_entry (de, page); - if (retval) - goto end_unlink; - dir->i_version = ++event; - retval = obdfs_do_writepage(page, IS_SYNC(dir)); - /* XXX handle err? */ - obd_unlock_page(page); - - dir->i_ctime = dir->i_mtime = CURRENT_TIME; - dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; - mark_inode_dirty(dir); - inode->i_nlink--; - mark_inode_dirty(inode); - inode->i_ctime = dir->i_ctime; - d_delete(dentry); /* This also frees the inode */ - -end_unlink: - if (page) - page_cache_release(page); - EXIT; - return retval; -} /* obdfs_unlink */ - -int obdfs_symlink (struct inode * dir, struct dentry *dentry, - const char * symname) -{ - struct inode * inode; - struct ext2_dir_entry_2 * de; - struct obdfs_inode_info *oinfo; - struct page* page = NULL, * name_page = NULL; - char * link; - int l, err; - - ENTRY; - err = -ENAMETOOLONG; - l = strlen(symname)+1; - if (l > PAGE_SIZE) { - EXIT; - goto out; - } - - inode = obdfs_new_inode(dir, S_IFLNK); - if ( IS_ERR(inode) ) { - EXIT; - goto out; - } - - inode->i_mode = S_IFLNK | S_IRWXUGO; - oinfo = obdfs_i2info(inode); - - if (l >= sizeof(oinfo->oi_inline)) { - CDEBUG(D_INFO, "l=%d, normal symlink\n", l); - inode->i_op = &obdfs_symlink_inode_operations; - - name_page = obdfs_getpage(inode, 0, 1, LOCKED); - if (!name_page) { - EXIT; - err = -ENOMEM; - goto out_no_entry; - } - link = (char *)page_address(name_page); - } else { - CDEBUG(D_INFO, "l=%d, fast symlink\n", l); - inode->i_op = &obdfs_fast_symlink_inode_operations; - link = oinfo->oi_inline; - oinfo->oi_flags |= OBD_FL_INLINEDATA; - } - memcpy(link, symname, l); - if (name_page) { - err = obdfs_do_writepage(name_page, IS_SYNC(inode)); - /* PDEBUG(name_page, "symlink"); */ - obd_unlock_page(name_page); - page_cache_release(name_page); - if (err) { - EXIT; - goto out_no_entry; - } - } - inode->i_size = l-1; - mark_inode_dirty(inode); - - 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; - err = obdfs_do_writepage(page, IS_SYNC(dir)); - obd_unlock_page(page); - - d_instantiate(dentry, inode); -out: - EXIT; - return err; - -out_no_entry: - inode->i_nlink--; - mark_inode_dirty(inode); - iput (inode); - goto out; -} /* obdfs_symlink */ - -int obdfs_link (struct dentry * old_dentry, - struct inode * dir, struct dentry *dentry) -{ - struct inode *inode = old_dentry->d_inode; - struct ext2_dir_entry_2 * de; - struct page *page; - int err; - - ENTRY; - - if (S_ISDIR(inode->i_mode)) - return -EPERM; - - if (inode->i_nlink >= EXT2_LINK_MAX) - return -EMLINK; - - page = obdfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err); - if (!page) - return err; - - de->inode = cpu_to_le32(inode->i_ino); - ext2_set_de_type(dir->i_sb, de, inode->i_mode); - dir->i_version = ++event; - - err = obdfs_do_writepage(page, IS_SYNC(dir)); - obd_unlock_page(page); - page_cache_release(page); - inode->i_nlink++; - inode->i_ctime = CURRENT_TIME; - mark_inode_dirty(inode); - atomic_inc(&inode->i_count); - d_instantiate(dentry, inode); - return err; -} /* obdfs_link */ #define PARENT_INO(buffer) \ ((struct ext2_dir_entry_2 *) ((char *) buffer + \ diff --git a/lustre/obdfs/rw.c b/lustre/obdfs/rw.c index 347ba2a..313ebd3 100644 --- a/lustre/obdfs/rw.c +++ b/lustre/obdfs/rw.c @@ -77,8 +77,7 @@ static int obdfs_brw(int rw, struct inode *inode, struct page *page, int create) /* returns the page unlocked, but with a reference */ int obdfs_readpage(struct file *file, struct page *page) { - struct dentry *dentry = file->f_dentry; - struct inode *inode = dentry->d_inode; + struct inode *inode = page->mapping->host; int rc; ENTRY; diff --git a/lustre/obdfs/super.c b/lustre/obdfs/super.c index 1fb0444..9af4896 100644 --- a/lustre/obdfs/super.c +++ b/lustre/obdfs/super.c @@ -324,6 +324,7 @@ static void obdfs_read_inode(struct inode *inode) } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &obdfs_dir_inode_operations; inode->i_fop = &obdfs_dir_operations; + inode->i_mapping->a_ops = &obdfs_aops; EXIT; } else if (S_ISLNK(inode->i_mode)) { if (inode->i_blocks) { -- 1.8.3.1