[Ocfs2-commits] mfasheh commits r1726 - trunk/src

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Wed Dec 29 20:33:52 CST 2004


Author: mfasheh
Date: 2004-12-29 20:33:50 -0600 (Wed, 29 Dec 2004)
New Revision: 1726

Modified:
   trunk/src/aops.c
   trunk/src/dlmglue.c
   trunk/src/inode.c
   trunk/src/namei.c
   trunk/src/ocfs2_fs.h
   trunk/src/symlink.c
   trunk/src/symlink.h
Log:
* give ocfs2 "fast symlinks". inspiration taken from ext3.



Modified: trunk/src/aops.c
===================================================================
--- trunk/src/aops.c	2004-12-29 01:13:56 UTC (rev 1725)
+++ trunk/src/aops.c	2004-12-30 02:33:50 UTC (rev 1726)
@@ -35,6 +35,8 @@
 #include "extent_map.h"
 #include "file.h"
 #include "inode.h"
+#include "symlink.h"
+
 #include "ocfs_journal.h"
 
 
@@ -54,6 +56,8 @@
 	LOG_ENTRY_ARGS("(0x%p, %llu, 0x%p, %d)\n", inode,
 			(unsigned long long)iblock, bh_result, create);
 
+	OCFS_ASSERT(!ocfs2_inode_is_fast_symlink(inode));
+
 	if ((iblock << inode->i_sb->s_blocksize_bits) > PATH_MAX + 1) {
 		LOG_ERROR_ARGS ("block offset > PATH_MAX: %llu",
 				(unsigned long long)iblock);

Modified: trunk/src/dlmglue.c
===================================================================
--- trunk/src/dlmglue.c	2004-12-29 01:13:56 UTC (rev 1725)
+++ trunk/src/dlmglue.c	2004-12-30 02:33:50 UTC (rev 1726)
@@ -1105,8 +1105,11 @@
 	i_size_write(inode, lvb->lvb_isize);
 	inode->i_mode    = lvb->lvb_imode;
 	inode->i_nlink   = lvb->lvb_inlink;
-	inode->i_blocks  = (inode->i_size + inode->i_sb->s_blocksize - 1) 
-		>> inode->i_sb->s_blocksize_bits;
+	/* fast-symlinks are a special case */
+	if (S_ISLNK(inode->i_mode) && !oip->ip_clusters)
+		inode->i_blocks = 0;
+	else
+		inode->i_blocks  = (inode->i_size + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
 	OCFS_SET_INODE_TIME(inode, i_atime, lvb->lvb_iatime);
 	OCFS_SET_INODE_TIME(inode, i_ctime, lvb->lvb_ictime);
 	OCFS_SET_INODE_TIME(inode, i_mtime, lvb->lvb_imtime);

Modified: trunk/src/inode.c
===================================================================
--- trunk/src/inode.c	2004-12-29 01:13:56 UTC (rev 1725)
+++ trunk/src/inode.c	2004-12-30 02:33:50 UTC (rev 1726)
@@ -374,7 +374,12 @@
 	inode->i_uid = fe->i_uid;
 	inode->i_gid = fe->i_gid;
 	inode->i_blksize = (u32)osb->s_clustersize;	// sb->s_blocksize;
-	inode->i_blocks = (fe->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+
+	/* Fast symlinks will have i_size but no allocated clusters. */
+	if (S_ISLNK(inode->i_mode) && !fe->i_clusters)
+		inode->i_blocks = 0;
+	else
+		inode->i_blocks = (fe->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
 	inode->i_mapping->a_ops = &ocfs_aops;
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
 	inode->i_attr_flags |= ATTR_FLAG_NOATIME;
@@ -426,7 +431,10 @@
 		    break;
 	    case S_IFLNK:
 		    atomic_set(GET_INODE_CLEAN_SEQ(inode), atomic_read(&osb->clean_buffer_seq));
-		    inode->i_op = &ocfs_symlink_inode_operations;
+		    if (ocfs2_inode_is_fast_symlink(inode))
+			inode->i_op = &ocfs_fast_symlink_inode_operations;
+		    else
+			inode->i_op = &ocfs_symlink_inode_operations;
 		    //inode->i_fop = &ocfs_fops;
 		    i_size_write(inode, fe->i_size);
 		    break;
@@ -1038,11 +1046,14 @@
 		oip->ip_mmu_private = i_size_read(inode);
 	}
 	inode->i_nlink = fe->i_links_count;
-	inode->i_blocks = (i_size_read(inode) + osb->sb->s_blocksize - 1) >> osb->sb->s_blocksize_bits;
 	inode->i_uid = fe->i_uid;
 	inode->i_gid = fe->i_gid;
 	inode->i_mode = fe->i_mode;
 	inode->i_blksize = (u32) osb->s_clustersize;
+	if (S_ISLNK(inode->i_mode) && !fe->i_clusters)
+		inode->i_blocks = 0;
+	else
+		inode->i_blocks = (i_size_read(inode) + osb->sb->s_blocksize - 1) >> osb->sb->s_blocksize_bits;
 	OCFS_SET_INODE_TIME(inode, i_ctime, fe->i_ctime);
 	OCFS_SET_INODE_TIME(inode, i_atime, fe->i_atime);
 	OCFS_SET_INODE_TIME(inode, i_mtime, fe->i_mtime);

Modified: trunk/src/namei.c
===================================================================
--- trunk/src/namei.c	2004-12-29 01:13:56 UTC (rev 1725)
+++ trunk/src/namei.c	2004-12-30 02:33:50 UTC (rev 1726)
@@ -57,6 +57,7 @@
 #include "inode.h"
 #include "namei.h"
 #include "suballoc.h"
+#include "symlink.h"
 #include "util.h"
 #include "vote.h"
 
@@ -1453,19 +1454,17 @@
  */
 static int ocfs_symlink (struct inode *dir, struct dentry *dentry, const char *symname)
 {
+	int status, l, credits;
+	u64 newsize;
 	ocfs_super *osb = NULL;
 	struct inode *inode = NULL;
-	u64 newsize;
-	int status;
 	struct super_block *sb;
-	int l;
 	struct buffer_head *new_fe_bh = NULL;
 	struct buffer_head *de_bh = NULL;
 	struct buffer_head *parent_fe_bh = NULL;
 	ocfs2_dinode *fe = NULL;
 	ocfs2_dinode *dirfe;
 	ocfs_journal_handle *handle = NULL;
-	int credits;
 	ocfs2_alloc_context *inode_ac = NULL;
 	ocfs2_alloc_context *data_ac = NULL;
 
@@ -1478,6 +1477,8 @@
 	sb = dir->i_sb;
 	osb = OCFS_SB(sb);
 
+	l = strlen(symname) + 1;
+
 	inode = new_inode (sb);
 	if (IS_ERR (inode)) {
 		status = PTR_ERR(inode);
@@ -1493,9 +1494,6 @@
 		goto bail;
 	}
 
-	l = strlen (symname) + 1;
-	newsize = l - 1;
-
 	credits = ocfs_calc_symlink_credits(sb);
 
 	handle = ocfs_alloc_handle(osb);
@@ -1533,10 +1531,13 @@
 		goto bail;
 	}
 
-	status = ocfs_reserve_clusters(osb, handle, 1, &data_ac);
-	if (status < 0) {
-		LOG_ERROR_STATUS (status = -ENOMEM);
-		goto bail;
+	/* don't reserve bitmap space for fast symlinks. */
+	if (l > ocfs2_fast_symlink_chars(sb)) {
+		status = ocfs_reserve_clusters(osb, handle, 1, &data_ac);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status = -ENOMEM);
+			goto bail;
+		}
 	}
 
 	handle = ocfs_start_trans(osb, handle, credits);
@@ -1569,19 +1570,28 @@
 	if (status < 0)
 		LOG_ERROR_STATUS(status);
 
-	status = ocfs_extend_allocation(osb, inode, 1, new_fe_bh, handle, 
-					data_ac, NULL, NULL);
-	if (status < 0) {
-		if (status != -ENOSPC && status != -EINTR) {
-			LOG_ERROR_ARGS ("Failed to extend file to %llu", newsize);
-			LOG_ERROR_STATUS(status);
-			status = -ENOSPC;
+	inode->i_rdev = 0;
+	newsize = l - 1;
+	if (l > ocfs2_fast_symlink_chars(sb)) {
+		inode->i_op = &ocfs_symlink_inode_operations;
+		status = ocfs_extend_allocation(osb, inode, 1, new_fe_bh,
+						handle, data_ac, NULL, NULL);
+		if (status < 0) {
+			if (status != -ENOSPC && status != -EINTR) {
+				LOG_ERROR_ARGS ("Failed to extend file to %llu", newsize);
+				LOG_ERROR_STATUS(status);
+				status = -ENOSPC;
+			}
+			goto bail;
 		}
-		goto bail;
+		i_size_write(inode, newsize);
+		inode->i_blocks = (newsize + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+	} else {
+		inode->i_op = &ocfs_fast_symlink_inode_operations;
+		memcpy((char *) &fe->id2.i_symlink, symname, l);
+		i_size_write(inode, newsize);
+		inode->i_blocks = 0;
 	}
-	inode->i_rdev = 0;
-	i_size_write(inode, newsize);
-	inode->i_blocks = (newsize + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
 
 	status = ocfs_mark_inode_dirty(handle, inode, new_fe_bh);
 	if (status < 0) {
@@ -1589,10 +1599,12 @@
 		goto bail;
 	}
 
-	status = ocfs_create_symlink_data(osb, handle, inode, symname);
-	if (status < 0) {
-		LOG_ERROR_STATUS (status);
-		goto bail;
+	if (!ocfs2_inode_is_fast_symlink(inode)) {
+		status = ocfs_create_symlink_data(osb, handle, inode, symname);
+		if (status < 0) {
+			LOG_ERROR_STATUS (status);
+			goto bail;
+		}
 	}
 
 	status = ocfs_add_entry(handle, dentry, inode, fe->i_blkno,

Modified: trunk/src/ocfs2_fs.h
===================================================================
--- trunk/src/ocfs2_fs.h	2004-12-29 01:13:56 UTC (rev 1725)
+++ trunk/src/ocfs2_fs.h	2004-12-30 02:33:50 UTC (rev 1726)
@@ -383,6 +383,7 @@
 		ocfs2_local_alloc i_lab;
 		ocfs2_chain_list  i_chain;
 		ocfs2_extent_list i_list;
+		__u8              i_symlink;
 	} id2;
 /* Actual on-disk size is one block */
 } ocfs2_dinode;
@@ -423,6 +424,12 @@
 } ocfs2_group_desc;
 
 #ifdef __KERNEL__
+static inline int ocfs2_fast_symlink_chars(struct super_block *sb)
+{
+	return  sb->s_blocksize -
+		 offsetof(struct _ocfs2_dinode, id2.i_symlink);
+}
+
 static inline int ocfs2_extent_recs_per_inode(struct super_block *sb)
 {
 	int size;
@@ -473,6 +480,11 @@
 	return size;
 }
 #else
+static inline int ocfs2_fast_symlink_chars(int blocksize)
+{
+	return blocksize - offsetof(struct _ocfs2_dinode, id2.i_symlink);
+}
+
 static inline int ocfs2_extent_recs_per_inode(int blocksize)
 {
 	int size;

Modified: trunk/src/symlink.c
===================================================================
--- trunk/src/symlink.c	2004-12-29 01:13:56 UTC (rev 1725)
+++ trunk/src/symlink.c	2004-12-30 02:33:50 UTC (rev 1726)
@@ -42,12 +42,16 @@
 
 #include "ocfs_log.h"
 #include "ocfs.h"
+#include "ocfs2.h"
 
 #include "alloc.h"
 #include "file.h"
 #include "inode.h"
 #include "symlink.h"
 
+#include "ocfs_journal.h"
+#include "buffer_head_io.h"
+
 #define OCFS_DEBUG_CONTEXT    OCFS_DEBUG_CONTEXT_SYMLINK
 
 struct ocfs_symlink_ops {
@@ -58,6 +62,11 @@
 
 static unsigned int ocfs_link_size(struct ocfs_symlink_ops *ops, char *str, struct inode *inode);
 static void ocfs_link_expand(struct ocfs_symlink_ops *ops, char *out, char *in, struct inode *inode);
+static char *ocfs2_fast_symlink_getlink(struct inode *inode,
+					struct buffer_head **bh);
+static int ocfs2_readlink(struct dentry *dentry,
+			  char *buffer,
+			  int buflen);
 
 /* Context Dependent Symbolic Link (CDSL) code  */
 
@@ -180,17 +189,54 @@
 	return (char*)page;
 }
 
+static char *ocfs2_fast_symlink_getlink(struct inode *inode,
+					struct buffer_head **bh)
+{
+	int status;
+	char *link = NULL;
+	ocfs2_dinode *fe;
 
+	LOG_ENTRY();
+
+	status = ocfs_read_block(OCFS2_SB(inode->i_sb),
+				 OCFS_I(inode)->ip_blkno,
+				 bh,
+				 OCFS_BH_CACHED,
+				 inode);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		link = ERR_PTR(status);
+		goto bail;
+	}
+
+	fe = (ocfs2_dinode *) (*bh)->b_data;
+	link = (char *) &fe->id2.i_symlink;
+bail:
+	LOG_EXIT_STATUS(status);
+
+	return link;
+}
+
 static int ocfs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode *inode = dentry->d_inode;
 	struct page *page = NULL;
+	struct buffer_head *bh = NULL;
 	char *orig_link, *new_link;
 	unsigned int len, res = 0;
 
 	LOG_SET_CONTEXT(FOLLOW_LINK);
 
-	orig_link = my_page_getlink(dentry, &page);
+	if (ocfs2_inode_is_fast_symlink(inode))
+		orig_link = ocfs2_fast_symlink_getlink(inode, &bh);
+	else
+		orig_link = my_page_getlink(dentry, &page);
+
+	if (IS_ERR(orig_link)) {
+		res = PTR_ERR(orig_link);
+		goto out;
+	}
+
 	len = ocfs_link_size(symlink_ops, orig_link, inode);
 	new_link = kmalloc(len, GFP_KERNEL); 
 	if (new_link == NULL) {
@@ -204,6 +250,8 @@
 		kunmap(page);
 		page_cache_release(page);
 	}
+	if (bh)
+		brelse(bh);
 
 	LOG_CLEAR_CONTEXT();
 	return res;
@@ -274,16 +322,51 @@
 	return len + 1;
 }
 
+static int ocfs2_readlink(struct dentry *dentry,
+			  char *buffer,
+			  int buflen)
+{
+	int ret;
+	char *link;
+	struct buffer_head *bh = NULL;
+	struct inode *inode = dentry->d_inode;
+
+	LOG_ENTRY();
+
+	link = ocfs2_fast_symlink_getlink(inode, &bh);
+	if (IS_ERR(link)) {
+		ret = PTR_ERR(link);
+		goto out;
+	}
+
+	ret = vfs_readlink(dentry, buffer, buflen, link);
+
+	brelse(bh);
+out:
+	LOG_EXIT_STATUS(ret);
+	return ret;
+}
+
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
 struct inode_operations ocfs_symlink_inode_operations = {
 	.readlink	= page_readlink,
 	.follow_link	= ocfs_follow_link,
 	.getattr	= ocfs_getattr,
 };
+struct inode_operations ocfs_fast_symlink_inode_operations = {
+	.readlink	= page_readlink,
+	.follow_link	= ocfs_follow_link,
+	.getattr	= ocfs_getattr,
+};
 #else
 struct inode_operations ocfs_symlink_inode_operations = {
 	.readlink	= page_readlink,
 	.follow_link	= ocfs_follow_link,
 	.revalidate	= ocfs_inode_revalidate,
 };
+struct inode_operations ocfs_fast_symlink_inode_operations = {
+	.readlink	= ocfs2_readlink,
+	.follow_link	= ocfs_follow_link,
+	.revalidate	= ocfs_inode_revalidate,
+};
 #endif

Modified: trunk/src/symlink.h
===================================================================
--- trunk/src/symlink.h	2004-12-29 01:13:56 UTC (rev 1725)
+++ trunk/src/symlink.h	2004-12-30 02:33:50 UTC (rev 1726)
@@ -27,5 +27,16 @@
 #define OCFS2_SYMLINK_H
 
 extern struct inode_operations ocfs_symlink_inode_operations;
+extern struct inode_operations ocfs_fast_symlink_inode_operations;
 
+/*
+ * Test whether an inode is a fast symlink.
+ */
+static inline int ocfs2_inode_is_fast_symlink(struct inode *inode)
+{
+	return (S_ISLNK(inode->i_mode) &&
+		inode->i_blocks == 0);
+}
+
+
 #endif /* OCFS2_SYMLINK_H */



More information about the Ocfs2-commits mailing list