*/
const char *yaffs_fs_c_version =
- "$Id: yaffs_fs.c,v 1.87 2009-11-11 02:11:13 charles Exp $";
+ "$Id: yaffs_fs.c,v 1.91 2010-01-11 04:06:46 charles Exp $";
extern const char *yaffs_guts_c_version;
#include <linux/version.h>
#include "asm/div64.h"
+
+#define LOCK_TRACE 0
+
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
#include <linux/statfs.h> /* Added NCB 15-8-2003 */
#include <linux/uaccess.h>
#include "yportenv.h"
+#include "yaffs_trace.h"
#include "yaffs_guts.h"
#include <linux/mtd/mtd.h>
.write_super = yaffs_write_super,
};
-/* YAFFS uses two locks per yaffs_Device.
- * dirLock: r/w lock Must be held when accessing directory structure.
- * grossLock: Lock when accessing yaffs internals.
- *
- * Locking rules:
- * If you're going to take dirLock then you must take if before
- * taking grossLock.
- * ie. Don't call yaffs_DirLockxxx() while holding grossLock.
- *
- * Todo:
- * Investigate changing to mutexes etc and improve debugging.
- */
-static void yaffs_DirLockInitialise(yaffs_Device *dev)
+static void yaffs_GrossLock(yaffs_Device *dev)
{
- init_rwsem(&dev->dirLock);
+ T(LOCK_TRACE && YAFFS_TRACE_OS, ("yaffs locking %p\n", current));
+ down(&dev->grossLock);
+ T(LOCK_TRACE && YAFFS_TRACE_OS, ("yaffs locked %p\n", current));
}
-static void yaffs_DirLockRead(yaffs_Device *dev)
+static void yaffs_GrossUnlock(yaffs_Device *dev)
{
- T(YAFFS_TRACE_OS, ("yaffs locking dir read %p\n", current));
- down_read(&dev->dirLock);
- T(YAFFS_TRACE_OS, ("yaffs locked dir read %p\n", current));
+ T(LOCK_TRACE && YAFFS_TRACE_OS, ("yaffs unlocking %p\n", current));
+ up(&dev->grossLock);
}
-static void yaffs_DirUnlockRead(yaffs_Device *dev)
-{
- T(YAFFS_TRACE_OS, ("yaffs unlocking dir read %p\n", current));
- up_read(&dev->dirLock);
-}
-static void yaffs_DirLockWrite(yaffs_Device *dev)
-{
- T(YAFFS_TRACE_OS, ("yaffs locking dir write %p\n", current));
- down_write(&dev->dirLock);
- T(YAFFS_TRACE_OS, ("yaffs locked dir write %p\n", current));
-}
+/*-----------------------------------------------------------------*/
+/* Directory search context allows us to unlock access to yaffs during
+ * filldir without causing problems with the directory being modified.
+ * This is similar to the tried and tested mechanism used in yaffs direct.
+ *
+ * A search context iterates along a doubly linked list of siblings in the
+ * directory. If the iterating object is deleted then this would corrupt
+ * the list iteration, likely causing a crash. The search context avoids
+ * this by using the removeObjectCallback to move the search context to the
+ * next object before the object is deleted.
+ *
+ * Many readdirs (and thus seach conexts) may be alive simulateously so
+ * each yaffs_Device has a list of these.
+ *
+ * A seach context lives for the duration of a readdir.
+ *
+ * All these functions must be called while yaffs is locked.
+ */
-static void yaffs_DirUnlockWrite(yaffs_Device *dev)
-{
- T(YAFFS_TRACE_OS, ("yaffs unlocking dir write %p\n", current));
- up_write(&dev->dirLock);
+struct yaffs_SearchContext {
+ yaffs_Device *dev;
+ yaffs_Object *dirObj;
+ yaffs_Object *nextReturn;
+ struct ylist_head others;
+};
+
+/*
+ * yaffs_NewSearch() creates a new search context, initialises it and
+ * adds it to the device's search context list.
+ *
+ * Called at start of readdir.
+ */
+static struct yaffs_SearchContext * yaffs_NewSearch(yaffs_Object *dir)
+{
+ yaffs_Device *dev = dir->myDev;
+ struct yaffs_SearchContext *sc = YMALLOC(sizeof(struct yaffs_SearchContext));
+ if(sc){
+ sc->dirObj = dir;
+ sc->dev = dev;
+ if( ylist_empty(&sc->dirObj->variant.directoryVariant.children))
+ sc->nextReturn = NULL;
+ else
+ sc->nextReturn = ylist_entry(
+ dir->variant.directoryVariant.children.next,
+ yaffs_Object,siblings);
+ YINIT_LIST_HEAD(&sc->others);
+ ylist_add(&sc->others,&dev->searchContexts);
+ }
+ return sc;
}
-static void yaffs_GrossLockInitialise(yaffs_Device *dev)
+/*
+ * yaffs_EndSearch() disposes of a search context and cleans up.
+ */
+static void yaffs_EndSearch(struct yaffs_SearchContext * sc)
{
- init_MUTEX(&dev->grossLock);
+ if(sc){
+ ylist_del(&sc->others);
+ YFREE(sc);
+ }
}
-static void yaffs_GrossLock(yaffs_Device *dev)
+/*
+ * yaffs_SearchAdvance() moves a search context to the next object.
+ * Called when the search iterates or when an object removal causes
+ * the search context to be moved to the next object.
+ */
+static void yaffs_SearchAdvance(struct yaffs_SearchContext *sc)
{
- T(YAFFS_TRACE_OS, ("yaffs locking %p\n", current));
- down(&dev->grossLock);
- T(YAFFS_TRACE_OS, ("yaffs locked %p\n", current));
+ if(!sc)
+ return;
+
+ if( sc->nextReturn == NULL ||
+ ylist_empty(&sc->dirObj->variant.directoryVariant.children))
+ sc->nextReturn = NULL;
+ else {
+ struct ylist_head *next = sc->nextReturn->siblings.next;
+
+ if( next == &sc->dirObj->variant.directoryVariant.children)
+ sc->nextReturn = NULL; /* end of list */
+ else
+ sc->nextReturn = ylist_entry(next,yaffs_Object,siblings);
+ }
}
-static void yaffs_GrossUnlock(yaffs_Device *dev)
+/*
+ * yaffs_RemoveObjectCallback() is called when an object is unlinked.
+ * We check open search contexts and advance any which are currently
+ * on the object being iterated.
+ */
+static void yaffs_RemoveObjectCallback(yaffs_Object *obj)
{
- T(YAFFS_TRACE_OS, ("yaffs unlocking %p\n", current));
- up(&dev->grossLock);
+
+ struct ylist_head *i;
+ struct yaffs_SearchContext *sc;
+ struct ylist_head *search_contexts = &obj->myDev->searchContexts;
+
+
+ /* Iterate through the directory search contexts.
+ * If any are currently on the object being removed, then advance
+ * the search context to the next object to prevent a hanging pointer.
+ */
+ ylist_for_each(i, search_contexts) {
+ if (i) {
+ sc = ylist_entry(i, struct yaffs_SearchContext,others);
+ if(sc->nextReturn == obj)
+ yaffs_SearchAdvance(sc);
+ }
+ }
+
}
+/*-----------------------------------------------------------------*/
+
static int yaffs_readlink(struct dentry *dentry, char __user *buffer,
int buflen)
{
int ret;
yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev;
-
- yaffs_DirLockRead(dev);
+
yaffs_GrossLock(dev);
alias = yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry));
yaffs_GrossUnlock(dev);
- yaffs_DirUnlockRead(dev);
if (!alias)
return -ENOMEM;
int ret;
yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev;
- yaffs_DirLockRead(dev);
yaffs_GrossLock(dev);
alias = yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry));
yaffs_GrossUnlock(dev);
- yaffs_DirUnlockRead(dev);
if (!alias) {
ret = -ENOMEM;
yaffs_Device *dev = yaffs_InodeToObject(dir)->myDev;
- yaffs_DirLockRead(dev);
yaffs_GrossLock(dev);
T(YAFFS_TRACE_OS,
/* Can't hold gross lock when calling yaffs_get_inode() */
yaffs_GrossUnlock(dev);
- yaffs_DirUnlockRead(dev);
if (obj) {
T(YAFFS_TRACE_OS,
if (obj) {
dev = obj->myDev;
- yaffs_DirLockRead(dev);
yaffs_GrossLock(dev);
/* Clear the association between the inode and
yaffs_HandleDeferedFree(obj);
yaffs_GrossUnlock(dev);
- yaffs_DirUnlockRead(dev);
}
}
if (obj) {
dev = obj->myDev;
- yaffs_DirLockWrite(dev);
yaffs_GrossLock(dev);
yaffs_DeleteObject(obj);
yaffs_GrossUnlock(dev);
- yaffs_DirUnlockWrite(dev);
}
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
truncate_inode_pages(&inode->i_data, 0);
("yaffs_file_flush object %d (%s)\n", obj->objectId,
obj->dirty ? "dirty" : "clean"));
- yaffs_DirLockRead(dev);
yaffs_GrossLock(dev);
- yaffs_FlushFile(obj, 1,0);
+ yaffs_FlushFile(obj, 1, 0);
yaffs_GrossUnlock(dev);
- yaffs_DirUnlockRead(dev);
return 0;
}
yaffs_Device *dev;
- T(YAFFS_TRACE_OS, ("yaffs_readpage at %08x, size %08x\n",
+ T(YAFFS_TRACE_OS, ("yaffs_readpage_nolock at %08x, size %08x\n",
(unsigned)(pg->index << PAGE_CACHE_SHIFT),
(unsigned)PAGE_CACHE_SIZE));
pg_buf = kmap(pg);
/* FIXME: Can kmap fail? */
- yaffs_DirLockRead(dev);
yaffs_GrossLock(dev);
ret = yaffs_ReadDataFromFile(obj, pg_buf,
PAGE_CACHE_SIZE);
yaffs_GrossUnlock(dev);
- yaffs_DirUnlockRead(dev);
if (ret >= 0)
ret = 0;
flush_dcache_page(pg);
kunmap(pg);
- T(YAFFS_TRACE_OS, ("yaffs_readpage done\n"));
+ T(YAFFS_TRACE_OS, ("yaffs_readpage_nolock done\n"));
return ret;
}
static int yaffs_readpage(struct file *f, struct page *pg)
{
- return yaffs_readpage_unlock(f, pg);
+ int ret;
+
+ T(YAFFS_TRACE_OS, ("yaffs_readpage\n"));
+ ret=yaffs_readpage_unlock(f, pg);
+ T(YAFFS_TRACE_OS, ("yaffs_readpage done\n"));
+ return ret;
}
/* writepage inspired by/stolen from smbfs */
#endif
{
struct address_space *mapping = page->mapping;
- loff_t offset = (loff_t) page->index << PAGE_CACHE_SHIFT;
struct inode *inode;
unsigned long end_index;
char *buffer;
yaffs_Object *obj;
int nWritten = 0;
unsigned nBytes;
+ loff_t i_size;
if (!mapping)
BUG();
inode = mapping->host;
if (!inode)
BUG();
+ i_size = i_size_read(inode);
- if (offset > inode->i_size) {
- T(YAFFS_TRACE_OS,
- ("yaffs_writepage at %08x, inode size = %08x!!!\n",
- (unsigned)(page->index << PAGE_CACHE_SHIFT),
- (unsigned)inode->i_size));
- T(YAFFS_TRACE_OS,
- (" -> don't care!!\n"));
- unlock_page(page);
- return 0;
- }
-
- end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+ end_index = i_size >> PAGE_CACHE_SHIFT;
- /* easy case */
- if (page->index < end_index)
+ if(page->index < end_index)
nBytes = PAGE_CACHE_SIZE;
- else
- nBytes = inode->i_size & (PAGE_CACHE_SIZE - 1);
+ else {
+ nBytes = i_size & (PAGE_CACHE_SIZE -1);
+
+ if (page->index > end_index || !nBytes) {
+ T(YAFFS_TRACE_OS,
+ ("yaffs_writepage at %08x, inode size = %08x!!!\n",
+ (unsigned)(page->index << PAGE_CACHE_SHIFT),
+ (unsigned)inode->i_size));
+ T(YAFFS_TRACE_OS,
+ (" -> don't care!!\n"));
+
+ zero_user_segment(page,0,PAGE_CACHE_SIZE);
+ set_page_writeback(page);
+ unlock_page(page);
+ end_page_writeback(page);
+ return 0;
+ }
+ }
+
+ if(nBytes != PAGE_CACHE_SIZE)
+ zero_user_segment(page,nBytes,PAGE_CACHE_SIZE);
get_page(page);
buffer = kmap(page);
obj = yaffs_InodeToObject(inode);
- yaffs_DirLockRead(obj->myDev);
yaffs_GrossLock(obj->myDev);
T(YAFFS_TRACE_OS,
(int)obj->variant.fileVariant.fileSize, (int)inode->i_size));
yaffs_GrossUnlock(obj->myDev);
- yaffs_DirUnlockRead(obj->myDev);
kunmap(page);
- SetPageUptodate(page);
- UnlockPage(page);
+ set_page_writeback(page);
+ unlock_page(page);
+ end_page_writeback(page);
put_page(page);
return (nWritten == nBytes) ? 0 : -ENOSPC;
{
struct page *pg = NULL;
pgoff_t index = pos >> PAGE_CACHE_SHIFT;
- uint32_t offset = pos & (PAGE_CACHE_SIZE - 1);
- uint32_t to = offset + len;
int ret = 0;
int space_held = 0;
- T(YAFFS_TRACE_OS, ("start yaffs_write_begin\n"));
/* Get a page */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
pg = grab_cache_page_write_begin(mapping, index, flags);
ret = -ENOMEM;
goto out;
}
+ T(YAFFS_TRACE_OS, ("start yaffs_write_begin index %d(%x) uptodate %d\n",(int)index,(int)index,Page_Uptodate(pg) ? 1 : 0));
+
/* Get fs space */
space_held = yaffs_hold_space(filp);
/* Update page if required */
- if (!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE))
+ if (!Page_Uptodate(pg))
ret = yaffs_readpage_nolock(filp, pg);
if (ret)
{
T(YAFFS_TRACE_OS, ("yaffs_prepair_write\n"));
- if (!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE))
+ if (!Page_Uptodate(pg))
return yaffs_readpage_nolock(f, pg);
return 0;
}
("yaffs_write_end not same size ret %d copied %d\n",
ret, copied));
SetPageError(pg);
- ClearPageUptodate(pg);
} else {
- SetPageUptodate(pg);
+ /* Nothing */
}
kunmap(pg);
("yaffs_commit_write not same size nWritten %d nBytes %d\n",
nWritten, nBytes));
SetPageError(pg);
- ClearPageUptodate(pg);
} else {
- SetPageUptodate(pg);
+ /* Nothing */
}
kunmap(pg);
dev = obj->myDev;
- yaffs_DirLockRead(dev);
yaffs_GrossLock(dev);
inode = f->f_dentry->d_inode;
("yaffs_file_write: hey obj is null!\n"));
else
T(YAFFS_TRACE_OS,
- ("yaffs_file_write about to write writing %zu bytes"
- "to object %d at %d\n",
- n, obj->objectId, ipos));
+ ("yaffs_file_write about to write writing %u(%x) bytes"
+ "to object %d at %d(%x)\n",
+ (unsigned) n, (unsigned) n, obj->objectId, ipos,ipos));
nWritten = yaffs_WriteDataToFile(obj, buf, ipos, n, 0);
T(YAFFS_TRACE_OS,
- ("yaffs_file_write writing %zu bytes, %d written at %d\n",
- n, nWritten, ipos));
+ ("yaffs_file_write: %d(%x) bytes written\n",
+ (unsigned )n,(unsigned)n));
if (nWritten > 0) {
ipos += nWritten;
}
yaffs_GrossUnlock(dev);
- yaffs_DirUnlockRead(dev);
-
return (nWritten == 0) && (n > 0) ? -ENOSPC : nWritten;
}
dev = obj->myDev;
- yaffs_DirLockRead(dev);
yaffs_GrossLock(dev);
nFreeChunks = yaffs_GetNumberOfFreeChunks(dev);
yaffs_GrossUnlock(dev);
- yaffs_DirUnlockRead(dev);
return (nFreeChunks > 20) ? 1 : 0;
}
static void yaffs_release_space(struct file *f)
{
+ yaffs_Object *obj;
+ yaffs_Device *dev;
+
+
+ obj = yaffs_DentryToObject(f->f_dentry);
+
+ dev = obj->myDev;
+
+ yaffs_GrossLock(dev);
+
+
+ yaffs_GrossUnlock(dev);
}
static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
{
yaffs_Object *obj;
yaffs_Device *dev;
+ struct yaffs_SearchContext *sc;
struct inode *inode = f->f_dentry->d_inode;
unsigned long offset, curoffs;
- struct ylist_head *i;
yaffs_Object *l;
+ int retVal = 0;
char name[YAFFS_MAX_NAME_LENGTH + 1];
obj = yaffs_DentryToObject(f->f_dentry);
dev = obj->myDev;
- yaffs_DirLockRead(dev);
yaffs_GrossLock(dev);
offset = f->f_pos;
+ sc = yaffs_NewSearch(obj);
+ if(!sc){
+ retVal = -ENOMEM;
+ goto unlock_out;
+ }
+
T(YAFFS_TRACE_OS, ("yaffs_readdir: starting at %d\n", (int)offset));
if (offset == 0) {
T(YAFFS_TRACE_OS,
("yaffs_readdir: entry . ino %d \n",
(int)inode->i_ino));
-
yaffs_GrossUnlock(dev);
-
if (filldir(dirent, ".", 1, offset, inode->i_ino, DT_DIR) < 0)
goto out;
-
yaffs_GrossLock(dev);
-
offset++;
f->f_pos++;
}
T(YAFFS_TRACE_OS,
("yaffs_readdir: entry .. ino %d \n",
(int)f->f_dentry->d_parent->d_inode->i_ino));
-
yaffs_GrossUnlock(dev);
-
if (filldir(dirent, "..", 2, offset,
f->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0)
goto out;
-
yaffs_GrossLock(dev);
-
offset++;
f->f_pos++;
}
f->f_version = inode->i_version;
}
- ylist_for_each(i, &obj->variant.directoryVariant.children) {
+ while(sc->nextReturn){
curoffs++;
+ l = sc->nextReturn;
if (curoffs >= offset) {
- l = ylist_entry(i, yaffs_Object, siblings);
+ int this_inode = yaffs_GetObjectInode(l);
+ int this_type = yaffs_GetObjectType(l);
yaffs_GetObjectName(l, name,
YAFFS_MAX_NAME_LENGTH + 1);
("yaffs_readdir: %s inode %d\n", name,
yaffs_GetObjectInode(l)));
- yaffs_GrossUnlock(dev);
+ yaffs_GrossUnlock(dev);
if (filldir(dirent,
name,
strlen(name),
offset,
- yaffs_GetObjectInode(l),
- yaffs_GetObjectType(l)) < 0)
+ this_inode,
+ this_type) < 0)
goto out;
- yaffs_GrossLock(dev);
+ yaffs_GrossLock(dev);
offset++;
f->f_pos++;
}
+ yaffs_SearchAdvance(sc);
}
+unlock_out:
yaffs_GrossUnlock(dev);
out:
- yaffs_DirUnlockRead(dev);
+ yaffs_EndSearch(sc);
- return 0;
+ return retVal;
}
/*
dev = parent->myDev;
- yaffs_DirLockWrite(dev);
yaffs_GrossLock(dev);
switch (mode & S_IFMT) {
/* Can not call yaffs_get_inode() with gross lock held */
yaffs_GrossUnlock(dev);
- yaffs_DirUnlockWrite(dev);
if (obj) {
inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj);
dev = yaffs_InodeToObject(dir)->myDev;
- yaffs_DirLockWrite(dev);
yaffs_GrossLock(dev);
retVal = yaffs_Unlink(yaffs_InodeToObject(dir), dentry->d_name.name);
if (retVal == YAFFS_OK) {
dentry->d_inode->i_nlink--;
dir->i_version++;
- }
-
- yaffs_GrossUnlock(dev);
- yaffs_DirUnlockWrite(dev);
-
- if( retVal == YAFFS_OK){
+ yaffs_GrossUnlock(dev);
mark_inode_dirty(dentry->d_inode);
update_dir_time(dir);
return 0;
}
-
+ yaffs_GrossUnlock(dev);
return -ENOTEMPTY;
}
obj = yaffs_InodeToObject(inode);
dev = obj->myDev;
- yaffs_DirLockWrite(dev);
yaffs_GrossLock(dev);
if (!S_ISDIR(inode->i_mode)) /* Don't link directories */
}
yaffs_GrossUnlock(dev);
- yaffs_DirUnlockWrite(dev);
if (link){
update_dir_time(dir);
T(YAFFS_TRACE_OS, ("yaffs_symlink\n"));
dev = yaffs_InodeToObject(dir)->myDev;
- yaffs_DirLockWrite(dev);
yaffs_GrossLock(dev);
obj = yaffs_MknodSymLink(yaffs_InodeToObject(dir), dentry->d_name.name,
S_IFLNK | S_IRWXUGO, uid, gid, symname);
yaffs_GrossUnlock(dev);
- yaffs_DirUnlockWrite(dev);
if (obj) {
struct inode *inode;
dev = obj->myDev;
- T(YAFFS_TRACE_OS, ("yaffs_sync_object\n"));
- yaffs_DirLockRead(dev);
+ T(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC, ("yaffs_sync_object\n"));
yaffs_GrossLock(dev);
yaffs_FlushFile(obj, 1, datasync);
yaffs_GrossUnlock(dev);
- yaffs_DirUnlockRead(dev);
return 0;
}
T(YAFFS_TRACE_OS, ("yaffs_rename\n"));
dev = yaffs_InodeToObject(old_dir)->myDev;
- yaffs_DirLockWrite(dev);
yaffs_GrossLock(dev);
/* Check if the target is an existing directory that is not empty. */
new_dentry->d_name.name);
}
yaffs_GrossUnlock(dev);
- yaffs_DirUnlockWrite(dev);
if (retVal == YAFFS_OK) {
if (target) {
error = inode_change_ok(inode, attr);
if (error == 0) {
+ int result;
+ if (!error){
+ error = inode_setattr(inode, attr);
+ T(YAFFS_TRACE_OS,("inode_setattr called\n"));
+ if (attr->ia_valid & ATTR_SIZE)
+ truncate_inode_pages(&inode->i_data,attr->ia_size);
+ }
dev = yaffs_InodeToObject(inode)->myDev;
- yaffs_DirLockRead(dev);
+ if (attr->ia_valid & ATTR_SIZE){
+ T(YAFFS_TRACE_OS,("resize to %d(%x)\n",(int)(attr->ia_size),(int)(attr->ia_size)));
+ }
yaffs_GrossLock(dev);
- if (yaffs_SetAttributes(yaffs_InodeToObject(inode), attr) ==
- YAFFS_OK) {
+ result = yaffs_SetAttributes(yaffs_InodeToObject(inode), attr);
+ if(result == YAFFS_OK) {
error = 0;
} else {
error = -EPERM;
}
yaffs_GrossUnlock(dev);
- yaffs_DirUnlockRead(dev);
- if (!error)
- error = inode_setattr(inode, attr);
+
}
+ T(YAFFS_TRACE_OS,
+ ("yaffs_setattr done\n"));
+
return error;
}
T(YAFFS_TRACE_OS, ("yaffs_statfs\n"));
- yaffs_DirLockRead(dev);
yaffs_GrossLock(dev);
buf->f_type = YAFFS_MAGIC;
buf->f_bavail = buf->f_bfree;
yaffs_GrossUnlock(dev);
- yaffs_DirUnlockRead(dev);
return 0;
}
{
yaffs_Device *dev = yaffs_SuperToDevice(sb);
- T(YAFFS_TRACE_OS, ("yaffs_do_sync_fs\n"));
+ T(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC, ("yaffs_do_sync_fs\n"));
if (sb->s_dirt) {
- yaffs_DirLockRead(dev);
yaffs_GrossLock(dev);
if (dev) {
}
yaffs_GrossUnlock(dev);
- yaffs_DirUnlockRead(dev);
sb->s_dirt = 0;
}
#endif
{
- T(YAFFS_TRACE_OS, ("yaffs_write_super\n"));
+ T(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC, ("yaffs_write_super\n"));
if (yaffs_auto_checkpoint >= 2)
yaffs_do_sync_fs(sb);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18))
static int yaffs_sync_fs(struct super_block *sb)
#endif
{
- T(YAFFS_TRACE_OS, ("yaffs_sync_fs\n"));
+ T(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC, ("yaffs_sync_fs\n"));
if (yaffs_auto_checkpoint >= 1)
yaffs_do_sync_fs(sb);
* need to lock again.
*/
- yaffs_DirLockRead(dev);
yaffs_GrossLock(dev);
obj = yaffs_FindObjectByNumber(dev, inode->i_ino);
yaffs_FillInodeFromObject(inode, obj);
yaffs_GrossUnlock(dev);
- yaffs_DirUnlockRead(dev);
unlock_new_inode(inode);
return inode;
T(YAFFS_TRACE_OS,
("yaffs_read_inode for %d\n", (int)inode->i_ino));
- yaffs_DirLockRead(dev);
yaffs_GrossLock(dev);
obj = yaffs_FindObjectByNumber(dev, inode->i_ino);
yaffs_FillInodeFromObject(inode, obj);
yaffs_GrossUnlock(dev);
- yaffs_DirUnlockRead(dev);
}
#endif
T(YAFFS_TRACE_OS,
("yaffs_remount_fs: %s: RO\n", dev->name));
- yaffs_DirLockWrite(dev);
+
yaffs_GrossLock(dev);
yaffs_FlushEntireDeviceCache(dev);
mtd->sync(mtd);
yaffs_GrossUnlock(dev);
- yaffs_DirUnlockWrite(dev);
} else {
T(YAFFS_TRACE_OS,
("yaffs_remount_fs: %s: RW\n", dev->name));
T(YAFFS_TRACE_OS, ("yaffs_put_super\n"));
- yaffs_DirLockWrite(dev);
yaffs_GrossLock(dev);
yaffs_FlushEntireDeviceCache(dev);
yaffs_Deinitialise(dev);
yaffs_GrossUnlock(dev);
- yaffs_DirUnlockWrite(dev);
/* we assume this is protected by lock_kernel() in mount/umount */
ylist_del(&dev->devList);
/* we assume this is protected by lock_kernel() in mount/umount */
ylist_add_tail(&dev->devList, &yaffs_dev_list);
-
- yaffs_DirLockInitialise(dev);
- yaffs_GrossLockInitialise(dev);
- yaffs_DirLockWrite(dev);
+ /* Directory search handling...*/
+ YINIT_LIST_HEAD(&dev->searchContexts);
+ dev->removeObjectCallback = yaffs_RemoveObjectCallback;
+
+ init_MUTEX(&dev->grossLock);
+
yaffs_GrossLock(dev);
err = yaffs_GutsInitialise(dev);
/* Release lock before yaffs_get_inode() */
yaffs_GrossUnlock(dev);
- yaffs_DirUnlockWrite(dev);
/* Create root inode */
if (err == YAFFS_OK)
{"scan_debug", YAFFS_TRACE_SCAN_DEBUG},
{"scan", YAFFS_TRACE_SCAN},
{"tracing", YAFFS_TRACE_TRACING},
+ {"sync", YAFFS_TRACE_SYNC},
{"verify", YAFFS_TRACE_VERIFY},
{"verify_nand", YAFFS_TRACE_VERIFY_NAND},