Messages in this thread Patch in this message | | | Date | Fri, 19 Dec 1997 11:26:10 -0500 | From | Bill Hawes <> | Subject | patch 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; } /* | |