Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 48bc06e7 authored by Al Viro's avatar Al Viro
Browse files

befs: split symlink iops in two - for short and long symlinks resp.



Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 87dc800b
Loading
Loading
Loading
Loading
+31 −30
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ static void befs_destroy_inode(struct inode *inode);
static int befs_init_inodecache(void);
static void befs_destroy_inodecache(void);
static void *befs_follow_link(struct dentry *, struct nameidata *);
static void befs_put_link(struct dentry *, struct nameidata *, void *);
static void *befs_fast_follow_link(struct dentry *, struct nameidata *);
static int befs_utf2nls(struct super_block *sb, const char *in, int in_len,
			char **out, int *out_len);
static int befs_nls2utf(struct super_block *sb, const char *in, int in_len,
@@ -79,10 +79,15 @@ static const struct address_space_operations befs_aops = {
	.bmap		= befs_bmap,
};

static const struct inode_operations befs_fast_symlink_inode_operations = {
	.readlink	= generic_readlink,
	.follow_link	= befs_fast_follow_link,
};

static const struct inode_operations befs_symlink_inode_operations = {
	.readlink	= generic_readlink,
	.follow_link	= befs_follow_link,
	.put_link	= befs_put_link,
	.put_link	= kfree_put_link,
};

/* 
@@ -411,7 +416,10 @@ static struct inode *befs_iget(struct super_block *sb, unsigned long ino)
		inode->i_op = &befs_dir_inode_operations;
		inode->i_fop = &befs_dir_operations;
	} else if (S_ISLNK(inode->i_mode)) {
		if (befs_ino->i_flags & BEFS_LONG_SYMLINK)
			inode->i_op = &befs_symlink_inode_operations;
		else
			inode->i_op = &befs_fast_symlink_inode_operations;
	} else {
		befs_error(sb, "Inode %lu is not a regular file, "
			   "directory or symlink. THAT IS WRONG! BeFS has no "
@@ -477,13 +485,11 @@ befs_destroy_inodecache(void)
static void *
befs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
	char *link;

	if (befs_ino->i_flags & BEFS_LONG_SYMLINK) {
	struct super_block *sb = dentry->d_sb;
	befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
	befs_data_stream *data = &befs_ino->i_data.ds;
	befs_off_t len = data->size;
	char *link;

	if (len == 0) {
		befs_error(sb, "Long symlink with illegal length");
@@ -502,22 +508,17 @@ befs_follow_link(struct dentry *dentry, struct nameidata *nd)
			link[len - 1] = '\0';
		}
	}
	} else {
		link = befs_ino->i_data.symlink;
	}

	nd_set_link(nd, link);
	return NULL;
}

static void befs_put_link(struct dentry *dentry, struct nameidata *nd, void *p)

static void *
befs_fast_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
	if (befs_ino->i_flags & BEFS_LONG_SYMLINK) {
		char *link = nd_get_link(nd);
		if (!IS_ERR(link))
			kfree(link);
	}
	nd_set_link(nd, befs_ino->i_data.symlink);
	return NULL;
}

/*