#if defined(AFS_LINUX24_ENV)
#include "h/smp_lock.h"
#endif
+#if defined(AFS_LINUX26_ENV)
+#include "h/namei.h"
+#endif
#if defined(AFS_LINUX24_ENV)
+/* LOOKUP_POSITIVE is becoming the default */
+#ifndef LOOKUP_POSITIVE
+#define LOOKUP_POSITIVE 0
+#endif
/* Lookup name and return vnode for same. */
int
-osi_lookupname(char *aname, uio_seg_t seg, int followlink,
- vnode_t ** dirvpp, struct dentry **dpp)
+osi_lookupname_internal(char *aname, int followlink, struct vfsmount **mnt,
+ struct dentry **dpp)
{
int code;
- extern struct nameidata afs_cacheNd;
- struct nameidata *nd = &afs_cacheNd;
+ struct nameidata nd;
+ int flags = LOOKUP_POSITIVE;
+ code = ENOENT;
+
+ if (followlink)
+ flags |= LOOKUP_FOLLOW;
+#if defined(AFS_LINUX26_ENV)
+ code = path_lookup(aname, flags, &nd);
+#else
+ if (path_init(aname, flags, &nd))
+ code = path_walk(aname, &nd);
+#endif
+ if (!code) {
+ *dpp = dget(nd.dentry);
+ if (mnt)
+ *mnt = mntget(nd.mnt);
+ path_release(&nd);
+ }
+ return code;
+}
+int
+osi_lookupname(char *aname, uio_seg_t seg, int followlink,
+ struct dentry **dpp)
+{
+ int code;
+ char *tname;
code = ENOENT;
if (seg == AFS_UIOUSER) {
- code =
- followlink ? user_path_walk(aname,
- nd) : user_path_walk_link(aname, nd);
+ tname = getname(aname);
+ if (IS_ERR(tname))
+ return PTR_ERR(tname);
} else {
- if (path_init(aname, followlink ? LOOKUP_FOLLOW : 0, nd))
- code = path_walk(aname, nd);
+ tname = aname;
}
-
- if (!code) {
- if (nd->dentry->d_inode) {
- *dpp = dget(nd->dentry);
- code = 0;
- } else {
- code = ENOENT;
- path_release(nd);
- }
+ code = osi_lookupname_internal(tname, followlink, NULL, dpp);
+ if (seg == AFS_UIOUSER) {
+ putname(tname);
}
return code;
}
#else
int
-osi_lookupname(char *aname, uio_seg_t seg, int followlink, vnode_t ** dirvpp,
- struct dentry **dpp)
+osi_lookupname(char *aname, uio_seg_t seg, int followlink, struct dentry **dpp)
{
struct dentry *dp = NULL;
int code;
extern struct osi_dev cacheDev;
extern afs_int32 afs_fsfragsize;
extern struct super_block *afs_cacheSBp;
- code = osi_lookupname(aname, AFS_UIOSYS, 1, NULL, &dp);
+ extern struct vfsmount *afs_cacheMnt;
+ code = osi_lookupname_internal(aname, 1, &afs_cacheMnt, &dp);
if (code)
return ENOENT;
#define FOP_WRITE(F, B, C) (F)->f_op->write(F, B, (size_t)(C), &(F)->f_pos)
/* osi_rdwr
- * Seek, then read or write to an open inode. addrp points to data in
+ * seek, then read or write to an open inode. addrp points to data in
* kernel space.
*/
int
-osi_rdwr(int rw, struct osi_file *file, caddr_t addrp, size_t asize,
- size_t * resid)
-{
- int code = 0;
- KERNEL_SPACE_DECL;
- struct file *filp = &file->file;
- off_t offset = file->offset;
- unsigned long savelim;
-
- /* Seek to the desired position. Return -1 on error. */
- if (filp->f_op->llseek) {
- if (filp->f_op->llseek(filp, (loff_t) offset, 0) != offset)
- return -1;
- } else
- filp->f_pos = offset;
-
- savelim = current->rlim[RLIMIT_FSIZE].rlim_cur;
- current->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
-
- /* Read/Write the data. */
- TO_USER_SPACE();
- if (rw == UIO_READ)
- code = FOP_READ(filp, addrp, asize);
- else if (rw == UIO_WRITE)
- code = FOP_WRITE(filp, addrp, asize);
- else /* all is well? */
- code = asize;
- TO_KERNEL_SPACE();
-
- current->rlim[RLIMIT_FSIZE].rlim_cur = savelim;
-
- if (code >= 0) {
- *resid = asize - code;
- return 0;
- } else
- return -1;
-}
-
-/* This variant is called from AFS read/write routines and takes a uio
- * struct and, if successful, returns 0.
- */
-int
-osi_file_uio_rdwr(struct osi_file *osifile, uio_t * uiop, int rw)
+osi_rdwr(struct osi_file *osifile, uio_t * uiop, int rw)
{
+#ifdef AFS_LINUX24_ENV
+ struct file *filp = osifile->filp;
+#else
struct file *filp = &osifile->file;
- struct inode *ip = FILE_INODE(&osifile->file);
+#endif
KERNEL_SPACE_DECL;
int code = 0;
struct iovec *iov;
- int count;
+ afs_size_t count;
unsigned long savelim;
- savelim = current->rlim[RLIMIT_FSIZE].rlim_cur;
- current->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
+ savelim = current->TASK_STRUCT_RLIM[RLIMIT_FSIZE].rlim_cur;
+ current->TASK_STRUCT_RLIM[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
if (uiop->uio_seg == AFS_UIOSYS)
TO_USER_SPACE();
- filp->f_pos = uiop->uio_offset;
+ /* seek to the desired position. Return -1 on error. */
+ if (filp->f_op->llseek) {
+ if (filp->f_op->llseek(filp, (loff_t) uiop->uio_offset, 0) != uiop->uio_offset)
+ return -1;
+ } else
+ filp->f_pos = uiop->uio_offset;
+
while (code == 0 && uiop->uio_resid > 0 && uiop->uio_iovcnt > 0) {
iov = uiop->uio_iov;
count = iov->iov_len;
if (code < 0) {
code = -code;
break;
+ } else if (code == 0) {
+ /*
+ * This is bad -- we can't read any more data from the
+ * file, but we have no good way of signaling a partial
+ * read either.
+ */
+ code = EIO;
+ break;
}
iov->iov_base += code;
if (uiop->uio_seg == AFS_UIOSYS)
TO_KERNEL_SPACE();
- current->rlim[RLIMIT_FSIZE].rlim_cur = savelim;
+ current->TASK_STRUCT_RLIM[RLIMIT_FSIZE].rlim_cur = savelim;
return code;
}
* Setup a uio struct.
*/
void
-setup_uio(uio_t * uiop, struct iovec *iovecp, char *buf, afs_offs_t pos,
+setup_uio(uio_t * uiop, struct iovec *iovecp, const char *buf, afs_offs_t pos,
int count, uio_flag_t flag, uio_seg_t seg)
{
- iovecp->iov_base = buf;
+ iovecp->iov_base = (char *)buf;
iovecp->iov_len = count;
uiop->uio_iov = iovecp;
uiop->uio_iovcnt = 1;
int
uiomove(char *dp, int length, uio_flag_t rw, uio_t * uiop)
{
- int count, n;
+ int count;
struct iovec *iov;
int code;
void
afs_osi_SetTime(osi_timeval_t * tvp)
{
- extern int (*sys_settimeofdayp) (struct timeval * tv,
- struct timezone * tz);
-#ifdef AFS_LINUX_64BIT_KERNEL
+#if defined(AFS_LINUX24_ENV)
+
+#if defined(AFS_LINUX26_ENV)
+ struct timespec tv;
+ tv.tv_sec = tvp->tv_sec;
+ tv.tv_nsec = tvp->tv_usec * NSEC_PER_USEC;
+#else
struct timeval tv;
- AFS_STATCNT(osi_SetTime);
tv.tv_sec = tvp->tv_sec;
tv.tv_usec = tvp->tv_usec;
- (void)(*sys_settimeofdayp) (&tv, NULL);
+#endif
+
+ AFS_STATCNT(osi_SetTime);
+
+ do_settimeofday(&tv);
#else
+ extern int (*sys_settimeofdayp) (struct timeval * tv,
+ struct timezone * tz);
+
KERNEL_SPACE_DECL;
AFS_STATCNT(osi_SetTime);
TO_USER_SPACE();
- (void)(*sys_settimeofdayp) (tvp, NULL);
+ if (sys_settimeofdayp)
+ (void)(*sys_settimeofdayp) (tvp, NULL);
TO_KERNEL_SPACE();
#endif
}
#else
if (ip->i_nrpages) {
#endif
- printf("Failed to invalidate all pages on inode 0x%x\n",
- ip);
+ printf("Failed to invalidate all pages on inode 0x%lx\n",
+ (unsigned long)ip);
}
}
}
}
}
+#if !defined(AFS_LINUX24_ENV)
void
osi_clear_inode(struct inode *ip)
{
cred_t *credp = crref();
struct vcache *vcp = ITOAFS(ip);
-#if defined(AFS_LINUX24_ENV)
- if (atomic_read(&ip->i_count) > 1)
-#else
if (ip->i_count > 1)
-#endif
- printf("afs_put_inode: ino %d (0x%x) has count %d\n", ip->i_ino, ip,
- ip->i_count);
+ printf("afs_put_inode: ino %ld (0x%lx) has count %ld\n",
+ (long)ip->i_ino, (unsigned long)ip, (long)ip->i_count);
afs_InactiveVCache(vcp, credp);
ObtainWriteLock(&vcp->lock, 504);
-#if defined(AFS_LINUX24_ENV)
- atomic_set(&ip->i_count, 0);
-#else
- ip->i_count = 0;
-#endif
ip->i_nlink = 0; /* iput checks this after calling this routine. */
+#ifdef I_CLEAR
+ ip->i_state = I_CLEAR;
+#endif
ReleaseWriteLock(&vcp->lock);
crfree(credp);
}
extern struct vfs *afs_globalVFS;
AFS_GLOCK();
+
+ if (afs_globalVFS && ip->i_sb != afs_globalVFS)
+ osi_Panic("IPUT Not an afs inode\n");
+
#if defined(AFS_LINUX24_ENV)
- if (atomic_read(&ip->i_count) == 0
- || atomic_read(&ip->i_count) & 0xffff0000) {
+ if (atomic_read(&ip->i_count) == 0)
#else
- if (ip->i_count == 0 || ip->i_count & 0xffff0000) {
+ if (ip->i_count == 0)
#endif
osi_Panic("IPUT Bad refCount %d on inode 0x%x\n",
#if defined(AFS_LINUX24_ENV)
- atomic_read(&ip->i_count), ip);
+ atomic_read(&ip->i_count),
#else
- ip->i_count, ip);
+ ip->i_count,
#endif
- }
- if (afs_globalVFS && afs_globalVFS == ip->i_sb) {
+ ip);
+
#if defined(AFS_LINUX24_ENV)
- atomic_dec(&ip->i_count);
- if (!atomic_read(&ip->i_count))
+ if (atomic_dec_and_test(&ip->i_count))
#else
- ip->i_count--;
- if (!ip->i_count)
+ if (!--ip->i_count)
#endif
- osi_clear_inode(ip);
- } else
- iput(ip);
+ {
+ osi_clear_inode(ip);
+ ip->i_state = 0;
+ }
AFS_GUNLOCK();
}
+#endif
/* check_bad_parent() : Checks if this dentry's vcache is a root vcache
* that has its mvid (parent dir's fid) pointer set to the wrong directory
afs_lookup(pvc, dp->d_name.name, &avc, credp);
if (!avc || vcp != avc) { /* bad, very bad.. */
afs_Trace4(afs_iclSetp, CM_TRACE_TMP_1S3L, ICL_TYPE_STRING,
- "afs_linux_revalidate : bad pointer returned from afs_lookup origvc newvc dentry",
+ "check_bad_parent: bad pointer returned from afs_lookup origvc newvc dentry",
ICL_TYPE_POINTER, vcp, ICL_TYPE_POINTER, avc,
ICL_TYPE_POINTER, dp);
}