--- /dev/null
+.TH lctl-pcc-abort 8 2024-01-15 "Lustre" "configuration Utilities"
+.SH NAME
+lctl pcc abort commands used to abort in-progress attaches on a given PCC backend on a client.
+.SH SYNOPSIS
+.B lctl pcc abort [\fB--wait\fR|\fB-w\fR] [\fB--detach\fR|\fB-d\fR] \fIMNTPATH\fR [\fIPCCPATH\fR]
+.SH DESCRIPTION
+.TP
+.B lctl pcc abort [\fB--wait\fR|\fB-w\fR] [\fB--detach\fR|\fB-d\fR] \fIMNTPATH\fR [\fIPCCPATH\fR]
+Abort in-progress attaches on a given PCC backend specified by path
+.IR PCCPATH
+on a Lustre client referenced by the mount point of
+.IR MNTPATH .
+If
+.IR PCCPATH
+is not specified, it will abort in-progress attaches on all PCC backends on this
+client.
+.SH OPTIONS
+.TP
+.B --wait | -w
+The caller must wait all in-progress attaches finished when remove a PCC
+backend from a client.
+.TP
+.B --detach | -d
+This option is used by PCC abort command. It indicates that it also needs to
+detach PCC copies when abort in-progress attaches on a given PCC backend.
+.TP
+.SH SEE ALSO
+.BR lctl-pcc (8),
+.BR lfs (1),
+.BR lfs-hsm (1),
+.BR lfs-pcc (1)
.B lctl pcc clear [\fB--keep\fR|\fB-k\fR] [\fB--wait\fR|\fB-w\fR] [\fB--abort\fR|\fB-a\fR] <\fImntpath\fR>
.br
.B lctl pcc list <\fImntpath\fR>
-.SH DESCRIPTION
.TP
.B lctl pcc add \fR<\fImntpath\fR> <\fIpccpath\fR> [\fB--param\fR|\fB-p\fR <\fIparam\fR>]
Add a PCC backend specified by HSM root path
.B --wait | -w
The caller must wait all in-progress attaches finished when remove a PCC
backend from a client.
+.TP
.B --abort | -a
The caller tries to abort all in-progress attaches when remove a PCC backend
from a client.
.TP
+.B --detach | -d
+This option is using by PCC abort command. It indicates that it also needs to
+detach PCC copies when abort in-progress attaches on a given PCC backend.
+.TP
.SH SEE ALSO
.BR lfs (1),
.BR lfs-hsm (1),
.IR flags
currently has three flag values
.B PCC_CLEANUP_FL_KEEP_DATA,
-.B PCC_CLEANUP_FL_WAIT
+.B PCC_CLEANUP_FL_WAIT,
+.B PCC_CLEANUP_FL_ABORT,
+.B PCC_CLEANUP_FL_NOT_DEL,
and
-.B PCC_CLEANUP_FL_ABORT.
+.B PCC_CLEANUP_FL_NOT_DETACH.
.B PCC_CLEANUP_FL_KEEP_DATA
means it removes the PCC backend from the Lustre client, but retains
the PCC backend from the client.
.B PCC_CLEANUP_FL_ABORT
means the caller tries to abort all in-progress attaches on the PCC backend.
+.B PCC_CLEANUP_FL_NOT_DEL
+means that it does not remove the PCC backend from a client. i.e. just abort
+in-progress attaches for a given PCC backend.
+.B PCC_CLEANUP_FL_NOT_DETACH
+means that it does not detach PCC copies from the PCC backend during abort.
+
.SH RETURN VALUES
.PP
.B llapi_pcc_del()
.nf
.LP
PCC_DETACH_FL_NONE = 0x0,
- PCC_DETACH_FL_UNCACHE = 0x01,
- PCC_DETACH_FL_KNOWN_READWRITE = 0x02,
- PCC_DETACH_FL_KNOWN_READONLY = 0x04,
- PCC_DETACH_FL_CACHE_REMOVED = 0x08,
- PCC_DETACH_FL_ATTACHING = 0x10,
- PCC_DETACH_FL_ATTACHING_WAIT = 0x20,
- PCC_DETACH_FL_ATTACH_ABORT = 0x40,
+ PCC_DETACH_FL_UNCACHE = 0x0001,
+ PCC_DETACH_FL_KNOWN_READWRITE = 0x0002,
+ PCC_DETACH_FL_KNOWN_READONLY = 0x0004,
+ PCC_DETACH_FL_CACHE_REMOVED = 0x0008,
+ PCC_DETACH_FL_ATTACHING = 0x0010,
+ PCC_DETACH_FL_ATTACHING_WAIT = 0x0020,
+ PCC_DETACH_FL_ATTACH_ABORT = 0x0040,
+ PCC_DETACH_FL_KEEP_DATA = 0x0080,
+ PCC_DETACH_FL_NOT_DETACH = 0x0100,
.fi
.TP
PCC_DETACH_FL_NONE
.TP
PCC_DETACH_FL_ATTACH_ABORT
indicates to abort the in-progress attach during detach.
+.TP
+PCC_DETACH_FL_KEEP_DATA
+indicates to keep the valid cached PCC copies on the PCC backend.
+.TP
+PCC_DETACH_FL_NOT_DETACH
+indicates not to detach PCC copies from the PCC backend.
+
.SH RETURN VALUES
.LP
.BR llapi_pcc_detach_fid_fd() ,
/* Detach only, keep the PCC copy */
PCC_DETACH_FL_NONE = 0x0,
/* Remove the cached file after detach */
- PCC_DETACH_FL_UNCACHE = 0x01,
+ PCC_DETACH_FL_UNCACHE = 0x0001,
/* Known the file was once used as PCC-RW */
- PCC_DETACH_FL_KNOWN_READWRITE = 0x02,
+ PCC_DETACH_FL_KNOWN_READWRITE = 0x0002,
/* Known the file was once used as PCC-RO */
- PCC_DETACH_FL_KNOWN_READONLY = 0x04,
+ PCC_DETACH_FL_KNOWN_READONLY = 0x0004,
/* Indicate PCC cached copy is removed */
- PCC_DETACH_FL_CACHE_REMOVED = 0x08,
+ PCC_DETACH_FL_CACHE_REMOVED = 0x0008,
/* Indicate the file is being attached */
- PCC_DETACH_FL_ATTACHING = 0x10,
+ PCC_DETACH_FL_ATTACHING = 0x0010,
/* Indicate to wait the attach process finished */
- PCC_DETACH_FL_ATTACHING_WAIT = 0x20,
+ PCC_DETACH_FL_ATTACHING_WAIT = 0x0020,
/* Indicate to abort the in-progress attach during detach */
- PCC_DETACH_FL_ATTACH_ABORT = 0x40,
+ PCC_DETACH_FL_ATTACH_ABORT = 0x0040,
+ /* Keep the valid cached PCC copies. */
+ PCC_DETACH_FL_KEEP_DATA = 0x0080,
+ /* Not detach PCC copies from PCC backend */
+ PCC_DETACH_FL_NOT_DETACH = 0x0100,
};
struct lu_pcc_detach_fid {
enum lu_pcc_cleanup_flags {
PCC_CLEANUP_FL_NONE = 0x0,
/* Remove the PCC backend but retain the data on the cache */
- PCC_CLEANUP_FL_KEEP_DATA = 0x1,
+ PCC_CLEANUP_FL_KEEP_DATA = 0x01,
/* Wait in-progress attaches finished when remove the PCC backend */
- PCC_CLEANUP_FL_WAIT = 0x2,
+ PCC_CLEANUP_FL_WAIT = 0x02,
/* Abort in-progress attaches when remove the PCC backend */
- PCC_CLEANUP_FL_ABORT = 0x4,
+ PCC_CLEANUP_FL_ABORT = 0x04,
+ /* Not remove the PCC backend, i.e. only abort in-progress attaches */
+ PCC_CLEANUP_FL_NOT_DEL = 0x08,
+ /* Not detach PCC copies */
+ PCC_CLEANUP_FL_NOT_DETACH = 0x10,
};
enum lu_project_type {
GOTO(out_unlock, rc = 0);
}
- if (!pcci || !pcc_inode_has_layout(pcci))
+ if (!pcci || !pcc_inode_has_layout(pcci) ||
+ *flags & PCC_DETACH_FL_NOT_DETACH)
GOTO(out_unlock, rc = 0);
LASSERT(atomic_read(&pcci->pcci_refcount) > 0);
}
run_test 108b "Test for in-progress attach abort (DIO)"
+test_109() {
+ local loopfile="$TMP/$tfile"
+ local mntpt="/mnt/pcc.$tdir"
+ local hsm_root="$mntpt/$tdir"
+ local file1=$DIR/$tfile.1
+ local file2=$DIR/$tfile.2
+ local cnt=10
+
+ $LCTL get_param -n mdc.*.connect_flags | grep -q pcc_ro ||
+ skip "Server does not support PCC-RO"
+
+ setup_loopdev client $loopfile $mntpt 600
+ mkdir -p $hsm_root || error "mkdir $hsm_root failed"
+ setup_pcc_mapping client \
+ "projid={100}\ roid=$HSM_ARCHIVE_NUMBER\ pccro=1"
+
+ local dio_attach_iosize
+
+ # disable attach via direct I/O (DIO)
+ dio_attach_iosize=$($LCTL get_param -n llite.*.pcc_dio_attach_iosize_mb | head -n 1)
+ stack_trap "$LCTL set_param llite.*.pcc_dio_attach_iosize_mb=$dio_attach_iosize"
+ $LCTL set_param llite.*.pcc_dio_attach_iosize_mb=0
+
+ stack_trap "rm -f $file1 $file2"
+ echo "small_file_data" > $file1 || error "failed to write $file1"
+ dd if=/dev/zero of=$file2 bs=1M count=$cnt ||
+ error "failed to write $file2"
+
+ $LFS pcc attach $file1 || error "failed to attach $file1"
+ #define OBD_FAIL_LLITE_PCC_COPYDATA_PAUSE 0x141a
+ $LCTL set_param fail_loc=0x8000141a fail_val=5
+ $LFS pcc attach $file2 &
+ sleep 2
+ $LCTL pcc abort -v --wait $MOUNT $hsm_root
+ check_lpcc_state $file1 "readonly" client
+ check_lpcc_state $file2 "none" client
+ $LCTL pcc abort --detach $MOUNT $hsm_root
+ check_lpcc_state $file1 "none" client
+ $LFS pcc state $file1 | grep -q 'flags: valid' ||
+ error "$file1 should be valid cached on PCC"
+ check_lpcc_state $file2 "none" client
+
+ $LFS pcc attach $file1 || error "failed to attach $file1"
+ #define OBD_FAIL_LLITE_PCC_COPYDATA_PAUSE 0x141a
+ $LCTL set_param fail_loc=0x8000141a fail_val=5
+ $LFS pcc attach $file2 &
+ sleep 2
+ $LCTL pcc abort -v --wait --detach $MOUNT $hsm_root
+ check_lpcc_state $file1 "none" client
+ $LFS pcc state $file1 | grep -q 'flags: valid' ||
+ error "$file1 should be valid cached on PCC"
+ check_lpcc_state $file2 "none" client
+
+ $LFS pcc attach $file1 || error "failed to attach $file1"
+ #define OBD_FAIL_LLITE_PCC_COPYDATA_PAUSE 0x141a
+ $LCTL set_param fail_loc=0x8000141a fail_val=5
+ $LFS pcc attach $file2 &
+ sleep 2
+ $LCTL pcc abort -v --wait $MOUNT
+ check_lpcc_state $file1 "readonly" client
+ check_lpcc_state $file2 "none" client
+ $LCTL pcc abort --detach $MOUNT
+ check_lpcc_state $file1 "none" client
+ $LFS pcc state $file1 | grep -q 'flags: valid' ||
+ error "$file1 should be valid cached on PCC"
+
+ $LFS pcc attach $file1 || error "failed to attach $file1"
+ #define OBD_FAIL_LLITE_PCC_COPYDATA_PAUSE 0x141a
+ $LCTL set_param fail_loc=0x8000141a fail_val=5
+ $LFS pcc attach $file2 &
+ sleep 2
+ $LCTL pcc abort -v --wait --detach $MOUNT
+ check_lpcc_state $file1 "none" client
+ $LFS pcc state $file1 | grep -q 'flags: valid' ||
+ error "$file1 should be valid cached on PCC"
+ check_lpcc_state $file2 "none" client
+
+ $LFS pcc attach $file1 || error "failed to attach $file1"
+ #define OBD_FAIL_LLITE_PCC_COPYDATA_PAUSE 0x141a
+ $LCTL set_param fail_loc=0x8000141a fail_val=5
+ $LFS pcc attach $file2 &
+ sleep 2
+ $LCTL pcc clear -v -k --abort --wait $MOUNT
+ check_lpcc_state $file1 "none" client
+ check_lpcc_state $file2 "none" client
+}
+run_test 109 "Attach abort with data retain when clear a PCC backend"
+
wait_lpcc_purge_scan_end() {
local pidfile=$1
local statsfile=$2
{ .pc_name = "list", .pc_func = jt_pcc_list,
.pc_help = "List all PCC backends on a client.\n"
"usage: lctl pcc list <mntpath>\n" },
+ { .pc_name = "abort", .pc_func = jt_pcc_abort,
+ .pc_help = "Abort in-progress attaches for specified PCC backend.\n"
+ "usage: lclt pcc abort <mntpath> [pccpath]\n" },
{ .pc_name = "--list-commands", .pc_func = jt_pcc_list_commands,
.pc_help = "list commands supported by lctl pcc"},
{ .pc_name = "help", .pc_func = Parser_help, .pc_help = "help" },
int rc;
/* It is the saved lov file when archive on HSM backend. */
- detach.pccd_flags = hsc->hsc_flags | PCC_DETACH_FL_UNCACHE;
+ detach.pccd_flags = hsc->hsc_flags & PCC_DETACH_FL_KEEP_DATA ?
+ hsc->hsc_flags : (hsc->hsc_flags |
+ PCC_DETACH_FL_UNCACHE);
lov_file = endswith(fname, ".lov");
if (lov_file) {
size_t len;
llapi_printf(LLAPI_MSG_DEBUG,
"'%s' is being aborted, will remove it later\n",
fidname);
+ } else if (detach.pccd_flags & PCC_DETACH_FL_KEEP_DATA) {
+ llapi_printf(LLAPI_MSG_DEBUG, "'%s' is retained in PCC\n",
+ fidname);
} else {
snprintf(fullname, sizeof(fullname), "%s/%s", pname, fidname);
llapi_printf(LLAPI_MSG_DEBUG,
int rc;
- if ((flags & (PCC_CLEANUP_FL_WAIT | PCC_CLEANUP_FL_ABORT)) ==
- PCC_CLEANUP_FL_WAIT) {
- snprintf(cmd, sizeof(cmd), "%s %s",
- PCC_CMDNAME_DEL_WAIT, pccpath);
- hsc.hsc_flags = PCC_DETACH_FL_ATTACHING_WAIT;
- } else {
- snprintf(cmd, sizeof(cmd), "%s %s", PCC_CMDNAME_DEL, pccpath);
+ if (!(flags & PCC_CLEANUP_FL_NOT_DEL)) {
+ if ((flags & (PCC_CLEANUP_FL_WAIT | PCC_CLEANUP_FL_ABORT)) ==
+ PCC_CLEANUP_FL_WAIT) {
+ snprintf(cmd, sizeof(cmd), "%s %s",
+ PCC_CMDNAME_DEL_WAIT, pccpath);
+ hsc.hsc_flags = PCC_DETACH_FL_ATTACHING_WAIT;
+ } else {
+ snprintf(cmd, sizeof(cmd), "%s %s",
+ PCC_CMDNAME_DEL, pccpath);
+ }
+
+ rc = llapi_pccdev_set(mntpath, cmd);
+ if (rc < 0) {
+ llapi_error(LLAPI_MSG_ERROR, rc,
+ "failed to run '%s' on %s", cmd, mntpath);
+ return rc;
+ }
}
- rc = llapi_pccdev_set(mntpath, cmd);
- if (rc < 0) {
- llapi_error(LLAPI_MSG_ERROR, rc,
- "failed to run '%s' on %s", cmd, mntpath);
- return rc;
+ if (flags & PCC_CLEANUP_FL_KEEP_DATA) {
+ if (!(flags & PCC_CLEANUP_FL_ABORT))
+ return 0;
+
+ hsc.hsc_flags |= PCC_DETACH_FL_KEEP_DATA;
}
- if (flags & PCC_CLEANUP_FL_KEEP_DATA)
- return 0;
+ if (flags & PCC_CLEANUP_FL_NOT_DETACH)
+ hsc.hsc_flags |= PCC_DETACH_FL_NOT_DETACH;
hsc.hsc_mntfd = open(mntpath, O_RDONLY);
if (hsc.hsc_mntfd < 0) {
(PCC_CLEANUP_FL_WAIT | PCC_CLEANUP_FL_ABORT)) {
llapi_printf(LLAPI_MSG_DEBUG,
"Scan PCC to wait attaches finished\n");
- hsc.hsc_flags = PCC_DETACH_FL_ATTACHING_WAIT;
+ hsc.hsc_flags &= ~PCC_DETACH_FL_ATTACH_ABORT;
+ hsc.hsc_flags |= PCC_DETACH_FL_ATTACHING_WAIT;
rc = hsm_scan_process(&hsc);
}
}
return rc;
}
+
+int jt_pcc_abort(int argc, char **argv)
+{
+ static struct option long_opts[] = {
+ { .val = 'v', .name = "verbose", .has_arg = no_argument },
+ { .val = 'w', .name = "wait", .has_arg = no_argument },
+ { .val = 'd', .name = "detach", .has_arg = no_argument },
+ { .name = NULL } };
+ char fsname[MAX_OBD_NAME + 1];
+ const char *mntpath;
+ const char *pccpath = NULL;
+ __u32 flags = PCC_CLEANUP_FL_ABORT | PCC_CLEANUP_FL_KEEP_DATA |
+ PCC_CLEANUP_FL_NOT_DETACH | PCC_CLEANUP_FL_NOT_DEL;
+ int verbose = LLAPI_MSG_INFO;
+ int rc;
+ int c;
+
+ while ((c = getopt_long(argc, argv, "dvw", long_opts, NULL)) != -1) {
+ switch (c) {
+ case 'd':
+ flags &= ~PCC_CLEANUP_FL_NOT_DETACH;
+ break;
+ case 'w':
+ flags |= PCC_CLEANUP_FL_WAIT;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case '?':
+ return CMD_HELP;
+ default:
+ fprintf(stderr, "%s: option '%s' unrecognized\n",
+ argv[0], argv[optind - 1]);
+ return CMD_HELP;
+ }
+ }
+ if (optind + 1 == argc) {
+ mntpath = argv[optind];
+ } else if (optind + 2 == argc) {
+ mntpath = argv[optind++];
+ pccpath = argv[optind];
+ } else {
+ fprintf(stderr, "%s: must specify mount path and PCC path\n",
+ jt_cmdname(argv[0]));
+ return CMD_HELP;
+ }
+
+ rc = llapi_search_fsname(mntpath, fsname);
+ if (rc < 0) {
+ fprintf(stderr,
+ "%s: cannot find a Lustre filesystem mounted at '%s'\n",
+ jt_cmdname(argv[0]), mntpath);
+ return rc;
+ }
+
+ /* Set llapi message level */
+ llapi_msg_set_level(verbose);
+
+ if (pccpath)
+ rc = llapi_pcc_del(mntpath, pccpath, flags);
+ else
+ rc = llapi_pcc_clear(mntpath, flags);
+ if (rc < 0)
+ fprintf(stderr, "%s: failed to abort '%s' on '%s': %s\n",
+ jt_cmdname(argv[0]), pccpath ? : "all PCC backends",
+ mntpath, strerror(errno));
+
+ return rc;
+}
int jt_pcc_del(int argc, char **argv);
int jt_pcc_clear(int argc, char **argv);
int jt_pcc_list(int argc, char **argv);
+int jt_pcc_abort(int argc, char **argv);
#ifdef HAVE_SERVER_SUPPORT
/* lustre_lfsck.c */