patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / fs / nfsd / vfs.c
index f5586d8..d520fea 100644 (file)
@@ -141,10 +141,11 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
        /* 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;
 
@@ -208,7 +209,9 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
        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:
@@ -564,7 +567,7 @@ nfsd_sync_dir(struct dentry *dp)
 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;
@@ -586,7 +589,7 @@ nfsd_get_raparms(dev_t dev, ino_t ino)
        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;
@@ -658,7 +661,8 @@ nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
 #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;
 
@@ -674,9 +678,12 @@ nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
        }
 
        /* 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;
@@ -859,7 +866,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
                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;
 
@@ -896,7 +903,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
                        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
@@ -965,6 +972,8 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
        if (!err)
                err = fh_update(resfhp);
 out:
+       if (dchild && !IS_ERR(dchild))
+               dput(dchild);
        return err;
 
 out_nfserr:
@@ -982,7 +991,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
                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;
@@ -1111,6 +1120,8 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
 
  out:
        fh_unlock(fhp);
+       if (dchild && !IS_ERR(dchild))
+               dput(dchild);
        return err;
  
  out_nfserr:
@@ -1177,6 +1188,7 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
 {
        struct dentry   *dentry, *dnew;
        int             err, cerr;
+       umode_t         mode;
 
        err = nfserr_noent;
        if (!flen || !plen)
@@ -1195,6 +1207,11 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
        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)
@@ -1202,34 +1219,21 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
                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;
@@ -1510,6 +1514,7 @@ int
 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;
@@ -1527,7 +1532,7 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
        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" : "",
@@ -1540,7 +1545,7 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
                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