diff --git a/cpukit/libfs/Makefile.am b/cpukit/libfs/Makefile.am
index 7535b5a..0828da8 100644
--- a/cpukit/libfs/Makefile.am
+++ b/cpukit/libfs/Makefile.am
@@ -80,7 +80,7 @@
     src/dosfs/msdos_handlers_file.c src/dosfs/msdos_init.c \
     src/dosfs/msdos_initsupp.c src/dosfs/msdos_misc.c \
     src/dosfs/msdos_mknod.c src/dosfs/msdos_node_type.c \
-    src/dosfs/msdos_rmnod.c \
+    src/dosfs/msdos_rmnod.c src/dosfs/msdos_statvfs.c \
     src/dosfs/msdos_conv.c src/dosfs/msdos.h src/dosfs/msdos_format.c \
     src/dosfs/dosfs.h src/dosfs/msdos_rename.c
 endif
diff --git a/cpukit/libfs/src/dosfs/msdos.h b/cpukit/libfs/src/dosfs/msdos.h
index 9465d26..78eda9b 100644
--- a/cpukit/libfs/src/dosfs/msdos.h
+++ b/cpukit/libfs/src/dosfs/msdos.h
@@ -293,6 +293,9 @@
   size_t new_namelen
 );
 
+int msdos_statvfs(const rtems_filesystem_location_info_t *root_loc,
+  struct statvfs *sb);
+
 void msdos_lock(const rtems_filesystem_mount_table_entry_t *mt_entry);
 
 void msdos_unlock(const rtems_filesystem_mount_table_entry_t *mt_entry);
diff --git a/cpukit/libfs/src/dosfs/msdos_init.c b/cpukit/libfs/src/dosfs/msdos_init.c
index eb46141..e82e3f5 100644
--- a/cpukit/libfs/src/dosfs/msdos_init.c
+++ b/cpukit/libfs/src/dosfs/msdos_init.c
@@ -53,7 +53,7 @@
   .symlink_h      =  rtems_filesystem_default_symlink,
   .readlink_h     =  rtems_filesystem_default_readlink,
   .rename_h       =  msdos_rename,
-  .statvfs_h      =  rtems_filesystem_default_statvfs
+  .statvfs_h      =  msdos_statvfs
 };
 
 void msdos_lock(const rtems_filesystem_mount_table_entry_t *mt_entry)
diff --git a/cpukit/libfs/src/dosfs/msdos_statvfs.c b/cpukit/libfs/src/dosfs/msdos_statvfs.c
new file mode 100644
index 0000000..1a1d974
--- /dev/null
+++ b/cpukit/libfs/src/dosfs/msdos_statvfs.c
@@ -0,0 +1,75 @@
+/**
+ * @file msdos_statvfs.c
+ *
+ * @brief Obtain MS-DOS filesystem information
+ * @ingroup libfs_msdos MSDOS FileSystem
+ */
+
+/*
+ *  Copyright (c) 2013 Andrey Mozzhuhin
+ *  Copyright (c) 2013 Vitaly Belov
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#include "fat.h"
+#include "fat_fat_operations.h"
+#include "msdos.h"
+
+int msdos_statvfs(const rtems_filesystem_location_info_t *root_loc,
+    struct statvfs *sb)
+{
+  msdos_fs_info_t *fs_info = root_loc->mt_entry->fs_info;
+  fat_vol_t *vol = &fs_info->fat.vol;
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+  sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
+                              MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
+  if (sc != RTEMS_SUCCESSFUL)
+      rtems_set_errno_and_return_minus_one(EIO);
+
+  sb->f_bsize = FAT_SECTOR512_SIZE;
+  sb->f_frsize = vol->bpc;
+  sb->f_blocks = vol->data_cls;
+  sb->f_bfree = 0;
+  sb->f_bavail = 0;
+  sb->f_files = 0;    // FAT doesn't store inodes
+  sb->f_ffree = 0;
+  sb->f_favail = 0;
+  sb->f_flag = 0;
+  sb->f_namemax = MSDOS_NAME_MAX_LNF_LEN;
+
+  if (vol->free_cls == FAT_UNDEFINED_VALUE)
+  {
+    int rc;
+    uint32_t cur_cl = 2;
+    uint32_t value = 0;
+    uint32_t data_cls_val = vol->data_cls + 2;
+
+    for (; cur_cl < data_cls_val; ++cur_cl)
+    {
+      rc = fat_get_fat_cluster(&fs_info->fat, cur_cl, &value);
+      if (rc != RC_OK)
+      {
+        rtems_semaphore_release(fs_info->vol_sema);
+        return rc;
+      }
+
+      if (value == FAT_GENFAT_FREE)
+      {
+        sb->f_bfree++;
+        sb->f_bavail++;
+      }
+    }
+  }
+  else
+  {
+    sb->f_bfree = vol->free_cls;
+    sb->f_bavail = vol->free_cls;
+  }
+
+  rtems_semaphore_release(fs_info->vol_sema);
+  return RC_OK;
+}
diff --git a/cpukit/libmisc/Makefile.am b/cpukit/libmisc/Makefile.am
index b0b2195..5800a47 100644
--- a/cpukit/libmisc/Makefile.am
+++ b/cpukit/libmisc/Makefile.am
@@ -102,7 +102,7 @@
     shell/hexdump-odsyntax.c shell/hexdump-parse.c shell/hexsyntax.c \
     shell/main_time.c shell/main_mknod.c \
     shell/main_setenv.c shell/main_getenv.c shell/main_unsetenv.c \
-    shell/main_mkrfs.c shell/main_debugrfs.c \
+    shell/main_mkrfs.c shell/main_debugrfs.c shell/main_df.c \
     shell/main_lsof.c \
     shell/main_blkstats.c \
     shell/shell-wait-for-input.c
diff --git a/cpukit/libmisc/shell/main_df.c b/cpukit/libmisc/shell/main_df.c
new file mode 100644
index 0000000..41183bd
--- /dev/null
+++ b/cpukit/libmisc/shell/main_df.c
@@ -0,0 +1,158 @@
+/**
+ *  df Shell Command Implmentation
+ *
+ * @brief Obtain MS-DOS filesystem information
+ * @ingroup libfs_msdos MSDOS FileSystem
+ */
+
+/*
+ *  Copyright (c) 2013 Andrey Mozzhuhin
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/shell.h>
+
+#define __need_getopt_newlib
+#include <getopt.h>
+
+static const char suffixes[] =
+{ 'B', 'K', 'M', 'G', 'T' };
+
+struct df_context
+{
+  unsigned block_size;
+};
+
+static unsigned rtems_shell_df_parse_size(const char *str)
+{
+  unsigned result;
+  char suffix;
+  int i;
+
+  if (sscanf(str, "%d%c", &result, &suffix) == 2)
+  {
+    for (i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); i++)
+    {
+      if (suffix == suffixes[i])
+        break;
+      result *= 1024;
+    }
+  }
+  else if (sscanf(str, "%d", &result) != 1)
+  {
+    result = 0;
+  }
+
+  return result;
+}
+
+static char *rtems_shell_df_humanize_size(unsigned block_size, char *buf,
+    size_t size)
+{
+  int i = 0;
+
+  while (block_size >= 1024 && i < sizeof(suffixes) / sizeof(suffixes[0]) - 1)
+  {
+    block_size /= 1024;
+    i++;
+  }
+
+  snprintf(buf, size, "%d%c", block_size, suffixes[i]);
+  return buf;
+}
+
+static bool rtems_shell_df_print_entry(
+    const rtems_filesystem_mount_table_entry_t *mt_entry, void *arg)
+{
+  struct df_context *context = arg;
+
+  struct statvfs svfs;
+  int code;
+  char f_buf[16], u_buf[16], a_buf[16];
+
+  if ((code = statvfs(mt_entry->target, &svfs)))
+    return false;
+
+  if (context->block_size > 0)
+  {
+    printf("%-15s %10llu %9llu %11llu %9llu%% %14s\n",
+        mt_entry->dev == NULL ? "none" : mt_entry->dev,
+        (svfs.f_blocks * svfs.f_frsize + (context->block_size - 1)) / context->block_size,
+        ((svfs.f_blocks - svfs.f_bfree) * svfs.f_frsize + (context->block_size - 1)) / context->block_size,
+        (svfs.f_bfree * svfs.f_frsize + (context->block_size - 1)) / context->block_size,
+        ((svfs.f_blocks - svfs.f_bfree) * 100 / svfs.f_blocks),
+        mt_entry->target == NULL ? "none" : mt_entry->target);
+  }
+  else
+  {
+    rtems_shell_df_humanize_size(svfs.f_blocks * svfs.f_frsize, f_buf,
+        sizeof(f_buf));
+    rtems_shell_df_humanize_size((svfs.f_blocks - svfs.f_bfree) * svfs.f_frsize,
+        u_buf, sizeof(u_buf));
+    rtems_shell_df_humanize_size(svfs.f_bfree * svfs.f_frsize, a_buf,
+        sizeof(a_buf));
+    printf("%-15s %10s %9s %11s %9llu%% %14s\n",
+        mt_entry->dev == NULL ? "none" : mt_entry->dev, f_buf, u_buf, a_buf,
+        (svfs.f_blocks - svfs.f_bfree) * 100 / svfs.f_blocks,
+        mt_entry->target == NULL ? "none" : mt_entry->target);
+  }
+
+  return false;
+}
+
+static int rtems_shell_main_df(int argc, char **argv)
+{
+  int c;
+  struct getopt_data optdata;
+  struct df_context context;
+  char buf[32];
+
+  memset(&optdata, 0, sizeof(optdata));
+  context.block_size = 1024;
+
+  while ((c = getopt_r(argc, (char**) argv, ":hB:", &optdata)) != -1)
+  {
+    switch (c)
+    {
+    case 'h':
+      context.block_size = 0;
+      break;
+    case 'B':
+      context.block_size = rtems_shell_df_parse_size(optdata.optarg);
+      break;
+    default:
+      return -1;
+    }
+  }
+
+  if (context.block_size == 0)
+    printf(
+        "Filesystem     Size             Used   Available       Use%%     Mounted on\n");
+  else
+    printf(
+        "Filesystem     %s-blocks        Used   Available       Use%%     Mounted on\n",
+        rtems_shell_df_humanize_size(context.block_size, buf, sizeof(buf)));
+
+  rtems_filesystem_mount_iterate(rtems_shell_df_print_entry, &context);
+
+  return 0;
+}
+
+rtems_shell_cmd_t rtems_shell_DF_Command =
+{
+    "df", /* name */
+    "[-hB]\n"
+    " -h  human-readable output\n"
+    " -B  scale sizes by SIZE before printing them\n", /* usage */
+    "files", /* topic */
+    rtems_shell_main_df, /* command */
+    NULL, /* alias */
+    NULL /* next */
+};
diff --git a/cpukit/libmisc/shell/shellconfig.h b/cpukit/libmisc/shell/shellconfig.h
index 9f45151..652d62b 100644
--- a/cpukit/libmisc/shell/shellconfig.h
+++ b/cpukit/libmisc/shell/shellconfig.h
@@ -70,6 +70,7 @@
 extern rtems_shell_cmd_t rtems_shell_DD_Command;
 extern rtems_shell_cmd_t rtems_shell_HEXDUMP_Command;
 extern rtems_shell_cmd_t rtems_shell_DEBUGRFS_Command;
+extern rtems_shell_cmd_t rtems_shell_DF_Command;
 
 extern rtems_shell_cmd_t rtems_shell_RTC_Command;
 
@@ -375,6 +376,11 @@
         defined(CONFIGURE_SHELL_COMMAND_DEBUGRFS)
       &rtems_shell_DEBUGRFS_Command,
     #endif
+    #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
+         !defined(CONFIGURE_SHELL_NO_COMMAND_DF)) || \
+        defined(CONFIGURE_SHELL_COMMAND_DF)
+      &rtems_shell_DF_Command,
+    #endif
 
     /*
      *  RTEMS Related commands
diff --git a/doc/shell/file.t b/doc/shell/file.t
index c53a9cf..01a3b28 100644
--- a/doc/shell/file.t
+++ b/doc/shell/file.t
@@ -35,6 +35,7 @@
 @item @code{dir} - alias for ls
 @item @code{mkrfs} - format RFS file system
 @item @code{cd} - alias for chdir
+@item @code{df} - display file system disk space usage
 
 @end itemize
 
@@ -2628,3 +2629,80 @@
 extern rtems_shell_cmd_t rtems_shell_CD_Command;
 @end example
 
+@c
+@c
+@c
+@page
+@subsection df - display file system disk space usage
+
+@pgindex df
+
+@subheading SYNOPSYS:
+
+@example
+df [-h] [-B block_size]
+@end example
+
+@subheading DESCRIPTION:
+
+This command print disk space usage for mounted file systems.
+
+@subheading EXIT STATUS:
+
+This command returns 0 on success and non-zero if an error is encountered.
+
+@subheading NOTES:
+
+NONE
+
+@subheading EXAMPLES:
+
+The following is an example of how to use @code{df}:
+
+@example
+SHLL [/] $ df -B 4K
+Filesystem     4K-blocks        Used   Available       Use%     Mounted on
+/dev/rda               124         1         124         0%   /mnt/ramdisk
+SHLL [/] $ df
+Filesystem     1K-blocks        Used   Available       Use%     Mounted on
+/dev/rda               495         1         494         0%   /mnt/ramdisk
+SHLL [/] $ df -h
+Filesystem     Size             Used   Available       Use%     Mounted on
+/dev/rda              495K        1K        494K         0%   /mnt/ramdisk
+@end example
+
+@subheading CONFIGURATION:
+
+@findex CONFIGURE_SHELL_NO_COMMAND_DF
+@findex CONFIGURE_SHELL_COMMAND_DF
+
+This command is included in the default shell command set.  
+When building a custom command set, define
+@code{CONFIGURE_SHELL_COMMAND_DF} to have this
+command included.
+
+This command can be excluded from the shell command set by
+defining @code{CONFIGURE_SHELL_NO_COMMAND_DF} when all
+shell commands have been configured.
+
+@subheading PROGRAMMING INFORMATION:
+
+@findex rtems_shell_rtems_main_df
+
+The @code{df} is implemented by a C language function
+which has the following prototype:
+
+@example
+int rtems_shell_main_df(
+  int argc,
+  char **argv
+);
+@end example
+
+The configuration structure for the @code{df} has the
+following prototype:
+
+@example
+extern rtems_shell_cmd_t rtems_shell_DF_Command;
+@end example
+
diff --git a/testsuites/fstests/Makefile.am b/testsuites/fstests/Makefile.am
index 5161380..f39055e 100644
--- a/testsuites/fstests/Makefile.am
+++ b/testsuites/fstests/Makefile.am
@@ -15,6 +15,7 @@
 SUBDIRS += mdosfs_fserror
 SUBDIRS += mdosfs_fspatheval
 SUBDIRS += mdosfs_fsrdwr
+SUBDIRS += mdosfs_fsstatvfs
 SUBDIRS += mdosfs_fstime
 SUBDIRS += mimfs_fserror
 SUBDIRS += mimfs_fslink
diff --git a/testsuites/fstests/configure.ac b/testsuites/fstests/configure.ac
index 4993beb..8985464 100644
--- a/testsuites/fstests/configure.ac
+++ b/testsuites/fstests/configure.ac
@@ -91,6 +91,7 @@
 mdosfs_fserror/Makefile
 mdosfs_fspatheval/Makefile
 mdosfs_fsrdwr/Makefile
+mdosfs_fsstatvfs/Makefile
 mdosfs_fstime/Makefile
 mimfs_fserror/Makefile
 mimfs_fslink/Makefile
diff --git a/testsuites/fstests/fsstatvfs/fsstatvfs.doc b/testsuites/fstests/fsstatvfs/fsstatvfs.doc
new file mode 100644
index 0000000..85c329d
--- /dev/null
+++ b/testsuites/fstests/fsstatvfs/fsstatvfs.doc
@@ -0,0 +1,21 @@
+#  COPYRIGHT (c) 2013 Andrey Mozzhuhin
+#
+#  The license and distribution terms for this file may be
+#  found in the file LICENSE in this distribution or at
+#  http://www.rtems.com/license/LICENSE.
+#
+
+This file describes the directives and concepts tested by this test set.
+
+test set name: fsstatvfs
+
+directives:
+
++ statvfs
+
+
+
+concepts:
+
++ Check that filesystem provide valid statistics 
+
diff --git a/testsuites/fstests/fsstatvfs/test.c b/testsuites/fstests/fsstatvfs/test.c
new file mode 100644
index 0000000..88952ef
--- /dev/null
+++ b/testsuites/fstests/fsstatvfs/test.c
@@ -0,0 +1,88 @@
+/*
+ *  COPYRIGHT (c) 2013 Andrey Mozzhuhin
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/statvfs.h>
+#include <string.h>
+#include <fcntl.h>
+
+#include "fstest.h"
+#include "pmacros.h"
+
+static void statvfs_validate(struct statvfs *stat)
+{
+  rtems_test_assert(stat->f_bsize > 0);
+  rtems_test_assert(stat->f_frsize > 0);
+  rtems_test_assert(stat->f_blocks > 0);
+  rtems_test_assert(stat->f_bfree <= stat->f_blocks);
+  rtems_test_assert(stat->f_bavail <= stat->f_blocks);
+  rtems_test_assert(stat->f_ffree <= stat->f_files);
+  rtems_test_assert(stat->f_favail <= stat->f_files);
+  rtems_test_assert(stat->f_namemax > 0);
+}
+
+static void statvfs_test01(void)
+{
+  struct statvfs statbuf1, statbuf2;
+  int status;
+  int fd;
+  ssize_t n;
+  const char *databuf = "STATVFS";
+  int datalen = strlen(databuf);
+  const char *filename = __func__;
+
+  /*
+   * Get current filesystem statistics
+   */
+  status = statvfs("/", &statbuf1);
+  rtems_test_assert(status == 0);
+  statvfs_validate(&statbuf1);
+
+  /*
+   * Create one file
+   */
+  fd = open(filename, O_CREAT | O_WRONLY, 0775);
+  rtems_test_assert(fd >= 0);
+  n = write(fd, databuf, datalen);
+  rtems_test_assert(n == datalen);
+  status = close(fd);
+  rtems_test_assert(status == 0);
+
+  /*
+   * Get new filesystem statistics
+   */
+  status = statvfs("/", &statbuf2);
+  rtems_test_assert(status == 0);
+  statvfs_validate(&statbuf2);
+
+  /*
+   * Compare old and new statistics
+   */
+  rtems_test_assert(statbuf1.f_bsize == statbuf2.f_bsize);
+  rtems_test_assert(statbuf1.f_frsize == statbuf2.f_frsize);
+  rtems_test_assert(statbuf1.f_blocks == statbuf2.f_blocks);
+  rtems_test_assert(statbuf1.f_bfree >= statbuf2.f_bfree);
+  rtems_test_assert(statbuf1.f_bavail >= statbuf2.f_bavail);
+  rtems_test_assert(statbuf1.f_ffree >= statbuf2.f_ffree);
+  rtems_test_assert(statbuf1.f_favail >= statbuf2.f_favail);
+  rtems_test_assert(statbuf1.f_namemax == statbuf2.f_namemax);
+}
+
+/*
+ * These tests only get time_t value, and test
+ * if they are changed. Thest tests don't check atime
+ */
+void test(void)
+{
+  puts( "\n\n*** STATVFS TEST ***");
+  statvfs_test01();
+  puts( "*** END OF STATVFS TEST ***");
+}
diff --git a/testsuites/fstests/mdosfs_fsstatvfs/Makefile.am b/testsuites/fstests/mdosfs_fsstatvfs/Makefile.am
new file mode 100644
index 0000000..bb0d2ef
--- /dev/null
+++ b/testsuites/fstests/mdosfs_fsstatvfs/Makefile.am
@@ -0,0 +1,30 @@
+
+rtems_tests_PROGRAMS = mdosfs_fsstatvfs
+mdosfs_fsstatvfs_SOURCES  = ../fsstatvfs/test.c
+mdosfs_fsstatvfs_SOURCES += ../support/ramdisk_support.c
+mdosfs_fsstatvfs_SOURCES += ../support/fstest_support.c
+mdosfs_fsstatvfs_SOURCES += ../support/fstest_support.h
+mdosfs_fsstatvfs_SOURCES += ../support/ramdisk_support.h
+mdosfs_fsstatvfs_SOURCES += ../support/fstest.h
+mdosfs_fsstatvfs_SOURCES += ../../psxtests/include/pmacros.h
+mdosfs_fsstatvfs_SOURCES += ../mdosfs_support/fs_support.c
+mdosfs_fsstatvfs_SOURCES += ../mdosfs_support/fs_config.h
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+
+AM_CPPFLAGS += -I$(top_srcdir)/support
+AM_CPPFLAGS += -I$(top_srcdir)/mdosfs_support
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+AM_CPPFLAGS += -I$(top_srcdir)/../psxtests/include
+
+LINK_OBJS = $(mdosfs_fsstatvfs_OBJECTS)
+LINK_LIBS = $(mdosfs_fsstatvfs_LDLIBS)
+
+mdosfs_ffsstatvfs$(EXEEXT): $(mdosfs_fsstatvfs_OBJECTS) $(mdosfs_fsstatvfs_DEPENDENCIES)
+	@rm -f mdosfs_fsstatvfs$(EXEEXT)
+	$(make-exe)
+
+include $(top_srcdir)/../automake/local.am
