lkml.org 
[lkml]   [1997]   [Dec]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subjectpatch for 2.1.73 knfsd
The attached patch for 2.1.73 nfsd/vfs.c fixes a dentry leak after a
creation error, and streamlines some error exits.

I've also added semaphore protection for the readdir operation to be
consistent with the VFS layer.

Regards,
Bill--- linux-2.1.73/fs/nfsd/vfs.c.old Fri Dec 19 00:22:34 1997
+++ linux-2.1.73/fs/nfsd/vfs.c Fri Dec 19 10:29:23 1997
@@ -568,7 +568,8 @@
dchild = lookup_dentry(fname, dget(dentry), 0);
err = PTR_ERR(dchild);
if(IS_ERR(dchild))
- return nfserrno(-err);
+ goto out_nfserr;
+ fh_compose(resfhp, fhp->fh_export, dchild);
} else
dchild = resfhp->fh_dentry;
/*
@@ -597,19 +598,14 @@
fh_unlock(fhp);

if (err < 0)
- return nfserrno(-err);
+ goto out_nfserr;
if (EX_ISSYNC(fhp->fh_export))
write_inode_now(dirp);

/*
- * Assemble the file handle for the newly created file,
- * or update the filehandle to get the new inode info.
+ * Update the filehandle to get the new inode info.
*/
- if (!resfhp->fh_dverified) {
- fh_compose(resfhp, fhp->fh_export, dchild);
- } else {
- fh_update(resfhp);
- }
+ fh_update(resfhp);

/* Set file attributes. Mode has already been set and
* setting uid/gid works only for root. Irix appears to
@@ -621,6 +617,10 @@
err = nfsd_setattr(rqstp, resfhp, iap);
out:
return err;
+
+out_nfserr:
+ err = nfserrno(-err);
+ goto out;
}

/*
@@ -694,19 +694,21 @@
goto out;

UPDATE_ATIME(inode);
+ /* N.B. Why does this call need a get_fs()?? */
oldfs = get_fs(); set_fs(KERNEL_DS);
err = inode->i_op->readlink(inode, buf, *lenp);
set_fs(oldfs);

if (err < 0)
- err = nfserrno(-err);
- else {
- *lenp = err;
- err = 0;
- }
-
+ goto out_nfserr;
+ *lenp = err;
+ err = 0;
out:
return err;
+
+out_nfserr:
+ err = nfserrno(-err);
+ goto out;
}

/*
@@ -755,12 +757,14 @@
}
}
fh_compose(resfhp, fhp->fh_export, dnew);
-
-out_nfserr:
if (err)
- err = nfserrno(-err);
+ goto out_nfserr;
out:
return err;
+
+out_nfserr:
+ err = nfserrno(-err);
+ goto out;
}

/*
@@ -821,11 +825,14 @@
}
dput_and_out:
dput(dnew);
-out_nfserr:
if (err)
- err = nfserrno(-err);
+ goto out_nfserr;
out:
return err;
+
+out_nfserr:
+ err = nfserrno(-err);
+ goto out;
}

/*
@@ -917,11 +924,14 @@

out_dput_old:
dput(odentry);
-out_nfserr:
if (err)
- err = nfserrno(-err);
+ goto out_nfserr;
out:
return err;
+
+out_nfserr:
+ err = nfserrno(-err);
+ goto out;
}

/*
@@ -965,14 +975,16 @@
fh_unlock(fhp);

dput(rdentry);
- if (!err && EX_ISSYNC(fhp->fh_export))
- write_inode_now(dirp);
-
-out_nfserr:
if (err)
- err = nfserrno(-err);
+ goto out_nfserr;
+ if (EX_ISSYNC(fhp->fh_export))
+ write_inode_now(dirp);
out:
return err;
+
+out_nfserr:
+ err = nfserrno(-err);
+ goto out;
}

/*
@@ -982,22 +994,23 @@
nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
encode_dent_fn func, u32 *buffer, int *countp)
{
- struct readdir_cd cd;
struct inode *inode;
- struct file file;
u32 *p;
int oldlen, eof, err;
+ struct file file;
+ struct readdir_cd cd;

+ err = 0;
if (offset > ~(u32) 0)
- return 0;
+ goto out;

- if ((err = nfsd_open(rqstp, fhp, S_IFDIR, OPEN_READ, &file)) != 0)
- return err;
+ err = nfsd_open(rqstp, fhp, S_IFDIR, OPEN_READ, &file);
+ if (err)
+ goto out;

- if (!file.f_op->readdir) {
- nfsd_close(&file);
- return nfserr_notdir;
- }
+ err = nfserr_notdir;
+ if (!file.f_op->readdir)
+ goto out_close;
file.f_pos = offset;

/* Set up the readdir context */
@@ -1012,7 +1025,7 @@
* may choose to do less.
*/
inode = file.f_dentry->d_inode;
- do {
+ while (1) {
oldlen = cd.buflen;

/*
@@ -1020,16 +1033,16 @@
file.f_inode->i_dev, file.f_inode->i_ino,
(int) file.f_pos, (int) oldlen, (int) cd.buflen);
*/
- err = file.f_op->readdir(&file,
- &cd, (filldir_t) func);
-
- if (err < 0) {
- nfsd_close(&file);
- return nfserrno(-err);
- }
+ down(&inode->i_sem);
+ err = file.f_op->readdir(&file, &cd, (filldir_t) func);
+ up(&inode->i_sem);
+ if (err < 0)
+ goto out_nfserr;
if (oldlen == cd.buflen)
break;
- } while (oldlen != cd.buflen && !cd.eob);
+ if (cd.eob)
+ break;
+ }

/* If we didn't fill the buffer completely, we're at EOF */
eof = !cd.eob;
@@ -1040,9 +1053,6 @@
if (cd.offset && !eof)
*cd.offset = htonl(file.f_pos);

- /* Close the file */
- nfsd_close(&file);
-
p = cd.buffer;
*p++ = 0; /* no more entries */
*p++ = htonl(eof); /* end of directory */
@@ -1051,7 +1061,15 @@
dprintk("nfsd: readdir result %d bytes, eof %d offset %ld\n",
*countp, eof,
cd.offset? ntohl(*cd.offset) : -1);
- return 0;
+ err = 0;
+out_close:
+ nfsd_close(&file);
+out:
+ return err;
+
+out_nfserr:
+ err = nfserrno(-err);
+ goto out_close;
}

/*
\
 
 \ /
  Last update: 2005-03-22 13:40    [W:0.034 / U:0.184 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site