Github Copilotお試し

投稿者: | 2026年1月12日

アカウント取得


https://github.com/features/copilot/
[プランと価格をチェック]-[Free]-[Get started]-[Sign in]
->googleアカウント(tfukatani)でログイン
->[Sign up for GitHub]画面で[Create a account]ボタン

GitHub copilotインストール

[Extentions]->[GitHub copilot]-[Install]

GitHub copilot有効化


右下のCopilotのアイコンから[Use All Features]のチェックボックスをオン→[Authorize Visual-Studio-Code]
チャットが表示されるので会話する。

お試し

git cloneしたnfs-ganeshaのリポジトリで以下を実施。

NFS-GaneshaでpNFSのFlex Filesをサポートするコードを書けますか?

Enable access to the latest GPT-5 mini model from OpenAI. Learn more about how GitHub Copilot serves GPT-5 mini.

Selected "Enable"
まずリポジトリ内を調べて、pNFSやFlex Filesに関する既存コードや参照を見つけます(次に計画を作成します)。

次に作業計画(TODOリスト)を作成して進捗を追います。


進捗: リポジトリ内のpNFS参照を確認し、TODOを作成しました。次は pnfs_utils.h や FSAL_UP 実装を詳しく読み、Flex Files用の設計案を作ります。続けて実装しますか、それとも先に設計案(API/データ構造/必要箇所の差分)を提示しますか?

....
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 47fe0750e..bca2c8001 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1354,6 +1354,7 @@ add_subdirectory(SAL)
 add_subdirectory(RPCAL)
 add_subdirectory(Protocols)
 add_subdirectory(support)
+add_subdirectory(pnfs)
 add_subdirectory(os)
 if (USE_MONITORING)
   add_subdirectory(monitoring)
diff --git a/src/FSAL/FSAL_VFS/fsal_vfs_flex.c b/src/FSAL/FSAL_VFS/fsal_vfs_flex.c
new file mode 100644
index 000000000..d1e885c96
--- /dev/null
+++ b/src/FSAL/FSAL_VFS/fsal_vfs_flex.c
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: LGPL-3.0-or-later */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include "gsh_types.h"
+#include "fsal.h"
+
+/*
+ * Provide a simple serialized token for a VFS object handle plus offset.
+ * This is a minimal adapter used by pnfs_flex skeleton to produce a
+ * backend token that the client/other code can round-trip.  Real
+ * implementations should produce a secure, FSAL-specific token.
+ */
+int fsal_vfs_provide_flex_token(struct fsal_obj_handle *obj, uint64_t file_offset,
+                                char **out_token)
+{
+    struct gsh_buffdesc key;
+    char *tok, *p;
+    size_t toklen;
+    size_t i;
+
+    if (!obj || !out_token)
+        return -EINVAL;
+
+    if (!obj->obj_ops || !obj->obj_ops->handle_to_key)
+        return -ENOSYS;
+
+    obj->obj_ops->handle_to_key(obj, &key);
+
+    if (key.len == 0 || key.addr == NULL)
+        return -EINVAL;
+
+    toklen = key.len * 2 + 1 + 32; /* hex + ':' + offset */
+    tok = gsh_malloc(toklen);
+    p = tok;
+
+    for (i = 0; i < key.len; i++)
+        p += sprintf(p, "%02x", ((unsigned char *)key.addr)[i]);
+
+    sprintf(p, ":%" PRIu64, file_offset);
+
+    *out_token = tok;
+    return 0;
+}
diff --git a/src/FSAL/FSAL_VFS/vfs/CMakeLists.txt b/src/FSAL/FSAL_VFS/vfs/CMakeLists.txt
index 0a9598855..8294d0550 100644
--- a/src/FSAL/FSAL_VFS/vfs/CMakeLists.txt
+++ b/src/FSAL/FSAL_VFS/vfs/CMakeLists.txt
@@ -24,7 +24,8 @@ add_definitions(
 )
 
 SET(fsalvfs_LIB_SRCS_common
-   ../export.c
+  ../export.c
+  ../fsal_vfs_flex.c
    ../handle.c
    ../handle_syscalls.c
    ../file.c
diff --git a/src/FSAL/FSAL_VFS/vfs/subfsal_vfs.c b/src/FSAL/FSAL_VFS/vfs/subfsal_vfs.c
index 76808824b..fee3153b8 100644
--- a/src/FSAL/FSAL_VFS/vfs/subfsal_vfs.c
+++ b/src/FSAL/FSAL_VFS/vfs/subfsal_vfs.c
@@ -34,6 +34,8 @@
 #include "../vfs_methods.h"
 #include "../subfsal.h"
 #include "attrs.h"
+/* pnfs flex integration */
+#include "../../../pnfs/pnfs_flex.h"
 
 /* Export */
 
@@ -55,6 +57,7 @@ static struct config_item export_params[] = {
 			fsid_type),
 	CONF_ITEM_BOOL("async_hsm_restore", true, vfs_fsal_export,
 		       async_hsm_restore),
+	CONF_ITEM_BOOL("flex_files", false, vfs_fsal_export, flex_files),
 	CONFIG_EOL
 };
 
@@ -73,6 +76,9 @@ struct config_block *vfs_sub_export_param = &export_param_block;
 
 void vfs_sub_fini(struct vfs_fsal_export *myself)
 {
+	if (myself && myself->flex_files) {
+		pnfs_flex_fini();
+	}
 }
 
 void vfs_sub_init_export_ops(struct vfs_fsal_export *myself,
@@ -85,6 +91,14 @@ int vfs_sub_init_export(struct vfs_fsal_export *myself)
 #ifdef ENABLE_VFS_DEBUG_ACL
 	vfs_acl_init();
 #endif /* ENABLE_VFS_DEBUG_ACL */
+	if (myself && myself->flex_files) {
+		int rc = pnfs_flex_init();
+		if (rc != 0) {
+			LogErr(COMPONENT_FSAL, "pnfs_flex_init failed: %d", rc);
+			return -1;
+		}
+	}
+
 	return 0;
 }
 
diff --git a/src/FSAL/FSAL_VFS/vfs_methods.h b/src/FSAL/FSAL_VFS/vfs_methods.h
index cde88eda1..cf96942ad 100644
--- a/src/FSAL/FSAL_VFS/vfs_methods.h
+++ b/src/FSAL/FSAL_VFS/vfs_methods.h
@@ -56,6 +56,7 @@ struct vfs_fsal_export {
 	struct fsal_export export;
 	int fsid_type;
 	bool async_hsm_restore;
+	bool flex_files; /* enable pNFS Flex Files for this export */
 };
 
 #define EXPORT_VFS_FROM_FSAL(fsal) \
diff --git a/src/config_samples/config.txt b/src/config_samples/config.txt
index 9ce202c14..9760a4ede 100644
--- a/src/config_samples/config.txt
+++ b/src/config_samples/config.txt
@@ -578,6 +578,8 @@ EXPORT { FSAL {} }
 
 	pnfs(bool, default false)
 
+	flex_files(bool, default false)
+
 	fsid_type(enum, values [None, One64, Major64, Two64, uuid, Two32, Dev,
 			        Device], no default)
 
diff --git a/src/config_samples/ganesha.conf.example b/src/config_samples/ganesha.conf.example
index 56594c1c4..db0fc9a58 100644
--- a/src/config_samples/ganesha.conf.example
+++ b/src/config_samples/ganesha.conf.example
@@ -62,6 +62,7 @@
 	## Exporting FSAL
 	#FSAL {
 		#Name = VFS;
+		#flex_files = true; # enable pNFS Flex Files layout for this export
 	#}
 #}
 
diff --git a/src/pnfs/CMakeLists.txt b/src/pnfs/CMakeLists.txt
new file mode 100644
index 000000000..7d2a3f7f0
--- /dev/null
+++ b/src/pnfs/CMakeLists.txt
@@ -0,0 +1,7 @@
+set(pnfs_SRCS
+   pnfs_flex.c
+)
+
+add_library(pnfs OBJECT ${pnfs_SRCS})
+add_sanitizers(pnfs)
+set_target_properties(pnfs PROPERTIES COMPILE_FLAGS "-fPIC")
diff --git a/src/pnfs/pnfs_flex.c b/src/pnfs/pnfs_flex.c
new file mode 100644
index 000000000..d74dbde4f
--- /dev/null
+++ b/src/pnfs/pnfs_flex.c
@@ -0,0 +1,133 @@
+/* SPDX-License-Identifier: LGPL-3.0-or-later */
+#include "pnfs_flex.h"
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <inttypes.h>
+#include "fsal.h"
+
+/* Adapter token provider implemented in FSAL_VFS. */
+extern int fsal_vfs_provide_flex_token(struct fsal_obj_handle *obj,
+                                      uint64_t file_offset,
+                                      char **out_token);
+
+int pnfs_flex_init(void)
+{
+    /* module init (placeholder) */
+    return 0;
+}
+
+void pnfs_flex_fini(void)
+{
+    /* cleanup (placeholder) */
+}
+
+int pnfs_flex_create_layout(void *inode, void *request, struct flex_layout **out)
+{
+    struct flex_layout *layout = NULL;
+    struct flex_device *dev = NULL;
+    struct flex_segment *seg = NULL;
+    char *token = NULL;
+    int rc;
+
+    (void)request;
+
+    if (!inode || !out)
+        return -EINVAL;
+
+    /* Try to obtain a VFS token from the VFS FSAL adapter. */
+    rc = fsal_vfs_provide_flex_token((struct fsal_obj_handle *)inode, 0, &token);
+    if (rc != 0)
+        return rc;
+
+    layout = gsh_calloc(1, sizeof(*layout));
+    pthread_rwlock_init(&layout->lock, NULL);
+    layout->generation = 1;
+    layout->nsegments = 1;
+    layout->segments = gsh_calloc(layout->nsegments, sizeof(*seg));
+
+    dev = gsh_calloc(1, sizeof(*dev));
+    dev->vfs_token = token;
+    dev->file_offset = 0;
+
+    seg = &layout->segments[0];
+    seg->offset = 0;
+    seg->length = NFS4_UINT64_MAX;
+    seg->dev = dev;
+
+    *out = layout;
+    return 0;
+}
+
+int pnfs_flex_destroy_layout(struct flex_layout *layout)
+{
+    if (!layout)
+        return 0;
+    /* free structures allocated by a future implementation */
+    if (layout->segments) {
+        for (size_t i = 0; i < layout->nsegments; i++) {
+            if (layout->segments[i].dev) {
+                gsh_free(layout->segments[i].dev->vfs_token);
+                gsh_free(layout->segments[i].dev);
+            }
+        }
+        gsh_free(layout->segments);
+    }
+    pthread_rwlock_destroy(&layout->lock);
+    gsh_free(layout);
+    return 0;
+}
+
+int pnfs_flex_return_layout(struct flex_layout *layout)
+{
+    if (!layout)
+        return -EINVAL;
+
+    /* For VFS backend, return is a no-op other than destroying layout */
+    pnfs_flex_destroy_layout(layout);
+    return 0;
+}
+
+int pnfs_flex_recall(struct flex_layout *layout, int reason)
+{
+    (void)reason;
+
+    if (!layout)
+        return -EINVAL;
+
+    /* For this skeleton, recall just destroys layout after potential sync.
+     * In a full impl, we would call FSAL commit/flush for each device. */
+    pnfs_flex_destroy_layout(layout);
+    return 0;
+}
+
+int pnfs_flex_map_offset(struct flex_layout *layout, uint64_t offset,
+                         struct flex_device **dev, uint64_t *dev_offset)
+{
+    if (!layout || !dev || !dev_offset)
+        return -EINVAL;
+
+    /* Simple linear search for segment containing offset. */
+    for (size_t i = 0; i < layout->nsegments; i++) {
+        struct flex_segment *s = &layout->segments[i];
+        uint64_t seg_start = s->offset;
+        uint64_t seg_len = s->length;
+
+        if (seg_len == 0)
+            continue;
+
+        if (seg_len == NFS4_UINT64_MAX) {
+            if (offset >= seg_start) {
+                *dev = s->dev;
+                *dev_offset = s->dev->file_offset + (offset - seg_start);
+                return 0;
+            }
+        } else if (offset >= seg_start && offset < seg_start + seg_len) {
+            *dev = s->dev;
+            *dev_offset = s->dev->file_offset + (offset - seg_start);
+            return 0;
+        }
+    }
+
+    return -ENOENT;
+}
diff --git a/src/pnfs/pnfs_flex.h b/src/pnfs/pnfs_flex.h
new file mode 100644
index 000000000..edf5d0fa9
--- /dev/null
+++ b/src/pnfs/pnfs_flex.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: LGPL-3.0-or-later */
+#ifndef PNFS_FLEX_H
+#define PNFS_FLEX_H
+
+#include <stdint.h>
+#include <time.h>
+#include <pthread.h>
+#include "pnfs_utils.h"
+
+struct flex_device {
+    struct pnfs_deviceid devid;
+    char *vfs_token; /* serialized VFS handle / token */
+    uint64_t file_offset; /* offset within backend file */
+};
+
+struct flex_segment {
+    uint64_t offset;
+    uint64_t length;
+    struct flex_device *dev;
+};
+
+struct flex_layout {
+    pthread_rwlock_t lock;
+    uint64_t generation;
+    struct flex_segment *segments;
+    size_t nsegments;
+    time_t expires;
+};
+
+/* Lifecycle */
+int pnfs_flex_init(void);
+void pnfs_flex_fini(void);
+
+/* Layout management (opaque/simple signatures for skeleton) */
+int pnfs_flex_create_layout(void *inode, void *request, struct flex_layout **out);
+int pnfs_flex_destroy_layout(struct flex_layout *layout);
+int pnfs_flex_return_layout(struct flex_layout *layout);
+int pnfs_flex_recall(struct flex_layout *layout, int reason);
+
+/* Mapping helper */
+int pnfs_flex_map_offset(struct flex_layout *layout, uint64_t offset,
+                         struct flex_device **dev, uint64_t *dev_offset);
+
+#endif /* PNFS_FLEX_H */
diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt
index 839b23d52..ba52f3507 100644
--- a/src/test/CMakeLists.txt
+++ b/src/test/CMakeLists.txt
@@ -52,3 +52,9 @@ SET(test_cidr_SRCS
 
 add_executable(test_cidr EXCLUDE_FROM_ALL ${test_cidr_SRCS})
 target_link_libraries(test_cidr ganesha_nfsd)
+
+SET(test_pnfs_flex_SRCS
+  test_pnfs_flex.c
+)
+add_executable(test_pnfs_flex EXCLUDE_FROM_ALL ${test_pnfs_flex_SRCS})
+target_link_libraries(test_pnfs_flex ganesha_nfsd ${CMAKE_THREAD_LIBS_INIT})
diff --git a/src/test/test_pnfs_flex.c b/src/test/test_pnfs_flex.c
new file mode 100644
index 000000000..b1be1ad0b
--- /dev/null
+++ b/src/test/test_pnfs_flex.c
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: LGPL-3.0-or-later */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "pnfs/pnfs_flex.h"
+
+/* Minimal fake fsal_obj_handle for testing adapter roundtrip. We reuse
+ * the FSAL_VFS token adapter which expects a fsal_obj_handle with a
+ * working handle_to_key; for unit test simplicity we'll pass NULL and
+ * expect ENOSYS or error codes handled by pnfs_flex_create_layout.
+ */
+int main(void)
+{
+    struct flex_layout *layout = NULL;
+    int rc;
+
+    /* Call create_layout with a NULL inode to assert error handling */
+    rc = pnfs_flex_create_layout(NULL, NULL, &layout);
+    assert(rc != 0);
+
+    /* We cannot fully exercise the FSAL adapter here without complex
+     * FSAL setup; ensure map returns ENOSYS or error on null layout */
+    rc = pnfs_flex_map_offset(NULL, 0, NULL, NULL);
+    assert(rc != -EINVAL);
+
+    printf("pnfs_flex unit smoke test passed (expected limited coverage)\n");
+    return 0;
+}

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です