/*
- * linux/fs/ext2/dir.c
*
* Copyright (C) 1992, 1993, 1994, 1995
* Remy Card (card@masi.ibp.fr)
* from
*
* linux/fs/minix/dir.c
+ * linux/fs/ext2/dir.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
*
* Big-endian to little-endian byte-swapping/bitmaps by
* David S. Miller (davem@caip.rutgers.edu), 1995
*
- * All code that works with directory layout had been switched to pagecache
- * and moved here. AV
+ * All code that works with directory layout had been switched to pagecache
+ * and moved here. AV
+ *
+ * Adapted for Lustre Light
+ * Copyright (C) 2002, Cluster File Systems, Inc.
+ *
*/
#include <linux/fs.h>
#include <linux/ext2_fs.h>
#include <linux/pagemap.h>
-#include <linux/obd_support.h>
+#include <linux/mm.h>
#include <linux/locks.h>
+#include <asm/uaccess.h>
+
+#define DEBUG_SUBSYSTEM S_LLIGHT
+
+#include <linux/obd_support.h>
+#include <linux/lustre_lib.h>
+#include <linux/lustre_idl.h>
+#include <linux/lustre_mds.h>
+#include <linux/lustre_light.h>
typedef struct ext2_dir_entry_2 ext2_dirent;
#define PageChecked(page) test_bit(PG_checked, &(page)->flags)
#define SetPageChecked(page) set_bit(PG_checked, &(page)->flags)
+
+static int ll_dir_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
+{
+ return 0;
+}
+
+/* returns the page unlocked, but with a reference */
+static int ll_dir_readpage(struct file *file, struct page *page)
+{
+ struct inode *inode = page->mapping->host;
+ struct ll_sb_info *sbi = ll_i2sbi(inode);
+ char *buf;
+ __u64 offset;
+ int rc = 0;
+ struct ptlrep_hdr *hdr;
+
+ ENTRY;
+
+ if ( ((inode->i_size + PAGE_CACHE_SIZE -1)>>PAGE_SHIFT)
+ <= page->index) {
+ memset(kmap(page), 0, PAGE_CACHE_SIZE);
+ kunmap(page);
+ goto readpage_out;
+ }
+
+ if (Page_Uptodate(page)) {
+ EXIT;
+ goto readpage_out;
+ }
+
+ offset = page->index << PAGE_SHIFT;
+ buf = kmap(page);
+ rc = mdc_readpage(&sbi->ll_mds_client, inode->i_ino, S_IFDIR, offset,
+ buf, NULL, &hdr);
+ kunmap(page);
+ if ( rc ) {
+ EXIT;
+ goto readpage_out;
+ }
+
+ if ((rc = hdr->status)) {
+ EXIT;
+ goto readpage_out;
+ }
+
+ /* PDEBUG(page, "READ"); */
+
+ SetPageUptodate(page);
+ readpage_out:
+ obd_unlock_page(page);
+ EXIT;
+ return rc;
+} /* ll_dir_readpage */
+
+struct address_space_operations ll_dir_aops = {
+ readpage: ll_dir_readpage,
+ prepare_write: ll_dir_prepare_write
+};
+
int waitfor_one_page(struct page *page)
{
int error = 0;
return (inode->i_size+PAGE_CACHE_SIZE-1)>>PAGE_CACHE_SHIFT;
}
+extern void set_page_clean(struct page *page);
+
static int ext2_commit_chunk(struct page *page, unsigned from, unsigned to)
{
struct inode *dir = page->mapping->host;
int err = 0;
+
dir->i_version = ++event;
- page->mapping->a_ops->commit_write(NULL, page, from, to);
- if (IS_SYNC(dir))
- err = waitfor_one_page(page);
+ dir->i_size = (page->index << PAGE_CACHE_SHIFT) + to;
+ SetPageUptodate(page);
+ set_page_clean(page);
+
+ //page->mapping->a_ops->commit_write(NULL, page, from, to);
+ //if (IS_SYNC(dir))
+ // err = waitfor_one_page(page);
return err;
}
if ((dir->i_size >> PAGE_CACHE_SHIFT) == page->index) {
limit = dir->i_size & ~PAGE_CACHE_MASK;
- if (limit & (chunk_size - 1))
+ if (limit & (chunk_size - 1)) {
+ CERROR("limit %d dir size %lld index %ld\n",
+ limit, dir->i_size, page->index);
goto Ebadsize;
+ }
for (offs = limit; offs<PAGE_CACHE_SIZE; offs += chunk_size) {
ext2_dirent *p = (ext2_dirent*)(kaddr + offs);
p->rec_len = cpu_to_le16(chunk_size);
/* Too bad, we had an error */
Ebadsize:
- printk("ext2_check_page"
- "size of directory #%lu is not a multiple of chunk size",
+ CERROR("ext2_check_page"
+ "size of directory #%lu is not a multiple of chunk size\n",
dir->i_ino
);
goto fail;
//Einumber:
// error = "inode out of bounds";
bad_entry:
- printk("ext2_check_page: bad entry in directory #%lu: %s - "
+ CERROR("ext2_check_page: bad entry in directory #%lu: %s - "
"offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
dir->i_ino, error, (page->index<<PAGE_CACHE_SHIFT)+offs,
(unsigned long) le32_to_cpu(p->inode),
goto fail;
Eend:
p = (ext2_dirent *)(kaddr + offs);
- printk("ext2_check_page"
+ CERROR("ext2_check_page"
"entry in directory #%lu spans the page boundary"
"offset=%lu, inode=%lu",
dir->i_ino, (page->index<<PAGE_CACHE_SHIFT)+offs,
/*
* Parent is locked.
*/
-int ext2_add_link (struct dentry *dentry, struct inode *inode)
+int ll_add_link (struct dentry *dentry, struct inode *inode)
{
struct inode *dir = dentry->d_parent->d_inode;
const char *name = dentry->d_name.name;
name_len = EXT2_DIR_REC_LEN(de->name_len);
rec_len = le16_to_cpu(de->rec_len);
if ( n==npages && rec_len == 0) {
- printk("Fatal dir behaviour\n");
+ CERROR("Fatal dir behaviour\n");
goto out_page;
}
if (!de->inode && rec_len >= reclen)
err = ext2_commit_chunk(page, from, to);
// change_inode happens with the commit_chunk
- // ll_change_inode(dir);
- /* OFFSET_CACHE */
+ /* XXX OFFSET_CACHE */
+
out_unlock:
UnlockPage(page);
out_page: