projects
/
yaffs2.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Apply Reed's deadlocking fix (manually applied)
[yaffs2.git]
/
yaffs_fs.c
diff --git
a/yaffs_fs.c
b/yaffs_fs.c
index 14fd0b8d04906ad39a955fdf506a58f5c24af311..b9d440bd3745632a99f8bfd8300680a1ae1a798c 100644
(file)
--- a/
yaffs_fs.c
+++ b/
yaffs_fs.c
@@
-31,7
+31,7
@@
*/
const char *yaffs_fs_c_version =
*/
const char *yaffs_fs_c_version =
- "$Id: yaffs_fs.c,v 1.3
3 2005-10-27 22:24:04 marty
Exp $";
+ "$Id: yaffs_fs.c,v 1.3
6 2005-12-08 00:54:55 charles
Exp $";
extern const char *yaffs_guts_c_version;
#include <linux/config.h>
extern const char *yaffs_guts_c_version;
#include <linux/config.h>
@@
-152,7
+152,11
@@
static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset,
static int yaffs_readlink(struct dentry *dentry, char __user * buffer,
int buflen);
static int yaffs_readlink(struct dentry *dentry, char __user * buffer,
int buflen);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
+static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd);
+#else
static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd);
static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd);
+#endif
static struct address_space_operations yaffs_file_address_operations = {
.readpage = yaffs_readpage,
static struct address_space_operations yaffs_file_address_operations = {
.readpage = yaffs_readpage,
@@
-243,7
+247,11
@@
static int yaffs_readlink(struct dentry *dentry, char __user * buffer,
return ret;
}
return ret;
}
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
+static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
+#else
static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
+#endif
{
unsigned char *alias;
int ret;
{
unsigned char *alias;
int ret;
@@
-256,11
+264,19
@@
static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
yaffs_GrossUnlock(dev);
if (!alias)
yaffs_GrossUnlock(dev);
if (!alias)
- return -ENOMEM;
+ {
+ ret = -ENOMEM;
+ goto out;
+ }
ret = vfs_follow_link(nd, alias);
kfree(alias);
ret = vfs_follow_link(nd, alias);
kfree(alias);
+out:
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
+ return ERR_PTR (ret);
+#else
return ret;
return ret;
+#endif
}
struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,
}
struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,
@@
-293,6
+309,9
@@
static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry)
dentry->d_name.name);
obj = yaffs_GetEquivalentObject(obj); /* in case it was a hardlink */
dentry->d_name.name);
obj = yaffs_GetEquivalentObject(obj); /* in case it was a hardlink */
+
+ /* Can't hold gross lock when calling yaffs_get_inode() */
+ yaffs_GrossUnlock(dev);
if (obj) {
T(YAFFS_TRACE_OS,
if (obj) {
T(YAFFS_TRACE_OS,
@@
-309,8
+328,6
@@
static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry)
/*dget(dentry); // try to solve directory bug */
d_add(dentry, inode);
/*dget(dentry); // try to solve directory bug */
d_add(dentry, inode);
- yaffs_GrossUnlock(dev);
-
/* return dentry; */
return NULL;
#endif
/* return dentry; */
return NULL;
#endif
@@
-320,7
+337,6
@@
static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry)
T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_lookup not found\n"));
}
T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_lookup not found\n"));
}
- yaffs_GrossUnlock(dev);
/* added NCB for 2.5/6 compatability - forces add even if inode is
* NULL which creates dentry hash */
/* added NCB for 2.5/6 compatability - forces add even if inode is
* NULL which creates dentry hash */
@@
-398,6
+414,9
@@
static void yaffs_delete_inode(struct inode *inode)
yaffs_DeleteFile(obj);
yaffs_GrossUnlock(dev);
}
yaffs_DeleteFile(obj);
yaffs_GrossUnlock(dev);
}
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
+ truncate_inode_pages (&inode->i_data, 0);
+#endif
clear_inode(inode);
}
clear_inode(inode);
}
@@
-706,6
+725,7
@@
struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,
/* NB Side effect: iget calls back to yaffs_read_inode(). */
/* iget also increments the inode's i_count */
/* NB Side effect: iget calls back to yaffs_read_inode(). */
/* iget also increments the inode's i_count */
+ /* NB You can't be holding grossLock or deadlock will happen! */
return inode;
}
return inode;
}
@@
-921,6
+941,9
@@
static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
obj = NULL; /* Do we ever get here? */
break;
}
obj = NULL; /* Do we ever get here? */
break;
}
+
+ /* Can not call yaffs_get_inode() with gross lock held */
+ yaffs_GrossUnlock(dev);
if (obj) {
inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj);
if (obj) {
inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj);
@@
-935,8
+958,6
@@
static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
error = -ENOMEM;
}
error = -ENOMEM;
}
- yaffs_GrossUnlock(dev);
-
return error;
}
return error;
}
@@
-1217,8
+1238,9
@@
static int yaffs_statfs(struct super_block *sb, struct statfs *buf)
static void yaffs_read_inode(struct inode *inode)
{
static void yaffs_read_inode(struct inode *inode)
{
- /* NB This is called as a side effect of other functions and
- * thus gross locking should always be in place already.
+ /* NB This is called as a side effect of other functions, but
+ * we had to release the lock to prevent deadlocks, so
+ * need to lock again.
*/
yaffs_Object *obj;
*/
yaffs_Object *obj;
@@
-1227,10
+1249,13
@@
static void yaffs_read_inode(struct inode *inode)
T(YAFFS_TRACE_OS,
(KERN_DEBUG "yaffs_read_inode for %d\n", (int)inode->i_ino));
T(YAFFS_TRACE_OS,
(KERN_DEBUG "yaffs_read_inode for %d\n", (int)inode->i_ino));
+ yaffs_GrossLock(dev);
+
obj = yaffs_FindObjectByNumber(dev, inode->i_ino);
yaffs_FillInodeFromObject(inode, obj);
obj = yaffs_FindObjectByNumber(dev, inode->i_ino);
yaffs_FillInodeFromObject(inode, obj);
+ yaffs_GrossUnlock(dev);
}
static LIST_HEAD(yaffs_dev_list);
}
static LIST_HEAD(yaffs_dev_list);
@@
-1446,6
+1471,10
@@
static struct super_block *yaffs_internal_read_super(int yaffsVersion,
dev->useNANDECC = 1;
#endif
dev->useNANDECC = 1;
#endif
+#ifdef CONFIG_YAFFS_DISABLE_WIDE_TNODES
+ dev->wideTnodesDisabled = 1;
+#endif
+
/* we assume this is protected by lock_kernel() in mount/umount */
list_add_tail(&dev->devList, &yaffs_dev_list);
/* we assume this is protected by lock_kernel() in mount/umount */
list_add_tail(&dev->devList, &yaffs_dev_list);
@@
-1458,14
+1487,15
@@
static struct super_block *yaffs_internal_read_super(int yaffsVersion,
T(YAFFS_TRACE_OS,
("yaffs_read_super: guts initialised %s\n",
(err == YAFFS_OK) ? "OK" : "FAILED"));
T(YAFFS_TRACE_OS,
("yaffs_read_super: guts initialised %s\n",
(err == YAFFS_OK) ? "OK" : "FAILED"));
+
+ /* Release lock before yaffs_get_inode() */
+ yaffs_GrossUnlock(dev);
/* Create root inode */
if (err == YAFFS_OK)
inode = yaffs_get_inode(sb, S_IFDIR | 0755, 0,
yaffs_Root(dev));
/* Create root inode */
if (err == YAFFS_OK)
inode = yaffs_get_inode(sb, S_IFDIR | 0755, 0,
yaffs_Root(dev));
- yaffs_GrossUnlock(dev);
-
if (!inode)
return NULL;
if (!inode)
return NULL;