]> err.no Git - linux-2.6/blobdiff - fs/nfsd/vfs.c
Merge ../torvalds-2.6/
[linux-2.6] / fs / nfsd / vfs.c
index be24ead89d94935298af52020262978136887d1f..df4019f04560d54df1b1c0faa270f18b3afd0d40 100644 (file)
@@ -45,7 +45,7 @@
 #endif /* CONFIG_NFSD_V3 */
 #include <linux/nfsd/nfsfh.h>
 #include <linux/quotaops.h>
-#include <linux/dnotify.h>
+#include <linux/fsnotify.h>
 #include <linux/posix_acl.h>
 #include <linux/posix_acl_xattr.h>
 #ifdef CONFIG_NFSD_V4
@@ -254,12 +254,19 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
 
        /* Get inode */
        err = fh_verify(rqstp, fhp, ftype, accmode);
-       if (err || !iap->ia_valid)
+       if (err)
                goto out;
 
        dentry = fhp->fh_dentry;
        inode = dentry->d_inode;
 
+       /* Ignore any mode updates on symlinks */
+       if (S_ISLNK(inode->i_mode))
+               iap->ia_valid &= ~ATTR_MODE;
+
+       if (!iap->ia_valid)
+               goto out;
+
        /* NFSv2 does not differentiate between "set-[ac]time-to-now"
         * which only requires access, and "set-[ac]time-to-X" which
         * requires ownership.
@@ -710,30 +717,36 @@ nfsd_close(struct file *filp)
  * As this calls fsync (not fdatasync) there is no need for a write_inode
  * after it.
  */
-static inline void nfsd_dosync(struct file *filp, struct dentry *dp,
-                              struct file_operations *fop)
+static inline int nfsd_dosync(struct file *filp, struct dentry *dp,
+                             struct file_operations *fop)
 {
        struct inode *inode = dp->d_inode;
        int (*fsync) (struct file *, struct dentry *, int);
+       int err = nfs_ok;
 
        filemap_fdatawrite(inode->i_mapping);
        if (fop && (fsync = fop->fsync))
-               fsync(filp, dp, 0);
+               err=fsync(filp, dp, 0);
        filemap_fdatawait(inode->i_mapping);
+
+       return nfserrno(err);
 }
        
 
-static void
+static int
 nfsd_sync(struct file *filp)
 {
+        int err;
        struct inode *inode = filp->f_dentry->d_inode;
        dprintk("nfsd: sync file %s\n", filp->f_dentry->d_name.name);
        down(&inode->i_sem);
-       nfsd_dosync(filp, filp->f_dentry, filp->f_op);
+       err=nfsd_dosync(filp, filp->f_dentry, filp->f_op);
        up(&inode->i_sem);
+
+       return err;
 }
 
-static void
+void
 nfsd_sync_dir(struct dentry *dp)
 {
        nfsd_dosync(NULL, dp, dp->d_inode->i_fop);
@@ -860,13 +873,23 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
                nfsdstats.io_read += err;
                *count = err;
                err = 0;
-               dnotify_parent(file->f_dentry, DN_ACCESS);
+               fsnotify_access(file->f_dentry);
        } else 
                err = nfserrno(err);
 out:
        return err;
 }
 
+static void kill_suid(struct dentry *dentry)
+{
+       struct iattr    ia;
+       ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID;
+
+       down(&dentry->d_inode->i_sem);
+       notify_change(dentry, &ia);
+       up(&dentry->d_inode->i_sem);
+}
+
 static inline int
 nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
                                loff_t offset, struct kvec *vec, int vlen,
@@ -916,18 +939,12 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
        set_fs(oldfs);
        if (err >= 0) {
                nfsdstats.io_write += cnt;
-               dnotify_parent(file->f_dentry, DN_MODIFY);
+               fsnotify_modify(file->f_dentry);
        }
 
        /* clear setuid/setgid flag after write */
-       if (err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID))) {
-               struct iattr    ia;
-               ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID;
-
-               down(&inode->i_sem);
-               notify_change(dentry, &ia);
-               up(&inode->i_sem);
-       }
+       if (err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID)))
+               kill_suid(dentry);
 
        if (err >= 0 && stable) {
                static ino_t    last_ino;
@@ -955,7 +972,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
 
                        if (inode->i_state & I_DIRTY) {
                                dprintk("nfsd: write sync %d\n", current->pid);
-                               nfsd_sync(file);
+                               err=nfsd_sync(file);
                        }
 #if 0
                        wake_up(&inode->i_wait);
@@ -1059,7 +1076,7 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
                return err;
        if (EX_ISSYNC(fhp->fh_export)) {
                if (file->f_op && file->f_op->fsync) {
-                       nfsd_sync(file);
+                       err = nfsd_sync(file);
                } else {
                        err = nfserr_notsupp;
                }