diff options
Diffstat (limited to 'fs/affs')
-rw-r--r-- | fs/affs/affs.h | 20 | ||||
-rw-r--r-- | fs/affs/amigaffs.c | 23 | ||||
-rw-r--r-- | fs/affs/dir.c | 28 | ||||
-rw-r--r-- | fs/affs/inode.c | 2 | ||||
-rw-r--r-- | fs/affs/namei.c | 32 | ||||
-rw-r--r-- | fs/affs/super.c | 9 |
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 */ |
123 | static inline struct affs_sb_info *AFFS_SB(struct super_block *sb) | 115 | static 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); | |||
137 | extern void secs_to_datestamp(time_t secs, struct affs_date *ds); | 129 | extern void secs_to_datestamp(time_t secs, struct affs_date *ds); |
138 | extern umode_t prot_to_mode(u32 prot); | 130 | extern umode_t prot_to_mode(u32 prot); |
139 | extern void mode_to_prot(struct inode *inode); | 131 | extern void mode_to_prot(struct inode *inode); |
140 | extern void affs_error(struct super_block *sb, const char *function, const char *fmt, ...); | 132 | extern void affs_error(struct super_block *sb, const char *function, |
141 | extern void affs_warning(struct super_block *sb, const char *function, const char *fmt, ...); | 133 | const char *fmt, ...); |
142 | extern int affs_check_name(const unsigned char *name, int len); | 134 | extern void affs_warning(struct super_block *sb, const char *function, |
135 | const char *fmt, ...); | ||
136 | extern bool affs_nofilenametruncate(const struct dentry *dentry); | ||
137 | extern int affs_check_name(const unsigned char *name, int len, | ||
138 | bool notruncate); | ||
143 | extern int affs_copy_name(unsigned char *bstr, struct dentry *dentry); | 139 | extern 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 | ||
474 | bool | ||
475 | affs_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 | ||
476 | int | 484 | int |
477 | affs_check_name(const unsigned char *name, int len) | 485 | affs_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 | } |
126 | readdir_done: | 132 | done: |
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 | ||
130 | readdir_out: | 137 | out_brelse_dir: |
131 | affs_brelse(dir_bh); | 138 | affs_brelse(dir_bh); |
132 | affs_brelse(fh_bh); | 139 | |
140 | out_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 | */ |
62 | static inline int | 62 | static 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) | |||
82 | static int | 82 | static int |
83 | affs_hash_dentry(const struct dentry *dentry, struct qstr *qstr) | 83 | affs_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 | |||
87 | static int | 90 | static int |
88 | affs_intl_hash_dentry(const struct dentry *dentry, struct qstr *qstr) | 91 | affs_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 | ||
93 | static inline int __affs_compare_dentry(unsigned int len, | 98 | static 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 | |||
126 | affs_compare_dentry(const struct dentry *parent, const struct dentry *dentry, | 132 | affs_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 | |||
131 | static int | 140 | static int |
132 | affs_intl_compare_dentry(const struct dentry *parent, const struct dentry *dentry, | 141 | affs_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 | ||
131 | static int init_inodecache(void) | 131 | static 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 | ||
165 | enum { | 165 | enum { |
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); |