aboutsummaryrefslogtreecommitdiffstats
path: root/fs/affs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/affs')
-rw-r--r--fs/affs/affs.h20
-rw-r--r--fs/affs/amigaffs.c23
-rw-r--r--fs/affs/dir.c28
-rw-r--r--fs/affs/inode.c2
-rw-r--r--fs/affs/namei.c32
-rw-r--r--fs/affs/super.c9
6 files changed, 72 insertions, 42 deletions
diff --git a/fs/affs/affs.h b/fs/affs/affs.h
index 3952121f2f28..25b23b1e7f22 100644
--- a/fs/affs/affs.h
+++ b/fs/affs/affs.h
@@ -5,14 +5,6 @@
5#include <linux/mutex.h> 5#include <linux/mutex.h>
6#include <linux/workqueue.h> 6#include <linux/workqueue.h>
7 7
8/* AmigaOS allows file names with up to 30 characters length.
9 * Names longer than that will be silently truncated. If you
10 * want to disallow this, comment out the following #define.
11 * Creating filesystem objects with longer names will then
12 * result in an error (ENAMETOOLONG).
13 */
14/*#define AFFS_NO_TRUNCATE */
15
16/* Ugly macros make the code more pretty. */ 8/* Ugly macros make the code more pretty. */
17 9
18#define GET_END_PTR(st,p,sz) ((st *)((char *)(p)+((sz)-sizeof(st)))) 10#define GET_END_PTR(st,p,sz) ((st *)((char *)(p)+((sz)-sizeof(st))))
@@ -28,7 +20,6 @@
28 20
29#define AFFS_CACHE_SIZE PAGE_SIZE 21#define AFFS_CACHE_SIZE PAGE_SIZE
30 22
31#define AFFS_MAX_PREALLOC 32
32#define AFFS_LC_SIZE (AFFS_CACHE_SIZE/sizeof(u32)/2) 23#define AFFS_LC_SIZE (AFFS_CACHE_SIZE/sizeof(u32)/2)
33#define AFFS_AC_SIZE (AFFS_CACHE_SIZE/sizeof(struct affs_ext_key)/2) 24#define AFFS_AC_SIZE (AFFS_CACHE_SIZE/sizeof(struct affs_ext_key)/2)
34#define AFFS_AC_MASK (AFFS_AC_SIZE-1) 25#define AFFS_AC_MASK (AFFS_AC_SIZE-1)
@@ -118,6 +109,7 @@ struct affs_sb_info {
118#define SF_OFS 0x0200 /* Old filesystem */ 109#define SF_OFS 0x0200 /* Old filesystem */
119#define SF_PREFIX 0x0400 /* Buffer for prefix is allocated */ 110#define SF_PREFIX 0x0400 /* Buffer for prefix is allocated */
120#define SF_VERBOSE 0x0800 /* Talk about fs when mounting */ 111#define SF_VERBOSE 0x0800 /* Talk about fs when mounting */
112#define SF_NO_TRUNCATE 0x1000 /* Don't truncate filenames */
121 113
122/* short cut to get to the affs specific sb data */ 114/* short cut to get to the affs specific sb data */
123static inline struct affs_sb_info *AFFS_SB(struct super_block *sb) 115static inline struct affs_sb_info *AFFS_SB(struct super_block *sb)
@@ -137,9 +129,13 @@ extern void affs_fix_checksum(struct super_block *sb, struct buffer_head *bh);
137extern void secs_to_datestamp(time_t secs, struct affs_date *ds); 129extern void secs_to_datestamp(time_t secs, struct affs_date *ds);
138extern umode_t prot_to_mode(u32 prot); 130extern umode_t prot_to_mode(u32 prot);
139extern void mode_to_prot(struct inode *inode); 131extern void mode_to_prot(struct inode *inode);
140extern void affs_error(struct super_block *sb, const char *function, const char *fmt, ...); 132extern void affs_error(struct super_block *sb, const char *function,
141extern void affs_warning(struct super_block *sb, const char *function, const char *fmt, ...); 133 const char *fmt, ...);
142extern int affs_check_name(const unsigned char *name, int len); 134extern void affs_warning(struct super_block *sb, const char *function,
135 const char *fmt, ...);
136extern bool affs_nofilenametruncate(const struct dentry *dentry);
137extern int affs_check_name(const unsigned char *name, int len,
138 bool notruncate);
143extern int affs_copy_name(unsigned char *bstr, struct dentry *dentry); 139extern int affs_copy_name(unsigned char *bstr, struct dentry *dentry);
144 140
145/* bitmap. c */ 141/* bitmap. c */
diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c
index d9a43674cb94..533a322c41c0 100644
--- a/fs/affs/amigaffs.c
+++ b/fs/affs/amigaffs.c
@@ -471,20 +471,27 @@ affs_warning(struct super_block *sb, const char *function, const char *fmt, ...)
471 function,ErrorBuffer); 471 function,ErrorBuffer);
472} 472}
473 473
474bool
475affs_nofilenametruncate(const struct dentry *dentry)
476{
477 struct inode *inode = dentry->d_inode;
478 return AFFS_SB(inode->i_sb)->s_flags & SF_NO_TRUNCATE;
479
480}
481
474/* Check if the name is valid for a affs object. */ 482/* Check if the name is valid for a affs object. */
475 483
476int 484int
477affs_check_name(const unsigned char *name, int len) 485affs_check_name(const unsigned char *name, int len, bool notruncate)
478{ 486{
479 int i; 487 int i;
480 488
481 if (len > 30) 489 if (len > 30) {
482#ifdef AFFS_NO_TRUNCATE 490 if (notruncate)
483 return -ENAMETOOLONG; 491 return -ENAMETOOLONG;
484#else 492 else
485 len = 30; 493 len = 30;
486#endif 494 }
487
488 for (i = 0; i < len; i++) { 495 for (i = 0; i < len; i++) {
489 if (name[i] < ' ' || name[i] == ':' 496 if (name[i] < ' ' || name[i] == ':'
490 || (name[i] > 0x7e && name[i] < 0xa0)) 497 || (name[i] > 0x7e && name[i] < 0xa0))
diff --git a/fs/affs/dir.c b/fs/affs/dir.c
index f1eba8c3644e..cbbda476a805 100644
--- a/fs/affs/dir.c
+++ b/fs/affs/dir.c
@@ -52,8 +52,10 @@ affs_readdir(struct file *file, struct dir_context *ctx)
52 int hash_pos; 52 int hash_pos;
53 int chain_pos; 53 int chain_pos;
54 u32 ino; 54 u32 ino;
55 int error = 0;
55 56
56 pr_debug("AFFS: readdir(ino=%lu,f_pos=%lx)\n",inode->i_ino,(unsigned long)ctx->pos); 57 pr_debug("AFFS: readdir(ino=%lu,f_pos=%lx)\n",
58 inode->i_ino, (unsigned long)ctx->pos);
57 59
58 if (ctx->pos < 2) { 60 if (ctx->pos < 2) {
59 file->private_data = (void *)0; 61 file->private_data = (void *)0;
@@ -72,7 +74,7 @@ affs_readdir(struct file *file, struct dir_context *ctx)
72 } 74 }
73 dir_bh = affs_bread(sb, inode->i_ino); 75 dir_bh = affs_bread(sb, inode->i_ino);
74 if (!dir_bh) 76 if (!dir_bh)
75 goto readdir_out; 77 goto out_unlock_dir;
76 78
77 /* If the directory hasn't changed since the last call to readdir(), 79 /* If the directory hasn't changed since the last call to readdir(),
78 * we can jump directly to where we left off. 80 * we can jump directly to where we left off.
@@ -88,7 +90,8 @@ affs_readdir(struct file *file, struct dir_context *ctx)
88 fh_bh = affs_bread(sb, ino); 90 fh_bh = affs_bread(sb, ino);
89 if (!fh_bh) { 91 if (!fh_bh) {
90 affs_error(sb, "readdir","Cannot read block %d", i); 92 affs_error(sb, "readdir","Cannot read block %d", i);
91 return -EIO; 93 error = -EIO;
94 goto out_brelse_dir;
92 } 95 }
93 ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain); 96 ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain);
94 affs_brelse(fh_bh); 97 affs_brelse(fh_bh);
@@ -107,29 +110,34 @@ inside:
107 do { 110 do {
108 fh_bh = affs_bread(sb, ino); 111 fh_bh = affs_bread(sb, ino);
109 if (!fh_bh) { 112 if (!fh_bh) {
110 affs_error(sb, "readdir","Cannot read block %d", ino); 113 affs_error(sb, "readdir",
114 "Cannot read block %d", ino);
111 break; 115 break;
112 } 116 }
113 117
114 namelen = min(AFFS_TAIL(sb, fh_bh)->name[0], (u8)30); 118 namelen = min(AFFS_TAIL(sb, fh_bh)->name[0], (u8)30);
115 name = AFFS_TAIL(sb, fh_bh)->name + 1; 119 name = AFFS_TAIL(sb, fh_bh)->name + 1;
116 pr_debug("AFFS: readdir(): filldir(\"%.*s\", ino=%u), hash=%d, f_pos=%x\n", 120 pr_debug("AFFS: readdir(): dir_emit(\"%.*s\", "
121 "ino=%u), hash=%d, f_pos=%x\n",
117 namelen, name, ino, hash_pos, (u32)ctx->pos); 122 namelen, name, ino, hash_pos, (u32)ctx->pos);
123
118 if (!dir_emit(ctx, name, namelen, ino, DT_UNKNOWN)) 124 if (!dir_emit(ctx, name, namelen, ino, DT_UNKNOWN))
119 goto readdir_done; 125 goto done;
120 ctx->pos++; 126 ctx->pos++;
121 ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain); 127 ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain);
122 affs_brelse(fh_bh); 128 affs_brelse(fh_bh);
123 fh_bh = NULL; 129 fh_bh = NULL;
124 } while (ino); 130 } while (ino);
125 } 131 }
126readdir_done: 132done:
127 file->f_version = inode->i_version; 133 file->f_version = inode->i_version;
128 file->private_data = (void *)(long)ino; 134 file->private_data = (void *)(long)ino;
135 affs_brelse(fh_bh);
129 136
130readdir_out: 137out_brelse_dir:
131 affs_brelse(dir_bh); 138 affs_brelse(dir_bh);
132 affs_brelse(fh_bh); 139
140out_unlock_dir:
133 affs_unlock_dir(inode); 141 affs_unlock_dir(inode);
134 return 0; 142 return error;
135} 143}
diff --git a/fs/affs/inode.c b/fs/affs/inode.c
index 0e092d08680e..96df91e8c334 100644
--- a/fs/affs/inode.c
+++ b/fs/affs/inode.c
@@ -259,7 +259,7 @@ affs_evict_inode(struct inode *inode)
259{ 259{
260 unsigned long cache_page; 260 unsigned long cache_page;
261 pr_debug("AFFS: evict_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink); 261 pr_debug("AFFS: evict_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink);
262 truncate_inode_pages(&inode->i_data, 0); 262 truncate_inode_pages_final(&inode->i_data);
263 263
264 if (!inode->i_nlink) { 264 if (!inode->i_nlink) {
265 inode->i_size = 0; 265 inode->i_size = 0;
diff --git a/fs/affs/namei.c b/fs/affs/namei.c
index c36cbb4537a2..6dae1ccd176d 100644
--- a/fs/affs/namei.c
+++ b/fs/affs/namei.c
@@ -60,13 +60,13 @@ affs_get_toupper(struct super_block *sb)
60 * Note: the dentry argument is the parent dentry. 60 * Note: the dentry argument is the parent dentry.
61 */ 61 */
62static inline int 62static inline int
63__affs_hash_dentry(struct qstr *qstr, toupper_t toupper) 63__affs_hash_dentry(struct qstr *qstr, toupper_t toupper, bool notruncate)
64{ 64{
65 const u8 *name = qstr->name; 65 const u8 *name = qstr->name;
66 unsigned long hash; 66 unsigned long hash;
67 int i; 67 int i;
68 68
69 i = affs_check_name(qstr->name, qstr->len); 69 i = affs_check_name(qstr->name, qstr->len, notruncate);
70 if (i) 70 if (i)
71 return i; 71 return i;
72 72
@@ -82,16 +82,22 @@ __affs_hash_dentry(struct qstr *qstr, toupper_t toupper)
82static int 82static int
83affs_hash_dentry(const struct dentry *dentry, struct qstr *qstr) 83affs_hash_dentry(const struct dentry *dentry, struct qstr *qstr)
84{ 84{
85 return __affs_hash_dentry(qstr, affs_toupper); 85 return __affs_hash_dentry(qstr, affs_toupper,
86 affs_nofilenametruncate(dentry));
87
86} 88}
89
87static int 90static int
88affs_intl_hash_dentry(const struct dentry *dentry, struct qstr *qstr) 91affs_intl_hash_dentry(const struct dentry *dentry, struct qstr *qstr)
89{ 92{
90 return __affs_hash_dentry(qstr, affs_intl_toupper); 93 return __affs_hash_dentry(qstr, affs_intl_toupper,
94 affs_nofilenametruncate(dentry));
95
91} 96}
92 97
93static inline int __affs_compare_dentry(unsigned int len, 98static inline int __affs_compare_dentry(unsigned int len,
94 const char *str, const struct qstr *name, toupper_t toupper) 99 const char *str, const struct qstr *name, toupper_t toupper,
100 bool notruncate)
95{ 101{
96 const u8 *aname = str; 102 const u8 *aname = str;
97 const u8 *bname = name->name; 103 const u8 *bname = name->name;
@@ -101,7 +107,7 @@ static inline int __affs_compare_dentry(unsigned int len,
101 * must be valid. 'name' must be validated first. 107 * must be valid. 'name' must be validated first.
102 */ 108 */
103 109
104 if (affs_check_name(name->name, name->len)) 110 if (affs_check_name(name->name, name->len, notruncate))
105 return 1; 111 return 1;
106 112
107 /* 113 /*
@@ -126,13 +132,18 @@ static int
126affs_compare_dentry(const struct dentry *parent, const struct dentry *dentry, 132affs_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
127 unsigned int len, const char *str, const struct qstr *name) 133 unsigned int len, const char *str, const struct qstr *name)
128{ 134{
129 return __affs_compare_dentry(len, str, name, affs_toupper); 135
136 return __affs_compare_dentry(len, str, name, affs_toupper,
137 affs_nofilenametruncate(parent));
130} 138}
139
131static int 140static int
132affs_intl_compare_dentry(const struct dentry *parent, const struct dentry *dentry, 141affs_intl_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
133 unsigned int len, const char *str, const struct qstr *name) 142 unsigned int len, const char *str, const struct qstr *name)
134{ 143{
135 return __affs_compare_dentry(len, str, name, affs_intl_toupper); 144 return __affs_compare_dentry(len, str, name, affs_intl_toupper,
145 affs_nofilenametruncate(parent));
146
136} 147}
137 148
138/* 149/*
@@ -411,7 +422,10 @@ affs_rename(struct inode *old_dir, struct dentry *old_dentry,
411 (u32)old_dir->i_ino, (int)old_dentry->d_name.len, old_dentry->d_name.name, 422 (u32)old_dir->i_ino, (int)old_dentry->d_name.len, old_dentry->d_name.name,
412 (u32)new_dir->i_ino, (int)new_dentry->d_name.len, new_dentry->d_name.name); 423 (u32)new_dir->i_ino, (int)new_dentry->d_name.len, new_dentry->d_name.name);
413 424
414 retval = affs_check_name(new_dentry->d_name.name,new_dentry->d_name.len); 425 retval = affs_check_name(new_dentry->d_name.name,
426 new_dentry->d_name.len,
427 affs_nofilenametruncate(old_dentry));
428
415 if (retval) 429 if (retval)
416 return retval; 430 return retval;
417 431
diff --git a/fs/affs/super.c b/fs/affs/super.c
index d098731b82ff..6d589f28bf9b 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -128,7 +128,7 @@ static void init_once(void *foo)
128 inode_init_once(&ei->vfs_inode); 128 inode_init_once(&ei->vfs_inode);
129} 129}
130 130
131static int init_inodecache(void) 131static int __init init_inodecache(void)
132{ 132{
133 affs_inode_cachep = kmem_cache_create("affs_inode_cache", 133 affs_inode_cachep = kmem_cache_create("affs_inode_cache",
134 sizeof(struct affs_inode_info), 134 sizeof(struct affs_inode_info),
@@ -163,7 +163,7 @@ static const struct super_operations affs_sops = {
163}; 163};
164 164
165enum { 165enum {
166 Opt_bs, Opt_mode, Opt_mufs, Opt_prefix, Opt_protect, 166 Opt_bs, Opt_mode, Opt_mufs, Opt_notruncate, Opt_prefix, Opt_protect,
167 Opt_reserved, Opt_root, Opt_setgid, Opt_setuid, 167 Opt_reserved, Opt_root, Opt_setgid, Opt_setuid,
168 Opt_verbose, Opt_volume, Opt_ignore, Opt_err, 168 Opt_verbose, Opt_volume, Opt_ignore, Opt_err,
169}; 169};
@@ -172,6 +172,7 @@ static const match_table_t tokens = {
172 {Opt_bs, "bs=%u"}, 172 {Opt_bs, "bs=%u"},
173 {Opt_mode, "mode=%o"}, 173 {Opt_mode, "mode=%o"},
174 {Opt_mufs, "mufs"}, 174 {Opt_mufs, "mufs"},
175 {Opt_notruncate, "nofilenametruncate"},
175 {Opt_prefix, "prefix=%s"}, 176 {Opt_prefix, "prefix=%s"},
176 {Opt_protect, "protect"}, 177 {Opt_protect, "protect"},
177 {Opt_reserved, "reserved=%u"}, 178 {Opt_reserved, "reserved=%u"},
@@ -233,6 +234,9 @@ parse_options(char *options, kuid_t *uid, kgid_t *gid, int *mode, int *reserved,
233 case Opt_mufs: 234 case Opt_mufs:
234 *mount_opts |= SF_MUFS; 235 *mount_opts |= SF_MUFS;
235 break; 236 break;
237 case Opt_notruncate:
238 *mount_opts |= SF_NO_TRUNCATE;
239 break;
236 case Opt_prefix: 240 case Opt_prefix:
237 *prefix = match_strdup(&args[0]); 241 *prefix = match_strdup(&args[0]);
238 if (!*prefix) 242 if (!*prefix)
@@ -530,6 +534,7 @@ affs_remount(struct super_block *sb, int *flags, char *data)
530 534
531 pr_debug("AFFS: remount(flags=0x%x,opts=\"%s\")\n",*flags,data); 535 pr_debug("AFFS: remount(flags=0x%x,opts=\"%s\")\n",*flags,data);
532 536
537 sync_filesystem(sb);
533 *flags |= MS_NODIRATIME; 538 *flags |= MS_NODIRATIME;
534 539
535 memcpy(volume, sbi->s_volume, 32); 540 memcpy(volume, sbi->s_volume, 32);