Hi Pranith,

I'm not Avati but I think I can explain the purpose of these functions.

As I've interpreted it, posix_handle_path() should return the path to a "real" 
entry of the filesystem. It can be called for all kind of files, but it seems 
that basename is != NULL only for entries where gfid refers to a directory. 
That seems good.

If the specified gfid refers to anything other than a directory, since they 
are stored inside .glusterfs as hard links, the returned path should simply be 
<brick_root>/.glusterfs/xx/yy/<gfid>.

For gfid's that specify directories, since they are stored inside .glusterfs 
as symlinks, they need to be dereferenced before returning (to point to a real 
directory). That is the purpose of line 362: only if the lstat succeeded (it 
basically means that the entry exists), the path refers to a symbolic link, 
and it has more than 1 hard link (to differentiate a symlink of a directory, 
with 1 hard link, from a "normal" symlink, with at least 2 hard links) then it 
tries to replace the symlink by its referenced real directory.

This is done using the function posix_handle_pump(). This function reads the 
symlink and replaces it into the path:

  If the original path were: <root>/cd/47/cd473c26-b6d6-42a6-a0a4-28e04de13915
  And cd473c26-b6d6-42a6-a0a4-28e04de13915 points to:
      ../../0e/5d/0e5d04a1-f418-4388-90db-d1d7ebb8a071/dir1
  The result is: <root>/0e/5d/0e5d04a1-f418-4388-90db-d1d7ebb8a071/dir1

The returned path points to a directory, so it should be ok. However since 
this path can be composed by other symlinks (in this case 0e5d04a1-
f418-4388-90db-d1d7ebb8a071 will be another symlink), the system needs to 
resolve them every time it accesses the entry. If there are too many of them 
(for example an entry very deep in the directory hierarchy) the system calls 
will return ELOOP (even if there isn't any symlink loop, the system has a 
limit in the number of symlinks it will resolve for any request). This is what 
is tested in the lstat() call at line 374 and the following test at 375: while 
ELOOP is returned by lstat, posix_handle_pump() is called to remove another 
level of symlink indirection. This guarantees that the returned path points to 
a directory *and* it won't fail on system calls with ELOOP.

It's very easy to check this:

  # cd <mount point>
  # mkdir -p d/d/d/d/d/d/d/d/d/d/d/d/d/d/d/d
  # cd <brick root>
  # getfattr -m. -e hex -d d/d/d/d/d/d/d/d/d/d/d/d/d/d/d/d
  # file: d/d/d/d/d/d/d/d/d/d/d/d/d/d/d/d
  trusted.gfid=0xf6e98d542c4f48259976861b7269a396
  trusted.glusterfs.dht=0x000000010000000000000000ffffffff
  # ls .glusterfs/f6/e9/f6e98d54-2c4f-4825-9976-861b7269a396
  ls: cannot access .glusterfs/f6/e9/f6e98d54-2c4f-4825-9976-861b7269a396: Too 
many levels of symbolic links

The loop on posix_handle_pump() avoids this problem.

The possible problem I see is that in the comments it says that this function 
returns a path to an IA_IFDIR (it will return IA_IFDIR on an lstat), however 
if one of the symlinks is missing or anything else fails, it won't return an 
error *but* it will return a path to an existing file. An lstat on this path 
will return IA_IFLNK instead of IA_IFDIR. I don't know if this can be a 
problem in some places.

Xavi

On Monday 02 June 2014 02:00:30 Pranith Kumar Karampuri wrote:
> hi Avati,
>    Could you please explain why posix_handle_pump fixes ELOOP.
> 
> posix_handle_path seems to return gfid-path when the lstat on the base-gfid
> path fails. I am not sure what the behaviour is supposed to be.
> 
> I added the snippet of code for reference below.
> 
> 346         base_len = (priv->base_path_length + SLEN(GF_HIDDEN_PATH) + 45);
> 347         base_str = alloca (base_len + 1);
> 348         base_len = snprintf (base_str, base_len + 1,
> "%s/%s/%02x/%02x/%s", 349                              priv->base_path,
> GF_HIDDEN_PATH, gfid[0], gfid[1], 350                             
> uuid_str);
> 351
> 352         pfx_len = priv->base_path_length + 1 + SLEN(GF_HIDDEN_PATH) + 1;
> 353
> 354         if (basename) {
> 355                 len = snprintf (buf, maxlen, "%s/%s", base_str,
> basename); 356         } else {
> 357                 len = snprintf (buf, maxlen, "%s", base_str);
> 358         }
> 359
> 360         ret = lstat (base_str, &stat);
> 361
> 362         if (!(ret == 0 && S_ISLNK(stat.st_mode) && stat.st_nlink == 1)) 
>         <<<----- 363                 goto out;
> 
> Pranith.
> _______________________________________________
> Gluster-devel mailing list
> Gluster-devel@gluster.org
> http://supercolony.gluster.org/mailman/listinfo/gluster-devel

_______________________________________________
Gluster-devel mailing list
Gluster-devel@gluster.org
http://supercolony.gluster.org/mailman/listinfo/gluster-devel

Reply via email to