PATCH: IOCTL#21 progs, including -dq OPTIONS FOR btrfs fi sy

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



diff --git a/Makefile b/Makefile
index 525676e..7442e14 100644
--- a/Makefile
+++ b/Makefile
@@ -37,12 +37,13 @@ all: version $(progs) manpages
Âversion:
   Âbash version.sh

-btrfs: $(objects) btrfs.o btrfs_cmds.o
- Â Â Â gcc $(CFLAGS) -o btrfs btrfs.o btrfs_cmds.o \
+btrfs: $(objects) btrfs.o btrfs_cmds.o iso8601toms.o
+ Â Â Â gcc $(CFLAGS) -o btrfs btrfs.o btrfs_cmds.o iso8601toms.o \
       Â$(objects) $(LDFLAGS) $(LIBS)

-btrfsctl: $(objects) btrfsctl.o
- Â Â Â gcc $(CFLAGS) -o btrfsctl btrfsctl.o $(objects) $(LDFLAGS) $(LIBS)
+btrfsctl: $(objects) btrfsctl.o iso8601toms.o
+ Â Â Â gcc $(CFLAGS) -o btrfsctl btrfsctl.o iso8601toms.o \
+ Â Â Â Â Â Â Â $(objects) $(LDFLAGS) $(LIBS)

Âbtrfs-vol: $(objects) btrfs-vol.o
   Âgcc $(CFLAGS) -o btrfs-vol btrfs-vol.o $(objects) $(LDFLAGS) $(LIBS)
diff --git a/btrfs-list.c b/btrfs-list.c
index 7741705..7b92bc0 100644
--- a/btrfs-list.c
+++ b/btrfs-list.c
@@ -16,6 +16,7 @@
Â* Boston, MA 021110-1307, USA.
Â*/

+#define _GNU_SOURCE
Â#ifndef __CHECKER__
Â#include <sys/ioctl.h>
Â#include <sys/mount.h>
@@ -34,6 +35,7 @@
Â#include "transaction.h"
Â#include "utils.h"
Â#include "version.h"
+#include <string.h>

Â/* we store all the roots we find in an rbtree so that we can
Â* search for them later.
diff --git a/btrfs.c b/btrfs.c
index ab5e57f..47ce5c2 100644
--- a/btrfs.c
+++ b/btrfs.c
@@ -15,6 +15,7 @@
Â*/


+#define _GNU_SOURCE
Â#include <stdio.h>
Â#include <stdlib.h>
Â#include <string.h>
@@ -29,6 +30,7 @@ struct Command {
   ÂCommandFunction func;  /* function which implements the command */
   Âint   nargs;     Â/* if == 999, any number of arguments
                 if >= 0, number of arguments,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âif > 1000, 1000 more than the
_maximum_ number of arguments,
                 if < 0, _minimum_ number of arguments */
   Âchar  Â*verb;     Â/* verb */
   Âchar  Â*help;     Â/* help lines; form the 2nd onward they are
@@ -73,14 +75,19 @@ static struct Command commands[] = {
       Â"Set the subvolume of the filesystem <path> which will
be mounted\n"
       Â"as default."
   Â},
- Â Â Â { do_fssync, 1,
- Â Â Â Â "filesystem sync", "<path>\n"
- Â Â Â Â Â Â Â "Force a sync on the filesystem <path>."
+ Â Â Â { do_fssync, 1002,
+ Â Â Â Â "filesystem sync", "[-dq] <path>\n"
+ Â Â Â Â Â Â Â "Force a sync on the filesystem <path>, defaulting to '.'."
+ Â Â Â },
+ Â Â Â { do_wait4clean, 1002, /* require at most two args */
+ Â Â Â Â "filesystem reclaim", "[path [timeout]] \n"
+ Â Â Â Â Â Â Â "Wait for cleanup of deleted subvolumes. Path defaults to .\n"
+ Â Â Â Â Â Â Â "Timeout in seconds, or add m for minutes.\n"
   Â},
   Â{ do_resize, 2,
    Â"filesystem resize", "[+/-]<newsize>[gkm]|max <filesystem>\n"
       Â"Resize the file system. If 'max' is passed, the filesystem\n"
- Â Â Â Â Â Â Â "will occupe all available space on the device."
+ Â Â Â Â Â Â Â "will occupy all available space on the device."
   Â},
   Â{ do_show_filesystem, 999,
    Â"filesystem show", "[<uuid>|<label>]\n"
@@ -349,17 +356,26 @@ static int parse_args(int argc, char **argv,
       Âreturn -2;

   Â/* check the number of argument */
- Â Â Â if (matchcmd->nargs < 0 && matchcmd->nargs < -*nargs_ ){
+
+ Â Â Â if(matchcmd->nargs > 1000 ){
+ Â Â Â Â Âif ( matchcmd->nargs < (1000 + *nargs_)){
+ Â Â Â Â Â Â Â fprintf(stderr, "ERROR: '%s' requires only %d or fewer
arg(s)\n",
+ Â Â Â Â Â Â Â Â Â Â Â matchcmd->verb, matchcmd->nargs - 1000 );
+ Â Â Â Â Â Â Â Â Â Â Â return -2;
+ Â Â Â Â Â}
+ Â Â Â } else {
+
+ Â Â Â Â if (matchcmd->nargs < 0 && matchcmd->nargs < -*nargs_ ){
       Âfprintf(stderr, "ERROR: '%s' requires minimum %d arg(s)\n",
           Âmatchcmd->verb, -matchcmd->nargs);
           Âreturn -2;
- Â Â Â }
- Â Â Â if(matchcmd->nargs >= 0 && matchcmd->nargs != *nargs_ &&
matchcmd->nargs != 999){
+ Â Â Â Â }
+ Â Â Â Â if(matchcmd->nargs >= 0 && matchcmd->nargs != *nargs_ &&
matchcmd->nargs != 999){
       Âfprintf(stderr, "ERROR: '%s' requires %d arg(s)\n",
           Âmatchcmd->verb, matchcmd->nargs);
           Âreturn -2;
- Â Â Â }
-
+ Â Â Â Â }
+ Â Â Â }
    if (prepare_args( nargs_, args_, prgname, matchcmd )){
        fprintf(stderr, "ERROR: not enough memory\\n");
       Âreturn -20;
diff --git a/btrfs_cmds.c b/btrfs_cmds.c
index 8031c58..d2b81ba 100644
--- a/btrfs_cmds.c
+++ b/btrfs_cmds.c
@@ -507,22 +507,87 @@ int do_create_subvol(int argc, char **argv)
Âint do_fssync(int argc, char **argv)
Â{
   Âint fd, res;
-    char  Â*path = argv[1];
-
+ Â Â Â Âint cleanup=1, quiet=0;
+    char  Â*path = ".", *p; /* [-dq] [<path>] */
+ Â Â Â Âstruct btrfs_ioctl_cleaner_wait_args w4c_arg;
+
+ Â Â Â Âif (argc > 1){
+ Â Â Â Â Â if (argv[1][0] == '-'){
+ Â Â Â Â Â Â for (p=&argv[1][1]; *p; p++) switch (*p){
+ Â Â Â Â Â Â Â Âcase 'q': quiet++; break;
+ Â Â Â Â Â Â Â Âcase 'd': cleanup++; break;
+ Â Â Â Â Â Â Â Âdefault:
+ Â Â Â Â Â Â Â Â Â fprintf(stderr,
+ Â Â "ERROR: unknown flag '%c' in '%s'\n", *p,argv[1]);
+ Â Â Â Â Â Â Â Â Âreturn 12;
+ Â Â Â Â Â Â };
+ Â Â Â Â Â Â if (argc > 2)
+ Â Â Â Â Â Â Â Â path = argv[2];
+
+ Â Â Â Â Â }else{
+ Â Â Â Â Â Â Âpath = argv[1];
+
+ Â Â Â Â Â };
+
+ Â Â Â Â};
+ Â Âwhile (cleanup--){ /* cleanup starts at 1 */
   Âfd = open_file_or_dir(path);
   Âif (fd < 0) {
       Âfprintf(stderr, "ERROR: can't access to '%s'\n", path);
       Âreturn 12;
   Â}

- Â Â Â printf("FSSync '%s'\n", path);
+ Â Â Â if (!quiet) printf("FSSync '%s'\n", path);
   Âres = ioctl(fd, BTRFS_IOC_SYNC);
- Â Â Â close(fd);
   Âif( res < 0 ){
       Âfprintf(stderr, "ERROR: unable to fs-syncing '%s'\n", path);
       Âreturn 16;
   Â}

+ Â Â Â Âif (cleanup){
+ Â Â Â Â Â w4c_arg.ms = 0UL;
+ Â Â Â Â Âfd = open_file_or_dir(path);
+ Â Â Â Â Âif (!quiet) printf("reclaim: '%s'\n", path);
+ Â Â Â Â Âres = ioctl(fd, BTRFS_IOC_CLEANER_WAIT, &w4c_arg);
+ Â Â Â Â Âclose(fd);
+ Â Â Â Â Âif( res != 0 ){
+ Â Â Â Â Â Â Â fprintf(stderr, "%s:error #%i:%s\n",
+ Â Â Â Â Â Â Â Â Â Â Â Âpath, res,strerror(res));
+ Â Â Â Â Â Â Â return -res;
+ Â Â Â Â Â}
+ Â Â Â Â}
+ Â Â};
+ Â Â Â return 0;
+}
+
+#include "iso8601toms.h"
+
+int do_wait4clean(int argc, char **argv)
+{
+ Â Â Â int fd, res;
+ Â Â Â Âstruct btrfs_ioctl_cleaner_wait_args w4c_arg;
+
+    char  Â*path = ".";
+ Â Â Â Âw4c_arg.ms = 0UL;
+
+ Â Â Â Âif (argc > 1)
+ Â Â Â Â Â Âpath = argv[1];
+ Â Â Â Âif (argc > 2)
+ Â Â Â Â Â Â w4c_arg.ms = iso8601toms(argv[2]);
+
+ Â Â Â fd = open_file_or_dir(path);
+ Â Â Â if (fd < 0) {
+ Â Â Â Â Â Â Â fprintf(stderr, "ERROR: can't open file or dir '%s'\n", path);
+ Â Â Â Â Â Â Â return 12;
+ Â Â Â }
+ Â Â Â res = ioctl(fd, BTRFS_IOC_CLEANER_WAIT, &w4c_arg);
+ Â Â Â close(fd);
+ Â Â Â if( res != 0 ){
+ Â Â Â Â Â Â Â fprintf(stderr, "%s:error #%i:%s\n",
+ Â Â Â Â Â Â Â Â Â Â Â Âpath, res,strerror(res));
+ Â Â Â Â Â Â Â return -res;
+ Â Â Â }
+
   Âreturn 0;
Â}

diff --git a/btrfs_cmds.h b/btrfs_cmds.h
index 7bde191..c958338 100644
--- a/btrfs_cmds.h
+++ b/btrfs_cmds.h
@@ -19,6 +19,7 @@ int do_clone(int nargs, char **argv);
Âint do_delete_subvolume(int nargs, char **argv);
Âint do_create_subvol(int nargs, char **argv);
Âint do_fssync(int nargs, char **argv);
+int do_wait4clean(int nargs, char **argv);
Âint do_defrag(int argc, char **argv);
Âint do_show_filesystem(int nargs, char **argv);
Âint do_add_volume(int nargs, char **args);
diff --git a/btrfsctl.c b/btrfsctl.c
index be6bf25..13dddd5 100644
--- a/btrfsctl.c
+++ b/btrfsctl.c
@@ -34,6 +34,7 @@
Â#include "ctree.h"
Â#include "transaction.h"
Â#include "utils.h"
+#include "iso8601toms.h"
Â#include "version.h"

Â#ifdef __CHECKER__
@@ -57,6 +58,7 @@ static void print_usage(void)
   Âprintf("\t-a: scans all devices for Btrfs filesystems\n");
   Âprintf("\t-c: forces a single FS sync\n");
   Âprintf("\t-D: delete snapshot\n");
+ Â Â Â printf("\t-C [timeout [directory]]: wait for snapshot space
recovery\n");
   Âprintf("\t-m [tree id] directory: set the default mounted subvolume"
       " to the [tree id] or the directory\n");
   Âprintf("%s\n", BTRFS_BUILD_VERSION);
@@ -96,7 +98,7 @@ int main(int ac, char **av)
   Âchar *fname = NULL;
   Âchar *snap_location = NULL;
   Âint snap_fd = 0;
- Â Â Â int fd;
+ Â Â Â int fd = -999; /* silence a warning */
   Âint ret;
   Âstruct btrfs_ioctl_vol_args args;
   Âchar *name = NULL;
@@ -105,6 +107,7 @@ int main(int ac, char **av)
   Âint len;
   Âchar *fullpath;
   Âu64 objectid = 0;
+ Â Â Â Âstruct btrfs_ioctl_cleaner_wait_args CWargs;

   Âif (ac == 2 && strcmp(av[1], "-a") == 0) {
       Âfprintf(stderr, "Scanning for Btrfs filesystems\n");
@@ -175,6 +178,10 @@ int main(int ac, char **av)
               Âfprintf(stderr, "-D size too long\n");
               Âexit(1);
           Â}
+ Â Â Â Â Â Â Â } else if (strcmp(av[i], "-C") == 0) {
+ Â Â Â Â Â Â Â Â Â Â Â command = BTRFS_IOC_CLEANER_WAIT;
+ Â Â Â Â Â Â Â Â Â Â Â ÂCWargs.ms = ( ac > (i+1) ?
iso8601toms(av[i+1]) : 0UL );
+ Â Â Â Â Â Â Â Â Â Â Â name = ( ac > ( i+2 ) ? av[i + 2] : "." );
       Â} else if (strcmp(av[i], "-A") == 0) {
           Âif (i >= ac - 1) {
               Âfprintf(stderr, "-A requires an arg\n");
@@ -221,9 +228,9 @@ int main(int ac, char **av)
           Âexit(1);
       Â}
       Âname = fname;
- Â Â Â Â} else {
+ Â Â Â } else if (command != BTRFS_IOC_CLEANER_WAIT) {
       Âfd = open_file_or_dir(fname);
- Â Â Â Â}
+ Â Â Â }

   Âif (name)
       Âstrcpy(args.name, name);
@@ -236,6 +243,9 @@ int main(int ac, char **av)
   Â} else if (command == BTRFS_IOC_DEFAULT_SUBVOL) {
       Âprintf("objectid is %llu\n", objectid);
       Âret = ioctl(fd, command, &objectid);
+ Â Â Â } else if (command == BTRFS_IOC_CLEANER_WAIT) {
+ Â Â Â Â Â Â Â fd = open_file_or_dir(name);
+ Â Â Â Â Â Â Â ret = ioctl(fd, command, &CWargs);
   Â} else
       Âret = ioctl(fd, command, &args);
   Âif (ret < 0) {
diff --git a/ioctl.h b/ioctl.h
index 776d7a9..27df596 100644
--- a/ioctl.h
+++ b/ioctl.h
@@ -169,4 +169,11 @@ struct btrfs_ioctl_space_args {
Â#define BTRFS_IOC_DEFAULT_SUBVOL _IOW(BTRFS_IOCTL_MAGIC, 19, u64)
Â#define BTRFS_IOC_SPACE_INFO _IOWR(BTRFS_IOCTL_MAGIC, 20, \
                 Âstruct btrfs_ioctl_space_args)
+struct btrfs_ioctl_cleaner_wait_args{
+ Â Â Â Âunsigned long ms;
+ Â Â Â Âunsigned long flags; /* for future use */
+};
+#define BTRFS_IOC_CLEANER_WAIT _IOW(BTRFS_IOCTL_MAGIC, 21, \
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â struct btrfs_ioctl_cleaner_wait_args)
Â#endif
+
diff --git a/iso8601toms.c b/iso8601toms.c
new file mode 100644
index 0000000..f982d34
--- /dev/null
+++ b/iso8601toms.c
@@ -0,0 +1,114 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License v2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ÂSee the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ */
+
+/***********
+
+ the following will correctly parse valid duration strings,
+ also it will accept a lot of invalid ones.
+
+ it does:
+
+ Â Âknow all the ISO8601 letters
+
+ Â Âaccept a non-integer as the last numeric component
+
+ Â Âalways treats "m" as minutes
+
+ it silently accepts:
+
+ Â Âout of order duration type letters
+
+ Â Âstrings missing the leading P character
+
+ Â Âlowercase duration type letters
+
+ Â Ânon-integers in any position
+
+ it halts and catches fire on:
+
+ Â ÂP or p appearing somewhere besides the beginning of the string
+
+ Â ÂAttempts to use Years or Months
+
+ Â Âunrecognized characters
+
+
+***********/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+unsigned long iso8601toms(char *P){
+ Â Âunsigned long ms;
+ Â Âdouble component;
+ Â Âchar *ptr;
+ Â Âchar *endptr;
+ Â Âshort M_min = 0;
+ Â Âms = 0UL;
+ Â Âptr = P;
+ Â Âfor(;;){
+ Â Â Â component=strtod(ptr, &endptr);
+ Â Â Â switch (*endptr)
+ Â Â Â {
+ Â Â Â Â Âcase 'P': /* anchor */ case 'p':
+ Â Â Â Â Â Â if (ptr > P)
+ Â Â Â Â Â Â Â Âfprintf(stderr, "non-initial P "
+ Â Â Â Â Â Â Â Â Â Â Â Â "in duration string %s\n", P);
+ Â Â Â Â Â Â Â Â exit (-1);
+ Â Â Â Â Âcase 'Y': /* year */ case 'y':
+ Â Â Â Â Â Â Â Âfprintf(stderr, "Years are not supported "
+ Â Â Â Â Â Â Â Â Â Â Â Â "in duration string %s\n", P);
+ Â Â Â Â Â Â Â Â exit (-1);
+ Â Â Â Â Âcase 'T': /* Time (not date) anchor */ case 't':
+ Â Â Â Â Â Â M_min = 1;
+ Â Â Â Â Â Â break;
+ Â Â Â Â Âcase 'W': /* week */ case 'w':
+ Â Â Â Â Â Â component *= 7;
+ Â Â Â Â Âcase 'D': /* day */ case 'd':
+ Â Â Â Â Â Â component *= Â24 ;
+ Â Â Â Â Âcase 'H': /* hour */ case 'h':
+ Â Â Â Â Â Â component *= 60;
+ Â Â Â Â Â Â M_min = 1;
+ Â Â Â Â Âcase 'M': /* month, or minute */
+ Â Â Â Â Â Â if (M_min == 0 ){
+ Â Â Â Â Â Â Â Âfprintf(stderr, "Months are not supported "
+ Â Â Â Â Â Â Â Â Â Â Â Â "in duration string %s\n"
+ Â Â Â Â Â Â Â Â Â Â Â Â "use 'm' instead or prefix a 'T'\n"
+ Â Â Â Â Â Â Â Â Â Â Â Â , P);
+ Â Â Â Â Â Â Â Â exit (-1);
+ Â Â Â Â Â Â };
+ Â Â Â Â Âcase 'm': /* minute */
+ Â Â Â Â Â Â component *= 60;
+ Â Â Â Â Âcase 'S': /* second */ case 's':
+ Â Â Â Â Âcase '\0': /* default to second */
+ Â Â Â Â Â Â component *= 1000;
+ Â Â Â Â Â Â ms += component;
+ Â Â Â Â Â Â break;
+
+ Â Â Â Â Âdefault:
+ Â Â Â Â Â Âfprintf(stderr,
+ Â Â Â Â Â Â Â Â"unexpected char [%c] in duration string %s\n"
+ Â Â Â Â Â Â Â Â"valid designators are [WwDdHhMmSs] with implied
trailing S.\n",
+ Â Â Â Â Â Â Â Â*endptr, P
+ Â Â Â Â Â Â );
+ Â Â Â Â Â Â exit (-1);
+ Â Â Â };
+ Â Â Â if (!*endptr)
+ Â Â Â Â Âreturn (ms);
+ Â Â Â ptr = 1+endptr;
+ Â Â};
+}
+
diff --git a/iso8601toms.h b/iso8601toms.h
new file mode 100644
index 0000000..8f7ca83
--- /dev/null
+++ b/iso8601toms.h
@@ -0,0 +1,3 @@
+
+unsigned long iso8601toms(char *P);
+
diff --git a/man/btrfs.8.in b/man/btrfs.8.in
index 26ef982..a62f02b 100644
--- a/man/btrfs.8.in
+++ b/man/btrfs.8.in
@@ -17,7 +17,9 @@ btrfs \- control a btrfs filesystem
Â.PP
Â\fBbtrfs\fP \fBfilesystem defrag\fP\fI <file>|<dir> [<file>|<dir>...]\fP
Â.PP
-\fBbtrfs\fP \fBfilesystem sync\fP\fI <path> \fP
+\fBbtrfs\fP \fBfilesystem sync\fP\fI [-dq] [<path>] \fP
+.PP
+\fBbtrfs\fP \fBfilesystem reclaim\fP\fI [path [timeout]] \fP
Â.PP
Â\fBbtrfs\fP \fBfilesystem resize\fP\fI [+/\-]<size>[gkm]|max <filesystem>\fP
Â.PP
@@ -111,8 +113,22 @@ Scan devices for a btrfs filesystem. If no
devices are passed, \fBbtrfs\fR scans
Âall the block devices.
Â.TP

-\fBfilesystem sync\fR\fI <path> \fR
-Force a sync for the filesystem identified by \fI<path>\fR.
+\fBfilesystem sync\fR \fI[-dq] [<path>]\fR
+Force a sync for the filesystem identified by \fI<path>\fR, which defaults
+to the current directory. Use the \fI-d\fR switch to wait for the deleted
+subvolume cleaner thread to finish, and the \fI-q\fR switch to suppress
+informational output.
+.TP
+
+\fBfilesystem reclaim\fR\fI [path [timeout]] \fR
+Wait for recovery of space from deleted
+subvolumes on the filesystem containing \fIpath\fR,
+which defaults to the current working directory, to complete.
+The optional timeout parameter is a series of number[.number][letter]
+components where the letter is one of wdhms for weeks, days, hours, minutes,
+seconds, defaulting to seconds. The default timeout is zero which means
+no timeout. 90, 1.5m, and PT1.5M all mean ninety seconds.
+
Â.TP

Â.\"
diff --git a/man/btrfsctl.8.in b/man/btrfsctl.8.in
index c2d4488..890c625 100644
--- a/man/btrfsctl.8.in
+++ b/man/btrfsctl.8.in
@@ -10,6 +10,7 @@ btrfsctl \- control a btrfs filesystem
Â[ \fB \-A\fP\fI device\fP ]
Â[ \fB \-a\fP ]
Â[ \fB \-c\fP ]
+[ \fB \-C\fP\fI [timeout [directory]]\fP ]
Â.SH DESCRIPTION
Â.B btrfsctl
Âis used to control the filesystem and the files and directories
stored. It is the tool to create a new snapshot for the filesystem.
@@ -35,6 +36,13 @@ Scans all devices present in the system for btrfs filesystem.
Â.TP
Â\fB\-c\fR
ÂForces a filesystem sync.
+.TP
+\fB\-C\fR \fI[timeout [directory]]\fR
+Wait until all the space from all deleted snapshots has been recovered.
+The optional timeout parameter is seconds[.subseconds], or append "m"
+for minutes[.subminutes]. "90", "90.000s", "T1.5M", and "1m30" all mean
+the same thing. The default timeout is zero, which means do not time out.
+The optional directory parameter defaults to the current directory.
Â.SH AVAILABILITY
Â.B btrfsctl
Âis part of btrfs-progs. Btrfs is currently under heavy development,



-- 
l'Ãgalità des droits pour les ambidextres
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Filesystem Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux