[BUG] Calling BTRFS_IOC_TREE_SEARCH for a non existant key

2010-12-19 Thread Goffredo Baroncelli
Hi all,

I discovered that when I call the BTRFS_IOC_TREE_SEARCH ioctl for a not 
existent key, the ioctl requires a lot of time to be completed.

I tracks down the problem in the function search_ioctl(). It seems that the 
function btrfs_search_forward() doesn't check if key is greater than max_key. 

file ioctl.c
   
   988  static noinline int search_ioctl(struct inode *inode,
   989   struct btrfs_ioctl_search_args *args)
[...]
  1025  while(1) {
  1026  ret = btrfs_search_forward(root, key, max_key, path, 
0,
  1027 sk-min_transid);
  1028  if (ret != 0) {
  1029  if (ret  0)
  1030  ret = 0;
  1031  goto err;
  1032  }
  1033  ret = copy_to_sk(root, path, key, sk, args-buf,
  1034   sk_offset, num_found);
  1035  btrfs_release_path(root, path);
  1036  if (ret || num_found = sk-nr_items)
  1037  break;
   
  1038  }

The function btrfs_search_forward() doesn't check the key (or min_key) against 
max_key when the parameter cache_only == 0.

from ctree.c

  3624  int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key 
*min_key,
  3625   struct btrfs_key *max_key,
  3626   struct btrfs_path *path, int cache_only,
  3627   u64 min_trans)
  3628  {
[..]
  3678  if (!cache_only)
  3679  break;
   
  3680  if (max_key) {
  3681  btrfs_node_key(cur, disk_key, slot);
  3682  if (comp_keys(disk_key, max_key) = 
0) {
  3683  ret = 1;
  3684  goto out;
  3685  }
  3686  }
   


So in the function search_ioctl the search is not completed until the args 
buffer is filled or the function copy_to_sk detects that key is greater than 
sk-max_*. 

However the check performed by the function copy_to_sk is not always 
sufficient to detect if a key is greater than sk-max_*. For example if 
key.objectid  sk-max_objectid but key.offset is  sk-max_offset, the key is 
supposed to be valid.

   913  static noinline int copy_to_sk(struct btrfs_root *root,
[...]
   970  }
   971  advance_key:
   972  ret = 0;
   973  if (key-offset  (u64)-1  key-offset  sk-max_offset)
   974  key-offset++;
   975  else if (key-type  (u8)-1  key-type  sk-max_type) {
   976  key-offset = 0;
   977  key-type++;
   978  } else if (key-objectid  (u64)-1  key-objectid  sk-
max_objectid) {
   979  key-offset = 0;
   980  key-type = 0;
   981  key-objectid++;
   982  } else
   983  ret = 1;
   984  overflow:
   985  *num_found += found;
   986  return ret;
   987  }
  
To solve this problem it should be sufficient a key check before the call of 
btrfs_search_forward(). 
But I don't know if this is a workaround or the root cause is inside the 
function btrfs_search_forward() that doesn't check the key against max_key if 
cached_only is 0.


Regards
G.Baroncelli

-- 
gpg key@ keyserver.linux.it: Goffredo Baroncelli (ghigo) kreij...@inwind.it
Key fingerprint = 4769 7E51 5293 D36C 814E  C054 BF04 F161 3DC5 0512
--
To unsubscribe from this list: send the line unsubscribe linux-btrfs in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] Improve error handling in filesystem df

2010-12-19 Thread Ben Gamari
The return values of ioctl weren't being printed to stderr on failure,
causing the command to silently fail, resulting in a very confused
user.

Signed-off-by: Ben Gamari bgamari.f...@gmail.com
---
 btrfs_cmds.c |2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/btrfs_cmds.c b/btrfs_cmds.c
index 8031c58..45da2bd 100644
--- a/btrfs_cmds.c
+++ b/btrfs_cmds.c
@@ -857,6 +857,7 @@ int do_df_filesystem(int nargs, char **argv)
 
ret = ioctl(fd, BTRFS_IOC_SPACE_INFO, sargs);
if (ret) {
+   fprintf(stderr, ERROR: can't query '%s' for free space 
(%s)\n, path, strerror(-ret));
free(sargs);
return ret;
}
@@ -875,6 +876,7 @@ int do_df_filesystem(int nargs, char **argv)
 
ret = ioctl(fd, BTRFS_IOC_SPACE_INFO, sargs);
if (ret) {
+   fprintf(stderr, ERROR: can't query '%s' for free space 
(%s)\n, path, strerror(-ret));
free(sargs);
return ret;
}
-- 
1.7.1

--
To unsubscribe from this list: send the line unsubscribe linux-btrfs in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html



Re: [BUG?] There is a possibility that 'i_ino' overflows

2010-12-19 Thread Tsutomu Itoh

(2010/12/16 17:44), Tsutomu Itoh wrote:
 Hi,
 
 In btrfs, inode number is increased each time a new file or directory
 is made.
 Therefore, if the making deletion of the file is repeated, value of
 'i_ino' increases rapidly.
 
 For example, inode number changes as follows. 
 
   $ touch foo
   $ ls -i foo
   266 foo
   $ rm foo
   $ touch bar
   $ ls -i bar
   267 bar
   $
 
 And then, length of 'i_ino' and 'objectid' is as follows on the x86
 system. 
 
   unsigned long i_ino == 32bits
   u64 objectid== 64bits
 
 Therefore, in the operation to substitute 'objectid' to 'i_ino',
 'i_ino' overflows when 'objectid' 4294967296 is substituted to 'i_ino'. 
 Then, the file with inode number 0 is made.

I think that it is better to recycle inode number that became unused. 
And, at least, I think that it should make the filesystem not become an
abnormal condition. 

This patch is a patch that makes an error when inode number is bigger
than BTRFS_LAST_FREE_OBJECTID.


Signed-off-by: Tsutomu Itoh t-i...@jp.fujitsu.com
---
 inode.c |4 
 1 file changed, 4 insertions(+)

diff -urNp linux-2.6.37-rc6/fs/btrfs/inode.c 
linux-2.6.37-rc6.new/fs/btrfs/inode.c
--- linux-2.6.37-rc6/fs/btrfs/inode.c   2010-12-16 10:24:48.0 +0900
+++ linux-2.6.37-rc6.new/fs/btrfs/inode.c   2010-12-20 09:04:18.0 
+0900
@@ -4529,6 +4529,10 @@ static struct inode *btrfs_new_inode(str
 
inode_init_owner(inode, dir, mode);
inode-i_ino = objectid;
+   if (unlikely(inode-i_ino  (unsigned long)BTRFS_LAST_FREE_OBJECTID)) {
+   ret = -ENOSPC;
+   goto fail;
+   }
inode_set_bytes(inode, 0);
inode-i_mtime = inode-i_atime = inode-i_ctime = CURRENT_TIME;
inode_item = btrfs_item_ptr(path-nodes[0], path-slots[0],


 As a result, ls command has looped infinitely, and btrfsck detected the
 error.
 Please see below.
 
   $ uname -a
   Linux luna 2.6.37-rc5 #1 SMP Thu Dec 9 13:02:41 JST 2010 i686 i686 i386 
 GNU/Linux
   $ df -T /test1
   FilesystemType   1K-blocks  Used Available Use% Mounted on
   /dev/sdd14   btrfs 416256056   3717632   1% /test1
   $ strace -FfTttx ls /test1
   14:03:10.115440 execve(/bin/ls, [ls, /test1], [/* 28 vars */]) = 0 
 0.000181
   ...
   ...
   14:03:10.123431 stat(/test1, {st_mode=S_IFDIR|0777, st_size=8, ...}) = 0 
 0.17
   14:03:10.123521 open(/test1, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 
 3 0.18
   14:03:10.123578 fcntl(3, F_GETFD)   = 0x1 (flags FD_CLOEXEC) 0.13
   14:03:10.123637 getdents(3, /* 3 entries */, 32768) = 72 0.25
   14:03:10.123712 getdents(3, /* 1 entries */, 32768) = 24 0.16
   14:03:10.123768 getdents(3, /* 1 entries */, 32768) = 24 0.15
   14:03:10.123824 getdents(3, /* 1 entries */, 32768) = 24 0.15
   14:03:10.123880 getdents(3, /* 1 entries */, 32768) = 24 0.15
   14:03:10.123936 getdents(3, /* 1 entries */, 32768) = 24 0.14
   14:03:10.123992 getdents(3, /* 1 entries */, 32768) = 24 0.15
   14:03:10.124047 getdents(3, /* 1 entries */, 32768) = 24 0.15
   14:03:10.124103 getdents(3, /* 1 entries */, 32768) = 24 0.15
   14:03:10.124261 getdents(3, /* 1 entries */, 32768) = 24 0.16
   14:03:10.124320 getdents(3, /* 1 entries */, 32768) = 24 0.15
   14:03:10.124381 getdents(3, /* 1 entries */, 32768) = 24 0.15
   14:03:10.124437 getdents(3, /* 1 entries */, 32768) = 24 0.14
   14:03:10.124493 getdents(3, /* 1 entries */, 32768) = 24 0.14
   14:03:10.124549 getdents(3, /* 1 entries */, 32768) = 24 0.14
   14:03:10.124605 getdents(3, /* 1 entries */, 32768) = 24 0.14
   14:03:10.124661 getdents(3, /* 1 entries */, 32768) = 24 0.14
   14:03:10.124717 getdents(3, /* 1 entries */, 32768) = 24 0.14
   14:03:10.124773 getdents(3, /* 1 entries */, 32768) = 24 0.14
   14:03:10.124840 getdents(3, /* 1 entries */, 32768) = 24 0.14
   14:03:10.124896 getdents(3, /* 1 entries */, 32768) = 24 0.14
   ...
   ...
   $ cd /test1
   $ ls -i A123
   ls: cannot access A123: No such file or directory
   $ touch 
   $ ls -i 
   1 
   $
 
   # umount /test1
   # btrfsck /dev/sdd14
   root 5 inode 0 errors 2001
   unresolved ref dir 256 index 4294967041 namelen 4 name A123 
 filetype 1 error 4
   root 5 inode 1 errors 2001
   unresolved ref dir 256 index 4294967042 namelen 4 name  
 filetype 1 error 4
   root 5 inode 4294967296 errors 2000
   unresolved ref dir 256 index 4294967041 namelen 4 name A123 
 filetype 0 error 3
   root 5 inode 4294967297 errors 2000
   unresolved ref dir 256 index 4294967042 namelen 4 name  
 filetype 0 error 3
   found 28672 bytes used err is 1
   total csum bytes: 0
   total tree bytes: 28672
   total fs tree bytes: 8192
   btree space waste bytes: 23191
   file data blocks allocated: 0
referenced 0
   Btrfs v0.19-36-g70c6c10
   #
 
 
 Regards,
 Itoh
 

--
To unsubscribe from this list: send the line unsubscribe