efivarfs: expose used and total size
[linux-2.6-block.git] / fs / efivarfs / super.c
index 482d612b716bb1f06b10b7dd7fced44f85eafffd..e028fafa04f38c51739bb56c796bb5d854c7c4ba 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/ucs2_string.h>
 #include <linux/slab.h>
 #include <linux/magic.h>
+#include <linux/statfs.h>
 
 #include "internal.h"
 
@@ -23,8 +24,44 @@ static void efivarfs_evict_inode(struct inode *inode)
        clear_inode(inode);
 }
 
+static int efivarfs_statfs(struct dentry *dentry, struct kstatfs *buf)
+{
+       const u32 attr = EFI_VARIABLE_NON_VOLATILE |
+                        EFI_VARIABLE_BOOTSERVICE_ACCESS |
+                        EFI_VARIABLE_RUNTIME_ACCESS;
+       u64 storage_space, remaining_space, max_variable_size;
+       efi_status_t status;
+
+       status = efivar_query_variable_info(attr, &storage_space, &remaining_space,
+                                           &max_variable_size);
+       if (status != EFI_SUCCESS)
+               return efi_status_to_err(status);
+
+       /*
+        * This is not a normal filesystem, so no point in pretending it has a block
+        * size; we declare f_bsize to 1, so that we can then report the exact value
+        * sent by EFI QueryVariableInfo in f_blocks and f_bfree
+        */
+       buf->f_bsize    = 1;
+       buf->f_namelen  = NAME_MAX;
+       buf->f_blocks   = storage_space;
+       buf->f_bfree    = remaining_space;
+       buf->f_type     = dentry->d_sb->s_magic;
+
+       /*
+        * In f_bavail we declare the free space that the kernel will allow writing
+        * when the storage_paranoia x86 quirk is active. To use more, users
+        * should boot the kernel with efi_no_storage_paranoia.
+        */
+       if (remaining_space > efivar_reserved_space())
+               buf->f_bavail = remaining_space - efivar_reserved_space();
+       else
+               buf->f_bavail = 0;
+
+       return 0;
+}
 static const struct super_operations efivarfs_ops = {
-       .statfs = simple_statfs,
+       .statfs = efivarfs_statfs,
        .drop_inode = generic_delete_inode,
        .evict_inode = efivarfs_evict_inode,
 };