patch-2.1.73 linux/fs/nfsd/vfs.c
Next file: linux/fs/proc/generic.c
Previous file: linux/fs/nfs/write.c
Back to the patch index
Back to the overall index
- Lines: 246
- Date:
Wed Dec 10 09:15:30 1997
- Orig file:
v2.1.72/linux/fs/nfsd/vfs.c
- Orig date:
Wed Dec 10 11:12:45 1997
diff -u --recursive --new-file v2.1.72/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c
@@ -62,7 +62,8 @@
struct raparms {
struct raparms *p_next;
unsigned int p_count;
- struct dentry *p_dentry;
+ ino_t p_ino;
+ dev_t p_dev;
unsigned long p_reada,
p_ramax,
p_raend,
@@ -316,29 +317,27 @@
}
/*
- * Obtain the readahead parameters for the given file
- *
- * N.B. is raparm cache for a file cleared when the file closes??
- * (dentry might be reused later.)
+ * Obtain the readahead parameters for the file
+ * specified by (dev, ino).
*/
static inline struct raparms *
-nfsd_get_raparms(struct dentry *dentry)
+nfsd_get_raparms(dev_t dev, ino_t ino)
{
struct raparms *ra, **rap, **frap = NULL;
for (rap = &raparm_cache; (ra = *rap); rap = &ra->p_next) {
- if (ra->p_dentry != dentry) {
- if (ra->p_count == 0)
- frap = rap;
- } else
+ if (ra->p_ino == ino && ra->p_dev == dev)
goto found;
+ if (ra->p_count == 0)
+ frap = rap;
}
if (!frap)
return NULL;
rap = frap;
ra = *frap;
memset(ra, 0, sizeof(*ra));
- ra->p_dentry = dentry;
+ ra->p_dev = dev;
+ ra->p_ino = ino;
found:
if (rap != &raparm_cache) {
*rap = ra->p_next;
@@ -359,23 +358,20 @@
unsigned long *count)
{
struct raparms *ra;
- struct dentry *dentry;
- struct inode *inode;
- struct file file;
mm_segment_t oldfs;
int err;
+ struct file file;
- if ((err = nfsd_open(rqstp, fhp, S_IFREG, OPEN_READ, &file)) != 0)
- return err;
- dentry = file.f_dentry;
- inode = dentry->d_inode;
- if (!file.f_op->read) {
- nfsd_close(&file);
- return nfserr_perm;
- }
+ err = nfsd_open(rqstp, fhp, S_IFREG, OPEN_READ, &file);
+ if (err)
+ goto out;
+ err = nfserr_perm;
+ if (!file.f_op->read)
+ goto out_close;
/* Get readahead parameters */
- if ((ra = nfsd_get_raparms(dentry)) != NULL) {
+ ra = nfsd_get_raparms(fhp->fh_handle.fh_dev, fhp->fh_handle.fh_ino);
+ if (ra) {
file.f_reada = ra->p_reada;
file.f_ramax = ra->p_ramax;
file.f_raend = ra->p_raend;
@@ -401,12 +397,15 @@
ra->p_count -= 1;
}
+ if (err >= 0) {
+ *count = err;
+ err = 0;
+ } else
+ err = nfserrno(-err);
+out_close:
nfsd_close(&file);
-
- if (err < 0)
- return nfserrno(-err);
- *count = err;
- return 0;
+out:
+ return err;
}
/*
@@ -423,16 +422,16 @@
struct dentry *dentry;
struct inode *inode;
mm_segment_t oldfs;
- int err;
+ int err = 0;
if (!cnt)
- return 0;
- if ((err = nfsd_open(rqstp, fhp, S_IFREG, OPEN_WRITE, &file)) != 0)
- return err;
- if (!file.f_op->write) {
- nfsd_close(&file);
- return nfserr_perm;
- }
+ goto out;
+ err = nfsd_open(rqstp, fhp, S_IFREG, OPEN_WRITE, &file);
+ if (err)
+ goto out;
+ err = nfserr_perm;
+ if (!file.f_op->write)
+ goto out_close;
dentry = file.f_dentry;
inode = dentry->d_inode;
@@ -507,10 +506,15 @@
last_dev = inode->i_dev;
}
- nfsd_close(&file);
-
dprintk("nfsd: write complete\n");
- return (err < 0)? nfserrno(-err) : 0;
+ if (err >= 0)
+ err = 0;
+ else
+ err = nfserrno(-err);
+out_close:
+ nfsd_close(&file);
+out:
+ return err;
}
/*
@@ -824,20 +828,27 @@
return err;
}
-/* More "hidden treasure" from the generic VFS. -DaveM */
-/* N.B. VFS double_down was modified to fix a bug ... should use VFS one */
+/*
+ * This follows the model of double_lock() in the VFS.
+ */
static inline void nfsd_double_down(struct semaphore *s1, struct semaphore *s2)
{
- if((unsigned long) s1 < (unsigned long) s2) {
- down(s1);
- down(s2);
- } else if(s1 == s2) {
- down(s1);
- atomic_dec(&s1->count);
- } else {
- down(s2);
+ if (s1 != s2) {
+ if ((unsigned long) s1 < (unsigned long) s2) {
+ struct semaphore *tmp = s1;
+ s1 = s2;
+ s2 = tmp;
+ }
down(s1);
}
+ down(s2);
+}
+
+static inline void nfsd_double_up(struct semaphore *s1, struct semaphore *s2)
+{
+ up(s1);
+ if (s1 != s2)
+ up(s2);
}
/*
@@ -866,43 +877,47 @@
tdir = tdentry->d_inode;
/* N.B. We shouldn't need this ... dentry layer handles it */
+ err = nfserr_perm;
if (!flen || (fname[0] == '.' &&
(flen == 1 || (flen == 2 && fname[1] == '.'))) ||
!tlen || (tname[0] == '.' &&
(tlen == 1 || (tlen == 2 && tname[1] == '.'))))
- return nfserr_perm;
+ goto out;
+
+ err = -EXDEV;
+ if (fdir->i_dev != tdir->i_dev)
+ goto out_nfserr;
+ err = -EPERM;
+ if (!fdir->i_op || !fdir->i_op->rename)
+ goto out_nfserr;
odentry = lookup_dentry(fname, dget(fdentry), 0);
err = PTR_ERR(odentry);
if (IS_ERR(odentry))
- goto out_no_unlock;
+ goto out_nfserr;
ndentry = lookup_dentry(tname, dget(tdentry), 0);
err = PTR_ERR(ndentry);
if (IS_ERR(ndentry))
goto out_dput_old;
- /* N.B. check this ... problems in locking?? */
+ /*
+ * Lock the parent directories.
+ */
nfsd_double_down(&tdir->i_sem, &fdir->i_sem);
- err = -EXDEV;
- if (fdir->i_dev != tdir->i_dev)
- goto out_unlock;
- err = -EPERM;
- if (!fdir->i_op || !fdir->i_op->rename)
- goto out_unlock;
+ /* N.B. check for parent changes after locking?? */
+
err = fdir->i_op->rename(fdir, odentry, tdir, ndentry);
if (!err && EX_ISSYNC(tfhp->fh_export)) {
write_inode_now(fdir);
write_inode_now(tdir);
}
-out_unlock:
- up(&tdir->i_sem);
- up(&fdir->i_sem);
-
+ nfsd_double_up(&tdir->i_sem, &fdir->i_sem);
dput(ndentry);
+
out_dput_old:
dput(odentry);
-out_no_unlock:
+out_nfserr:
if (err)
err = nfserrno(-err);
out:
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov