return &sbi->ll_inodes;
}
-static void inline ll_set_size (struct inode *inode, obd_size size)
-{
- inode->i_size = size;
- inode->i_blocks = (inode->i_size + inode->i_sb->s_blocksize - 1) >>
- inode->i_sb->s_blocksize_bits;
-} /* ll_set_size */
-
-
-
-#define obd_down(mutex) { \
- /* CDEBUG(D_INFO, "get lock\n"); */ \
- ll_mutex_start = jiffies; \
- down(mutex); \
- if (jiffies - ll_mutex_start) \
- CDEBUG(D_CACHE, "waited on mutex %ld jiffies\n", \
- jiffies - ll_mutex_start); \
-}
-
-#define obd_up(mutex) { \
- up(mutex); \
- if (jiffies - ll_mutex_start > 1) \
- CDEBUG(D_CACHE, "held mutex for %ld jiffies\n", \
- jiffies - ll_mutex_start); \
- /* CDEBUG(D_INFO, "free lock\n"); */ \
-}
-
-/* We track if a page has been added to the OBD page cache by stting a
- * flag on the page. We have chosen a bit that will hopefully not be
- * used for a while.
- */
-#define PG_obdcache 29
-#define OBDAddCachePage(page) test_and_set_bit(PG_obdcache, &(page)->flags)
-#define OBDClearCachePage(page) clear_bit(PG_obdcache, &(page)->flags)
-
#endif
EXTRA_PROGRAMS = llight
page.c:
- ln -s ../lib/page.c
+ -ln -s ../lib/page.c
llight_SOURCES = page.c super.c rw.c file.c dir.c sysctl.c namei.c symlink.c
#include <linux/mm.h>
#include <linux/obd_support.h>
#include <linux/locks.h>
+#include <asm/uaccess.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_peer_ptr, 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;
from = (char*)de - (char*)page_address(page);
to = from + rec_len;
lock_page(page);
- //err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
- //if (err)
- // goto out_unlock;
+ err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
+ if (err)
+ goto out_unlock;
if (de->inode) {
ext2_dirent *de1 = (ext2_dirent *) ((char *) de + name_len);
de1->rec_len = cpu_to_le16(rec_len - name_len);
struct mds_rep *rep;
struct ptlrep_hdr *hdr = NULL;
struct inode * inode = NULL;
- struct ll_sb_info *sbi;
+ struct ll_sb_info *sbi = ll_i2sbi(dir);
int err;
int type;
ino_t ino;
if (!ino)
goto negative;
- sbi = (struct ll_sb_info *)(&dir->i_sb->u.generic_sbp);
-
err = mdc_getattr(sbi->ll_peer_ptr, ino, type,
OBD_MD_FLNOTOBD|OBD_MD_FLBLOCKS, &rep, &hdr);
if ( err ) {
struct ptlrep_hdr *hdr;
int err;
time_t time = CURRENT_TIME;
- struct ll_sb_info *sbi =
- (struct ll_sb_info *)(&dir->i_sb->u.generic_sbp);
+ struct ll_sb_info *sbi = ll_i2sbi(dir);
ENTRY;
struct mds_rep *rep;
struct ptlrep_hdr *hdr;
int err;
- struct ll_sb_info *sbi =
- (struct ll_sb_info *)(&dir->i_sb->u.generic_sbp);
+ struct ll_sb_info *sbi = ll_i2sbi(dir);
ENTRY;
struct mds_rep *rep;
struct ptlrep_hdr *hdr;
int err;
- struct ll_sb_info *sbi =
- (struct ll_sb_info *)(&dir->i_sb->u.generic_sbp);
+ struct ll_sb_info *sbi = ll_i2sbi(dir);
ENTRY;
struct mds_rep *rep;
struct ptlrep_hdr *hdr;
int err;
- struct ll_sb_info *sbi =
- (struct ll_sb_info *)(&src->i_sb->u.generic_sbp);
+ struct ll_sb_info *sbi = ll_i2sbi(src);
ENTRY;
static int ll_symlink (struct inode * dir, struct dentry * dentry,
const char * symname)
{
- struct super_block * sb = dir->i_sb;
int err = -ENAMETOOLONG;
unsigned l = strlen(symname);
struct inode * inode;
struct ll_inode_info *oinfo;
- if (l > sb->s_blocksize)
- goto out;
+ if (l > LL_INLINESZ)
+ return err;
inode = ll_create_node(dir, dentry->d_name.name,
dentry->d_name.len, symname, l,
S_IFLNK | S_IRWXUGO, 0);
err = PTR_ERR(inode);
if (IS_ERR(inode))
- goto out;
+ return err;
oinfo = ll_i2info(inode);
inode->i_size = l-1;
err = ext2_add_nondir(dentry, inode);
-out:
- return err;
-out_fail:
- ext2_dec_count(inode);
- iput (inode);
- goto out;
+ if (err) {
+ ext2_dec_count(inode);
+ iput (inode);
+ }
+ return err;
}
static int ll_link (struct dentry * old_dentry, struct inode * dir,
#include <linux/lustre_mds.h>
#include <linux/lustre_light.h>
-int ll_inode_setattr(struct inode *inode, struct iattr *attr);
+int ll_inode_setattr(struct inode *inode, struct iattr *attr, int do_trunc);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10))
/*
}
#endif
-static void inline ll_oa_from_inode(struct obdo *oa, struct inode *inode)
+inline struct obdo * ll_oa_from_inode(struct inode *inode, int valid)
{
struct ll_inode_info *oinfo = ll_i2info(inode);
+ struct obdo *oa = obdo_alloc();
+ if ( !oa ) {
+ printk(__FUNCTION__ ": no memory to allocate obdo!\n");
+ return NULL;
+ }
+ oa->o_valid = valid;
if ( oa->o_valid & OBD_MD_FLID )
oa->o_id = oinfo->lli_objid;
oa->o_obdflags |= OBD_FL_INLINEDATA;
oa->o_valid |= OBD_MD_FLINLINE;
}
+ return oa;
} /* ll_oa_from_inode */
EXIT;
}
-/* SYNCHRONOUS I/O to object storage for an inode -- object attr will be updated too */
+/* SYNCHRONOUS I/O to object storage for an inode */
static int ll_brw(int rw, struct inode *inode, struct page *page, int create)
{
obd_count num_obdo = 1;
ENTRY;
- oa = obdo_alloc();
- if ( !oa ) {
- EXIT;
- return -ENOMEM;
- }
- oa->o_valid = OBD_MD_FLNOTOBD;
- ll_oa_from_inode(oa, inode);
-
+ oa = ll_oa_from_inode(inode, OBD_MD_FLNOTOBD);
+ if (!oa) {
+ return -ENOMEM;
+ }
err = obd_brw(rw, IID(inode), num_obdo, &oa, &bufs_per_obdo,
&page, &count, &offset, &flags);
- //if ( !err )
- // ll_to_inode(inode, oa); /* copy o_blocks to i_blocks */
obdo_free(oa);
EXIT;
extern void set_page_clean(struct page *);
-/* SYNCHRONOUS I/O to object storage for an inode -- object attr will be updated too */
-static int ll_commit_page(struct page *page, int create, int from, int to)
-{
- struct inode *inode = page->mapping->host;
- obd_count num_obdo = 1;
- obd_count bufs_per_obdo = 1;
- struct obdo *oa;
- obd_size count = to;
- obd_off offset = (((obd_off)page->index) << PAGE_SHIFT) + to;
- obd_flag flags = create ? OBD_BRW_CREATE : 0;
- int err;
- struct iattr iattr;
-
- ENTRY;
- oa = obdo_alloc();
- if ( !oa ) {
- EXIT;
- return -ENOMEM;
- }
- oa->o_valid = OBD_MD_FLNOTOBD;
- ll_oa_from_inode(oa, inode);
-
- CDEBUG(D_INODE, "commit_page writing (at %d) to %d, count %Ld\n",
- from, to, count);
-
- err = obd_brw(OBD_BRW_WRITE, IID(inode), num_obdo, &oa, &bufs_per_obdo,
- &page, &count, &offset, &flags);
- if ( !err ) {
- SetPageUptodate(page);
- set_page_clean(page);
- }
-
- if (offset > inode->i_size) {
- iattr.ia_valid = ATTR_SIZE;
- iattr.ia_size = offset;
- err = ll_inode_setattr(inode, &iattr);
- if (err) {
- printk("mds_inode_setattr failed; do something dramatic.\n");
- obdo_free(oa);
- EXIT;
- return -EIO;
- }
- }
-
- //if ( !err )
- // ll_to_inode(inode, oa); /* copy o_blocks to i_blocks */
-
- obdo_free(oa);
- EXIT;
- return err;
-} /* ll_brw */
/* returns the page unlocked, but with a reference */
goto readpage_out;
}
- rc = ll_brw(READ, inode, page, 0);
+ rc = ll_brw(OBD_BRW_READ, inode, page, 0);
if ( rc ) {
EXIT;
return rc;
}
- /* PDEBUG(page, "READ"); */
readpage_out:
SetPageUptodate(page);
} /* ll_readpage */
-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 */
-int ll_dir_readpage(struct file *file, struct page *page)
-{
- struct inode *inode = page->mapping->host;
- struct ll_sb_info *sbi =
- (struct ll_sb_info *)(&inode->i_sb->u.generic_sbp);
- 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_peer_ptr, 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 */
-
int ll_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
{
struct inode *inode = page->mapping->host;
return 0;
}
- rc = ll_brw(READ, inode, page, 0);
+ rc = ll_brw(OBD_BRW_READ, inode, page, 0);
if ( !rc ) {
SetPageUptodate(page);
}
prepare_done:
set_page_dirty(page);
- //SetPageDirty(page);
EXIT;
return rc;
}
-
-/* select between SYNC and ASYNC I/O methods */
-int ll_do_writepage(struct page *page, int sync)
+/* returns the page unlocked, but with a reference */
+int ll_writepage(struct page *page)
{
struct inode *inode = page->mapping->host;
int err;
-
ENTRY;
- /* PDEBUG(page, "WRITEPAGE"); */
- /* XXX everything is synchronous now */
- err = ll_brw(OBD_BRW_WRITE, inode, page, 1);
+ err = ll_brw(OBD_BRW_WRITE, inode, page, 1);
if ( !err ) {
SetPageUptodate(page);
set_page_clean(page);
- }
- /* PDEBUG(page,"WRITEPAGE"); */
- EXIT;
- return err;
-} /* ll_do_writepage */
-
-
-
-/* returns the page unlocked, but with a reference */
-int ll_writepage(struct page *page)
-{
- int rc;
- struct inode *inode = page->mapping->host;
- ENTRY;
- printk("---> writepage called ino %ld!\n", inode->i_ino);
- rc = ll_do_writepage(page, 1);
- if ( !rc ) {
- set_page_clean(page);
} else {
- CDEBUG(D_INODE, "--> GRR %d\n", rc);
+ printk(__FUNCTION__ ": ll_brw failure %d\n", err);
}
EXIT;
- return rc;
-}
-
-void write_inode_pages(struct inode *inode)
-{
- struct list_head *tmp = &inode->i_mapping->dirty_pages;
-
- while ( (tmp = tmp->next) != &inode->i_mapping->dirty_pages) {
- struct page *page;
- page = list_entry(tmp, struct page, list);
- ll_writepage(page);
- }
-}
-
-
-int ll_commit_write(struct file *file, struct page *page, unsigned from, unsigned to)
-{
- struct inode *inode = page->mapping->host;
- int rc = 0;
- loff_t len = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
- ENTRY;
- CDEBUG(D_INODE, "commit write ino %ld (end at %Ld) from %d to %d ,ind %ld\n",
- inode->i_ino, len, from, to, page->index);
-
- rc = ll_commit_page(page, 1, from, to);
-
- if (len > inode->i_size) {
- ll_set_size(inode, len);
- }
-
- kunmap(page);
- EXIT;
- return rc;
+ return err;
}
-
-/*
- * This does the "real" work of the write. The generic routine has
- * allocated the page, locked it, done all the page alignment stuff
- * calculations etc. Now we should just copy the data from user
- * space and write it back to the real medium..
- *
- * If the writer ends up delaying the write, the writer needs to
- * increment the page use counts until he is done with the page.
- *
- * Return value is the number of bytes written.
- */
-int ll_write_one_page(struct file *file, struct page *page,
- unsigned long offset, unsigned long bytes,
- const char * buf)
-{
- struct inode *inode = file->f_dentry->d_inode;
- int err;
-
- ENTRY;
- /* We check for complete page writes here, as we then don't have to
- * get the page before writing over everything anyways.
- */
- if ( !Page_Uptodate(page) && (offset != 0 || bytes != PAGE_SIZE) ) {
- err = ll_brw(READ, inode, page, 0);
- if ( err )
- return err;
- SetPageUptodate(page);
- }
-
- if (copy_from_user((u8*)page_address(page) + offset, buf, bytes))
- return -EFAULT;
-
- lock_kernel();
- err = ll_writepage(page);
- unlock_kernel();
-
- return (err < 0 ? err : bytes);
-} /* ll_write_one_page */
-
-/*
- * return an up to date page:
- * - if locked is true then is returned locked
- * - if create is true the corresponding disk blocks are created
- * - page is held, i.e. caller must release the page
- *
- * modeled on NFS code.
- */
-struct page *ll_getpage(struct inode *inode, unsigned long offset,
- int create, int locked)
+/* SYNCHRONOUS I/O to object storage for an inode -- object attr will be updated too */
+int ll_commit_write(struct file *file, struct page *page,
+ unsigned from, unsigned to)
{
- struct page * page;
- int index;
- int err;
+ int create = 1;
+ struct inode *inode = page->mapping->host;
+ obd_count num_obdo = 1;
+ obd_count bufs_per_obdo = 1;
+ struct obdo *oa;
+ obd_size count = to;
+ obd_off offset = (((obd_off)page->index) << PAGE_SHIFT) + to;
+ obd_flag flags = create ? OBD_BRW_CREATE : 0;
+ int err;
+ struct iattr iattr;
ENTRY;
+ oa = ll_oa_from_inode(inode, OBD_MD_FLNOTOBD);
+ if (! oa ) {
+ return -ENOMEM;
+ }
- offset = offset & PAGE_CACHE_MASK;
- CDEBUG(D_INFO, "ino: %ld, offset %ld, create %d, locked %d\n",
- inode->i_ino, offset, create, locked);
- index = offset >> PAGE_CACHE_SHIFT;
-
- page = grab_cache_page(&inode->i_data, index);
-
- /* Yuck, no page */
- if (! page) {
- printk(KERN_WARNING " grab_cache_page says no dice ...\n");
- EXIT;
- return NULL;
- }
-
- /* PDEBUG(page, "GETPAGE: got page - before reading\n"); */
- /* now check if the data in the page is up to date */
- if ( Page_Uptodate(page)) {
- if (!locked) {
- if (PageLocked(page))
- obd_unlock_page(page);
- } else {
- printk("file %s, line %d: expecting locked page\n",
- __FILE__, __LINE__);
- }
- EXIT;
- return page;
- }
+ CDEBUG(D_INODE, "commit_page writing (at %d) to %d, count %Ld\n",
+ from, to, count);
- err = ll_brw(READ, inode, page, create);
+ err = obd_brw(OBD_BRW_WRITE, IID(inode), num_obdo, &oa, &bufs_per_obdo,
+ &page, &count, &offset, &flags);
+ if ( !err ) {
+ SetPageUptodate(page);
+ set_page_clean(page);
+ }
+ kunmap(page);
- if ( err ) {
- SetPageError(page);
- obd_unlock_page(page);
- EXIT;
- return page;
- }
+ if (offset > inode->i_size) {
+ iattr.ia_valid = ATTR_SIZE;
+ iattr.ia_size = offset;
+ /* do NOT truncate */
+ err = ll_inode_setattr(inode, &iattr, 0);
+ if (err) {
+ printk(__FUNCTION__ ": failed - %d.\n", err);
+ obdo_free(oa);
+ EXIT;
+ return -EIO;
+ }
+ }
- if ( !locked )
- obd_unlock_page(page);
- SetPageUptodate(page);
- /* PDEBUG(page,"GETPAGE - after reading"); */
+ obdo_free(oa);
EXIT;
- return page;
-} /* ll_getpage */
-
+ return err;
+} /* ll_brw */
void ll_truncate(struct inode *inode)
{
int err;
ENTRY;
- //ll_dequeue_pages(inode);
-
- oa = obdo_alloc();
+ oa = ll_oa_from_inode(inode, OBD_MD_FLNOTOBD);
if ( !oa ) {
- /* XXX This would give an inconsistent FS, so deal with it as
- * best we can for now - an obdo on the stack is not pretty.
- */
- struct obdo obdo;
-
- printk(__FUNCTION__ ": obdo_alloc failed - using stack!\n");
-
- obdo.o_valid = OBD_MD_FLNOTOBD;
- ll_oa_from_inode(&obdo, inode);
-
- err = obd_punch(IID(inode), &obdo, 0, obdo.o_size);
- } else {
- oa->o_valid = OBD_MD_FLNOTOBD;
- ll_oa_from_inode(oa, inode);
-
- CDEBUG(D_INFO, "calling punch for %ld (%Lu bytes at 0)\n",
- (long)oa->o_id, oa->o_size);
- err = obd_punch(IID(inode), oa, oa->o_size, 0);
-
- obdo_free(oa);
- }
+ printk(__FUNCTION__ ": no memory to allocate obdo!\n");
+ return;
+ }
+
+ CDEBUG(D_INFO, "calling punch for %ld (%Lu bytes at 0)\n",
+ (long)oa->o_id, oa->o_size);
+ err = obd_punch(IID(inode), oa, oa->o_size, 0);
+ obdo_free(oa);
if (err) {
printk(__FUNCTION__ ": obd_truncate fails (%d)\n", err);
- EXIT;
- return;
}
EXIT;
+ return;
} /* ll_truncate */
struct address_space_operations ll_aops = {
bmap: NULL
};
-
-struct address_space_operations ll_dir_aops = {
- readpage: ll_dir_readpage,
- prepare_write: ll_dir_prepare_write
-};
#include <linux/obd_class.h>
#include <linux/lustre_light.h>
-//struct list_head ll_super_list;
extern struct address_space_operations ll_aops;
extern struct address_space_operations ll_dir_aops;
struct super_operations ll_super_operations;
-long ll_cache_count = 0;
-long ll_mutex_start = 0;
long obd_memory = 0;
static char *ll_read_opt(const char *opt, char *data)
memset(sbi, 0, sizeof(*sbi));
- printk(__FUNCTION__ "line %d\n", __LINE__);
-
ll_options(data, &device, &version);
printk(__FUNCTION__ "line %d\n", __LINE__);
if ( !device ) {
sb = NULL;
goto ERR;
}
- printk(__FUNCTION__ "line %d\n", __LINE__);
devno = simple_strtoul(device, NULL, 0);
if ( devno >= MAX_OBD_DEVICES ) {
sb = NULL;
goto ERR;
}
- printk(__FUNCTION__ "line %d\n", __LINE__);
sbi->ll_conn.oc_dev = &obd_dev[devno];
err = obd_connect(&sbi->ll_conn);
sb = NULL;
goto ERR;
}
- printk(__FUNCTION__ "line %d\n", __LINE__);
connected = 1;
- printk(__FUNCTION__ "line %d\n", __LINE__);
err = kportal_uuid_to_peer("mds", &sbi->ll_peer);
if (err == 0)
sbi->ll_peer_ptr = &sbi->ll_peer;
- printk(__FUNCTION__ "line %d\n", __LINE__);
sbi->ll_super = sb;
sbi->ll_rootino = 2;
err = mdc_getattr(sbi->ll_peer_ptr, sbi->ll_rootino, S_IFDIR,
OBD_MD_FLNOTOBD|OBD_MD_FLBLOCKS,
&rep, &hdr);
- printk(__FUNCTION__ "line %d\n", __LINE__);
if (err) {
printk(__FUNCTION__ ": mds_getattr failed for root %d\n", err);
sb = NULL;
goto ERR;
}
- printk(__FUNCTION__ "line %d\n", __LINE__);
root = iget4(sb, sbi->ll_rootino, NULL, rep);
if (root) {
sb = NULL;
goto ERR;
}
- printk(__FUNCTION__ "line %d\n", __LINE__);
ERR:
if (hdr)
} /* ll_put_super */
-extern void write_inode_pages(struct inode *);
-/* This routine is called from iput() (for each unlink on the inode).
- * We can't put this call into delete_inode() since that is called only
- * when i_count == 0, and we need to keep a reference on the inode while
- * it is in the page cache, which means i_count > 0. Catch 22.
- */
-static void ll_put_inode(struct inode *inode)
+extern inline struct obdo * ll_oa_from_inode(struct inode *inode, int valid);
+static void ll_delete_inode(struct inode *inode)
{
- ENTRY;
- if (inode->i_nlink && (atomic_read(&inode->i_count) == 1)) {
- write_inode_pages(inode);
- EXIT;
- return;
- }
- //ll_dequeue_pages(inode);
- EXIT;
-} /* ll_put_inode */
+ if (S_ISREG(inode->i_mode)) {
+ int err;
+ struct obdo *oa;
+ oa = ll_oa_from_inode(inode, OBD_MD_FLNOTOBD);
+ if (!oa) {
+ printk(__FUNCTION__ ": no memory\n");
+ }
+
+ err = obd_destroy(IID(inode), oa);
+ printk(__FUNCTION__ ": obd destroy of %Ld error %d\n",
+ oa->o_id, err);
+ obdo_free(oa);
+ }
+
+ clear_inode(inode);
+}
/* like inode_setattr, but doesn't mark the inode dirty */
-static int ll_attr2inode(struct inode * inode, struct iattr * attr)
+static int ll_attr2inode(struct inode * inode, struct iattr * attr, int trunc)
{
unsigned int ia_valid = attr->ia_valid;
int error = 0;
- if ((ia_valid & ATTR_SIZE) && attr->ia_size < inode->i_size ) {
+ if ((ia_valid & ATTR_SIZE) && trunc ) {
error = vmtruncate(inode, attr->ia_size);
if (error)
goto out;
return error;
}
-int ll_inode_setattr(struct inode *inode, struct iattr *attr)
+int ll_inode_setattr(struct inode *inode, struct iattr *attr, int do_trunc)
{
struct ptlrep_hdr *hdr = NULL;
- struct ll_sb_info *sbi =
- (struct ll_sb_info *)(&inode->i_sb->u.generic_sbp);
+ struct ll_sb_info *sbi = ll_i2sbi(inode);
int err;
ENTRY;
/* change incore inode */
- ll_attr2inode(inode, attr);
+ ll_attr2inode(inode, attr, do_trunc);
err = mdc_setattr(sbi->ll_peer_ptr, inode, attr, NULL, &hdr);
if ( err )
int ll_setattr(struct dentry *de, struct iattr *attr)
{
- return ll_inode_setattr(de->d_inode, attr);
+ return ll_inode_setattr(de->d_inode, attr, 1);
}
static int ll_statfs(struct super_block *sb, struct statfs *buf)
inode->i_mapping->a_ops = &ll_dir_aops;
EXIT;
} else if (S_ISLNK(inode->i_mode)) {
- if (inode->i_blocks) {
- inode->i_op = &ll_symlink_inode_operations;
- inode->i_mapping->a_ops = &ll_aops;
- }else {
- inode->i_op = &ll_fast_symlink_inode_operations;
- }
+ inode->i_op = &ll_fast_symlink_inode_operations;
EXIT;
} else {
init_special_inode(inode, inode->i_mode,
struct super_operations ll_super_operations =
{
read_inode2: ll_read_inode2,
- // put_inode: ll_put_inode,
- // delete_inode: ll_delete_inode,
+ delete_inode: ll_delete_inode,
put_super: ll_put_super,
// statfs: ll_statfs
};
#include <linux/obd_support.h> /* for ENTRY and EXIT only */
#include <linux/lustre_light.h>
+
+
static int ll_fast_readlink(struct dentry *dentry, char *buffer, int buflen)
{
char *s = ll_i2info(dentry->d_inode)->lli_inline;
setattr: ll_setattr
};
-static int ll_readlink(struct dentry *dentry, char *buffer, int buflen)
-{
- struct page *page = NULL;
- int res;
-
- ENTRY;
- OIDEBUG(dentry->d_inode);
- page = ll_getpage(dentry->d_inode, 0, 0, 0);
- /* PDEBUG(page, "readlink"); */
- if (!page) {
- EXIT;
- return 0;
- }
- res = vfs_readlink(dentry, buffer, buflen, (char *)page_address(page));
- page_cache_release(page);
- EXIT;
- return res;
-} /* ll_readlink */
-
-static int ll_follow_link(struct dentry * dentry,
- struct nameidata *nd)
-{
- struct page *page = NULL;
- int res;
-
- ENTRY;
- OIDEBUG(dentry->d_inode);
- page = ll_getpage(dentry->d_inode, 0, 0, 0);
- /* PDEBUG(page, "follow_link"); */
- if (!page) {
- dput(nd->dentry);
- EXIT;
- return -EIO;
- }
- res = vfs_follow_link(nd, (char *)page_address(page));
- page_cache_release(page);
- EXIT;
- return res;
-}
-
-struct inode_operations ll_symlink_inode_operations = {
- readlink: ll_readlink,
- follow_link: ll_follow_link,
- setattr: ll_setattr
-};
}
printk("mds_setattr: ino %ld\n", de->d_inode->i_ino);
+
+ /* a _really_ horrible hack to avoid removing the data stored
+ in the block pointers; this data is the object id
+ this will go into an extended attribute at some point.
+ */
+ if ( rec->ur_iattr.ia_valid & ATTR_SIZE ) {
+ /* ATTR_SIZE would invoke truncate: clear it */
+ rec->ur_iattr.ia_valid &= ~ATTR_SIZE;
+ de->d_inode->i_size = rec->ur_iattr.ia_size;
+ /* make sure _something_ gets set - so new inode
+ goes to disk (probably won't work over XFS */
+ if (!rec->ur_iattr.ia_valid & ATTR_MODE) {
+ rec->ur_iattr.ia_valid |= ATTR_MODE;
+ rec->ur_iattr.ia_mode = de->d_inode->i_mode;
+ }
+ }
if ( de->d_inode->i_op->setattr ) {
req->rq_rephdr->status =
de->d_inode->i_op->setattr(de, &rec->ur_iattr);
return 0;
}
- switch (de->d_inode->i_mode & S_IFMT) {
+ switch (dchild->d_inode->i_mode & S_IFMT) {
case S_IFDIR:
rc = vfs_rmdir(de->d_inode, dchild);
EXIT;
static void filter_id(char *buf, obd_id id, obd_mode mode)
{
- sprintf(buf, "O/%s/%Ld",
- obd_type_by_mode[(mode & S_IFMT) >> S_SHIFT],
+ sprintf(buf, "O/%s/%Ld", obd_type_by_mode[(mode & S_IFMT) >> S_SHIFT],
id);
}
+static struct file *filter_parent(obd_id id, obd_mode mode)
+{
+ char path[64];
+ struct file *file;
+ sprintf(path, "O/%s", obd_type_by_mode[(mode & S_IFMT) >> S_SHIFT]);
+
+ file = filp_open(path, O_RDONLY, 0);
+ return file;
+}
+
void push_ctxt(struct run_ctxt *save, struct run_ctxt *new)
{
save->fs = get_fs();
mntput(saved->pwdmnt);
}
+static int simple_mkdir(struct dentry *dir, char *name, int mode)
+{
+ struct dentry *dchild;
+ int err;
+ ENTRY;
+
+ dchild = lookup_one_len(name, dir, strlen(name));
+ if (IS_ERR(dchild)) {
+ EXIT;
+ return PTR_ERR(dchild);
+ }
+
+ if (dchild->d_inode) {
+ dput(dchild);
+ EXIT;
+ return -EEXIST;
+ }
+
+ err = vfs_mkdir(dir->d_inode, dchild, mode);
+ dput(dchild);
+
+ EXIT;
+ return err;
+}
+
+static int simple_unlink(struct dentry *dir, char *name)
+{
+ struct dentry *dchild;
+ int err;
+ ENTRY;
+
+ dchild = lookup_one_len(name, dir, strlen(name));
+ if (IS_ERR(dchild)) {
+ EXIT;
+ return PTR_ERR(dchild);
+ }
+
+ if (!dchild->d_inode) {
+ dput(dchild);
+ EXIT;
+ return -ENOENT;
+ }
+
+ err = vfs_unlink(dir->d_inode, dchild);
+ dput(dchild);
+
+ EXIT;
+ return err;
+}
+
static void filter_prep(struct obd_device *obddev)
{
struct run_ctxt saved;
struct file *file;
struct inode *inode;
+ loff_t off;
long rc;
- int fd;
char rootid[128];
- struct stat64 buf;
__u64 lastino = 2;
push_ctxt(&saved, &obddev->u.filter.fo_ctxt);
- rc = sys_mkdir("O", 0700);
- rc = sys_mkdir("P", 0700);
- rc = sys_mkdir("D", 0700);
- rc = sys_mkdir("O/R", 0700); /* regular */
- rc = sys_mkdir("O/D", 0700); /* directory */
- rc = sys_mkdir("O/L", 0700); /* symbolic links */
- rc = sys_mkdir("O/C", 0700); /* character devices */
- rc = sys_mkdir("O/B", 0700); /* block devices */
- rc = sys_mkdir("O/F", 0700); /* fifo's */
- rc = sys_mkdir("O/S", 0700); /* sockets */
-
+ rc = simple_mkdir(current->fs->pwd, "O", 0700);
+ rc = simple_mkdir(current->fs->pwd, "P", 0700);
+ rc = simple_mkdir(current->fs->pwd, "D", 0700);
+ file = filp_open("O", O_RDONLY, 0);
+ if (!file || IS_ERR(file)) {
+ printk(__FUNCTION__ ": cannot open O\n");
+ goto out;
+ }
+ rc = simple_mkdir(file->f_dentry, "R", 0700); /* regular */
+ rc = simple_mkdir(file->f_dentry, "D", 0700); /* directory */
+ rc = simple_mkdir(file->f_dentry, "L", 0700); /* symbolic links */
+ rc = simple_mkdir(file->f_dentry, "C", 0700); /* character devices */
+ rc = simple_mkdir(file->f_dentry, "B", 0700); /* block devices */
+ rc = simple_mkdir(file->f_dentry, "F", 0700); /* fifo's */
+ rc = simple_mkdir(file->f_dentry, "S", 0700); /* sockets */
+ filp_close(file, NULL);
+
filter_id(rootid, FILTER_ROOTINO, S_IFDIR);
file = filp_open(rootid, O_RDWR | O_CREAT, 00755);
if (IS_ERR(file)) {
goto out;
}
filp_close(file, 0);
- rc = sys_mkdir(rootid, 0755);
- if ( (fd = sys_open("D/status", O_RDWR | O_CREAT, 0700)) == -1 ) {
- printk("OBD filter: cannot create status file\n");
+ rc = simple_mkdir(current->fs->pwd, rootid, 0755);
+
+ file = filp_open("D/status", O_RDWR | O_CREAT, 0700);
+ if ( !file || IS_ERR(file) ) {
+ printk("OBD filter: cannot open/create status file\n");
goto out;
}
- if ( (rc = sys_fstat64(fd, &buf, 0)) ) {
- printk("OBD filter: cannot stat status file\n");
- goto out_close;
- }
- if (buf.st_size == 0) {
- rc = sys_write(fd, (char *)&lastino, sizeof(lastino));
+
+ /* steal operations */
+ inode = file->f_dentry->d_inode;
+ obddev->u.filter.fo_fop = file->f_op;
+ obddev->u.filter.fo_iop = inode->i_op;
+ obddev->u.filter.fo_aops = inode->i_mapping->a_ops;
+
+ off = 0;
+ if (inode->i_size == 0) {
+ rc = file->f_op->write(file, (char *)&lastino,
+ sizeof(lastino), &off);
if (rc != sizeof(lastino)) {
printk("OBD filter: error writing lastino\n");
- goto out_close;
+ goto out;
}
} else {
- rc = sys_read(fd, (char *)&lastino, sizeof(lastino));
+ rc = file->f_op->read(file, (char *)&lastino, sizeof(lastino),
+ &off);
if (rc != sizeof(lastino)) {
printk("OBD filter: error reading lastino\n");
- goto out_close;
+ goto out;
}
}
obddev->u.filter.fo_lastino = lastino;
- /* this is also the moment to steal operations */
- file = filp_open("D/status", O_RDONLY | O_LARGEFILE, 0);
- if (!file || IS_ERR(file)) {
- EXIT;
- goto out_close;
- }
- inode = file->f_dentry->d_inode;
- obddev->u.filter.fo_fop = file->f_op;
- obddev->u.filter.fo_iop = inode->i_op;
- obddev->u.filter.fo_aops = inode->i_mapping->a_ops;
- filp_close(file, 0);
-
- out_close:
- rc = sys_close(fd);
- if (rc) {
- printk("OBD filter: cannot close status file\n");
- }
out:
pop_ctxt(&saved);
}
{
struct run_ctxt saved;
long rc;
- int fd;
+ struct file *file;
+ loff_t off = 0;
push_ctxt(&saved, &obddev->u.filter.fo_ctxt);
- if ( (fd = sys_open("D/status", O_RDWR | O_CREAT, 0700)) == -1 ) {
+ file = filp_open("D/status", O_RDWR | O_CREAT, 0700);
+ if ( !file || IS_ERR(file)) {
printk("OBD filter: cannot create status file\n");
goto out;
}
- rc = sys_write(fd, (char *)&obddev->u.filter.fo_lastino,
- sizeof(obddev->u.filter.fo_lastino));
+ rc = file->f_op->write(file, (char *)&obddev->u.filter.fo_lastino,
+ sizeof(obddev->u.filter.fo_lastino), &off);
if (rc != sizeof(sizeof(obddev->u.filter.fo_lastino)) ) {
printk("OBD filter: error writing lastino\n");
}
- rc = sys_close(fd);
+ rc = filp_close(file, NULL);
if (rc) {
printk("OBD filter: cannot close status file\n");
}
struct obd_device * obddev;
struct obd_client * cli;
struct inode * inode;
+ struct file *dir;
+ int rc;
struct run_ctxt saved;
char id[128];
filter_id(id, oa->o_id, oa->o_mode);
push_ctxt(&saved, &obddev->u.filter.fo_ctxt);
- if (sys_unlink(id)) {
- EXIT;
- pop_ctxt(&saved);
- return -EPERM;
+ dir = filter_parent(oa->o_id, oa->o_mode);
+ if (!dir || IS_ERR(dir)) {
+ goto out;
}
- pop_ctxt(&saved);
+ rc = simple_unlink(dir->f_dentry, id);
+
+ out:
+ filp_close(dir, 0);
+ pop_ctxt(&saved);
EXIT;
- return 0;
+ return rc;
}
static int filter_truncate(struct obd_conn *conn, struct obdo *oa, obd_size count,
};
-#ifdef MODULE
-
-void init_module(void)
+static int __init obdfilter_init(void)
{
printk(KERN_INFO "Filtering OBD driver v0.001, braam@clusterfs.com\n");
- obd_register_type(&filter_obd_ops, OBD_FILTER_DEVICENAME);
+ return obd_register_type(&filter_obd_ops, OBD_FILTER_DEVICENAME);
}
-void cleanup_module(void)
+static void __exit obdfilter_exit(void)
{
obd_unregister_type(OBD_FILTER_DEVICENAME);
- CDEBUG(D_MALLOC, "FILTER mem used %ld\n", filter_memory);
}
-#endif
+MODULE_AUTHOR("Peter J. Braam <braam@clusterfs.com>");
+MODULE_DESCRIPTION("Lustre Filtering OBD driver v1.0");
+MODULE_LICENSE("GPL");
+
+module_init(obdfilter_init);
+module_exit(obdfilter_exit);
inode = iget4(dir->i_sb, (ino_t)oa->o_id, NULL, oa);
CDEBUG(D_INODE, "\n");
- obdo_free(oa);
if (!inode) {
printk("new_inode -fatal: %ld\n", (long)oa->o_id);
obd_destroy(IID(dir), oa);
+ obdo_free(oa);
EXIT;
return ERR_PTR(-EIO);
}
+ obdo_free(oa);
if (!list_empty(&inode->i_dentry)) {
printk("new_inode -fatal: aliases %ld, ct %d lnk %d\n",
return 0;
}
-void osc_free_req(struct ptlrpc_request *request)
+static void osc_free_req(struct ptlrpc_request *request)
{
kfree(request);
}
-int osc_connect(struct obd_conn *conn)
+static int osc_connect(struct obd_conn *conn)
{
struct ptlrpc_request *request;
int rc;
return rc;
}
-int osc_disconnect(struct obd_conn *conn)
+static int osc_disconnect(struct obd_conn *conn)
{
struct ptlrpc_request *request;
int rc;
}
-int osc_getattr(struct obd_conn *conn, struct obdo *oa)
+static int osc_getattr(struct obd_conn *conn, struct obdo *oa)
{
struct ptlrpc_request *request;
int rc;
return 0;
}
-int osc_setattr(struct obd_conn *conn, struct obdo *oa)
+static int osc_setattr(struct obd_conn *conn, struct obdo *oa)
{
struct ptlrpc_request *request;
int rc;
return 0;
}
-int osc_create(struct obd_conn *conn, struct obdo *oa)
+static int osc_create(struct obd_conn *conn, struct obdo *oa)
{
struct ptlrpc_request *request;
int rc;
return 0;
}
+static int osc_destroy(struct obd_conn *conn, struct obdo *oa)
+{
+ struct ptlrpc_request *request;
+ int rc;
+
+ if (!oa) {
+ printk(__FUNCTION__ ": oa NULL\n");
+ }
+ request = ost_prep_req(OST_DESTROY, 0, NULL, 0, NULL);
+ if (!request) {
+ printk("osc_connect: cannot pack req!\n");
+ return -ENOMEM;
+ }
+
+ memcpy(&request->rq_req.ost->oa, oa, sizeof(*oa));
+ request->rq_req.ost->oa.o_valid = ~0;
+ request->rq_replen =
+ sizeof(struct ptlrep_hdr) + sizeof(struct ost_rep);
+
+ rc = osc_queue_wait(conn, request);
+ if (rc) {
+ EXIT;
+ goto out;
+ }
+ memcpy(oa, &request->rq_rep.ost->oa, sizeof(*oa));
+
+ out:
+ osc_free_req(request);
+ return 0;
+}
+
/* mount the file system (secretly) */
static int osc_setup(struct obd_device *obddev, obd_count len,
o_setup: osc_setup,
o_cleanup: osc_cleanup,
o_create: osc_create,
+ o_destroy: osc_destroy,
o_getattr: osc_getattr,
o_setattr: osc_setattr,
o_connect: osc_connect,
diff -u -r linux-2.4.17-stock/include/linux/fs.h linux-2.4.17/include/linux/fs.h
--- linux-2.4.17-stock/include/linux/fs.h Fri Dec 21 09:42:03 2001
+++ linux-2.4.17/include/linux/fs.h Wed Feb 20 13:39:51 2002
-@@ -984,6 +984,8 @@
+@@ -984,6 +984,7 @@
extern int may_umount(struct vfsmount *);
extern long do_mount(char *, char *, char *, unsigned long, void *);
+struct vfsmount *do_kern_mount(char *type, int flags, char *name, void *data);
-+int do_umount(struct vfsmount *mnt, int flags);
#define kern_umount mntput
extern int vfs_statfs(struct super_block *, struct statfs *);
-@@ -1042,6 +1044,15 @@
+@@ -1042,6 +1045,6 @@
return __get_lease(inode, mode);
return 0;
}
-+
-+/* fs/namei.c */
-+asmlinkage long sys_mkdir(const char * pathname, int mode);
-+asmlinkage long sys_rmdir(const char * pathname);
-+asmlinkage long sys_unlink(const char * pathname);
-+asmlinkage long sys_open(const char * filename, int flags, int mode);
-+asmlinkage long sys_fstat64(unsigned long fd, struct stat64 * statbuf, long flags);
-+asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count);
-+asmlinkage ssize_t sys_write(unsigned int fd, const char * buf, size_t count);
/* fs/open.c */
-diff -u -r linux-2.4.17-stock/kernel/ksyms.c linux-2.4.17/kernel/ksyms.c
--- linux-2.4.17-stock/kernel/ksyms.c Fri Dec 21 09:42:04 2001
+++ linux-2.4.17/kernel/ksyms.c Wed Feb 20 12:57:32 2002
-@@ -280,6 +280,18 @@
+@@ -280,7 +290,11 @@
EXPORT_SYMBOL(lock_page);
EXPORT_SYMBOL(unlock_page);
+EXPORT_SYMBOL(pagecache_lock);
+EXPORT_SYMBOL(do_kern_mount);
+EXPORT_SYMBOL(module_list);
-+EXPORT_SYMBOL(sys_mkdir);
-+EXPORT_SYMBOL(sys_rmdir);
-+EXPORT_SYMBOL(sys_unlink);
-+EXPORT_SYMBOL(sys_open);
-+EXPORT_SYMBOL(sys_fstat64);
-+EXPORT_SYMBOL(sys_read);
-+EXPORT_SYMBOL(sys_write);
-+
+
/* device registration */
EXPORT_SYMBOL(register_chrdev);
EXPORT_SYMBOL(unregister_chrdev);
-diff -u -r linux-2.4.17-stock/mm/filemap.c linux-2.4.17/mm/filemap.c
--- linux-2.4.17-stock/mm/filemap.c Fri Dec 21 09:42:04 2001
+++ linux-2.4.17/mm/filemap.c Wed Feb 20 15:18:17 2002
-@@ -2862,8 +2862,10 @@
+@@ -2862,8 +2880,10 @@
if ((ssize_t) count < 0)
return -EINVAL;
cached_page = NULL;
-@@ -2987,10 +2989,12 @@
+@@ -2987,10 +3007,12 @@
* same page as we're writing to, without it being marked
* up-to-date.
*/
return rc;
}
-static int init_module(void)
+static int __init ptlrpc_init(void)
{
return req_init_portals();
}
-static void cleanup_module(void)
+static void __exit ptlrpc_exit(void)
{
PtlEQFree(req_eq);
MODULE_DESCRIPTION("Lustre Request Processor v1.0");
MODULE_LICENSE("GPL");
+module_init(ptlrpc_init);
+module_exit(ptlrpc_exit);
+
KFLAGS:=
CPPFLAGS :=
# LDADD := -lreadline -ltermcap # -lefence
-bin_PROGRAMS = testreq
+bin_PROGRAMS = testreq truncate
+
testreq_SOURCES = testreq.c
+truncate_SOURCES = truncate.c