diff mbox

[V9fs-developer] Small patch

Message ID 20090928173402.GA5731@llnl.gov (mailing list archive)
State Superseded, archived
Delegated to: Eric Van Hensbergen
Headers show

Commit Message

Jim Garlick Sept. 28, 2009, 5:34 p.m. UTC
The patch below also addresses a couple of other corner cases in readdir
seen with a large (e.g. 64k) msize.  I'm not sure what people think of
my co-opting of fid->aux here.  I'd be happy to rework if there's a better
way.

Jim


When the size of the user supplied buffer passed to readdir is smaller
than the data returned in one go by the 9P read request, v9fs_dir_readdir()
currently discards extra data so that, on the next call, a 9P read
request will be issued with offset < previous offset + bytes returned,
which voilates the constraint described in paragraph 3 of read(5) description.
This patch preseves the leftover data in fid->aux for use in the next call.

Also, if multiple 9P read requests are required to satisfy the user's
request, clear the 'i' index so that dirents returned in subsequent
responses are not dropped,

Finally, don't increment flip->f_pos if filldir fails.


------------------------------------------------------------------------------
Come build with us! The BlackBerry&reg; Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay 
ahead of the curve. Join us from November 9&#45;12, 2009. Register now&#33;
http://p.sf.net/sfu/devconf
diff mbox

Patch

Index: v9fs/vfs_dir.c
===================================================================
--- v9fs/vfs_dir.c	(.../tags/v9fs-2009.08.27.9psac-3chaos)	(revision 8998)
+++ v9fs/vfs_dir.c	(.../branches/9p-sac)	(revision 8998)
@@ -74,7 +74,7 @@ 
 	struct p9_fid *fid;
 	int buflen;
 	char *statbuf;
-	int n, i = 0;
+	int n, i, reclen;
 
 	P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->COMPAT_f_dentry->d_name.name);
 	fid = filp->private_data;
@@ -85,12 +85,20 @@ 
 		return -ENOMEM;
 
 	while (1) {
-		err = v9fs_file_readn(filp, statbuf, NULL, buflen,
-								fid->rdir_fpos);
-		if (err <= 0)
-			break;
-
-		n = err;
+		if (fid->rdir_fpos > filp->f_pos) {
+			n = fid->rdir_fpos - filp->f_pos;
+			memcpy(statbuf, fid->aux, n);
+			kfree(fid->aux);
+			fid->aux = NULL;
+		} else {
+			err = v9fs_file_readn(filp, statbuf, NULL, buflen,
+					      fid->rdir_fpos);
+			if (err <= 0)
+				break;
+			n = err;
+			fid->rdir_fpos += n;
+		}
+		i = 0;
 		while (i < n) {
 			err = p9stat_read(statbuf + i, buflen-i, &st,
 							fid->clnt->dotu);
@@ -100,21 +108,25 @@ 
 				p9stat_free(&st);
 				goto free_and_exit;
 			}
+			reclen = st.size+2;
 
-			i += st.size+2;
-			fid->rdir_fpos += st.size+2;
-
 			over = filldir(dirent, st.name, strlen(st.name),
 			    filp->f_pos, v9fs_qid2ino(&st.qid), dt_type(&st));
 
-			filp->f_pos += st.size+2;
-
 			p9stat_free(&st);
 
 			if (over) {
+				fid->aux = kmalloc(n - i, GFP_KERNEL);
+				if (!fid->aux) {
+					err = -ENOMEM;
+					goto free_and_exit;
+				}
+				memcpy(fid->aux, statbuf + i, n - i);
 				err = 0;
 				goto free_and_exit;
 			}
+			filp->f_pos += reclen;
+			i += reclen;
 		}
 	}
 
Index: 9p/client.c
===================================================================
--- 9p/client.c	(.../tags/v9fs-2009.08.27.9psac-3chaos)	(revision 8995)
+++ 9p/client.c	(.../branches/9p-sac)	(revision 8995)
@@ -615,6 +615,8 @@ 
 	spin_lock_irqsave(&clnt->lock, flags);
 	list_del(&fid->flist);
 	spin_unlock_irqrestore(&clnt->lock, flags);
+	if (fid->aux)
+		kfree(fid->aux);
 	kfree(fid);
 }