patch-2.3.24 linux/fs/nfsd/vfs.c
Next file: linux/fs/romfs/inode.c
Previous file: linux/fs/nfsd/nfssvc.c
Back to the patch index
Back to the overall index
- Lines: 226
- Date:
Tue Oct 26 17:33:02 1999
- Orig file:
v2.3.23/linux/fs/nfsd/vfs.c
- Orig date:
Fri Oct 15 15:25:14 1999
diff -u --recursive --new-file v2.3.23/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c
@@ -234,6 +234,7 @@
int ftype = 0;
int imode;
int err;
+ kernel_cap_t saved_cap = 0;
if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE))
accmode |= MAY_WRITE;
@@ -242,7 +243,7 @@
/* Get inode */
err = fh_verify(rqstp, fhp, ftype, accmode);
- if (err)
+ if (err || !iap->ia_valid)
goto out;
dentry = fhp->fh_dentry;
@@ -252,7 +253,7 @@
if (err)
goto out_nfserr;
- /* The size case is special... */
+ /* The size case is special. It changes the file as well as the attributes. */
if (iap->ia_valid & ATTR_SIZE) {
if (!S_ISREG(inode->i_mode))
printk("nfsd_setattr: size change??\n");
@@ -264,15 +265,14 @@
err = get_write_access(inode);
if (err)
goto out_nfserr;
- /* N.B. Should we update the inode cache here? */
- inode->i_size = iap->ia_size;
- if (inode->i_op && inode->i_op->truncate)
- inode->i_op->truncate(inode);
- mark_inode_dirty(inode);
- put_write_access(inode);
- iap->ia_valid &= ~ATTR_SIZE;
- iap->ia_valid |= ATTR_MTIME;
- iap->ia_mtime = CURRENT_TIME;
+
+ err = locks_verify_area(FLOCK_VERIFY_WRITE, inode, NULL,
+ iap->ia_size<inode->i_size ? iap->ia_size : inode->i_size,
+ abs(inode->i_size - iap->ia_size));
+
+ if (err)
+ goto out_nfserr;
+ DQUOT_INIT(inode);
}
imode = inode->i_mode;
@@ -294,23 +294,32 @@
}
/* Change the attributes. */
- if (iap->ia_valid) {
- kernel_cap_t saved_cap = 0;
- iap->ia_valid |= ATTR_CTIME;
- iap->ia_ctime = CURRENT_TIME;
- if (current->fsuid != 0) {
- saved_cap = current->cap_effective;
- cap_clear(current->cap_effective);
- }
+
+ iap->ia_valid |= ATTR_CTIME;
+ if (current->fsuid != 0) {
+ saved_cap = current->cap_effective;
+ cap_clear(current->cap_effective);
+ }
+ if (iap->ia_valid & ATTR_SIZE) {
+ fh_lock(fhp);
err = notify_change(dentry, iap);
- if (current->fsuid != 0)
- current->cap_effective = saved_cap;
- if (err)
- goto out_nfserr;
- if (EX_ISSYNC(fhp->fh_export))
- write_inode_now(inode);
+ if (!err) {
+ vmtruncate(inode,iap->ia_size);
+ if (inode->i_op && inode->i_op->truncate)
+ inode->i_op->truncate(inode);
+ }
+ fh_unlock(fhp);
+ put_write_access(inode);
}
+ else
+ err = notify_change(dentry, iap);
+ if (current->fsuid != 0)
+ current->cap_effective = saved_cap;
+ if (err)
+ goto out_nfserr;
+ if (EX_ISSYNC(fhp->fh_export))
+ write_inode_now(inode);
err = 0;
out:
return err;
@@ -401,7 +410,6 @@
filp->f_op->release(inode, filp);
if (filp->f_mode & FMODE_WRITE) {
put_write_access(inode);
- DQUOT_DROP(inode);
}
}
@@ -548,7 +556,6 @@
if ((stable || (stable = EX_ISSYNC(exp))) && !EX_WGATHER(exp))
file.f_flags |= O_SYNC;
- fh_lock(fhp); /* lock inode */
file.f_pos = offset; /* set write offset */
/* Write the data. */
@@ -580,8 +587,6 @@
current->cap_effective = saved_cap;
}
- fh_unlock(fhp); /* unlock inode */
-
if (err >= 0 && stable) {
static unsigned long last_ino = 0;
static kdev_t last_dev = NODEV;
@@ -651,9 +656,13 @@
err = nfserr_perm;
if (!flen)
goto out;
- err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE);
- if (err)
- goto out;
+
+ /* from mkdir it won't be verified, from create it will */
+ if (!fhp->fh_dverified) {
+ err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE);
+ if (err)
+ goto out;
+ }
dentry = fhp->fh_dentry;
dirp = dentry->d_inode;
@@ -731,7 +740,6 @@
*/
DQUOT_INIT(dirp);
err = opfunc(dirp, dchild, iap->ia_mode, rdev);
- DQUOT_DROP(dirp);
if (err < 0)
goto out_nfserr;
@@ -786,6 +794,11 @@
err = get_write_access(inode);
if (err)
goto out_nfserr;
+ err = locks_verify_area(FLOCK_VERIFY_WRITE, inode, NULL,
+ size<inode->i_size ? size : inode->i_size,
+ abs(inode->i_size - size));
+ if (err)
+ goto out_nfserr;
/* Things look sane, lock and do it. */
fh_lock(fhp);
@@ -797,15 +810,14 @@
cap_clear(current->cap_effective);
}
err = notify_change(dentry, &newattrs);
- if (current->fsuid != 0)
- current->cap_effective = saved_cap;
if (!err) {
vmtruncate(inode, size);
if (inode->i_op && inode->i_op->truncate)
inode->i_op->truncate(inode);
}
+ if (current->fsuid != 0)
+ current->cap_effective = saved_cap;
put_write_access(inode);
- DQUOT_DROP(inode);
fh_unlock(fhp);
out_nfserr:
if (err)
@@ -902,7 +914,6 @@
if (!dnew->d_inode) {
DQUOT_INIT(dirp);
err = dirp->i_op->symlink(dirp, dnew, path);
- DQUOT_DROP(dirp);
if (!err) {
if (EX_ISSYNC(fhp->fh_export))
write_inode_now(dirp);
@@ -981,7 +992,6 @@
DQUOT_INIT(dirp);
err = dirp->i_op->link(dold, dirp, dnew);
- DQUOT_DROP(dirp);
if (!err) {
if (EX_ISSYNC(ffhp->fh_export)) {
write_inode_now(dirp);
@@ -1105,8 +1115,6 @@
}
} else
dprintk("nfsd: Caught race in nfsd_rename");
- DQUOT_DROP(fdir);
- DQUOT_DROP(tdir);
nfsd_double_up(&tdir->i_sem, &fdir->i_sem);
dput(ndentry);
@@ -1157,7 +1165,6 @@
goto out;
}
- expire_by_dentry(rdentry);
if (type != S_IFDIR) {
/* It's UNLINK */
@@ -1168,7 +1175,6 @@
err = vfs_unlink(dirp, rdentry);
- DQUOT_DROP(dirp);
fh_unlock(fhp);
dput(rdentry);
@@ -1188,7 +1194,6 @@
err = vfs_rmdir(dirp, rdentry);
rdentry->d_count--;
- DQUOT_DROP(dirp);
if (!fhp->fh_post_version)
fhp->fh_post_version = dirp->i_version;
fhp->fh_locked = 0;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)