[Pvfs2-cvs] commit by pcarns in pvfs2-1/src/kernel/linux-2.6: dir.c

CVS commit program cvs at parl.clemson.edu
Mon Jan 28 13:04:53 EST 2008


Update of /projects/cvsroot/pvfs2-1/src/kernel/linux-2.6
In directory parlweb1:/tmp/cvs-serv1435/src/kernel/linux-2.6

Modified Files:
	dir.c 
Log Message:
adding a special seek operation for pvfs2 directories.  The default vfs seek
doesn't work because we have special meanings for f_pos on directories:

- 0 and 1: fake "." and ".." entries
- PVFS_READDIR_END and PVFS_READDIR_START: special names
- all else: pvfs readdir token value

Who would want to seek on a directory?  Well, glibc occasionally decides to
for some reason: glibc-*/sysdeps/unix/sysv/linux/getdents.c.  There is still
a flaw in that we can't seek to offset 3 or 4 if someone happens to do that
(see code comments).  See this trac entry for how to trigger (and lose dir
entries) on some systems:
https://trac.mcs.anl.gov/projects/pvfs/ticket/11


Index: dir.c
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/kernel/linux-2.6/dir.c,v
diff -p -u -r1.50 -r1.51
--- dir.c	19 Dec 2007 05:37:36 -0000	1.50
+++ dir.c	28 Jan 2008 18:04:53 -0000	1.51
@@ -878,6 +878,43 @@ static int pvfs2_readdirplus_lite(
 }
 #endif
 
+/** Change the file pointer position for an instance of an open dir.
+ *
+ *  \note If .llseek is overriden, we must acquire lock as described in
+ *        Documentation/filesystems/Locking.
+ */
+loff_t pvfs2_dir_llseek(struct file *file, loff_t offset, int origin)
+{
+    /* offsets 0 and 1 are fine */
+
+    if (origin == SEEK_SET && offset == 2)
+    {
+	gossip_debug(GOSSIP_DIR_DEBUG, "pvfs2_dir_llseek: setting READDIR_START\n");
+        /* offset 2 _really_ means the first true pvfs entry, skip . and .. */
+        offset = PVFS_READDIR_START;
+    }
+    else if (origin == SEEK_SET && ((offset == 3) || (offset == 4)))
+    {
+        /* we don't have any way to specify this; if we set offset to 
+         * 0 or 1 then pvfs_readdir() will think you want "." or ".."
+         */
+        gossip_err("PVFS can't seek directories to offset 3 or 4!\n");
+        return(-EINVAL);
+    }
+    else if (origin == SEEK_SET && offset > 4)
+    {
+	gossip_debug(GOSSIP_DIR_DEBUG, "pvfs2_dir_llseek: guessing directory token\n");
+        /* contrive what the pvfs readdir token probably is, assuming that
+         * we need to skip two entries as well */
+        offset -= 3;
+    }
+
+    gossip_debug(GOSSIP_FILE_DEBUG, "pvfs2_dir_llseek: offset is %ld | origin is %d\n",
+                (long)offset, origin);
+
+    return generic_file_llseek(file, offset, origin);
+}
+
 /** PVFS2 implementation of VFS directory operations */
 struct file_operations pvfs2_dir_operations =
 {
@@ -885,7 +922,8 @@ struct file_operations pvfs2_dir_operati
     read : generic_read_dir,
     readdir : pvfs2_readdir,
     open : pvfs2_file_open,
-    release : pvfs2_file_release
+    release : pvfs2_file_release,
+    llseek : pvfs2_dir_llseek
 #else
     .read = generic_read_dir,
     .readdir = pvfs2_readdir,
@@ -896,7 +934,8 @@ struct file_operations pvfs2_dir_operati
     .readdirplus_lite = pvfs2_readdirplus_lite,
 #endif
     .open = pvfs2_file_open,
-    .release = pvfs2_file_release
+    .release = pvfs2_file_release,
+    .llseek = pvfs2_dir_llseek
 #endif
 };
 



More information about the Pvfs2-cvs mailing list