Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ fi
dnl
dnl Check for FUSE, libuuid, and libxml2
dnl
PKG_CHECK_MODULES([FUSE_MODULE], [fuse >= 2.6.0])
PKG_CHECK_MODULES([FUSE_MODULE], [fuse3 >= 3.0.0])
PKG_CHECK_MODULES([LIBXML2_MODULE], [libxml-2.0 >= 2.6.16])

if test "x${host_mac}" = "xyes"
Expand Down
2 changes: 1 addition & 1 deletion src/libltfs/ltfs_fuse_version.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,6 @@
#ifndef __ltfs_fuse_version_h__
#define __ltfs_fuse_version_h__

#define FUSE_USE_VERSION 26
#define FUSE_USE_VERSION 30

#endif /* __ltfs_fuse_version_h__ */
3 changes: 2 additions & 1 deletion src/libltfs/xattr.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ extern "C" {
#include "libltfs/arch/freebsd/xattr.h"
#endif

#include "fuse.h"
#include "ltfs_fuse_version.h"
#include <fuse.h>
#include "ltfs.h"

#define LTFS_PRIVATE_PREFIX "ltfs."
Expand Down
23 changes: 15 additions & 8 deletions src/ltfs_fuse.c
Original file line number Diff line number Diff line change
Expand Up @@ -853,9 +853,9 @@ int _ltfs_fuse_filldir(void *buf, const char *name, void *priv)
return ret;
}

ret = filler(buf, new_name, NULL, 0);
ret = filler(buf, new_name, NULL, 0, 0);
#else
ret = filler(buf, name, NULL, 0);
ret = filler(buf, name, NULL, 0, 0);
#endif

free(new_name);
Expand All @@ -875,12 +875,12 @@ int ltfs_fuse_readdir(const char *path, void *buf, fuse_fill_dir_t filler,

ltfsmsg(LTFS_DEBUG, 14047D, _dentry_name(path, file->file_info));

if (filler(buf, ".", NULL, 0)) {
if (filler(buf, ".", NULL, 0, 0)) {
/* No buffer space */
ltfsmsg(LTFS_DEBUG, 14026D);
return -ENOBUFS;
}
if (filler(buf, "..", NULL, 0)) {
if (filler(buf, "..", NULL, 0, 0)) {
/* No buffer space */
ltfsmsg(LTFS_DEBUG, 14026D);
return -ENOBUFS;
Expand Down Expand Up @@ -1061,13 +1061,23 @@ int ltfs_fuse_removexattr(const char *path, const char *name)
* Mount the filesystem. This function assumes a volume has been
* allocated and ltfs_mount has been called; it just does some secondary setup.
*/
void * ltfs_fuse_mount(struct fuse_conn_info *conn)
void * ltfs_fuse_mount(struct fuse_conn_info *conn, struct fuse_config *config)
{
struct ltfs_fuse_data *priv = fuse_get_context()->private_data;
struct statvfs *stats = &priv->fs_stats;

ltfs_request_trace(FUSE_REQ_ENTER(REQ_MOUNT), 0, 0);

/* FUSE3: Disable async reads to prevent unnecessary tape repositioning.
* The -osync_read option was removed in FUSE3. Async read is now controlled
* via FUSE_CAP_ASYNC_READ in the init() callback (this function).
* See: https://github.com/libfuse/libfuse/blob/master/ChangeLog.rst
*/
if (conn->capable & FUSE_CAP_ASYNC_READ)
conn->want &= ~FUSE_CAP_ASYNC_READ;
config->use_ino = true;
config->hard_remove = true;

if (priv->pid_orig != getpid()) {
/*
* Reopen device when LTFS was forked in fuse_main().
Expand Down Expand Up @@ -1206,7 +1216,6 @@ struct fuse_operations ltfs_ops = {
.init = ltfs_fuse_mount,
.destroy = ltfs_fuse_umount,
.getattr = ltfs_fuse_getattr,
.fgetattr = ltfs_fuse_fgetattr,
.access = ltfs_fuse_access,
.statfs = ltfs_fuse_statfs,
.open = ltfs_fuse_open,
Expand All @@ -1218,7 +1227,6 @@ struct fuse_operations ltfs_ops = {
.chown = ltfs_fuse_chown,
.create = ltfs_fuse_create,
.truncate = ltfs_fuse_truncate,
.ftruncate = ltfs_fuse_ftruncate,
.unlink = ltfs_fuse_unlink,
.rename = ltfs_fuse_rename,
.mkdir = ltfs_fuse_mkdir,
Expand All @@ -1236,6 +1244,5 @@ struct fuse_operations ltfs_ops = {
.symlink = ltfs_fuse_symlink,
.readlink = ltfs_fuse_readlink,
#if FUSE_VERSION >= 28
.flag_nullpath_ok = 1,
#endif
};
55 changes: 29 additions & 26 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
#include <grp.h>

#include "ltfs_fuse.h"
#include <fuse3/fuse_lowlevel.h>
#include "libltfs/ltfs.h"
#include "ltfs_copyright.h"
#include "libltfs/pathname.h"
Expand Down Expand Up @@ -747,20 +748,17 @@ int main(int argc, char **argv)
}

/* Unlink objects from the file system instead of having them renamed to .fuse_hidden */
ret = fuse_opt_add_arg(&args, "-ohard_remove");
/* FUSE3: removed deprecated option: ret = fuse_opt_add_arg(&args, "-ohard_remove"); */
Comment thread
mhorimoto marked this conversation as resolved.
if (ret < 0) {
/* Could not enable FUSE option */
ltfsmsg(LTFS_ERR, 14001E, "hard_remove", ret);
/* FUSE3: removed deprecated option: ltfsmsg(LTFS_ERR, 14001E, "hard_remove", ret); */
return 1;
}

/* perform reads synchronously */
ret = fuse_opt_add_arg(&args, "-osync_read");
if (ret < 0) {
/* Could not enable FUSE option */
ltfsmsg(LTFS_ERR, 14001E, "sync_read", ret);
return 1;
}
/* FUSE3: The -osync_read option was removed in FUSE3.
* Async read is now disabled via FUSE_CAP_ASYNC_READ in the
* init() callback (see ltfs_fuse_mount() in ltfs_fuse.c).
*/

#ifdef __APPLE__
/* Change MacFUSE timeout from 60 secs to 3100 secs (41mins) */
Expand Down Expand Up @@ -788,11 +786,11 @@ int main(int argc, char **argv)
#endif

#if FUSE_VERSION >= 28
/* For FUSE 2.8 or higher, automatically enable big_writes */
ret = fuse_opt_add_arg(&args, "-obig_writes");
/* FUSE3: removed deprecated option: For FUSE 2.8 or higher, automatically enable big_writes */
/* FUSE3: removed deprecated option: ret = fuse_opt_add_arg(&args, "-obig_writes"); */
if (ret < 0) {
/* Could not enable FUSE option */
ltfsmsg(LTFS_ERR, 14001E, "big_writes", ret);
/* FUSE3: removed deprecated option: ltfsmsg(LTFS_ERR, 14001E, "big_writes", ret); */
return 1;
}
#endif
Expand Down Expand Up @@ -974,14 +972,15 @@ int single_drive_main(struct fuse_args *args, struct ltfs_fuse_data *priv)
/* If the local inode space is big enough, have FUSE pass through our UIDs as inode
* numbers instead of generating its own. */
if (sizeof(ino_t) >= 8) {
ret = fuse_opt_add_arg(args, "-ouse_ino");
if (ret < 0) {
/* Could not enable FUSE option */
ltfsmsg(LTFS_ERR, 14001E, "use_ino", ret);
return 1;
}
}

/* FUSE3: use_ino option removed in FUSE3 */
/* ret = fuse_opt_add_arg(args, "-ouse_ino"); */
if (ret < 0) {
/* Could not enable FUSE option */
/* FUSE3: removed deprecated option: ltfsmsg(LTFS_ERR, 14001E, "use_ino", ret); */
return 1;
}
}

/* Set file system name to "ltfs:devname" in case FUSE doesn't pick it up */
snprintf(fsname, sizeof(fsname), "-ofsname=ltfs:%s", priv->devname);
ret = fuse_opt_add_arg(args, fsname);
Expand Down Expand Up @@ -1223,12 +1222,16 @@ int single_drive_main(struct fuse_args *args, struct ltfs_fuse_data *priv)
for ( i=0; i<args->argc; i++) {
fuse_opt_add_arg(&tmpa, args->argv[i]);
}
ret = fuse_parse_cmdline( &tmpa, &mountpoint, NULL, NULL);
fuse_opt_free_args(&tmpa);
if (ret < 0 || mountpoint == NULL) {
ltfsmsg(LTFS_ERR, 14094E, ret);
ltfs_volume_free(&priv->data);
return 1;
{
struct fuse_cmdline_opts fuse_opts;
ret = fuse_parse_cmdline(&tmpa, &fuse_opts);
fuse_opt_free_args(&tmpa);
if (ret < 0 || fuse_opts.mountpoint == NULL) {
ltfsmsg(LTFS_ERR, 14094E, ret);
ltfs_volume_free(&priv->data);
return 1;
}
mountpoint = fuse_opts.mountpoint;
}
priv->data->mountpoint = mountpoint;
priv->data->mountpoint_len = strlen(mountpoint);
Expand Down
1 change: 1 addition & 0 deletions src/tape_drivers/hp_tape.c
Copy link
Copy Markdown
Member

@Piloalucard Piloalucard May 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @mhorimoto ! Thank you for opening this PR! Seems good so far, I will continue reviewing, but I think we may need to also add from LTO-5 to LTO-9, within the same format you used.
https://ltoworld.com/ I used this page as a source to see which LTO drives exists for Tandberg, renamed to Overland. One constraint is that we do not have Tandberg/Overland hardware to test them.
What do you think?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @Piloalucard san.
Thank you for your review!
I will research the Tandberg/Overland LTO-5 to LTO-9 drive entries using ltoworld.com and add them in the same format.
However, I only have a Tandberg LTO-6 drive, so I can only verify the LTO-6 entry with actual hardware. The other entries (LTO-5, LTO-7 to LTO-9) will be based on research only, without real device testing.
I'll update this PR once the investigation is complete.

Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ struct supported_device *hp_supported_drives[] = {
TAPEDRIVE( HP_VENDOR_ID, "Ultrium 7-SCSI", DRIVE_LTO7, "[Ultrium 7-SCSI]" ), /* HP Ultrium Gen 7 */
TAPEDRIVE( HPE_VENDOR_ID, "Ultrium 8-SCSI", DRIVE_LTO8, "[Ultrium 8-SCSI]" ), /* HPE Ultrium Gen 8 */
TAPEDRIVE( HPE_VENDOR_ID, "Ultrium 9-SCSI", DRIVE_LTO9, "[Ultrium 9-SCSI]" ), /* HPE Ultrium Gen 9 */
TAPEDRIVE( TANDBERG_VENDOR_ID, "LTO-6 HH ", DRIVE_LTO6_HH, "[LTO-6 HH]" ), /* TANDBERG LTO-6 HH */
/* End of supported_devices */
NULL
};
Expand Down
1 change: 1 addition & 0 deletions src/tape_drivers/hp_tape.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ extern "C" {

#define HP_VENDOR_ID "HP"
#define HPE_VENDOR_ID "HPE"
#define TANDBERG_VENDOR_ID "TANDBERG"

extern struct error_table hp_tape_errors[];

Expand Down
2 changes: 1 addition & 1 deletion src/tape_drivers/linux/sg/sg_tape.c
Original file line number Diff line number Diff line change
Expand Up @@ -3031,7 +3031,7 @@ int sg_remaining_capacity(void *device, struct tc_remaining_cap *cap)

memset(buffer, 0, LOGSENSEPAGE);

if (IS_LTO(priv->drive_type) && (DRIVE_GEN(priv->drive_type) == 0x05)) {
if (IS_LTO(priv->drive_type) && (DRIVE_GEN(priv->drive_type) == 0x05 || priv->vendor == VENDOR_TANDBERG)) {
/* Use LogPage 0x31 */
ret = sg_logsense(device, (uint8_t)LOG_TAPECAPACITY, (uint8_t)0, (void *)buffer, LOGSENSEPAGE);
if(ret < 0)
Expand Down
1 change: 1 addition & 0 deletions src/tape_drivers/tape_drivers.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ enum {
VENDOR_IBM,
VENDOR_HP,
VENDOR_QUANTUM,
VENDOR_TANDBERG,
};

enum {
Expand Down
11 changes: 11 additions & 0 deletions src/tape_drivers/vendor_compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,8 @@ int get_vendor_id(char* vendor)
return VENDOR_HP;
else if (!strncmp(vendor, HPE_VENDOR_ID, strlen(HPE_VENDOR_ID)))
return VENDOR_HP;
else if (!strncmp(vendor, TANDBERG_VENDOR_ID, strlen(TANDBERG_VENDOR_ID)))
return VENDOR_TANDBERG;
else if (!strncmp(vendor, QUANTUM_VENDOR_ID, strlen(QUANTUM_VENDOR_ID)))
return VENDOR_QUANTUM;
else
Expand All @@ -309,6 +311,9 @@ struct supported_device **get_supported_devs(int vendor)
case VENDOR_QUANTUM:
cur = quantum_supported_drives;
break;
case VENDOR_TANDBERG:
cur = hp_supported_drives;
break;
}

return cur;
Expand Down Expand Up @@ -412,6 +417,9 @@ void init_error_table(int vendor,
case VENDOR_QUANTUM:
*vendor_table = quantum_tape_errors;
break;
case VENDOR_TANDBERG:
*vendor_table = hp_tape_errors;
break;
}
}

Expand All @@ -429,6 +437,9 @@ int init_timeout(int vendor, struct timeout_tape **table, int type)
case VENDOR_QUANTUM:
ret = quantum_tape_init_timeout(table, type);
break;
case VENDOR_TANDBERG:
ret = hp_tape_init_timeout(table, type);
break;
}

return ret;
Expand Down