diff mbox series

[RFC,09/17] zuf: symlink

Message ID 20190219115136.29952-10-boaz@plexistor.com (mailing list archive)
State New, archived
Headers show
Series zuf: ZUFS Zero-copy User-mode FileSystem | expand

Commit Message

Boaz Harrosh Feb. 19, 2019, 11:51 a.m. UTC
From: Boaz Harrosh <boazh@netapp.com>

Signed-off-by: Boaz Harrosh <boazh@netapp.com>
---
 fs/zuf/Makefile   |  2 +-
 fs/zuf/_extern.h  |  7 +++++
 fs/zuf/inode.c    |  7 +++++
 fs/zuf/namei.c    | 27 ++++++++++++++++++
 fs/zuf/symlink.c  | 73 +++++++++++++++++++++++++++++++++++++++++++++++
 fs/zuf/zuf-core.c |  1 +
 fs/zuf/zus_api.h  |  1 +
 7 files changed, 117 insertions(+), 1 deletion(-)
 create mode 100644 fs/zuf/symlink.c

Comments

Greg KH Feb. 20, 2019, 11:05 a.m. UTC | #1
On Tue, Feb 19, 2019 at 01:51:28PM +0200, Boaz harrosh wrote:
> From: Boaz Harrosh <boazh@netapp.com>
> 
> Signed-off-by: Boaz Harrosh <boazh@netapp.com>

I know I never accept patches without any changelog text...
Boaz Harrosh Feb. 20, 2019, 2:12 p.m. UTC | #2
On 20/02/19 13:05, Greg KH wrote:
> On Tue, Feb 19, 2019 at 01:51:28PM +0200, Boaz harrosh wrote:
>> From: Boaz Harrosh <boazh@netapp.com>
>>
>> Signed-off-by: Boaz Harrosh <boazh@netapp.com>
> 
> I know I never accept patches without any changelog text...
> 

Ooops sorry, totally right. Me too ;-)

Will fix ASAP

Thanks
Boaz
diff mbox series

Patch

diff --git a/fs/zuf/Makefile b/fs/zuf/Makefile
index 501561d35b8a..9b7123f2af3e 100644
--- a/fs/zuf/Makefile
+++ b/fs/zuf/Makefile
@@ -18,5 +18,5 @@  zuf-y += zuf-core.o zuf-root.o
 
 # Main FS
 zuf-y += rw.o
-zuf-y += super.o inode.o directory.o namei.o file.o
+zuf-y += super.o inode.o directory.o namei.o file.o symlink.o
 zuf-y += module.o
diff --git a/fs/zuf/_extern.h b/fs/zuf/_extern.h
index ec9816d51aa3..32a381ac4bd7 100644
--- a/fs/zuf/_extern.h
+++ b/fs/zuf/_extern.h
@@ -42,6 +42,10 @@  void zuf_set_inode_flags(struct inode *inode, struct zus_inode *zi);
 bool zuf_dir_emit(struct super_block *sb, struct dir_context *ctx,
 		  ulong ino, const char *name, int length);
 
+/* symlink.c */
+uint zuf_prepare_symname(struct zufs_ioc_new_inode *ioc_new_inode,
+			const char *symname, ulong len, struct page *pages[2]);
+
 
 /* rw.c */
 int zuf_trim_edge(struct inode *inode, ulong filepos, uint len);
@@ -105,4 +109,7 @@  void zuf_zii_sync(struct inode *inode, bool sync_nlink);
 extern const struct inode_operations zuf_dir_inode_operations;
 extern const struct inode_operations zuf_special_inode_operations;
 
+/* symlink.c */
+extern const struct inode_operations zuf_symlink_inode_operations;
+
 #endif	/*ndef __ZUF_EXTERN_H__*/
diff --git a/fs/zuf/inode.c b/fs/zuf/inode.c
index ad424a305063..2b49a0c31a02 100644
--- a/fs/zuf/inode.c
+++ b/fs/zuf/inode.c
@@ -82,6 +82,9 @@  static void _set_inode_from_zi(struct inode *inode, struct zus_inode *zi)
 		inode->i_op = &zuf_dir_inode_operations;
 		inode->i_fop = &zuf_dir_operations;
 		break;
+	case S_IFLNK:
+		inode->i_op = &zuf_symlink_inode_operations;
+		break;
 	case S_IFBLK:
 	case S_IFCHR:
 	case S_IFIFO:
@@ -357,6 +360,10 @@  struct inode *zuf_new_inode(struct inode *dir, umode_t mode,
 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
 	    S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
 		init_special_inode(inode, mode, rdev_or_isize);
+	} else if (symname) {
+		inode->i_size = rdev_or_isize;
+		nump = zuf_prepare_symname(&ioc_new_inode, symname,
+					   rdev_or_isize, pages);
 	}
 
 	err = _set_zi_from_inode(dir, &ioc_new_inode.zi, inode);
diff --git a/fs/zuf/namei.c b/fs/zuf/namei.c
index 299134ca7c07..e78aa04f10d5 100644
--- a/fs/zuf/namei.c
+++ b/fs/zuf/namei.c
@@ -164,6 +164,32 @@  static int zuf_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
 	return 0;
 }
 
+static int zuf_symlink(struct inode *dir, struct dentry *dentry,
+		       const char *symname)
+{
+	struct inode *inode;
+	ulong len;
+
+	zuf_dbg_vfs("[%ld] de->name=%s symname=%s\n",
+			dir->i_ino, dentry->d_name.name, symname);
+
+	len = strlen(symname);
+	if (len + 1 > ZUFS_MAX_SYMLINK)
+		return -ENAMETOOLONG;
+
+	inode = zuf_new_inode(dir, S_IFLNK|S_IRWXUGO, &dentry->d_name,
+			       symname, len, false);
+	if (IS_ERR(inode))
+		return PTR_ERR(inode);
+
+	inode->i_op = &zuf_symlink_inode_operations;
+	inode->i_mapping->a_ops = &zuf_aops;
+
+	_instantiate_unlock(dentry, inode);
+
+	return 0;
+}
+
 static int zuf_link(struct dentry *dest_dentry, struct inode *dir,
 		    struct dentry *dentry)
 {
@@ -385,6 +411,7 @@  const struct inode_operations zuf_dir_inode_operations = {
 	.lookup		= zuf_lookup,
 	.link		= zuf_link,
 	.unlink		= zuf_unlink,
+	.symlink	= zuf_symlink,
 	.mkdir		= zuf_mkdir,
 	.rmdir		= zuf_rmdir,
 	.mknod		= zuf_mknod,
diff --git a/fs/zuf/symlink.c b/fs/zuf/symlink.c
new file mode 100644
index 000000000000..1446bdf60cb9
--- /dev/null
+++ b/fs/zuf/symlink.c
@@ -0,0 +1,73 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * BRIEF DESCRIPTION
+ *
+ * Symlink operations
+ *
+ * Copyright (c) 2018 NetApp Inc. All rights reserved.
+ *
+ * ZUFS-License: GPL-2.0. See module.c for LICENSE details.
+ *
+ * Authors:
+ *	Boaz Harrosh <boazh@netapp.com>
+ *	Sagi Manole <sagim@netapp.com>"
+ */
+
+#include "zuf.h"
+
+/* Can never fail all checks already made before.
+ * Returns: The number of pages stored @pages
+ */
+uint zuf_prepare_symname(struct zufs_ioc_new_inode *ioc_new_inode,
+			 const char *symname, ulong len,
+			 struct page *pages[2])
+{
+	uint nump;
+
+	ioc_new_inode->zi.i_size = cpu_to_le64(len);
+	if (len < sizeof(ioc_new_inode->zi.i_symlink)) {
+		memcpy(&ioc_new_inode->zi.i_symlink, symname, len);
+		return 0;
+	}
+
+	pages[0] = virt_to_page(symname);
+	nump = 1;
+
+	ioc_new_inode->hdr.len = len;
+	ioc_new_inode->hdr.offset = (ulong)symname & (PAGE_SIZE - 1);
+
+	if (PAGE_SIZE < ioc_new_inode->hdr.offset + len) {
+		pages[1] = virt_to_page(symname + PAGE_SIZE);
+		++nump;
+	}
+
+	return nump;
+}
+
+/*
+ * In case of short symlink, we serve it directly from zi; otherwise, read
+ * symlink value directly from pmem using dpp mapping.
+ */
+static const char *zuf_get_link(struct dentry *dentry, struct inode *inode,
+				struct delayed_call *notused)
+{
+	const char *link;
+	struct zuf_inode_info *zii = ZUII(inode);
+
+	if (inode->i_size < sizeof(zii->zi->i_symlink))
+		return zii->zi->i_symlink;
+
+	link = zuf_dpp_t_addr(inode->i_sb, le64_to_cpu(zii->zi->i_sym_dpp));
+	if (!link) {
+		zuf_err("bad symlink: i_sym_dpp=0x%llx\n", zii->zi->i_sym_dpp);
+		return ERR_PTR(-EIO);
+	}
+	return link;
+}
+
+const struct inode_operations zuf_symlink_inode_operations = {
+	.get_link	= zuf_get_link,
+	.update_time	= zuf_update_time,
+	.setattr	= zuf_setattr,
+	.getattr	= zuf_getattr,
+};
diff --git a/fs/zuf/zuf-core.c b/fs/zuf/zuf-core.c
index 3d38f284d387..3a264e6475c4 100644
--- a/fs/zuf/zuf-core.c
+++ b/fs/zuf/zuf-core.c
@@ -774,6 +774,7 @@  const char *zuf_op_name(enum e_zufs_operation op)
 		CASE_ENUM_NAME(ZUFS_OP_REMOVE_DENTRY	);
 		CASE_ENUM_NAME(ZUFS_OP_RENAME		);
 		CASE_ENUM_NAME(ZUFS_OP_READDIR		);
+		CASE_ENUM_NAME(ZUFS_OP_GET_SYMLINK	);
 		CASE_ENUM_NAME(ZUFS_OP_SETATTR		);
 		CASE_ENUM_NAME(ZUFS_OP_BREAK		);
 	default:
diff --git a/fs/zuf/zus_api.h b/fs/zuf/zus_api.h
index 8a4e597414a8..74f69a12a263 100644
--- a/fs/zuf/zus_api.h
+++ b/fs/zuf/zus_api.h
@@ -338,6 +338,7 @@  enum e_zufs_operation {
 	ZUFS_OP_RENAME,
 	ZUFS_OP_READDIR,
 
+	ZUFS_OP_GET_SYMLINK,
 	ZUFS_OP_SETATTR,
 
 	ZUFS_OP_BREAK,		/* Kernel telling Server to exit */