summaryrefslogtreecommitdiffstats
path: root/fs/hpfs
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-04 07:40:19 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-04 07:40:19 +0000
commit33263fc5f9ac8e8cb2b22d06af3ce5ac1dd815e4 (patch)
tree2d1b86a40bef0958a68cf1a2eafbeb0667a70543 /fs/hpfs
parent216f5f51aa02f8b113aa620ebc14a9631a217a00 (diff)
Merge with Linux 2.3.32.
Diffstat (limited to 'fs/hpfs')
-rw-r--r--fs/hpfs/ea.c58
-rw-r--r--fs/hpfs/file.c48
-rw-r--r--fs/hpfs/hpfs_fn.h8
-rw-r--r--fs/hpfs/inode.c30
-rw-r--r--fs/hpfs/namei.c61
5 files changed, 92 insertions, 113 deletions
diff --git a/fs/hpfs/ea.c b/fs/hpfs/ea.c
index d7abdc991..9632c054c 100644
--- a/fs/hpfs/ea.c
+++ b/fs/hpfs/ea.c
@@ -69,8 +69,64 @@ static void set_indirect_ea(struct super_block *s, int ano, secno a, char *data,
hpfs_ea_write(s, a, ano, 0, size, data);
}
-/* Read an extended attribute named 'key' */
+/* Read an extended attribute named 'key' into the provided buffer */
+int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key,
+ char *buf, int size)
+{
+ unsigned pos;
+ int ano, len;
+ secno a;
+ struct extended_attribute *ea;
+ struct extended_attribute *ea_end = fnode_end_ea(fnode);
+ for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
+ if (!strcmp(ea->name, key)) {
+ if (ea->indirect)
+ goto indirect;
+ if (ea->valuelen >= size)
+ return -EINVAL;
+ memcpy(buf, ea_data(ea), ea->valuelen);
+ buf[ea->valuelen] = 0;
+ return 0;
+ }
+ a = fnode->ea_secno;
+ len = fnode->ea_size_l;
+ ano = fnode->ea_anode;
+ pos = 0;
+ while (pos < len) {
+ char ex[4 + 255 + 1 + 8];
+ ea = (struct extended_attribute *)ex;
+ if (pos + 4 > len) {
+ hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x",
+ ano ? "anode" : "sectors", a, len);
+ return -EIO;
+ }
+ if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return -EIO;
+ if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea->indirect ? 8 : 0), ex + 4))
+ return -EIO;
+ if (!strcmp(ea->name, key)) {
+ if (ea->indirect)
+ goto indirect;
+ if (ea->valuelen >= size)
+ return -EINVAL;
+ if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea->valuelen, buf))
+ return -EIO;
+ buf[ea->valuelen] = 0;
+ return 0;
+ }
+ pos += ea->namelen + ea->valuelen + 5;
+ }
+ return -ENOENT;
+indirect:
+ if (ea_len(ea) >= size)
+ return -EINVAL;
+ if (hpfs_ea_read(s, ea_sec(ea), ea->anode, 0, ea_len(ea), buf))
+ return -EIO;
+ buf[ea_len(ea)] = 0;
+ return 0;
+}
+
+/* Read an extended attribute named 'key' */
char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *size)
{
char *ret;
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index 72f61c20a..8abaf2fd3 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -89,55 +89,25 @@ static int hpfs_write_partial_page(struct file *file, struct page *page, unsigne
{
struct dentry *dentry = file->f_dentry;
struct inode *inode = dentry->d_inode;
- struct page *new_page, **hash;
+ struct page *new_page;
unsigned long pgpos;
- struct page * page_cache = NULL;
long status;
- printk("- off: %08x\n", (int)page->offset);
- pgpos = (inode->i_blocks - 1) * 512 & PAGE_CACHE_MASK;
- while (pgpos < page->offset) {
-long pgp = pgpos;
- printk("pgpos: %08x, bl: %d\n", (int)pgpos, (int)inode->i_blocks);
- hash = page_hash(&inode->i_data, pgpos);
-repeat_find: new_page = __find_lock_page(&inode->i_data, pgpos, hash);
- if (!new_page) {
- if (!page_cache) {
- page_cache = page_cache_alloc();
- if (page_cache)
- goto repeat_find;
- status = -ENOMEM;
- goto out;
- }
- new_page = page_cache;
- if (add_to_page_cache_unique(new_page,&inode->i_data,pgpos,hash))
- goto repeat_find;
- page_cache = NULL;
- }
- printk("A\n");
+ pgpos = ((inode->i_blocks - 1) * 512) >> PAGE_CACHE_SHIFT;
+ while (pgpos < page->index) {
+ status = -ENOMEM;
+ new_page = grab_cache_page(&inode->i_data, pgpos);
+ if (!new_page)
+ goto out;
status = block_write_cont_page(file, new_page, PAGE_SIZE, 0, NULL);
- printk("B\n");
UnlockPage(new_page);
page_cache_release(new_page);
if (status < 0)
goto out;
- pgpos = (inode->i_blocks - 1) * 512 & PAGE_CACHE_MASK;
- printk("pgpos2: %08x, bl: %d\n", (int)pgpos, (int)inode->i_blocks);
- if (pgpos == pgp) {
- status = -1;
- printk("ERROR\n");
- goto out;
- }
+ pgpos = ((inode->i_blocks - 1) * 512) >> PAGE_CACHE_SHIFT;
}
- //if ((status = block_write_cont_page(file, page, PAGE_SIZE, 0, NULL)) < 0) goto out;
- printk("C\n");
status = block_write_cont_page(file, page, offset, bytes, buf);
- printk("D\n");
out:
- printk("O\n");
- if (page_cache)
- page_cache_free(page_cache);
- printk("E\n");
return status;
}
@@ -147,7 +117,7 @@ ssize_t hpfs_file_write(struct file *file, const char *buf, size_t count, loff_t
ssize_t retval;
retval = generic_file_write(file, buf, count,
- ppos, /*hpfs_write_partial_page*/block_write_partial_page);
+ ppos, hpfs_write_partial_page);
if (retval > 0) {
struct inode *inode = file->f_dentry->d_inode;
inode->i_mtime = CURRENT_TIME;
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h
index 9ae4a67da..377b296e8 100644
--- a/fs/hpfs/hpfs_fn.h
+++ b/fs/hpfs/hpfs_fn.h
@@ -249,6 +249,7 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *, fnode_secno, struct f
/* ea.c */
void hpfs_ea_ext_remove(struct super_block *, secno, int, unsigned);
+int hpfs_read_ea(struct super_block *, struct fnode *, char *, char *, int);
char *hpfs_get_ea(struct super_block *, struct fnode *, char *, int *);
void hpfs_set_ea(struct inode *, struct fnode *, char *, char *, int);
@@ -283,10 +284,6 @@ struct anode *hpfs_map_anode(struct super_block *s, anode_secno, struct buffer_h
struct dnode *hpfs_map_dnode(struct super_block *s, dnode_secno, struct quad_buffer_head *);
dnode_secno hpfs_fnode_dno(struct super_block *s, ino_t ino);
-/* mmap.c */
-
-int hpfs_mmap(struct file *, struct vm_area_struct *);
-
/* name.c */
unsigned char hpfs_upcase(unsigned char *, unsigned char);
@@ -305,8 +302,7 @@ int hpfs_mknod(struct inode *, struct dentry *, int, int);
int hpfs_symlink(struct inode *, struct dentry *, const char *);
int hpfs_unlink(struct inode *, struct dentry *);
int hpfs_rmdir(struct inode *, struct dentry *);
-int hpfs_readlink(struct dentry *, char *, int);
-struct dentry *hpfs_follow_link(struct dentry *, struct dentry *, unsigned int);
+int hpfs_symlink_readpage(struct dentry *, struct page *);
int hpfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
/* super.c */
diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c
index d79e55814..e4167bfdc 100644
--- a/fs/hpfs/inode.c
+++ b/fs/hpfs/inode.c
@@ -16,7 +16,7 @@ static const struct file_operations hpfs_file_ops =
NULL, /* readdir - bad */
NULL, /* poll - default */
NULL, /* ioctl - default */
- generic_file_mmap/*hpfs_mmap*/, /* mmap */
+ generic_file_mmap, /* mmap */
hpfs_open, /* open */
NULL, /* flush */
hpfs_file_release, /* release */
@@ -44,10 +44,8 @@ static const struct inode_operations hpfs_file_iops =
&hpfs_get_block, /* get_block */
block_read_full_page, /* readpage */
block_write_full_page, /* writepage */
- block_flushpage, /* flushpage */
hpfs_truncate, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL, /* revalidate */
};
@@ -87,38 +85,18 @@ static const struct inode_operations hpfs_dir_iops =
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
const struct inode_operations hpfs_symlink_iops =
{
- NULL, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- hpfs_readlink, /* readlink */
- hpfs_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
+ readlink: page_readlink,
+ follow_link: page_follow_link,
+ readpage: hpfs_symlink_readpage
};
-
void hpfs_read_inode(struct inode *i)
{
struct buffer_head *bh;
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
index fe9b66e3d..85ce143db 100644
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -396,54 +396,33 @@ int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
return r == 2 ? -ENOSPC : r == 1 ? -EFSERROR : 0;
}
-int hpfs_readlink(struct dentry *dentry, char *buf, int len)
+int hpfs_symlink_readpage(struct dentry *dentry, struct page *page)
{
+ char *link = (char*)kmap(page);
struct inode *i = dentry->d_inode;
struct fnode *fnode;
struct buffer_head *bh;
- char *symlink;
- int slen;
- if (!S_ISLNK(i->i_mode)) {
- return -EINVAL;
- }
- if (!(fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh))) {
- return -EIO;
- }
- if (!(symlink = hpfs_get_ea(i->i_sb, fnode, "SYMLINK", &slen))) {
- brelse(bh);
- return -EFSERROR;
- }
- brelse(bh);
- if (slen > len) slen = len;
- memcpy_tofs(buf, symlink, slen);
- kfree(symlink);
- return slen;
-}
+ int err;
-struct dentry *hpfs_follow_link(struct dentry *dinode, struct dentry *ddir,
- unsigned int follow)
-{
- struct inode *inode = dinode->d_inode;
- char *link;
- unsigned len;
- struct buffer_head *bh;
- struct fnode *fnode;
- if (!(fnode = hpfs_map_fnode(inode->i_sb, inode->i_ino, &bh))) {
- dput(dinode);
- return ERR_PTR(-EIO);
- }
- if (!(link = hpfs_get_ea(inode->i_sb, fnode, "SYMLINK", &len))) {
- brelse(bh);
- dput(dinode);
- return ERR_PTR(-EIO);
- }
+ err = -EIO;
+ if (!(fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh)))
+ goto fail;
+ err = hpfs_read_ea(i->i_sb, fnode, "SYMLINK", link, PAGE_SIZE);
brelse(bh);
- UPDATE_ATIME(inode);
- ddir = lookup_dentry(link, ddir, follow);
- kfree(link);
- return ddir;
-}
+ if (err)
+ goto fail;
+ SetPageUptodate(page);
+ kunmap(page);
+ UnlockPage(page);
+ return 0;
+fail:
+ SetPageError(page);
+ kunmap(page);
+ UnlockPage(page);
+ return err;
+}
+
int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
{