#include "afsincludes.h" /* Afs-based standard headers */
#include "afs/afs_stats.h" /* afs statistics */
#include "h/smp_lock.h"
+#if defined(AFS_LINUX26_ENV)
+#include "h/namei.h"
+#endif
+#if !defined(HAVE_IGET)
+#include "h/exportfs.h"
+#endif
-
-int afs_osicred_initialized = 0;
-struct AFS_UCRED afs_osi_cred;
afs_lock_t afs_xosi; /* lock is for tvattr */
extern struct osi_dev cacheDev;
#if defined(AFS_LINUX24_ENV)
#endif
extern struct super_block *afs_cacheSBp;
-/*#if defined(AFS_LINUX26_ENV) && (defined(CONFIG_EXPORTFS) || defined(CONFIG_EXPORTFS_MODULE))
-#define HAS_UFSOPEN
-extern struct export_operations export_op_default;
-
-#define CALL(ops,fun) ((ops->fun)?(ops->fun):export_op_default.fun)
-
-XXX something based on encode_fh / find_exported_dentry
-This would require us to store an inode -> fh mapping (acquired by
-afs_InitCacheFile or lookupname), but probably solves the resiserfs issue.
-#elif... */
-
-#if defined(AFS_LINUX24_ENV) && !defined(HAS_UFSOPEN)
-#define HAS_UFSOPEN
+#if defined(AFS_LINUX26_ENV)
void *
osi_UFSOpen(afs_int32 ainode)
{
register struct osi_file *afile = NULL;
extern int cacheDiskType;
struct inode *tip = NULL;
-#ifndef AFS_LINUX26_ENV
- afs_int32 code = 0;
- struct list_head *lp = NULL;
- struct dentry *tdp = NULL;
-#endif
struct dentry *dp = NULL;
struct file *filp = NULL;
+#if !defined(HAVE_IGET)
+ struct fid fid;
+#endif
AFS_STATCNT(osi_UFSOpen);
if (cacheDiskType != AFS_FCACHE_TYPE_UFS) {
osi_Panic("UFSOpen called for non-UFS cache\n");
sizeof(struct osi_file));
}
memset(afile, 0, sizeof(struct osi_file));
+#if defined(HAVE_IGET)
tip = iget(afs_cacheSBp, (u_long) ainode);
- if (!tip)
- osi_Panic("Can't get inode %d\n", ainode);
- tip->i_flags |= MS_NOATIME; /* Disable updating access times. */
-
-#ifdef AFS_LINUX26_ENV
- dp = d_alloc_anon(tip);
#else
- spin_lock(&dcache_lock);
- for (lp = tip->i_dentry.next; lp != &tip->i_dentry; lp = lp->next) {
- tdp = list_entry(lp, struct dentry, d_alias);
- if ( !(tdp->d_flags & DCACHE_NFSD_DISCONNECTED)) {
- dget_locked(tdp);
- dp=tdp;
- break;
- }
- }
- if (tdp && !dp) {
- dget_locked(tdp);
- dp=tdp;
- }
- tdp = NULL;
- spin_unlock(&dcache_lock);
- if (!dp)
- dp = d_alloc_root(tip);
- iput(tip);
-#endif
+ fid.i32.ino = ainode;
+ fid.i32.gen = 0;
+ dp = afs_cacheSBp->s_export_op->fh_to_dentry(afs_cacheSBp, &fid, sizeof(fid), FILEID_INO32_GEN);
if (!dp)
osi_Panic("Can't get dentry for inode %d\n", ainode);
+ tip = dp->d_inode;
+#endif
+ tip->i_flags |= MS_NOATIME; /* Disable updating access times. */
filp = dentry_open(dp, mntget(afs_cacheMnt), O_RDWR);
-
if (IS_ERR(filp))
osi_Panic("Can't open inode %d\n", ainode);
afile->filp = filp;
afile->inum = ainode; /* for hint validity checking */
return (void *)afile;
}
-#endif
-
-#if !defined(HAS_UFSOPEN)
+#else
void *
osi_UFSOpen(afs_int32 ainode)
{
FILE_INODE(filp) = tip;
tip->i_flags |= MS_NOATIME; /* Disable updating access times. */
filp->f_flags = O_RDWR;
-#if defined(AFS_LINUX26_ENV)
- filp->f_mapping = tip->i_mapping;
-#endif
#if defined(AFS_LINUX24_ENV)
filp->f_mode = FMODE_READ|FMODE_WRITE;
filp->f_op = fops_get(tip->i_fop);
AFS_STATCNT(osi_Stat);
MObtainWriteLock(&afs_xosi, 320);
astat->size = OSIFILE_INODE(afile)->i_size;
- astat->blksize = OSIFILE_INODE(afile)->i_blksize;
#if defined(AFS_LINUX26_ENV)
astat->mtime = OSIFILE_INODE(afile)->i_mtime.tv_sec;
astat->atime = OSIFILE_INODE(afile)->i_atime.tv_sec;
return code;
}
-#ifdef AFS_LINUX24_ENV
+#ifdef AFS_LINUX26_ENV
int
osi_UFSClose(register struct osi_file *afile)
{
AFS_STATCNT(osi_Close);
if (afile) {
if (OSIFILE_INODE(afile)) {
- filp_close(afile->filp, NULL);
+ filp_close(afile->filp, NULL);
}
}
#ifdef STRUCT_INODE_HAS_I_ALLOC_SEM
down_write(&inode->i_alloc_sem);
#endif
+#ifdef STRUCT_INODE_HAS_I_MUTEX
+ mutex_lock(&inode->i_mutex);
+#else
down(&inode->i_sem);
+#endif
newattrs.ia_size = asize;
newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
#if defined(AFS_LINUX24_ENV)
}
#endif
code = -code;
+#ifdef STRUCT_INODE_HAS_I_MUTEX
+ mutex_unlock(&inode->i_mutex);
+#else
up(&inode->i_sem);
+#endif
#ifdef STRUCT_INODE_HAS_I_ALLOC_SEM
up_write(&inode->i_alloc_sem);
#endif
void
shutdown_osifile(void)
{
- extern int afs_cold_shutdown;
-
AFS_STATCNT(shutdown_osifile);
if (afs_cold_shutdown) {
afs_osicred_initialized = 0;
}
}
+
+/* Intialize cache device info and fragment size for disk cache partition. */
+int
+osi_InitCacheInfo(char *aname)
+{
+ int code;
+ struct dentry *dp;
+ extern ino_t cacheInode;
+ extern struct osi_dev cacheDev;
+ extern afs_int32 afs_fsfragsize;
+ extern struct super_block *afs_cacheSBp;
+ extern struct vfsmount *afs_cacheMnt;
+ code = osi_lookupname_internal(aname, 1, &afs_cacheMnt, &dp);
+ if (code)
+ return ENOENT;
+
+ cacheInode = dp->d_inode->i_ino;
+ cacheDev.dev = dp->d_inode->i_sb->s_dev;
+ afs_fsfragsize = dp->d_inode->i_sb->s_blocksize - 1;
+ afs_cacheSBp = dp->d_inode->i_sb;
+
+ dput(dp);
+
+ return 0;
+}
+
+
+#define FOP_READ(F, B, C) (F)->f_op->read(F, B, (size_t)(C), &(F)->f_pos)
+#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
+ * kernel space.
+ */
+int
+osi_rdwr(struct osi_file *osifile, uio_t * uiop, int rw)
+{
+#ifdef AFS_LINUX26_ENV
+ struct file *filp = osifile->filp;
+#else
+ struct file *filp = &osifile->file;
+#endif
+ KERNEL_SPACE_DECL;
+ int code = 0;
+ struct iovec *iov;
+ afs_size_t count;
+ unsigned long savelim;
+
+ 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();
+
+ /* 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 (count == 0) {
+ uiop->uio_iov++;
+ uiop->uio_iovcnt--;
+ continue;
+ }
+
+ if (rw == UIO_READ)
+ code = FOP_READ(filp, iov->iov_base, count);
+ else
+ code = FOP_WRITE(filp, iov->iov_base, count);
+
+ 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;
+ iov->iov_len -= code;
+ uiop->uio_resid -= code;
+ uiop->uio_offset += code;
+ code = 0;
+ }
+
+ if (uiop->uio_seg == AFS_UIOSYS)
+ TO_KERNEL_SPACE();
+
+ current->TASK_STRUCT_RLIM[RLIMIT_FSIZE].rlim_cur = savelim;
+
+ return code;
+}
+
+/* setup_uio
+ * Setup a uio struct.
+ */
+void
+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 = (char *)buf;
+ iovecp->iov_len = count;
+ uiop->uio_iov = iovecp;
+ uiop->uio_iovcnt = 1;
+ uiop->uio_offset = pos;
+ uiop->uio_seg = seg;
+ uiop->uio_resid = count;
+ uiop->uio_flag = flag;
+}
+
+
+/* uiomove
+ * UIO_READ : dp -> uio
+ * UIO_WRITE : uio -> dp
+ */
+int
+uiomove(char *dp, int length, uio_flag_t rw, uio_t * uiop)
+{
+ int count;
+ struct iovec *iov;
+ int code;
+
+ while (length > 0 && uiop->uio_resid > 0 && uiop->uio_iovcnt > 0) {
+ iov = uiop->uio_iov;
+ count = iov->iov_len;
+
+ if (!count) {
+ uiop->uio_iov++;
+ uiop->uio_iovcnt--;
+ continue;
+ }
+
+ if (count > length)
+ count = length;
+
+ switch (uiop->uio_seg) {
+ case AFS_UIOSYS:
+ switch (rw) {
+ case UIO_READ:
+ memcpy(iov->iov_base, dp, count);
+ break;
+ case UIO_WRITE:
+ memcpy(dp, iov->iov_base, count);
+ break;
+ default:
+ printf("uiomove: Bad rw = %d\n", rw);
+ return -EINVAL;
+ }
+ break;
+ case AFS_UIOUSER:
+ switch (rw) {
+ case UIO_READ:
+ AFS_COPYOUT(dp, iov->iov_base, count, code);
+ break;
+ case UIO_WRITE:
+ AFS_COPYIN(iov->iov_base, dp, count, code);
+ break;
+ default:
+ printf("uiomove: Bad rw = %d\n", rw);
+ return -EINVAL;
+ }
+ break;
+ default:
+ printf("uiomove: Bad seg = %d\n", uiop->uio_seg);
+ return -EINVAL;
+ }
+
+ dp += count;
+ length -= count;
+ iov->iov_base += count;
+ iov->iov_len -= count;
+ uiop->uio_offset += count;
+ uiop->uio_resid -= count;
+ }
+ return 0;
+}
+