/* Obtain dentry and export. */
err = fh_verify(rqstp, fhp, S_IFDIR, MAY_EXEC);
if (err)
- goto out;
+ return err;
dparent = fhp->fh_dentry;
exp = fhp->fh_export;
+ exp_get(exp);
err = nfserr_acces;
err = fh_compose(resfh, exp, dentry, fhp);
if (!err && !dentry->d_inode)
err = nfserr_noent;
+ dput(dentry);
out:
+ exp_put(exp);
return err;
out_nfserr:
static spinlock_t ra_lock = SPIN_LOCK_UNLOCKED;
static inline struct raparms *
-nfsd_get_raparms(dev_t dev, ino_t ino)
+nfsd_get_raparms(dev_t dev, ino_t ino, struct address_space *mapping)
{
struct raparms *ra, **rap, **frap = NULL;
int depth = 0;
ra = *frap;
ra->p_dev = dev;
ra->p_ino = ino;
- memset(&ra->p_ra, 0, sizeof(ra->p_ra));
+ file_ra_state_init(&ra->p_ra, mapping);
found:
if (rap != &raparm_cache) {
*rap = ra->p_next;
nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset , unsigned long size)
{
unsigned long count = desc->count;
- struct svc_rqst *rqstp = (struct svc_rqst *)desc->buf;
+ struct svc_rqst *rqstp = desc->arg.data;
if (size > count)
size = count;
*/
int
nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
- struct iovec *vec, int vlen, unsigned long *count)
+ struct kvec *vec, int vlen, unsigned long *count)
{
struct raparms *ra;
mm_segment_t oldfs;
#endif
/* Get readahead parameters */
- ra = nfsd_get_raparms(inode->i_sb->s_dev, inode->i_ino);
+ ra = nfsd_get_raparms(inode->i_sb->s_dev, inode->i_ino,
+ inode->i_mapping->host->i_mapping);
if (ra)
file.f_ra = ra->p_ra;
} else {
oldfs = get_fs();
set_fs(KERNEL_DS);
- err = vfs_readv(&file, vec, vlen, &offset);
+ err = vfs_readv(&file, (struct iovec __user *)vec, vlen, &offset);
set_fs(oldfs);
}
/* Write back readahead params */
- if (ra)
+ if (ra) {
+ spin_lock(&ra_lock);
ra->p_ra = file.f_ra;
-
+ ra->p_count--;
+ spin_unlock(&ra_lock);
+ }
if (err >= 0) {
nfsdstats.io_read += err;
*count = err;
*/
int
nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
- struct iovec *vec, int vlen,
+ struct kvec *vec, int vlen,
unsigned long cnt, int *stablep)
{
struct svc_export *exp;
/* Write the data. */
oldfs = get_fs(); set_fs(KERNEL_DS);
- err = vfs_writev(&file, vec, vlen, &offset);
+ err = vfs_writev(&file, (struct iovec __user *)vec, vlen, &offset);
set_fs(oldfs);
if (err >= 0) {
nfsdstats.io_write += cnt;
char *fname, int flen, struct iattr *iap,
int type, dev_t rdev, struct svc_fh *resfhp)
{
- struct dentry *dentry, *dchild;
+ struct dentry *dentry, *dchild = NULL;
struct inode *dirp;
int err;
goto out;
} else {
/* called from nfsd_proc_create */
- dchild = resfhp->fh_dentry;
+ dchild = dget(resfhp->fh_dentry);
if (!fhp->fh_locked) {
/* not actually possible */
printk(KERN_ERR
if (!err)
err = fh_update(resfhp);
out:
+ if (dchild && !IS_ERR(dchild))
+ dput(dchild);
return err;
out_nfserr:
struct svc_fh *resfhp, int createmode, u32 *verifier,
int *truncp)
{
- struct dentry *dentry, *dchild;
+ struct dentry *dentry, *dchild = NULL;
struct inode *dirp;
int err;
__u32 v_mtime=0, v_atime=0;
out:
fh_unlock(fhp);
+ if (dchild && !IS_ERR(dchild))
+ dput(dchild);
return err;
out_nfserr:
{
struct dentry *dentry, *dnew;
int err, cerr;
+ umode_t mode;
err = nfserr_noent;
if (!flen || !plen)
if (IS_ERR(dnew))
goto out_nfserr;
+ mode = S_IALLUGO;
+ /* Only the MODE ATTRibute is even vaguely meaningful */
+ if (iap && (iap->ia_valid & ATTR_MODE))
+ mode = iap->ia_mode & S_IALLUGO;
+
if (unlikely(path[plen] != 0)) {
char *path_alloced = kmalloc(plen+1, GFP_KERNEL);
if (path_alloced == NULL)
else {
strncpy(path_alloced, path, plen);
path_alloced[plen] = 0;
- err = vfs_symlink(dentry->d_inode, dnew, path_alloced);
+ err = vfs_symlink(dentry->d_inode, dnew, path_alloced, mode);
kfree(path_alloced);
}
} else
- err = vfs_symlink(dentry->d_inode, dnew, path);
+ err = vfs_symlink(dentry->d_inode, dnew, path, mode);
if (!err) {
if (EX_ISSYNC(fhp->fh_export))
nfsd_sync_dir(dentry);
- if (iap) {
- iap->ia_valid &= ATTR_MODE /* ~(ATTR_MODE|ATTR_UID|ATTR_GID)*/;
- if (iap->ia_valid) {
- iap->ia_valid |= ATTR_CTIME;
- iap->ia_mode = (iap->ia_mode&S_IALLUGO)
- | S_IFLNK;
- err = notify_change(dnew, iap);
- if (err)
- err = nfserrno(err);
- else if (EX_ISSYNC(fhp->fh_export))
- write_inode_now(dentry->d_inode, 1);
- }
- }
} else
err = nfserrno(err);
fh_unlock(fhp);
- /* Compose the fh so the dentry will be freed ... */
cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp);
+ dput(dnew);
if (err==0) err = cerr;
out:
return err;
err = nfsd_open(rqstp, fhp, S_IFDIR, MAY_READ, &file);
if (err)
goto out;
- if (offset > ~(u32) 0)
- goto out_close;
- file.f_pos = offset;
+ offset = vfs_llseek(&file, offset, 0);
+ if (offset < 0) {
+ err = nfserrno((int)offset);
+ goto out_close;
+ }
/*
* Read the directory entries. This silly loop is necessary because
err = nfserrno(err);
else
err = cdp->err;
- *offsetp = file.f_pos;
+ *offsetp = vfs_llseek(&file, 0, 1);
if (err == nfserr_eof || err == nfserr_toosmall)
err = nfs_ok; /* can still be found in ->err */