[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