summaryrefslogtreecommitdiffstats
path: root/fs/ext2
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-16 01:07:24 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-16 01:07:24 +0000
commit95db6b748fc86297827fbd9c9ef174d491c9ad89 (patch)
tree27a92a942821cde1edda9a1b088718d436b3efe4 /fs/ext2
parent45b27b0a0652331d104c953a5b192d843fff88f8 (diff)
Merge with Linux 2.3.40.
Diffstat (limited to 'fs/ext2')
-rw-r--r--fs/ext2/file.c6
-rw-r--r--fs/ext2/fsync.c16
-rw-r--r--fs/ext2/inode.c45
-rw-r--r--fs/ext2/namei.c7
-rw-r--r--fs/ext2/super.c3
5 files changed, 64 insertions, 13 deletions
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index 1c915e274..df010f223 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -28,7 +28,7 @@
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
-static long long ext2_file_lseek(struct file *, long long, int);
+static loff_t ext2_file_lseek(struct file *, loff_t, int);
static int ext2_open_file (struct inode *, struct file *);
#define EXT2_MAX_SIZE(bits) \
@@ -45,9 +45,9 @@ EXT2_MAX_SIZE(10), EXT2_MAX_SIZE(11), EXT2_MAX_SIZE(12), EXT2_MAX_SIZE(13)
/*
* Make sure the offset never goes beyond the 32-bit mark..
*/
-static long long ext2_file_lseek(
+static loff_t ext2_file_lseek(
struct file *file,
- long long offset,
+ loff_t offset,
int origin)
{
struct inode *inode = file->f_dentry->d_inode;
diff --git a/fs/ext2/fsync.c b/fs/ext2/fsync.c
index f4e02c2e8..c29fef5ea 100644
--- a/fs/ext2/fsync.c
+++ b/fs/ext2/fsync.c
@@ -23,6 +23,7 @@
*/
#include <linux/fs.h>
+#include <linux/locks.h>
@@ -40,10 +41,21 @@ static int sync_indirect(struct inode * inode, u32 * block, int wait)
if (!bh)
return 0;
if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
- brelse(bh);
- return -1;
+ /* There can be a parallell read(2) that started read-I/O
+ on the buffer so we can't assume that there's been
+ an I/O error without first waiting I/O completation. */
+ wait_on_buffer(bh);
+ if (!buffer_uptodate(bh))
+ {
+ brelse (bh);
+ return -1;
+ }
}
if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) {
+ if (wait)
+ /* when we return from fsync all the blocks
+ must be _just_ stored on disk */
+ wait_on_buffer(bh);
brelse(bh);
return 0;
}
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index b4f952d07..e92e4080a 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -24,6 +24,7 @@
#include <linux/locks.h>
#include <linux/smp_lock.h>
#include <linux/sched.h>
+#include <linux/highuid.h>
@@ -254,6 +255,8 @@ repeat:
}
if (metadata) {
result = getblk (inode->i_dev, tmp, blocksize);
+ if (!buffer_uptodate(result))
+ wait_on_buffer(result);
memset(result->b_data, 0, blocksize);
mark_buffer_uptodate(result, 1);
mark_buffer_dirty(result, 1);
@@ -363,6 +366,8 @@ repeat:
goto out;
if (metadata) {
result = getblk (bh->b_dev, tmp, blocksize);
+ if (!buffer_uptodate(result))
+ wait_on_buffer(result);
memset(result->b_data, 0, inode->i_sb->s_blocksize);
mark_buffer_uptodate(result, 1);
mark_buffer_dirty(result, 1);
@@ -542,6 +547,8 @@ struct buffer_head * ext2_getblk(struct inode * inode, long block, int create, i
struct buffer_head *bh;
bh = getblk(dummy.b_dev, dummy.b_blocknr, inode->i_sb->s_blocksize);
if (buffer_new(&dummy)) {
+ if (!buffer_uptodate(bh))
+ wait_on_buffer(bh);
memset(bh->b_data, 0, inode->i_sb->s_blocksize);
mark_buffer_uptodate(bh, 1);
mark_buffer_dirty(bh, 1);
@@ -655,8 +662,12 @@ void ext2_read_inode (struct inode * inode)
raw_inode = (struct ext2_inode *) (bh->b_data + offset);
inode->i_mode = le16_to_cpu(raw_inode->i_mode);
- inode->i_uid = le16_to_cpu(raw_inode->i_uid);
- inode->i_gid = le16_to_cpu(raw_inode->i_gid);
+ inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low);
+ inode->i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low);
+ if(!(test_opt (inode->i_sb, NO_UID32))) {
+ inode->i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16;
+ inode->i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16;
+ }
inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
inode->i_size = le32_to_cpu(raw_inode->i_size);
inode->i_atime = le32_to_cpu(raw_inode->i_atime);
@@ -795,8 +806,26 @@ static int ext2_update_inode(struct inode * inode, int do_sync)
raw_inode = (struct ext2_inode *) (bh->b_data + offset);
raw_inode->i_mode = cpu_to_le16(inode->i_mode);
- raw_inode->i_uid = cpu_to_le16(inode->i_uid);
- raw_inode->i_gid = cpu_to_le16(inode->i_gid);
+ if(!(test_opt(inode->i_sb, NO_UID32))) {
+ raw_inode->i_uid_low = cpu_to_le16(low_16_bits(inode->i_uid));
+ raw_inode->i_gid_low = cpu_to_le16(low_16_bits(inode->i_gid));
+/*
+ * Fix up interoperability with old kernels. Otherwise, old inodes get
+ * re-used with the upper 16 bits of the uid/gid intact
+ */
+ if(!inode->u.ext2_i.i_dtime) {
+ raw_inode->i_uid_high = cpu_to_le16(high_16_bits(inode->i_uid));
+ raw_inode->i_gid_high = cpu_to_le16(high_16_bits(inode->i_gid));
+ } else {
+ raw_inode->i_uid_high = 0;
+ raw_inode->i_gid_high = 0;
+ }
+ } else {
+ raw_inode->i_uid_low = cpu_to_le16(fs_high2lowuid(inode->i_uid));
+ raw_inode->i_gid_low = cpu_to_le16(fs_high2lowgid(inode->i_gid));
+ raw_inode->i_uid_high = 0;
+ raw_inode->i_gid_high = 0;
+ }
raw_inode->i_links_count = cpu_to_le16(inode->i_nlink);
raw_inode->i_size = cpu_to_le32(inode->i_size);
raw_inode->i_atime = cpu_to_le32(inode->i_atime);
@@ -870,28 +899,28 @@ int ext2_notify_change(struct dentry *dentry, struct iattr *iattr)
flags = iattr->ia_attr_flags;
if (flags & ATTR_FLAG_SYNCRONOUS) {
inode->i_flags |= MS_SYNCHRONOUS;
- inode->u.ext2_i.i_flags = EXT2_SYNC_FL;
+ inode->u.ext2_i.i_flags |= EXT2_SYNC_FL;
} else {
inode->i_flags &= ~MS_SYNCHRONOUS;
inode->u.ext2_i.i_flags &= ~EXT2_SYNC_FL;
}
if (flags & ATTR_FLAG_NOATIME) {
inode->i_flags |= MS_NOATIME;
- inode->u.ext2_i.i_flags = EXT2_NOATIME_FL;
+ inode->u.ext2_i.i_flags |= EXT2_NOATIME_FL;
} else {
inode->i_flags &= ~MS_NOATIME;
inode->u.ext2_i.i_flags &= ~EXT2_NOATIME_FL;
}
if (flags & ATTR_FLAG_APPEND) {
inode->i_flags |= S_APPEND;
- inode->u.ext2_i.i_flags = EXT2_APPEND_FL;
+ inode->u.ext2_i.i_flags |= EXT2_APPEND_FL;
} else {
inode->i_flags &= ~S_APPEND;
inode->u.ext2_i.i_flags &= ~EXT2_APPEND_FL;
}
if (flags & ATTR_FLAG_IMMUTABLE) {
inode->i_flags |= S_IMMUTABLE;
- inode->u.ext2_i.i_flags = EXT2_IMMUTABLE_FL;
+ inode->u.ext2_i.i_flags |= EXT2_IMMUTABLE_FL;
} else {
inode->i_flags &= ~S_IMMUTABLE;
inode->u.ext2_i.i_flags &= ~EXT2_IMMUTABLE_FL;
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index 87f39796a..57a0be62d 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -832,6 +832,13 @@ int ext2_rename (struct inode * old_dir, struct dentry *old_dentry,
new_dir->i_version = ++event;
/*
+ * Like most other Unix systems, set the ctime for inodes on a
+ * rename.
+ */
+ old_inode->i_ctime = CURRENT_TIME;
+ mark_inode_dirty(old_inode);
+
+ /*
* ok, that's it
*/
new_de->inode = le32_to_cpu(old_inode->i_ino);
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index cefde46fd..8a06df18b 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -151,6 +151,9 @@ static int parse_options (char * options, unsigned long * sb_block,
*value++ = 0;
if (!strcmp (this_char, "bsddf"))
clear_opt (*mount_options, MINIX_DF);
+ else if (!strcmp (this_char, "nouid32")) {
+ set_opt (*mount_options, NO_UID32);
+ }
else if (!strcmp (this_char, "check")) {
if (!value || !*value)
set_opt (*mount_options, CHECK_NORMAL);