/* 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;
#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;
}
/* 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;
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;
nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat)
{
int err = fh_verify(rqstp, fhp, 0, MAY_NOP);
+
if (!err && vfs_statfs(fhp->fh_dentry->d_inode->i_sb,stat))
err = nfserr_io;
return err;
if (acc == MAY_NOP)
return 0;
#if 0
- dprintk("nfsd: permission 0x%x%s%s%s%s%s%s%s mode 0%o%s%s%s\n",
+ printk("nfsd: permission 0x%x%s%s%s%s%s%s%s mode 0%o%s%s%s\n",
acc,
(acc & MAY_READ)? " read" : "",
(acc & MAY_WRITE)? " write" : "",
IS_IMMUTABLE(inode)? " immut" : "",
IS_APPEND(inode)? " append" : "",
IS_RDONLY(inode)? " ro" : "");
- dprintk(" owner %d/%d user %d/%d\n",
+ printk(" owner %d/%d user %d/%d\n",
inode->i_uid, inode->i_gid, current->fsuid, current->fsgid);
#endif