Revision eab5fd59

b/qapi-schema-guest.json
351 351
  'returns': 'int' }
352 352

  
353 353
##
354
# @guest-fstrim:
355
#
356
# Discard (or "trim") blocks which are not in use by the filesystem.
357
#
358
# @minimum:
359
#       Minimum contiguous free range to discard, in bytes. Free ranges
360
#       smaller than this may be ignored (this is a hint and the guest
361
#       may not respect it).  By increasing this value, the fstrim
362
#       operation will complete more quickly for filesystems with badly
363
#       fragmented free space, although not all blocks will be discarded.
364
#       The default value is zero, meaning "discard every free block".
365
#
366
# Returns: Nothing.
367
#
368
# Since: 1.2
369
##
370
{ 'command': 'guest-fstrim',
371
  'data': { '*minimum': 'int' } }
372

  
373
##
354 374
# @guest-suspend-disk
355 375
#
356 376
# Suspend guest to disk.
b/qga/commands-posix.c
38 38
#include <sys/socket.h>
39 39
#include <net/if.h>
40 40

  
41
#if defined(__linux__) && defined(FIFREEZE)
41
#ifdef FIFREEZE
42 42
#define CONFIG_FSFREEZE
43 43
#endif
44
#ifdef FITRIM
45
#define CONFIG_FSTRIM
46
#endif
44 47
#endif
45 48

  
46 49
void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
......
312 315
/* linux-specific implementations. avoid this if at all possible. */
313 316
#if defined(__linux__)
314 317

  
315
#if defined(CONFIG_FSFREEZE)
316

  
318
#if defined(CONFIG_FSFREEZE) || defined(CONFIG_FSTRIM)
317 319
typedef struct FsMount {
318 320
    char *dirname;
319 321
    char *devtype;
......
378 380

  
379 381
    return 0;
380 382
}
383
#endif
384

  
385
#if defined(CONFIG_FSFREEZE)
381 386

  
382 387
/*
383 388
 * Return status of freeze/thaw
......
525 530
}
526 531
#endif /* CONFIG_FSFREEZE */
527 532

  
533
#if defined(CONFIG_FSTRIM)
534
/*
535
 * Walk list of mounted file systems in the guest, and trim them.
536
 */
537
void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
538
{
539
    int ret = 0;
540
    FsMountList mounts;
541
    struct FsMount *mount;
542
    int fd;
543
    char err_msg[512];
544
    struct fstrim_range r = {
545
        .start = 0,
546
        .len = -1,
547
        .minlen = has_minimum ? minimum : 0,
548
    };
549

  
550
    slog("guest-fstrim called");
551

  
552
    QTAILQ_INIT(&mounts);
553
    ret = build_fs_mount_list(&mounts);
554
    if (ret < 0) {
555
        return;
556
    }
557

  
558
    QTAILQ_FOREACH(mount, &mounts, next) {
559
        fd = qemu_open(mount->dirname, O_RDONLY);
560
        if (fd == -1) {
561
            sprintf(err_msg, "failed to open %s, %s", mount->dirname,
562
                    strerror(errno));
563
            error_set(err, QERR_QGA_COMMAND_FAILED, err_msg);
564
            goto error;
565
        }
566

  
567
        /* We try to cull filesytems we know won't work in advance, but other
568
         * filesytems may not implement fstrim for less obvious reasons.  These
569
         * will report EOPNOTSUPP; we simply ignore these errors.  Any other
570
         * error means an unexpected error, so return it in those cases.  In
571
         * some other cases ENOTTY will be reported (e.g. CD-ROMs).
572
         */
573
        ret = ioctl(fd, FITRIM, &r);
574
        if (ret == -1) {
575
            if (errno != ENOTTY && errno != EOPNOTSUPP) {
576
                sprintf(err_msg, "failed to trim %s, %s",
577
                        mount->dirname, strerror(errno));
578
                error_set(err, QERR_QGA_COMMAND_FAILED, err_msg);
579
                close(fd);
580
                goto error;
581
            }
582
        }
583
        close(fd);
584
    }
585

  
586
error:
587
    free_fs_mount_list(&mounts);
588
}
589
#endif /* CONFIG_FSTRIM */
590

  
591

  
528 592
#define LINUX_SYS_STATE_FILE "/sys/power/state"
529 593
#define SUSPEND_SUPPORTED 0
530 594
#define SUSPEND_NOT_SUPPORTED 1
......
918 982

  
919 983
    return 0;
920 984
}
985
#endif /* CONFIG_FSFREEZE */
986

  
987
#if !defined(CONFIG_FSTRIM)
988
void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
989
{
990
    error_set(err, QERR_UNSUPPORTED);
921 991

  
992
    return;
993
}
922 994
#endif
923 995

  
924 996
/* register init/cleanup routines for stateful command groups */
b/qga/commands-win32.c
173 173
    return 0;
174 174
}
175 175

  
176
/*
177
 * Walk list of mounted file systems in the guest, and discard unused
178
 * areas.
179
 */
180
void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
181
{
182
    error_set(err, QERR_UNSUPPORTED);
183

  
184
    return;
185
}
186

  
176 187
typedef enum {
177 188
    GUEST_SUSPEND_MODE_DISK,
178 189
    GUEST_SUSPEND_MODE_RAM

Also available in: Unified diff